home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / cri.py < prev    next >
Encoding:
Python Source  |  2008-02-17  |  62.0 KB  |  1,535 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2008
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # -------------------------------------------------------------
  36. # The RenderMan (R) Interface Procedures and Protocol are:
  37. # Copyright 1988, 1989, 2000, Pixar
  38. # All Rights Reserved
  39. #
  40. # RenderMan (R) is a registered trademark of Pixar
  41. # -------------------------------------------------------------
  42. # $Id: ri.py,v 1.4 2006/02/14 19:29:39 mbaas Exp $
  43.  
  44. import types, re
  45. import ri
  46. from cgtypes import vec3
  47. try:
  48.     import ctypes
  49.     _has_ctypes = True
  50. except ImportError:
  51.     # If importing ctypes fails (which should only happen on older Python versions)
  52.     # the loadRI() function can still be used to load the standard ri module
  53.     # (and get the shortened function names without the "Ri" prefix).
  54.     _has_ctypes = False
  55.     
  56. if _has_ctypes:
  57.     import _cri
  58.     from _cri import importRINames
  59.  
  60. try:
  61.     import numpy
  62.     from numpy.ctypeslib import ndpointer
  63.     _has_numpy = True
  64. except ImportError:
  65.     _has_numpy = False
  66.     
  67.  
  68. def loadRI(libName):
  69.     """Load a RenderMan library and return a module-like handle to it.
  70.     
  71.     libName is the name of a shared library that implements the RenderMan
  72.     interface. The name can either be an absolute file name or just the
  73.     name of the library (without suffix or "lib" prefix) in which case 
  74.     the function tries to find the library file itself.
  75.     The return value is the library handle as returned by the ctypes 
  76.     LoadLibrary() function. This handle has already been prepared so that
  77.     it can be used like a module that contains the RenderMan interface.
  78.     
  79.     It is also possible to pass in None or an empty string in which case
  80.     the built-in ri module will be returned.
  81.     """
  82.     if libName is None or libName=="":
  83.         _ri = ri
  84.     else: 
  85.         if not _has_ctypes:
  86.             raise ImportError("The ctypes module is not available. Please upgrade to a newer Python version (2.5 or newer) or install ctypes separately.")
  87.         _ri = _cri.loadRI(libName)
  88.         _ri = _RenderManAPI(_ri)
  89.     
  90.     # Create an alias for every Ri function and RI_ constant that has the prefix removed...
  91.     for name in dir(_ri):
  92.         if name.startswith("Ri"):
  93.             setattr(_ri, name[2:], getattr(_ri, name))
  94.         elif name.startswith("RI_"):
  95.             setattr(_ri, name[3:], getattr(_ri, name))
  96.  
  97.     return _ri
  98.  
  99. class _ProceduralWrapper:
  100.     """Helper class for RiProcedural.
  101.     
  102.     The main purpose of this class is to ensure that all relevant Python
  103.     objects (the ctypes functions) are kept alive for as long as the
  104.     procedural is active. And while we have an instance of this class
  105.     around, it also stores the data value which is passed on the user
  106.     functions. This means, the C data value is not used at all (as every
  107.     procedural will have its own _ProceduralWrapper instance).
  108.     
  109.     The subdiv() and free() methods of this class are the actual functions
  110.     that get passed to the C RiProcedural function.
  111.     """
  112.     def __init__(self, RMAPI, data, subdivFunc, freeFunc):
  113.         # A reference to the "ri" object that has spawned this wrapper instance
  114.         self.RMAPI = RMAPI
  115.         # The wrapped up data value
  116.         self.data = data
  117.         # The user subdiv function
  118.         self.subdivFunc = subdivFunc
  119.         # The user free function (may be None)
  120.         self.freeFunc = freeFunc
  121.         
  122.         # The ctypes function wrappers that get passed to the C function
  123.         self.cSubdivideFunc = RMAPI.RtProcSubdivFunc(self.subdivide)
  124.         self.cFreeFunc = RMAPI.RtProcFreeFunc(self.free)
  125.         
  126.     def subdivide(self, dataPtr, detail):
  127.         """Subdivide function wrapper.
  128.         
  129.         Unwraps the data value and calls the user subdiv function.
  130.         """
  131.         self.subdivFunc(self.data, detail)
  132.         
  133.     def free(self, dataPtr):
  134.         """Free function wrapper.
  135.         
  136.         Unwraps the data value, calls the user free function and
  137.         removes this wrapper instance from the ri object (because
  138.         the associated Python objects need no longer be kept alive).
  139.         """
  140.         if self.freeFunc is not None:
  141.             self.freeFunc(self.data)
  142.         try:
  143.             del self.RMAPI._procWrappers[self]
  144.         except KeyError:
  145.             pass
  146.     
  147.  
  148. class _RenderManAPI:
  149.     """RenderMan interface.
  150.     
  151.     An instance of this class can be used in a "module-like" fashion,
  152.     i.e. it defines all the functions and constants from the RenderMan
  153.     standard and behaves much like the "ri" module.
  154.     """
  155.     
  156.     def __init__(self, rimod):
  157.         """Constructor.
  158.         
  159.         rimod is the unterlying ctypes library handle as returned by _cri.loadRI().
  160.         """
  161.         self._ri = rimod
  162.         
  163.         # Regular expression to parse declarations
  164.         self._declRe = re.compile(r"^\s*(?:(constant|uniform|varying|vertex) )?\s*"
  165.                                    "(float|integer|string|color|point|vector|normal|matrix|hpoint)\s*"
  166.                                    "(?:\[\s*([0-9]+)\s*\])?\s*(\w+)$")
  167.         
  168.         # Copy the RI_ and Rt attributes...
  169.         for name in dir(rimod):
  170.             if name[:2] in ["Rt", "RI"]:
  171.                 setattr(self, name, getattr(rimod, name))
  172.                 
  173.         # "Import" the error handlers, filters and basis functions...
  174.         for name in ["RiErrorAbort", "RiErrorIgnore", "RiErrorPrint",
  175.                      "RiBoxFilter", "RiTriangleFilter", "RiCatmullRomFilter",
  176.                      "RiGaussianFilter", "RiSincFilter",
  177.                      "RiBezierBasis", "RiBSplineBasis", "RiCatmullRomBasis",
  178.                      "RiHermiteBasis", "RiPowerBasis",
  179.                      "RiProcDelayedReadArchive", "RiProcRunProgram", 
  180.                      "RiProcDynamicLoad", "RiProcFree"]:
  181.             if hasattr(rimod, name):
  182.                 setattr(self, name, getattr(rimod, name))
  183.  
  184.         # Variable declarations.
  185.         # Key: Variable name - Value: (class, type, n)
  186.         self._declarations = {}
  187.         self._standardDeclarations(self._ri)
  188.         
  189.         # Stores the _ProceduralWrapper objects
  190.         self._procWrappers = {}
  191.         
  192.         # Lookup table ctypes type -> numpy type
  193.         self._numpyTypes = {}
  194.         if _has_numpy:
  195.             # Fill the _numpyTypes dict
  196.             RtFloat = self._ri.RtFloat
  197.             if RtFloat==ctypes.c_float:
  198.                 self._numpyTypes[RtFloat] = numpy.float32
  199.             elif RtFloat==ctypes.c_double:
  200.                 self._numpyTypes[RtFloat] = numpy.float64
  201.             else:
  202.                 raise TypeError("RtFloat is of an unknown type")
  203.             
  204.             self._numpyTypes[self._ri.RtInt] = numpy.int_
  205.  
  206.         
  207.     def _getRiLastError(self):
  208.         return self._ri.RiLastError
  209.     
  210.     def _setRiLastError(self, val):
  211.         self._ri.RiLastError = val
  212.         
  213.     RiLastError = property(_getRiLastError, _setRiLastError)
  214.     LastError = property(_getRiLastError, _setRiLastError)
  215.         
  216.     def RiArchiveRecord(self, type, format, *args):
  217.         """Output a user data record.
  218.     
  219.         type is one of RI_COMMENT, RI_STRUCTURE or RI_VERBATIM.
  220.     
  221.         Example: RiArchiveRecord(RI_COMMENT, "Frame %d", 2)
  222.         """
  223.         self._ri.RiArchiveRecord(type, format, *args)
  224.  
  225.     def RiAreaLightSource(self, name, *paramlist, **keyparams):
  226.         """Start the definition of an area light and return the light handle.
  227.     
  228.         Example: RiAttributeBegin()
  229.                  area1 = RiAreaLightSource("arealight", intensity=0.75)
  230.                  ....
  231.                  RiAttributeEnd()
  232.                  RiIlluminate(area1, RI_TRUE)
  233.         """
  234.         self._ri.RiAreaLightSource(name, *self._createCParamList(paramlist, keyparams))
  235.  
  236.     def RiAtmosphere(self, name, *paramlist, **keyparams):
  237.         """Set the current atmosphere shader.
  238.     
  239.         If name is RI_NULL then no atmosphere shader is used.
  240.     
  241.         Example: RiAtmosphere("fog")
  242.         """
  243.         self._ri.RiAtmosphere(name, *self._createCParamList(paramlist, keyparams))
  244.  
  245.     def RiAttribute(self, name, *paramlist, **keyparams):
  246.         """Set an implementation-specific attribute.
  247.     
  248.         Example: RiAttribute("displacementbound", "sphere", 0.5)
  249.         """
  250.         a = self._createCParamList(paramlist, keyparams)
  251.         self._ri.RiAttribute(name, *self._createCParamList(paramlist, keyparams))
  252.         
  253.     def RiAttributeBegin(self):
  254.         """Push the current set of attributes onto the attribute stack.
  255.     
  256.         Example: RiAttributeBegin()
  257.                  ...
  258.                  RiAttributeEnd()
  259.         """
  260.         self._ri.RiAttributeBegin()
  261.  
  262.     def RiAttributeEnd(self):
  263.         """Pops the current set of attributes from the attribute stack."""
  264.         self._ri.RiAttributeEnd()
  265.  
  266.     def RiBasis(self, ubasis, ustep, vbasis, vstep):
  267.         """Set the current basis for the u and v direction.
  268.     
  269.         ubasis/vbasis can either be one of the predefined basis matrices
  270.         RiHermiteBasis, RiCatmullRomBasis, RiBezierBasis, RiBSplineBasis,
  271.         RiPowerBasis or it can be a user defined matrix.
  272.     
  273.         For the predefined matrices there are also predefined variables
  274.         which can be used for the step parameters:
  275.         RI_HERMITESTEP, RI_CATMULLROMSTEP, RI_BEZIERSTEP, RI_BSPLINESTEP,
  276.         RI_POWERSTEP.
  277.     
  278.         Example: RiBasis(RiBezierBasis, RI_BEZIERSTEP,
  279.                          RiHermiteBasis, RI_HERMITESTEP)
  280.         """
  281.         ubasis = self._toCArray(self._ri.RtFloat, ubasis)
  282.         vbasis = self._toCArray(self._ri.RtFloat, vbasis)
  283.         self._ri.RiBasis(ubasis, ustep, vbasis, vstep)
  284.  
  285.     def RiBegin(self, name):
  286.         """Starts the main block using a particular rendering method.
  287.         
  288.         The default renderer is selected by passing RI_NULL as name.
  289.     
  290.         Example: RiBegin(RI_NULL)
  291.                  ...
  292.                  RiEnd()
  293.         """
  294.         self._ri.RiBegin(name)
  295.         
  296.     def RiBlobby(self, nleaf, code, floats, strings, *paramlist, **keyparams):
  297.         """Create a blobby surface.
  298.     
  299.         Number of array elements for primitive variables:
  300.         -------------------------------------------------
  301.         constant: 1              varying: nleaf
  302.         uniform:  1              vertex:  nleaf
  303.     
  304.         Example: RiBlobby(2, [1001,0, 1003,0,16, 0,2,0,1],
  305.                           [1.5,0,0,0, 0,1.5,0,0, 0,0,1.5,0, 0,0,-.1,1,
  306.                           0.4, 0.01,0.3, 0.08], ["flat.zfile"])
  307.         """
  308.         code = self._toCArray(self._ri.RtInt, code)
  309.         floats = self._toCArray(self._ri.RtFloat, floats)
  310.         strings = self._toCArray(self._ri.RtString, strings)
  311.         self._ri.RiBlobby(nleaf, len(code), code, len(floats), floats, len(strings), strings, *self._createCParamList(paramlist, keyparams))
  312.  
  313.     def RiBound(self, bound):
  314.         """Set the bounding box for subsequent primitives.
  315.     
  316.         bound must be a sequence of six floating point values specifying
  317.         the extent of the box along each coordinate direction:
  318.         bound = [xmin, xmax, ymin, ymax, zmin, zmax]
  319.     
  320.         Example: RiBound([-1,1, 0,1, 0.5,0.75])
  321.         """
  322.         bound = self._toCArray(self._ri.RtFloat, bound)
  323.         self._ri.RiBound(bound)
  324.  
  325.     def RiClipping(self, near, far):
  326.         """Sets the near and the far clipping plane along the direction of view.
  327.     
  328.         near and far must be positive values in the range from RI_EPSILON to
  329.         RI_INFINITY.
  330.     
  331.         Example: RiClipping(0.1, 100)
  332.         """
  333.         self._ri.RiClipping(near, far)
  334.         
  335.     def RiClippingPlane(self, x, y, z, nx, ny, nz):
  336.         """Adds a new clipping plane, defined by a surface point and its normal.
  337.     
  338.         All the geometry in positive normal direction is clipped.
  339.     
  340.         Example: RiClippingPlane(0,0,0, 0,0,-1) clips everything below the XY plane
  341.         """
  342.         self._ri.RiClippingPlane(x, y, z, nx, ny, nz)
  343.     
  344.     def RiColor(self, Cs):
  345.         """Set the current color.
  346.     
  347.         Cs must be a sequence of at least N values where N is the number of
  348.         color samples (set by RiColorSamples(), default is 3).
  349.     
  350.         Example: RiColor([0.2,0.5,0.2])
  351.         """
  352.         Cs = self._toCArray(self._ri.RtFloat, Cs)
  353.         self._ri.RiColor(Cs)
  354.         
  355.     def RiColorSamples(self, nRGB, RGBn):
  356.         """Redefine the number of color components to be used for specifying colors.
  357.     
  358.         nRGB is a n x 3 matrix that can be used to transform the n component color
  359.         to a RGB color (n -> RGB).
  360.         RGBn is just the opposite, its a 3 x n matrix that's used to transform
  361.         a RGB color to a n component color (RGB -> n).
  362.         Thus, the new number of color components is len(matrix)/3 (matrix is
  363.         either nRGB or RGBn).
  364.     
  365.         Example: RiColorSamples([0.3,0.3,0.3], [1,1,1])
  366.         """
  367.         nRGB = self._toCArray(self._ri.RtFloat, nRGB)
  368.         RGBn = self._toCArray(self._ri.RtFloat, RGBn)
  369.         if len(nRGB)!=len(RGBn):
  370.             raise ValueError, "The conversion matrices must have the same number of elements."
  371.         if len(nRGB)%3!=0:
  372.             raise ValueError, "Invalid number of elements in the conversion matrices."
  373.         n = len(nRGB)/3
  374.         self._ri.RiColorSamples(n, nRGB, RGBn)
  375.  
  376.     def RiConcatTransform(self, transform):
  377.         """Concatenate a transformation onto the current transformation.
  378.     
  379.         transform must be a sequence that evaluates to 16 floating point
  380.         values (4x4 matrix).
  381.     
  382.         Example: RiConcatTransform([2,0,0,0, 0,2,0,0, 0,0,2,0, 0,0,0,1])
  383.                  RiConcatTransform([[2,0,0,0], [0,2,0,0], [0,0,2,0], [0,0,0,1]])
  384.         """
  385.         transform = self._toCArray(self._ri.RtFloat, transform)
  386.         self._ri.RiConcatTransform(transform)
  387.         
  388.     def RiCone(self, height, radius, thetamax, *paramlist, **keyparams):
  389.         """Create a cone (along the z axis).
  390.     
  391.         Number of array elements for primitive variables:
  392.         -------------------------------------------------
  393.         constant: 1              varying: 4
  394.         uniform:  1              vertex:  4
  395.     
  396.         Example: RiCone(1.5, 0.7, 360)
  397.         """
  398.         self._ri.RiCone(height, radius, thetamax, *self._createCParamList(paramlist, keyparams))
  399.  
  400.     def RiContext(self, handle):
  401.         """Set the current active rendering context.
  402.     
  403.         Example: ctx1 = RiGetContext()
  404.                  ...
  405.                  RiContext(ctx1)
  406.         """
  407.         self._ri.RiContext(handle)
  408.     
  409.     def RiCoordinateSystem(self, spacename):
  410.         """Mark the current coordinate system with a name.
  411.     
  412.         Example: RiCoordinateSystem("lamptop")
  413.         """
  414.         self._ri.RiCoordinateSystem(spacename)
  415.         
  416.     def RiCoordSysTransform(self, spacename):
  417.         """Replace the current transformation matrix with spacename.
  418.     
  419.         Example: RiCoordSysTransform("lamptop")
  420.         """
  421.         self._ri.RiCoordSysTransform(spacename)
  422.     
  423.     def RiCropWindow(self, left, right, bottom, top):
  424.         """Specify a subwindow to render.
  425.     
  426.         The values each lie between 0 and 1.
  427.     
  428.         Example: RiCropWindow(0.0, 1.0 , 0.0, 1.0)  (renders the entire frame)
  429.                  RiCropWindow(0.5, 1.0 , 0.0, 0.5)  (renders the top right quarter)
  430.         """
  431.         self._ri.RiCropWindow(left, right, bottom, top)
  432.         
  433.     def RiCurves(self, type, nvertices, wrap, *paramlist, **keyparams):
  434.         """Create a number of curve primitives.
  435.     
  436.         type is either RI_LINEAR or RI_CUBIC.
  437.         nvertices is an array with the number of vertices in each curve.
  438.         wrap is either RI_PERIODIC or RI_NONPERIODIC.
  439.         The width of the curves can be specified with the parameter
  440.         RI_WIDTH (varying float) or RI_CONSTANTWIDTH (constant float).
  441.     
  442.         Number of array elements for primitive variables:
  443.         -------------------------------------------------
  444.         constant: 1              varying: #segments (depends on type and wrap)
  445.         uniform:  #curves        vertex:  #points
  446.     
  447.         Example: RiCurves(RI_CUBIC, [4], RI_NONPERIODIC,
  448.                           P=[0,0,0, -1,-0.5,1, 2,0.5,1, 1,0,-1],
  449.                           width=[0.1, 0.04])
  450.         """
  451.         nvertices = self._toCArray(self._ri.RtInt, nvertices)
  452.         self._ri.RiCurves(type, len(nvertices), nvertices, wrap, *self._createCParamList(paramlist, keyparams))
  453.  
  454.     def RiCylinder(self, radius,zmin,zmax,thetamax,*paramlist, **keyparams):
  455.         """Create a cylinder (along the z axis).
  456.     
  457.         Number of array elements for primitive variables:
  458.         -------------------------------------------------
  459.         constant: 1              varying: 4
  460.         uniform:  1              vertex:  4
  461.     
  462.         Example: RiCylinder(1.5, 0.0, 1.0, 360)
  463.         """
  464.         self._ri.RiCylinder(radius, zmin, zmax, thetamax, *self._createCParamList(paramlist, keyparams))
  465.    
  466.     def RiDeclare(self, name, declaration):
  467.         """Declare the name and type of a variable.
  468.     
  469.         The syntax of the declaration is:  [class] [type] ['['n']']
  470.     
  471.         class ::= constant | uniform | varying | vertex
  472.         type  ::= float | integer | string | color | point | vector | normal |
  473.                   matrix | hpoint
  474.         
  475.         Example: RiDeclare("foo","uniform float")
  476.                  RiDeclare("bar","constant integer [4]")
  477.                  RiDeclare("mycolor", "varying color")
  478.         """
  479.         # Process the declaration internally so that parameter lists can be
  480.         # constructed properly...
  481.         decl = "%s %s"%(declaration, name)
  482.         m = self._declRe.match(decl)
  483.         if m is None:
  484.             raise ValueError, "Invalid declaration: %s"%decl
  485.         # Groups is a 4-tuple (class, type, n, name)
  486.         grps = m.groups()
  487.         self._declarations[grps[3]] = grps[:3]
  488.         
  489.         # Forward the call...
  490.         return self._ri.RiDeclare(name, declaration)
  491.  
  492.     def RiDepthOfField(self, fstop, focallength, focaldistance):
  493.         """Set depth of field parameters.
  494.     
  495.         If fstop is RI_INFINITY depth of field is turned off.
  496.     
  497.         Example: RiDepthOfField(22,45,1200)
  498.         """
  499.         self._ri.RiDepthOfField(fstop, focallength, focaldistance)
  500.         
  501.     def RiDetail(self, bound):
  502.         """Set the current bounding box.
  503.     
  504.         bound must be a sequence of six floating point values specifying
  505.         the extent of the box along each coordinate direction:
  506.         bound = [xmin, xmax, ymin, ymax, zmin, zmax]
  507.     
  508.         Example: RiDetail([10,20,40,70,0,1])
  509.         """
  510.         bound = self._toCArray(self._ri.RtFloat, bound)
  511.         self._ri.RiDetail(bound)
  512.     
  513.     def RiDetailRange(self, minvisible, lowertransition, uppertransition, maxvisible):
  514.         """Set the current detail range.
  515.     
  516.         The values of the parameters must satisfy the following ordering:
  517.         minvisible <= lowertransition <= uppertransition <= maxvisible
  518.     
  519.                     lowertransition  uppertransition
  520.      visibility         |____________________|       
  521.         ^               /                    \\
  522.         |              /                      \\
  523.         |_____________/                        \\_____________\\ Level of detail
  524.                      |                          |            /
  525.                  minvisible                      maxvisible
  526.     
  527.         Example: RiDetailRange(0,0,10,20)
  528.         """
  529.         self._ri.RiDetailRange(minvisible, lowertransition, uppertransition, maxvisible)
  530.  
  531.     def RiDisk(self, height, radius, thetamax, *paramlist, **keyparams):
  532.         """Create a disk (parallel to the XY plane).
  533.     
  534.         Number of array elements for primitive variables:
  535.         -------------------------------------------------
  536.         constant: 1              varying: 4
  537.         uniform:  1              vertex:  4
  538.     
  539.         Example: RiDisk(0.0, 1.0, 360)"""
  540.         self._ri.RiDisk(height, radius, thetamax, *self._createCParamList(paramlist, keyparams))
  541.  
  542.     def RiDisplacement(self, name, *paramlist, **keyparams):
  543.         """Set the current displacement shader.
  544.     
  545.         Example: RiDisplacement("dented", km=1.5)
  546.         """
  547.         self._ri.RiDisplacement(name, *self._createCParamList(paramlist, keyparams))
  548.         
  549.     def RiDisplay(self, name, type, mode, *paramlist, **keyparams):
  550.         """Specify the destination and type of the output.
  551.     
  552.         Example: RiDisplay("frame0001.tif", RI_FILE, RI_RGB)
  553.                  RiDisplay("myimage.tif", RI_FRAMEBUFFER, RI_RGB)
  554.         """
  555.         self._ri.RiDisplay(name, type, mode, *self._createCParamList(paramlist, keyparams))
  556.  
  557.     def RiEnd(self):
  558.         """Terminates the main block.
  559.         """
  560.         self._ri.RiEnd()
  561.         
  562.     def RiErrorHandler(self, handler):
  563.         try:
  564.             self._ri.RiErrorHandler(handler)
  565.         except ctypes.ArgumentError:
  566.             self._ri.RiErrorHandler(self._ri.RtErrorHandler(handler))
  567.  
  568.     def RiExposure(self, gain, gamma):
  569.         """Sets the parameters for the output color transformation.
  570.     
  571.         The transformation is color_out = (color_in*gain)^(1/gamma)
  572.     
  573.         Example: RiExposure(1.3, 2.2)
  574.         """
  575.         self._ri.RiExposure(gain, gamma)
  576.  
  577.     def RiExterior(self, name, *paramlist, **keyparams):
  578.         """Set the current exterior volume shader.
  579.     
  580.         Example: RiExterior("fog")
  581.         """
  582.         self._ri.RiExterior(name, *self._createCParamList(paramlist, keyparams))
  583.     
  584.     def RiFormat(self, xres, yres, aspect):
  585.         """Set the resolution of the output image and the aspect ratio of a pixel.
  586.     
  587.         Example: RiFormat(720,576,1)"""
  588.         self._ri.RiFormat(xres, yres, aspect)
  589.         
  590.     def RiFrameAspectRatio(self, frameratio):
  591.         """Set the ratio between width and height of the image.
  592.     
  593.         Example: RiFrameAspectRatio(4.0/3)
  594.         """
  595.         self._ri.RiFrameAspectRatio(frameratio)
  596.  
  597.     def RiFrameBegin(self, number):
  598.         """Start a new frame.
  599.     
  600.         Example: RiFrameBegin(1)
  601.                  ...
  602.                  RiFrameEnd()
  603.         """
  604.         self._ri.RiFrameBegin(number)
  605.  
  606.     def RiFrameEnd(self):
  607.         """Terminates a frame."""
  608.         self._ri.RiFrameEnd()
  609.  
  610.     def RiGeneralPolygon(self, nverts, *paramlist, **keyparams):
  611.         """Create a general planar concave polygon with holes.
  612.     
  613.         Number of array elements for primitive variables:
  614.         -------------------------------------------------
  615.         constant: 1              varying: #total vertices
  616.         uniform:  1              vertex:  #total vertices
  617.     
  618.         Example: RiGeneralPolygon([4,3], P=[0,0,0, 0,1,0, 0,1,1, 0,0,1, \\
  619.                                             0,0.25,0.5, 0,0.75,0.75, 0,0.75,0.25])
  620.         """
  621.         nverts = self._toCArray(self._ri.RtInt, nverts)
  622.         self._ri.RiGeneralPolygon(len(nverts), nverts, *self._createCParamList(paramlist, keyparams))
  623.  
  624.     def RiGeometricApproximation(self, type, value):
  625.         """Sets parameters for approximating surfaces.
  626.     
  627.         Example: RiGeometricApproximation(RI_FLATNESS, 0.5)
  628.         """
  629.         self._ri.RiGeometricApproximation(type, value)
  630.         
  631.     def RiGeometry(self, type, *paramlist, **keyparams):
  632.         """Create an implementation-specific geometric primitive.
  633.     
  634.         Example: RiGeometry("teapot")
  635.         """
  636.         self._ri.RiGeometry(type, *self._createCParamList(paramlist, keyparams))
  637.  
  638.     def RiGetContext(self):
  639.         """Set the current active rendering context.
  640.     
  641.         Example: ctx1 = RiGetContext()
  642.                  ...
  643.                  RiContext(ctx1)
  644.         """
  645.         return self._ri.RiGetContext()
  646.     
  647.     def RiHider(self, type, *paramlist, **keyparams):
  648.         """Choose a hidden-surface elimination technique.
  649.     
  650.         Example: RiHider(RI_HIDDEN)  (default)
  651.         """
  652.         self._ri.RiHider(type, *self._createCParamList(paramlist, keyparams))
  653.  
  654.     def RiHyperboloid(self, point1, point2, thetamax, *paramlist, **keyparams):
  655.         """Create a hyperboloid (with the z axis as symmetry axis).
  656.     
  657.         Example: RiHyperboloid([1,0,0],[1,1,1],360)
  658.         """
  659.         point1 =self._toCArray(self._ri.RtFloat, point1)
  660.         point2 =self._toCArray(self._ri.RtFloat, point2)
  661.         self._ri.RiHyperboloid(point1, point2, thetamax, *self._createCParamList(paramlist, keyparams))
  662.  
  663.     def RiIdentity(self):
  664.         """Set the current transformation to the identity.
  665.     
  666.         Example: RiIdentity()
  667.         """
  668.         self._ri.RiIdentity()
  669.         
  670.     def RiIlluminate(self, light, onoff):
  671.         """Activate or deactive a light source.
  672.     
  673.         Example: RiIlluminate(lgt, RI_TRUE)
  674.         """
  675.         self._ri.RiIlluminate(light, onoff)
  676.         
  677.     def RiImager(self, name, *paramlist, **keyparams):
  678.         """Set an imager shader.
  679.     
  680.         if name is RI_NULL, no imager shader is used.
  681.     
  682.         Example: RiImager("background", "color bgcolor", [0.3,0.3,0.9])
  683.         """
  684.         self._ri.RiImager(name, *self._createCParamList(paramlist, keyparams))
  685.    
  686.     def RiInterior(self, name, *paramlist, **keyparams):
  687.         """Set the current interior volume shader.
  688.     
  689.         Example: RiInterior("water")
  690.         """
  691.         self._ri.RiInterior(name, *self._createCParamList(paramlist, keyparams))
  692.  
  693.     def RiLightSource(self, name, *paramlist, **keyparams):
  694.         """Add another light source and return its light handle.
  695.     
  696.         name is the name of the light source shader. 
  697.     
  698.         Example: light1 = RiLightSource("distantlight", intensity=1.5)
  699.         """
  700.         return self._ri.RiLightSource(name, *self._createCParamList(paramlist, keyparams))
  701.  
  702.     def RiMakeCubeFaceEnvironment(self, px,nx,py,ny,pz,nz, texname, fov, filterfunc, swidth, twidth, *paramlist, **keyparams):
  703.         """Convert six image files into an environment map.
  704.     
  705.         The px/nx images are the views in positive/negative x direction.
  706.         fov is the field of view that was used to generate the individual images.
  707.         filterfunc is either one of the predefined filter (RiGaussianFilter,
  708.         RiBoxFilter, RiTriangleFilter, RiSincFilter, RiCatmullRomFilter) or
  709.         a callable that takes four float arguments x, y, width, height. 
  710.         swidth and twidth define the support of the filter.
  711.     
  712.         Example: RiMakeCubeFaceEnvironment("px.tif","nx.tif","py.tif","ny.tif",
  713.                                            "pz.tif","nz.tif", "tex.tif", 92.0,
  714.                                             RiGaussianFilter, 2,2)
  715.         """
  716.         swidth = self._ri.RtFloat(swidth)
  717.         twidth = self._ri.RtFloat(twidth)
  718.         # Try passing the function in directly first (in case it's a standard
  719.         # filter). If this fails, function must be a custom filter.
  720.         try:
  721.             self._ri.RiMakeCubeFaceEnvironment(px, nx, py, ny, pz, nz, texname, fov, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))
  722.         except ctypes.ArgumentError:
  723.             filterfunc = self._ri.RtFilterFunc(filterfunc)
  724.             self._ri.RiMakeCubeFaceEnvironment(px, nx, py, ny, pz, nz, texname, fov, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))
  725.  
  726.     def RiMakeLatLongEnvironment(self, picname, texname, filterfunc, swidth, twidth, *paramlist, **keyparams):
  727.         """Convert an image file into an environment map.
  728.     
  729.         filterfunc is either one of the predefined filter (RiGaussianFilter,
  730.         RiBoxFilter, RiTriangleFilter, RiSincFilter, RiCatmullRomFilter) or
  731.         a callable that takes four float arguments x, y, width, height. 
  732.         swidth and twidth define the support of the filter.
  733.     
  734.         Example: RiMakeLatLongEnvironment("img.tif", "tex.tif",
  735.                                           RiGaussianFilter, 2,2)
  736.         """
  737.         swidth = self._ri.RtFloat(swidth)
  738.         twidth = self._ri.RtFloat(twidth)
  739.         # Try passing the function in directly first (in case it's a standard
  740.         # filter). If this fails, function must be a custom filter.
  741.         try:
  742.             self._ri.RiMakeLatLongEnvironment(picname, texname, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))
  743.         except ctypes.ArgumentError:
  744.             filterfunc = self._ri.RtFilterFunc(filterfunc)
  745.             self._ri.RiMakeLatLongEnvironment(picname, texname, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))
  746.         
  747.     def RiMakeShadow(self, picname, shadowname, *paramlist, **keyparams):
  748.         """Transform a depth image into a shadow map.
  749.     
  750.         Example: RiMakeShadow("depthimg.tif", "shadow.tif")
  751.         """
  752.         self._ri.RiMakeShadow(picname, shadowname, *self._createCParamList(paramlist, keyparams))
  753.  
  754.     def RiMakeTexture(self, picname, texname, swrap, twrap, filterfunc, swidth, twidth, *paramlist, **keyparams):
  755.         """Convert an image file into a texture file.
  756.     
  757.         swrap and twrap are one of RI_PERIODIC, RI_CLAMP or RI_BLACK.
  758.         filterfunc is either one of the predefined filter (RiGaussianFilter,
  759.         RiBoxFilter, RiTriangleFilter, RiSincFilter, RiCatmullRomFilter) or
  760.         a callable that takes four float arguments x, y, width, height. 
  761.         swidth and twidth define the support of the filter.
  762.     
  763.         Example: RiMakeTexture("img.tif", "tex.tif", RI_PERIODIC, RI_CLAMP, \\
  764.                                RiGaussianFilter, 2,2)
  765.         """
  766.         swidth = self._ri.RtFloat(swidth)
  767.         twidth = self._ri.RtFloat(twidth)
  768.         # Try passing the function in directly first (in case it's a standard
  769.         # filter). If this fails, function must be a custom filter.
  770.         try:
  771.             self._ri.RiMakeTexture(picname, texname, swrap, twrap, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))
  772.         except ctypes.ArgumentError:
  773.             filterfunc = self._ri.RtFilterFunc(filterfunc)
  774.             self._ri.RiMakeTexture(picname, texname, swrap, twrap, filterfunc, swidth, twidth, *self._createCParamList(paramlist, keyparams))            
  775.  
  776.     def RiMatte(self, onoff):
  777.         """Indicates whether subsequent primitives are matte objects.
  778.     
  779.         Example: RiMatte(RI_TRUE)
  780.         """
  781.         self._ri.RiMatte(onoff)
  782.  
  783.     def RiMotionBegin(self, *times):
  784.         """Start the definition of a moving primitive.
  785.     
  786.         You can specify the time values directly or inside a sequence,
  787.         for example, RiMotionBegin(0,1) or RiMotionBegin([0,1]).
  788.     
  789.         Example: RiMotionBegin(0.0, 1.0)
  790.                  RiTranslate(1.0, 0.0, 0.0)
  791.                  RiTranslate(1.0, 2.0, 0.0)
  792.                  RiMotionEnd()
  793.         """
  794.         # For some reason the time values must be doubles...
  795.         times = tuple(map(lambda v: ctypes.c_double(v), self._flatten(times)))
  796.         self._ri.RiMotionBegin(len(times), *times)
  797.         
  798.     def RiMotionEnd(self):
  799.         "Terminates the definition of a moving primitive."
  800.         self._ri.RiMotionEnd()
  801.  
  802.     def RiNuPatch(self, nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, *paramlist, **keyparams):
  803.         """Create a NURBS patch.
  804.     
  805.         Number of array elements for primitive variables:
  806.         -------------------------------------------------
  807.         constant: 1              varying: #segment corners
  808.         uniform:  #segments      vertex:  nu*nv
  809.         """
  810.         uknot = self._toCArray(self._ri.RtFloat, uknot)
  811.         vknot = self._toCArray(self._ri.RtFloat, vknot)
  812.         self._ri.RiNuPatch(nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, *self._createCParamList(paramlist, keyparams))
  813.  
  814.     def RiObjectBegin(self, *paramlist, **keyparams):
  815.         """Start the definition of a retained model and return the object handle.
  816.     
  817.         Example: obj1 = RiObjectBegin()
  818.                  ...
  819.                  RiObjectEnd()
  820.         """
  821.         return self._ri.RiObjectBegin(*self._createCParamList(paramlist, keyparams))
  822.         
  823.     def RiObjectEnd(self):
  824.         """Terminate the definition of a retained model."""
  825.         self._ri.RiObjectEnd()
  826.     
  827.     def RiObjectInstance(self, handle):
  828.         """Create an instance of a previously defined model.
  829.     
  830.         Example: RiObjectInstance(obj1)
  831.         """
  832.         self._ri.RiObjectInstance(handle)
  833.  
  834.     def RiOpacity(self, Os):
  835.         """Set the current opacity.
  836.     
  837.         Os must be a sequence of at least N values where N is the number
  838.         of color samples (set by RiColorSamples(), default is 3). The
  839.         opacity values must lie in the range from 0 to 1 (where 0 means
  840.         completely transparent and 1 means completely opaque).
  841.     
  842.         Example: RiOpacity([0,0,1])
  843.         """
  844.         Os = self._toCArray(self._ri.RtFloat, Os)
  845.         self._ri.RiOpacity(Os)
  846.  
  847.     def RiOption(self, name, *paramlist, **keyparams):
  848.         """Set an implementation-specific option.
  849.     
  850.         Example: RiOption("searchpath", "shader","~/shaders:&")
  851.         """
  852.         self._ri.RiOption(name, *self._createCParamList(paramlist, keyparams))
  853.  
  854.     def RiOrientation(self, orientation):
  855.         """Set the orientation of subsequent surfaces.
  856.     
  857.         orientation is either RI_OUTSIDE, RI_INSIDE, RI_LH (left handed)
  858.         or RI_RH (right handed).
  859.         """
  860.         self._ri.RiOrientation(orientation)
  861.  
  862.     def RiParaboloid(self, rmax, zmin, zmax, thetamax, *paramlist, **keyparams):
  863.         """Create a paraboloid (with the z axis as symmetry axis).
  864.     
  865.         Number of array elements for primitive variables:
  866.         -------------------------------------------------
  867.         constant: 1              varying: 4
  868.         uniform:  1              vertex:  4
  869.     
  870.         Example: RiParaboloid(1.0, 0.0, 1.0, 360)
  871.         """
  872.         self._ri.RiParaboloid(rmax, zmin, zmax, thetamax, *self._createCParamList(paramlist, keyparams))
  873.  
  874.     def RiPatch(self, type, *paramlist, **keyparams):
  875.         """RiPatch(type, paramlist)
  876.     
  877.         type is one of RI_BILINEAR (4 vertices) or RI_BICUBIC (16 vertices).
  878.     
  879.         Number of array elements for primitive variables:
  880.         -------------------------------------------------
  881.         constant: 1              varying: 4
  882.         uniform:  1              vertex:  4/16 (depends on type)
  883.     
  884.         Example: RiPatch(RI_BILINEAR, P=[0,0,0, 1,0,0, 0,1,0, 1,1,0])
  885.         """
  886.         self._ri.RiPatch(type, *self._createCParamList(paramlist, keyparams))
  887.  
  888.     def RiPatchMesh(self, type, nu, uwrap, nv, vwrap, *paramlist, **keyparams):
  889.         """Create a mesh made of patches.
  890.     
  891.         type is one of RI_BILINEAR or RI_BICUBIC.
  892.         uwrap/vwrap can be RI_PERIODIC or RI_NONPERIODIC.
  893.         The number of control points is nu*nv.
  894.     
  895.         Number of array elements for primitive variables:
  896.         -------------------------------------------------
  897.         constant: 1              varying: #patch corners (depends on uwrap/vwrap)
  898.         uniform:  #patches       vertex:  nu*nv (same as "P")
  899.     
  900.         """
  901.         self._ri.RiPatchMesh(type, nu, uwrap, nv, vwrap, *self._createCParamList(paramlist, keyparams))
  902.  
  903.     def RiPerspective(self, fov):
  904.         """Concatenate a perspective transformation onto the current transformation.
  905.         
  906.         Example: RiPerspective(45)"""
  907.         self._ri.RiPerspective(fov)
  908.  
  909.     def RiPixelFilter(self, function, xwidth, ywidth):
  910.         """Set a pixel filter function and its width in pixels.
  911.  
  912.         function is either one of the predefined filter (RiGaussianFilter,
  913.         RiBoxFilter, RiTriangleFilter, RiSincFilter, RiCatmullRomFilter) or
  914.         a callable that takes four float arguments x, y, width, height. 
  915.         xwidth and ywidth define the support of the filter.
  916.     
  917.         Example: RiPixelFilter(RiGaussianFilter, 2.0, 1.0)
  918.         """
  919.         xwidth = self._ri.RtFloat(xwidth)
  920.         ywidth = self._ri.RtFloat(ywidth)
  921.         # Try passing the function in directly first (in case it's a standard
  922.         # filter). If this fails, function must be a custom filter.
  923.         try:
  924.             self._ri.RiPixelFilter(function, xwidth, ywidth)
  925.         except ctypes.ArgumentError:
  926.             self._ri.RiPixelFilter(self._ri.RtFilterFunc(function), xwidth, ywidth)
  927.     
  928.     def RiPixelSamples(self, xsamples, ysamples):
  929.         """Set the sampling rate in horizontal and vertical direction.
  930.     
  931.         Example: RiPixelSamples(2,2)"""
  932.         self._ri.RiPixelSamples(xsamples, ysamples)
  933.  
  934.     def RiPixelVariance(self, variance):
  935.         """Limit the acceptable variance in the output value of pixels.
  936.     
  937.         Example: RiPixelVariance(0.01)"""
  938.         self._ri.RiPixelVariance(variance)
  939.     
  940.     def RiPoints(self, *paramlist, **keyparams):
  941.         """Create individual points.
  942.     
  943.         The size of the points can be either set with the primitive variable
  944.         RI_WIDTH (one float per point) or RI_CONSTANTWIDTH (one float for all
  945.         points).
  946.     
  947.         Number of array elements for primitive variables:
  948.         -------------------------------------------------
  949.         constant: 1              varying: #points
  950.         uniform:  1              vertex:  #points    
  951.         """
  952.         params = self._createCParamList(paramlist, keyparams)
  953.         for i in range(0, len(params), 2):
  954.             if params[i]=="P":
  955.                 n = len(params[i+1])
  956.                 if n%3!=0:
  957.                     raise ValueError, 'Invalid number of floats in the "P" parameter.'
  958.                 n /= 3  
  959.                 break
  960.         else:
  961.             raise ValueError, 'Parameter "P" is missing.'  
  962.         self._ri.RiPoints(n, *params)
  963.  
  964.     def RiPointsGeneralPolygons(self, nloops, nverts, vertids, *paramlist, **keyparams):
  965.         """Create a polyhedron made of general planar concave polygons.
  966.     
  967.         nloops:  The number of loops for each polygon
  968.         nverts:  The number of vertices in each loop
  969.         vertids: The vertex indices of the loop vertices (0-based)
  970.         The vertices themselves are stored in the parameter list (parameter "P").
  971.     
  972.         Number of array elements for primitive variables:
  973.         -------------------------------------------------
  974.         constant: 1              varying: #vertices (*)
  975.         uniform:  #polygons      vertex:  #vertices (*)
  976.     
  977.         (*) max(vertids)+1
  978.         """
  979.         nloops = self._toCArray(self._ri.RtInt, nloops)
  980.         nverts = self._toCArray(self._ri.RtInt, nverts)
  981.         vertids = self._toCArray(self._ri.RtInt, vertids)
  982.         self._ri.RiPointsGeneralPolygons(len(nloops), nloops, nverts, vertids, *self._createCParamList(paramlist, keyparams))
  983.  
  984.     def RiPointsPolygons(self, nverts, vertids, *paramlist, **keyparams):
  985.         """Create a polyhedron made of planar convex polygons that share vertices.
  986.     
  987.         nverts:  An array with the number of vertices in each polygon
  988.         vertids: The vertex indices of the polygon vertices (0-based)
  989.         The vertices themselves are stored in the parameter list (parameter "P").
  990.     
  991.         Number of array elements for primitive variables:
  992.         -------------------------------------------------
  993.         constant: 1              varying: #vertices (*)
  994.         uniform:  #polygons      vertex:  #vertices (*)
  995.     
  996.         (*) max(vertids)+1
  997.         """
  998.         nverts = self._toCArray(self._ri.RtInt, nverts)
  999.         vertids = self._toCArray(self._ri.RtInt, vertids)
  1000.         self._ri.RiPointsPolygons(len(nverts), nverts, vertids, *self._createCParamList(paramlist, keyparams))
  1001.  
  1002.     def RiPolygon(self, *paramlist, **keyparams):
  1003.         """Create a planar and convex polygon.
  1004.     
  1005.         The parameter list must include at least position ("P") information.
  1006.     
  1007.         Number of array elements for primitive variables:
  1008.         -------------------------------------------------
  1009.         constant: 1              varying: #vertices
  1010.         uniform:  1              vertex:  #vertices
  1011.     
  1012.         Example: RiPolygon(P=[0,1,0, 0,1,1, 0,0,1, 0,0,0])
  1013.         """
  1014.         params = self._createCParamList(paramlist, keyparams)
  1015.         for i in range(0, len(params), 2):
  1016.             if params[i]=="P":
  1017.                 n = len(params[i+1])
  1018.                 if n%3!=0:
  1019.                     raise ValueError, 'Invalid number of floats in the "P" parameter.'
  1020.                 n /= 3  
  1021.                 break
  1022.         else:
  1023.             raise ValueError, 'Parameter "P" is missing.'  
  1024.         self._ri.RiPolygon(n, *params)
  1025.  
  1026.     def RiProcedural(self, data, bound, subdividefunc, freefunc=None):
  1027.         """Declare a procedural model.
  1028.     
  1029.         subdividefunc and freefunc may either be the standard RenderMan
  1030.         procedurals (RiProcDelayedReadArchive, RiProcRunProgram,
  1031.         RiProcDynamicLoad and RiProcFree) or Python callables.
  1032.         In the former case, data must be a sequence of strings or a single
  1033.         string containing the data for the functions. In the latter case,
  1034.         data may be any Python object which is just passed on to the
  1035.         functions.
  1036.         freefunc is optional and defaults to None.
  1037.     
  1038.         Example: RiProcedural("mymodel.rib", [-1,1,-1,1,-1,1], \\
  1039.                               RiProcDelayedReadArchive, RI_NULL)
  1040.                               
  1041.                  RiProcedural(["python teapot.py",""],[0,1,0,1,0,1], \\
  1042.                               RiProcRunProgram, RI_NULL)
  1043.                               
  1044.                  RiProcedural(["teapot.so",""],[0,1,0,1,0,1], \\
  1045.                               RiProcDynamicLoad, RI_NULL)
  1046.         """
  1047.         bound = self._toCArray(self._ri.RtFloat, bound)
  1048.             
  1049.         callMode = 0
  1050.         # Try to convert the data into a string array. If this fails,
  1051.         # don't even try to do a call without function wrapper...
  1052.         try:
  1053.             if data is None:
  1054.                 data2 = ""
  1055.             else:
  1056.                 data2 = data
  1057.             # Put everything into a list and append an empty string. This is
  1058.             # done so that you can also just pass one single string in all cases.
  1059.             data2 = [data2]+[""]
  1060.             stringArray = self._toCArray(self._ri.RtString, data2)
  1061.         except:
  1062.             callMode = 1
  1063.         
  1064.         # Try to use the functions directly (this will only work for builtin functions)...
  1065.         if callMode==0:
  1066.             try:
  1067.                 self._ri.RiProcedural(ctypes.byref(stringArray), bound, subdividefunc, freefunc)
  1068.                 callMode = 2
  1069.             except ctypes.ArgumentError:
  1070.                 callMode = 1
  1071.         
  1072.         # Use a wrapper function (this must be used for Python callables)...
  1073.         if callMode==1:
  1074.             procWrapper = _ProceduralWrapper(RMAPI=self, data=data, subdivFunc=subdividefunc, freeFunc=freefunc)
  1075.             # Keep a reference to the instance so that it is kept alive...
  1076.             self._procWrappers[procWrapper] = 1
  1077.             # Call the procedural function (the data value is now the wrapped
  1078.             # one from within the wrapper object)...
  1079.             self._ri.RiProcedural(0, bound, procWrapper.cSubdivideFunc, procWrapper.cFreeFunc)
  1080.         
  1081.  
  1082.     def RiProjection(self, name, *paramlist, **keyparams):
  1083.         """Specify a projection method.
  1084.     
  1085.         The standard projections are RI_PERSPECTIVE and RI_ORTHOGRAPHIC.
  1086.         The perspective projection takes one optional parameter, RI_FOV.
  1087.     
  1088.         Example: RiProjection(RI_PERSPECTIVE, fov=45)
  1089.         """
  1090.         self._ri.RiProjection(name, *self._createCParamList(paramlist, keyparams))
  1091.  
  1092.     def RiQuantize(self, type, one, min, max, ditheramplitude):
  1093.         """Set the quantization parameters for colors and depth.
  1094.     
  1095.         Example: RiQuantize(RI_RGBA, 2048, -1024, 3071, 1.0)
  1096.         """
  1097.         self._ri.RiQuantize(type, one, min, max, ditheramplitude)
  1098.  
  1099.     def RiReadArchive(self, filename, callback=None, *paramlist, **keyparams):
  1100.         """Include an archive file.
  1101.     
  1102.         RiExample: RiReadArchive("teapot.rib")
  1103.         """
  1104.         if callable(callback):
  1105.             callback = self._ri.RtArchiveCallback(callback)
  1106.         self._ri.RiReadArchive(filename, callback, *self._createCParamList(paramlist, keyparams))
  1107.  
  1108.     def RiRelativeDetail(self, relativedetail):
  1109.         """Set the factor for all level of detail calculations.
  1110.     
  1111.         Example: RiRelativeDetail(0.7)"""
  1112.         self._ri.RiRelativeDetail(relativedetail)
  1113.  
  1114.     def RiReverseOrientation(self):
  1115.         """Causes the current orientation to be toggled.
  1116.     
  1117.         Example: RiReverseOrientation()
  1118.         """
  1119.         self._ri.RiReverseOrientation()
  1120.  
  1121.     def RiRotate(self, angle, *axis):
  1122.         """Rotate about angle degrees about the given axis.
  1123.     
  1124.         The axis is either given as 3 scalars or a sequence of 3 scalars.
  1125.     
  1126.         Example: RiRotate(90, 1,0,0)
  1127.         """
  1128.         axis = self._toCArray(self._ri.RtFloat, axis)
  1129.         self._ri.RiRotate(angle, *tuple(axis))
  1130.  
  1131.     def RiScale(self, *scale):
  1132.         """Concatenate a scaling onto the current transformation.
  1133.     
  1134.         The scaling is either given as 3 scalars or a sequence of 3 scalars.
  1135.     
  1136.         Example: RiScale(2,2,2)"""
  1137.         scale = self._toCArray(self._ri.RtFloat, scale)
  1138.         self._ri.RiScale(*tuple(scale))
  1139.  
  1140.     def RiScreenWindow(self, left, right, bottom, top):
  1141.         """Specify the extents of the output image on the image plane.
  1142.     
  1143.         Example: RiScreenWindow(-1,1,-1,1)
  1144.         """
  1145.         self._ri.RiScreenWindow(left, right, bottom, top)
  1146.  
  1147.     def RiShadingInterpolation(self, type):
  1148.         """Specify how shading samples are interpolated.
  1149.     
  1150.         type can be RI_CONSTANT or RI_SMOOTH.
  1151.     
  1152.         Example: RiShadingInterpolation(RI_SMOOTH)"""
  1153.         self._ri.RiShadingInterpolation(type)
  1154.  
  1155.     def RiShadingRate(self, size):
  1156.         """Set the current shading rate to an area of size pixels.
  1157.     
  1158.         Example: RiShadingRate(1.0)
  1159.         """
  1160.         self._ri.RiShadingRate(size)
  1161.  
  1162.     def RiShutter(self, opentime, closetime):
  1163.         """Set the times at which the shutter opens and closes.
  1164.     
  1165.         Example: RiShutter(0.1, 0.9)
  1166.         """
  1167.         self._ri.RiShutter(opentime, closetime)
  1168.  
  1169.     def RiSides(self, nsides):
  1170.         """Specify the number of visible sides of subsequent surfaces.
  1171.     
  1172.         Example: RiSides(1)"""
  1173.         self._ri.RiSides(nsides)
  1174.  
  1175.     def RiSkew(self, angle, *vecs):
  1176.         """Concatenate a skew onto the current transformation.
  1177.     
  1178.         angle is given in degrees.
  1179.         The two vectors are each given as 3 scalars or a sequence
  1180.         of 3 scalars.
  1181.     
  1182.         Example: RiSkew(45, 0,1,0, 1,0,0)
  1183.         """
  1184.         vecs = self._flatten(vecs)
  1185.         self._ri.RiSkew(angle, *vecs)
  1186.         
  1187.     def RiSolidBegin(self, type):
  1188.         """Start the definition of a solid object.
  1189.     
  1190.         type is one of RI_PRIMITIVE, RI_UNION, RI_DIFFERENCE and RI_INTERSECTION.
  1191.     
  1192.         Example: RiSolidBegin(RI_INTERSECTION)
  1193.                  RiSolidBegin(RI_PRIMITIVE)
  1194.                  ...
  1195.                  RiSolidEnd()
  1196.                  RiSolidBegin(RI_PRIMITIVE)
  1197.                  ...
  1198.                  RiSolidEnd()
  1199.                  RiSolidEnd()
  1200.         """
  1201.         self._ri.RiSolidBegin(type)
  1202.  
  1203.     def RiSolidEnd(self):
  1204.         """Terminate the definition of a solid object."""
  1205.         self._ri.RiSolidEnd()
  1206.  
  1207.     def RiSphere(self, radius,zmin,zmax,thetamax,*paramlist, **keyparams):
  1208.         """Create a sphere.
  1209.     
  1210.         Number of array elements for primitive variables:
  1211.         -------------------------------------------------
  1212.         constant: 1              varying: 4
  1213.         uniform:  1              vertex:  4
  1214.     
  1215.         Example: RiSphere(1.0, -1.0, 1.0, 360)
  1216.         """
  1217.         self._ri.RiSphere(radius, zmin, zmax, thetamax, *self._createCParamList(paramlist, keyparams))
  1218.  
  1219.     def RiSubdivisionMesh(self, scheme, nverts, vertids, tags, nargs, intargs, floatargs, *paramlist, **keyparams):
  1220.         """Create a subdivision surface.
  1221.     
  1222.         The only standard scheme is currently "catmull-clark".
  1223.         nverts:  The number of vertices in each face
  1224.         vertids: The vertex indices of the face vertices (0-based)
  1225.         tags: A string array of tag names.
  1226.         nargs: The number of int and float args for each tag.
  1227.         intargs: The integer arguments.
  1228.         floatargs: The float arguments.
  1229.         The vertices themselves are stored in the parameter list (parameter "P").
  1230.         
  1231.     
  1232.         Number of array elements for primitive variables:
  1233.         -------------------------------------------------
  1234.         constant: 1              varying: #vertices (*)
  1235.         uniform:  #faces         vertex:  #vertices (*)
  1236.     
  1237.         (*) max(vertids)+1
  1238.         """
  1239.         nverts = self._toCArray(self._ri.RtInt, nverts)
  1240.         vertids = self._toCArray(self._ri.RtInt, vertids)
  1241.         tags = self._toCArray(self._ri.RtToken, tags)
  1242.         nargs = self._toCArray(self._ri.RtInt, nargs)
  1243.         intargs = self._toCArray(self._ri.RtInt, intargs)
  1244.         floatargs = self._toCArray(self._ri.RtFloat, floatargs)
  1245.         self._ri.RiSubdivisionMesh(scheme, len(nverts), nverts, vertids, len(tags), tags, nargs, intargs, floatargs, *self._createCParamList(paramlist, keyparams))
  1246.  
  1247.     def RiSurface(self, name, *paramlist, **keyparams):
  1248.         """Set the current surface shader.
  1249.     
  1250.         Example: RiSurface("plastic", Kd=0.7, Ks=0.3)"""
  1251.         self._ri.RiSurface(name, *self._createCParamList(paramlist, keyparams))
  1252.  
  1253.     def RiTextureCoordinates(self, s1, t1, s2, t2, s3, t3, s4, t4):
  1254.         """Set the current set of texture coordinates.
  1255.     
  1256.         Declares a projection from the unit square [(0,0), (1,0), (0,1), (1,1)]
  1257.         in parameter space to quadrilateral [(s1,t1), (s2,t2), (s3,t3), (s4,t4)]
  1258.         in texture space.
  1259.     
  1260.         Example: RiTextureCoordinates(0.0, 0.0, 2.0, -0.5, -0.5, 1.75, 3.0, 3.0)"""
  1261.         self._ri.RiTextureCoordinates(s1, t1, s2, t2, s3, t3, s4, t4)
  1262.  
  1263.     def RiTorus(self, major, minor, phimin, phimax, thetamax, *paramlist, **keyparams):
  1264.         """Create a torus (with the z axis as symmetry axis).
  1265.     
  1266.         Number of array elements for primitive variables:
  1267.         -------------------------------------------------
  1268.         constant: 1              varying: 4
  1269.         uniform:  1              vertex:  4
  1270.     
  1271.         Example: RiTorus(1.5, 0.1, 0, 360, 360)
  1272.         """
  1273.         self._ri.RiTorus(major, minor, phimin, phimax, thetamax, *self._createCParamList(paramlist, keyparams))
  1274.         
  1275.     def RiTransform(self, transform):
  1276.         """Set the current transformation.
  1277.     
  1278.         transform must be a sequence that evaluates to 16 floating point
  1279.         values (4x4 matrix).
  1280.     
  1281.         Example: RiTransform([2,0,0,0, 0,2,0,0, 0,0,2,0, 0,0,0,1])
  1282.                  RiTransform([[2,0,0,0], [0,2,0,0], [0,0,2,0], [0,0,0,1]])
  1283.         """
  1284.         transform = self._toCArray(self._ri.RtFloat, transform)
  1285.         self._ri.RiTransform(transform)
  1286.  
  1287.     def RiTransformBegin(self):
  1288.         """Push the current transformation on the transformation stack.
  1289.     
  1290.         Example: RiTransformBegin()
  1291.                  ...
  1292.                  RiTransformEnd()
  1293.         """
  1294.         self._ri.RiTransformBegin()
  1295.  
  1296.     def RiTransformEnd(self):
  1297.         """Pop the current transformation from the stack."""
  1298.         self._ri.RiTransformEnd()
  1299.  
  1300.     def RiTransformPoints(self, fromspace, tospace, points):
  1301.         """Transform a set of points from one space to another.
  1302.         
  1303.         points must be a sequence of points where each point is another
  1304.         sequence with 3 floats.
  1305.         The return value is a sequence of vec3 objects containing the
  1306.         transformed points. None is returned in case of an error.
  1307.         """
  1308.         points = (len(points)*self._ri.RtPoint)(*map(lambda p: tuple(p), points))
  1309.         n = len(points)
  1310.         res = self._ri.RiTransformPoints(fromspace, tospace, n, points)
  1311.         if res==0:
  1312.             return None
  1313.         
  1314.         return map(lambda p: vec3(p), points)
  1315.     
  1316.     def RiTranslate(self, *translate):
  1317.         """Concatenate a translation onto the current transformation.
  1318.     
  1319.         The translation is either given as 3 scalars or a sequence of
  1320.         3 scalars.
  1321.     
  1322.         Example: RiTranslate(1.2, 4.3, -0.5)
  1323.                  or
  1324.                  RiTranslate( (1.2, 4.3, -0.5) )
  1325.         """
  1326.         translate = self._toCArray(self._ri.RtFloat, translate)
  1327.         self._ri.RiTranslate(*tuple(translate))
  1328.     
  1329.     def RiTrimCurve(self, ncurves, order, knot, min, max, n, u, v, w):
  1330.         """Set the current trim curve.
  1331.         """
  1332.         ncurves = self._toCArray(self._ri.RtInt, ncurves)
  1333.         order = self._toCArray(self._ri.RtInt, order)
  1334.         knot = self._toCArray(self._ri.RtFloat, knot)
  1335.         min = self._toCArray(self._ri.RtFloat, min)
  1336.         max = self._toCArray(self._ri.RtFloat, max)
  1337.         n = self._toCArray(self._ri.RtInt, n)
  1338.         u = self._toCArray(self._ri.RtFloat, u)
  1339.         v = self._toCArray(self._ri.RtFloat, v)
  1340.         w = self._toCArray(self._ri.RtFloat, w)
  1341.         self._ri.RiTrimCurve(len(ncurves), ncurves, order, knot, min, max, n, u, v, w)
  1342.  
  1343.     def RiWorldBegin(self):
  1344.         """Start the world block.
  1345.     
  1346.         Example: RiWorldBegin()
  1347.                  ...
  1348.                  RiWorldEnd()
  1349.         """
  1350.         self._ri.RiWorldBegin()
  1351.  
  1352.     def RiWorldEnd(self):
  1353.         """Terminates the world block."""
  1354.         self._ri.RiWorldEnd()
  1355.  
  1356.         
  1357.     def _toCArray(self, ctype, seq):
  1358.         """Convert and flatten a sequence into a ctypes array.
  1359.         
  1360.         ctype is the base type of the array and seq is the sequence that is
  1361.         to be flattened and converted. The return value is a ctypes
  1362.         array type with ctype as element type.
  1363.         If seq is already a ctypes sequence or a numpy array then no
  1364.         data conversion is done and the input is used directly.
  1365.         """
  1366.         # Is the value already a ctypes array? Then there's nothing to do
  1367.         if isinstance(seq, ctypes.Array):
  1368.             if seq._type_!=ctype:
  1369.                 raise TypeError, "ctypes array should be of type %s instead of %s"%(getattr(ctype, "__name__", "?"), getattr(seq._type_, "__name__", "?"))
  1370.             return seq
  1371.         
  1372.         # Is the sequence a numpy array?
  1373.         if hasattr(seq, "ctypes"):
  1374.             try:
  1375.                 self._assertNumPyArrayType(seq, ctype)
  1376.             except TypeError, e:
  1377.                 raise TypeError("numpy error: %s"%e)
  1378.             n = seq.size
  1379.             Cls = (n*ctype)
  1380.             seq = Cls.from_address(seq.ctypes.data)
  1381.             return seq
  1382.             
  1383.         # Convert the sequence into a ctypes array...
  1384.         seq = self._flatten(seq)
  1385.         return (len(seq)*ctype)(*seq)
  1386.     
  1387.     def _assertNumPyArrayType(self, seq, ctype):
  1388.         """Make sure a numpy array contains elements of the correct type.
  1389.         
  1390.         seq must be a numpy array and ctype is the ctypes type that the
  1391.         array elements must match.
  1392.         Raises a TypeError exception when seq is of the wrong type.
  1393.         """
  1394.         dtype = self._numpyTypes.get(ctype, None)
  1395.         if dtype is None:
  1396.             raise TypeError, "numpy arrays cannot be used for this parameter type (%s)"%getattr(ctype, "__name__", "?")
  1397.         np = ndpointer(dtype=dtype, flags='CONTIGUOUS')
  1398.         # Just call from_param() to test the type. The actual return value is not needed.
  1399.         np.from_param(seq)
  1400.        
  1401.     def _flatten(self, seq):
  1402.         """Return a list of the individual items in a (possibly nested) sequence.
  1403.         """
  1404.         res = []
  1405.         ScalarTypes = [types.IntType, types.LongType, types.FloatType, types.StringType]
  1406.         for v in seq:
  1407.             vtype = type(v)
  1408.             # v=scalar?
  1409.             if vtype in ScalarTypes:
  1410.                 res.append(v)
  1411.             # no stadard scalar or string. Then it might be a sequence..
  1412.             else:
  1413.                 # Check if it is really a sequence...
  1414.                 try:
  1415.                     n = len(v)
  1416.                 except:
  1417.                     res.append(v)
  1418.                     continue
  1419.                 res += self._flatten(v)
  1420.         return res
  1421.         
  1422.     def _createCParamList(self, paramlist, keyparams):    
  1423.         """
  1424.         Combine the keyparams with the paramlist into one paramlist
  1425.         and convert sequence values.
  1426.         Appends None (RI_NULL) to the parameter list.
  1427.         """
  1428.         # Combine the paramlist and keyparams values...
  1429.         res = ri._merge_paramlist(paramlist, keyparams)
  1430.     
  1431.         # Check if the values need conversion...
  1432.         for i in range(0, len(res), 2):
  1433.             token = res[i].strip()
  1434.             
  1435.             ##### Determine the type of the variable #####
  1436.             
  1437.             # Try to process any inline declaration...
  1438.             m = self._declRe.match(token)
  1439.             # No inline declaration or invalid declaration...
  1440.             if m is None:
  1441.                 # If the token doesn't contain a space then it must have been 
  1442.                 # just a name without inline declaration. In this case, try
  1443.                 # to get the declaration from the previously declared tokens...
  1444.                 if token.find(" ")==-1:
  1445.                     decl = self._declarations.get(token, None)
  1446.                     if decl is None:
  1447.                         raise ValueError, 'Token "%s" is not declared.'%token
  1448.                 else:
  1449.                     raise ValueError, 'Invalid inline declaration: %s'%token
  1450.             else:
  1451.                 decl = m.groups()[:3]
  1452.                 
  1453.             cls,type,n = decl
  1454.             
  1455.             # The actual size is not checked here, so we only determine
  1456.             # the "base" type...
  1457.             if type=="integer":
  1458.                 ctype = self._ri.RtInt
  1459.             elif type=="string":
  1460.                 ctype = self._ri.RtString
  1461.             else:
  1462.                 ctype = self._ri.RtFloat 
  1463.  
  1464.             # Check if the value is a sequence. If not, turn it into a list...
  1465.             if isinstance(res[i+1], basestring):
  1466.                 res[i+1] = [res[i+1]]
  1467.             try:
  1468.                 n = len(res[i+1])
  1469.             except:
  1470.                 res[i+1] = [res[i+1]]
  1471.             
  1472.             # Convert the value(s) into a ctypes array (even single values
  1473.             # must be converted)...
  1474.             try:
  1475.                 res[i+1] = self._toCArray(ctype, res[i+1])
  1476.             except TypeError, e:
  1477.                 raise TypeError('Parameter "%s": %s'%(res[i], e))
  1478.  
  1479.         res.append(None)
  1480.         return res
  1481.  
  1482.     def _standardDeclarations(self, ri):
  1483.         """Predeclare standard parameters.
  1484.         """
  1485.         decls = {ri.RI_AMPLITUDE:"uniform float",
  1486.                  ri.RI_BACKGROUND:"color",
  1487.                  ri.RI_BEAMDISTRIBUTION:"float",
  1488.                  ri.RI_CONEANGLE:"float",
  1489.                  ri.RI_CONEDELTAANGLE:"float",
  1490.                  ri.RI_CONSTANTWIDTH:"constant float",
  1491.                  ri.RI_CS:"varying color",
  1492.                  ri.RI_DISTANCE:"float",
  1493.                  ri.RI_FOV:"float",
  1494.                  ri.RI_FROM:"point",
  1495.                  ri.RI_HANDLEID:"string",
  1496.                  ri.RI_INTENSITY:"float",
  1497.                  ri.RI_KA:"uniform float",
  1498.                  ri.RI_KD:"uniform float",
  1499.                  ri.RI_KR:"uniform float",
  1500.                  ri.RI_KS:"uniform float",
  1501.                  ri.RI_LIGHTCOLOR:"color",
  1502.                  ri.RI_MAXDISTANCE:"float",
  1503.                  ri.RI_MINDISTANCE:"float",
  1504.                  ri.RI_N:"varying normal",
  1505.                  ri.RI_NP:"uniform normal",
  1506.                  ri.RI_ORIGIN:"integer[2]",
  1507.                  ri.RI_OS:"varying color",
  1508.                  ri.RI_P:"vertex point", 
  1509.                  ri.RI_PW:"vertex hpoint",
  1510.                  ri.RI_PZ:"vertex point",
  1511.                  ri.RI_ROUGHNESS:"uniform float",
  1512.                  ri.RI_S:"varying float", 
  1513.                  ri.RI_SPECULARCOLOR:"uniform color",
  1514.                  ri.RI_ST:"varying float[2]",
  1515.                  ri.RI_T:"varying float",
  1516.                  ri.RI_TEXTURENAME:"string",
  1517.                  ri.RI_TO:"point",
  1518.                  ri.RI_WIDTH:"varying float",
  1519.                  "shader":"string",
  1520.                  "archive":"string",
  1521.                  "texture":"string",
  1522.                  "procedural":"string",
  1523.                  "endofframe":"integer",
  1524.                  "sphere":"float",
  1525.                  "coordinatesystem":"string",
  1526.                  "name":"string",
  1527.                  "sense":"string"
  1528.                 }
  1529.         
  1530.         # Fill the declarations dict...
  1531.         for name,decl in decls.iteritems():
  1532.             m = self._declRe.match("%s %s"%(decl, name))
  1533.             grps = m.groups()
  1534.             self._declarations[grps[3]] = grps[:3]
  1535.