cgkit-commits Mailing List for Python Computer Graphics Kit (Page 5)
Brought to you by:
mbaas
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(40) |
Feb
(69) |
Mar
(43) |
Apr
(81) |
May
(92) |
Jun
(56) |
Jul
(35) |
Aug
(59) |
Sep
(41) |
Oct
(26) |
Nov
(15) |
Dec
(12) |
2006 |
Jan
(20) |
Feb
(23) |
Mar
(47) |
Apr
(87) |
May
(43) |
Jun
(7) |
Jul
(20) |
Aug
(5) |
Sep
(29) |
Oct
(83) |
Nov
(34) |
Dec
(16) |
2007 |
Jan
(11) |
Feb
|
Mar
|
Apr
|
May
(4) |
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2008 |
Jan
(3) |
Feb
(24) |
Mar
(2) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(4) |
Sep
(8) |
Oct
(2) |
Nov
(1) |
Dec
|
2009 |
Jan
(8) |
Feb
(22) |
Mar
(5) |
Apr
(10) |
May
(9) |
Jun
(8) |
Jul
(2) |
Aug
(13) |
Sep
(10) |
Oct
|
Nov
|
Dec
(1) |
2010 |
Jan
(3) |
Feb
(1) |
Mar
(4) |
Apr
(2) |
May
(3) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
(7) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(1) |
Nov
(4) |
Dec
(5) |
2013 |
Jan
|
Feb
(5) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <mb...@us...> - 2009-03-01 11:11:34
|
Revision: 298 http://cgkit.svn.sourceforge.net/cgkit/?rev=298&view=rev Author: mbaas Date: 2009-03-01 11:11:30 +0000 (Sun, 01 Mar 2009) Log Message: ----------- Update Modified Paths: -------------- cgkit/trunk/changelog.txt Modified: cgkit/trunk/changelog.txt =================================================================== --- cgkit/trunk/changelog.txt 2009-03-01 11:10:48 UTC (rev 297) +++ cgkit/trunk/changelog.txt 2009-03-01 11:11:30 UTC (rev 298) @@ -10,6 +10,11 @@ Bug fixes/enhancements: +- ri/cri: Added the following calls: + RiArchiveBegin(), RiArchiveEnd(), RiCamera(), RiDisplayChannel(), + RiIfBegin(), RiElseIf(), RiElse(), RiIfEnd(), + RiMakeBrickMap(), RiResource(), RiResourceBegin(), RiResourceEnd(), + RiScopedCoordinateSystem(), RiShader(), RiSystem(). - cri: numpy integer arrays were not properly supported on 64-bit systems - mayaascii: Bugfix #2119263: The setAttr command wasn't recognizing the channelBox option (+ some other bugfixes). This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-03-01 11:10:51
|
Revision: 297 http://cgkit.svn.sourceforge.net/cgkit/?rev=297&view=rev Author: mbaas Date: 2009-03-01 11:10:48 +0000 (Sun, 01 Mar 2009) Log Message: ----------- Added RenderMan calls that are newer than the 3.2 spec. Modified Paths: -------------- cgkit/trunk/cgkit/_cri.py cgkit/trunk/cgkit/cri.py cgkit/trunk/cgkit/ri.py cgkit/trunk/doc/tex/ri.tex Modified: cgkit/trunk/cgkit/_cri.py =================================================================== --- cgkit/trunk/cgkit/_cri.py 2009-03-01 11:09:15 UTC (rev 296) +++ cgkit/trunk/cgkit/_cri.py 2009-03-01 11:10:48 UTC (rev 297) @@ -455,7 +455,87 @@ ri.RiSincFilter.argtypes = [c_float, c_float, c_float, c_float] ri.RiSincFilter.restype = c_float + # Optional calls from the 3.4 API: + if hasattr(ri, "RiArchiveBegin"): + ri.RiArchiveBegin.argtypes = [RtToken] + ri.RiArchiveBegin.restype = c_void_p + else: + ri.RiArchiveBegin = _undefinedFunctionSubstitute + + if hasattr(ri, "RiArchiveEnd"): + ri.RiArchiveEnd.argtypes = [] + else: + ri.RiArchiveEnd = _undefinedFunctionSubstitute + + if hasattr(ri, "RiCamera"): + ri.RiCamera.argtypes = [RtToken] + else: + ri.RiCamera = _undefinedFunctionSubstitute + + if hasattr(ri, "RiDisplayChannel"): + ri.RiDisplayChannel.argtypes = [RtToken] + else: + ri.RiDisplayChannel = _undefinedFunctionSubstitute + + if hasattr(ri, "RiElse"): + ri.RiElse.argtypes = [] + else: + ri.RiElse = _undefinedFunctionSubstitute + + if hasattr(ri, "RiElseIf"): + ri.RiElseIf.argtypes = [RtToken] + else: + ri.RiElseIf = _undefinedFunctionSubstitute + + if hasattr(ri, "RiIfBegin"): + ri.RiIfBegin.argtypes = [RtToken] + else: + ri.RiIfBegin = _undefinedFunctionSubstitute + + if hasattr(ri, "RiIfEnd"): + ri.RiIfEnd.argtypes = [] + else: + ri.RiIfEnd = _undefinedFunctionSubstitute + + if hasattr(ri, "RiMakeBrickMap"): + ri.RiMakeBrickMap.argtypes = [RtInt, POINTER(c_char_p), c_char_p] + else: + ri.RiMakeBrickMap = _undefinedFunctionSubstitute + + if hasattr(ri, "RiResource"): + ri.RiResource.argtypes = [RtToken, RtToken] + else: + ri.RiResource = _undefinedFunctionSubstitute + + if hasattr(ri, "RiResourceBegin"): + ri.RiResourceBegin.argtypes = [] + else: + ri.RiResourceBegin = _undefinedFunctionSubstitute + + if hasattr(ri, "RiResourceEnd"): + ri.RiResourceEnd.argtypes = [] + else: + ri.RiResourceEnd = _undefinedFunctionSubstitute + + if hasattr(ri, "RiScopedCoordinateSystem"): + ri.RiScopedCoordinateSystem.argtypes = [RtToken] + else: + ri.RiScopedCoordinateSystem = _undefinedFunctionSubstitute + + if hasattr(ri, "RiShader"): + ri.RiShader.argtypes = [RtToken, RtToken] + else: + ri.RiShader = _undefinedFunctionSubstitute + + if hasattr(ri, "RiSystem"): + ri.RiSystem.argtypes = [c_char_p] + else: + ri.RiSystem = _undefinedFunctionSubstitute + +def _undefinedFunctionSubstitute(*args, **kwargs): + raise NotImplementedError("This function call is not implemented by this implementation of the RenderMan interface") + def _getLastError(ri): """Getter function for the RiLastError variable. """ Modified: cgkit/trunk/cgkit/cri.py =================================================================== --- cgkit/trunk/cgkit/cri.py 2009-03-01 11:09:15 UTC (rev 296) +++ cgkit/trunk/cgkit/cri.py 2009-03-01 11:10:48 UTC (rev 297) @@ -218,6 +218,26 @@ RiLastError = property(_getRiLastError, _setRiLastError) LastError = property(_getRiLastError, _setRiLastError) + def RiArchiveBegin(self, archivename, *paramlist, **keyparams): + """Begin an inline archive. + + Example: RiArchiveBegin("myarchive") + ... + RiArchiveEnd() + RiReadArchive("myarchive") + """ + return self._ri.RiArchiveBegin(archivename, *self._createCParamList(paramlist, keyparams)) + + def RiArchiveEnd(self): + """Terminate an inline archive. + + Example: RiArchiveBegin("myarchive") + ... + RiArchiveEnd() + RiReadArchive("myarchive") + """ + self._ri.RiArchiveEnd() + def RiArchiveRecord(self, type, format, *args): """Output a user data record. @@ -327,6 +347,13 @@ bound = self._toCArray(self._ri.RtFloat, bound) self._ri.RiBound(bound) + def RiCamera(self, name, *paramlist, **keyparams): + """Mark the current camera description. + + Example: RiCamera("rightcamera") + """ + self._ri.RiCamera(name, *self._createCParamList(paramlist, keyparams)) + def RiClipping(self, near, far): """Sets the near and the far clipping plane along the direction of view. @@ -533,6 +560,13 @@ """ self._ri.RiDetailRange(minvisible, lowertransition, uppertransition, maxvisible) + def RiDisplayChannel(self, channel, *paramlist, **keyparams): + """Defines a new display channel. + + Example: RiDisplayChannel("color aovCi", "string opacity", "aovOi") + """ + self._ri.RiDisplayChannel(channel, *self._createCParamList(paramlist, keyparams)) + def RiDisk(self, height, radius, thetamax, *paramlist, **keyparams): """Create a disk (parallel to the XY plane). @@ -558,7 +592,18 @@ RiDisplay("myimage.tif", RI_FRAMEBUFFER, RI_RGB) """ self._ri.RiDisplay(name, type, mode, *self._createCParamList(paramlist, keyparams)) + + def RiElse(self): + """Add an else block to a conditional block. + """ + + self._ri.RiElse() + def RiElseIf(self, expression, *paramlist, **keyparams): + """Add an else-if block to a conditional block. + """ + self._ri.RiElseIf(expression, *self._createCParamList(paramlist, keyparams)) + def RiEnd(self): """Terminates the main block. """ @@ -672,6 +717,16 @@ """ self._ri.RiIdentity() + def RiIfBegin(self, expression, *paramlist, **keyparams): + """Begin a conditional block. + """ + self._ri.RiIfBegin(expression, *self._createCParamList(paramlist, keyparams)) + + def RiIfEnd(self): + """Terminate a conditional block. + """ + self._ri.RiIfEnd() + def RiIlluminate(self, light, onoff): """Activate or deactive a light source. @@ -704,6 +759,15 @@ """ return self._ri.RiLightSource(name, *self._createCParamList(paramlist, keyparams)) + def RiMakeBrickMap(self, ptcnames, bkmname, *paramlist, **keyparams): + """Create a brick map file from a list of point cloud file names. + + Example: RiMakeBrickMap(["sphere.ptc", "box.ptc"], "spherebox.bkm", "float maxerror", 0.002) + """ + n = len(ptcnames) + names = (n*ctypes.c_char_p)(*ptcnames) + self._ri.RiMakeBrickMap(n, names, bkmname, *self._createCParamList(paramlist, keyparams)) + def RiMakeCubeFaceEnvironment(self, px,nx,py,ny,pz,nz, texname, fov, filterfunc, swidth, twidth, *paramlist, **keyparams): """Convert six image files into an environment map. @@ -1116,6 +1180,21 @@ Example: RiRelativeDetail(0.7)""" self._ri.RiRelativeDetail(relativedetail) + def RiResource(self, handle, type, *paramlist, **keyparams): + """Create or operate on a named resource of a particular type. + """ + self._ri.RiResource(handle, type, *self._createCParamList(paramlist, keyparams)) + + def RiResourceBegin(self): + """Push the current set of resources. + """ + self._ri.RiResourceBegin() + + def RiResourceEnd(self): + """Pop the current set of resources. + """ + self._ri.RiResourceEnd() + def RiReverseOrientation(self): """Causes the current orientation to be toggled. @@ -1142,6 +1221,13 @@ scale = self._toCArray(self._ri.RtFloat, scale) self._ri.RiScale(*tuple(scale)) + def RiScopedCoordinateSystem(self, spacename): + """Mark the current coordinate system with a name but store it on a separate stack. + + Example: RiScopedCoordinateSystem("lamptop") + """ + self._ri.RiScopedCoordinateSystem(spacename) + def RiScreenWindow(self, left, right, bottom, top): """Specify the extents of the output image on the image plane. @@ -1149,6 +1235,13 @@ """ self._ri.RiScreenWindow(left, right, bottom, top) + def RiShader(self, name, handle, *paramlist, **keyparams): + """Set the current coshader. + + Example: RiShader("plastic", "plastic_layer", Kd=0.7, Ks=0.3) + """ + self._ri.RiShader(name, handle, *self._createCParamList(paramlist, keyparams)) + def RiShadingInterpolation(self, type): """Specify how shading samples are interpolated. @@ -1255,6 +1348,11 @@ Example: RiSurface("plastic", Kd=0.7, Ks=0.3)""" self._ri.RiSurface(name, *self._createCParamList(paramlist, keyparams)) + def RiSystem(self, cmd): + """Execute an arbitrary command in the same environment as the current rendering pass. + """ + self._ri.RiSystem(cmd) + def RiTextureCoordinates(self, s1, t1, s2, t2, s3, t3, s4, t4): """Set the current set of texture coordinates. Modified: cgkit/trunk/cgkit/ri.py =================================================================== --- cgkit/trunk/cgkit/ri.py 2009-03-01 11:09:15 UTC (rev 296) +++ cgkit/trunk/cgkit/ri.py 2009-03-01 11:10:48 UTC (rev 297) @@ -280,7 +280,8 @@ The version number is automatically placed into the stream before any "real" Ri calls are made. Output from RiArchiveRecord() will - be placed before the version number. + be placed before the version number. (Note: The version line is disabled + for now). """ def __init__(self, outstream): @@ -299,7 +300,9 @@ def write(self, data): """Write data into the stream.""" if self.output_version: - self.out.write('version 3.03\n') + # The binding contains newer calls, so this version number + # might not be accurate anyway. +# self.out.write('version 3.03\n') self.output_version = 0 self.out.write(data) @@ -1029,6 +1032,15 @@ _ribout.write('ShadingInterpolation "'+type+'"\n') +# RiShader +def RiShader(name, handle, *paramlist, **keyparams): + """Set the current coshader. + + Example: RiShader("plastic", "plastic_layer", Kd=0.7, Ks=0.3)""" + + _ribout.write('Shader "'+name+'"'+' "'+handle+'"'+ \ + _paramlist2string(paramlist, keyparams)+"\n") + # RiSurface def RiSurface(name, *paramlist, **keyparams): """Set the current surface shader. @@ -1128,6 +1140,14 @@ _ribout.write('Display "'+name+'" "'+type+'" "'+mode+'"'+ \ _paramlist2string(paramlist, keyparams)+"\n") +# RiDisplayChannel +def RiDisplayChannel(channel, *paramlist, **keyparams): + """Defines a new display channel. + + Example: RiDisplayChannel("color aovCi", "string opacity", "aovOi") + """ + _ribout.write('DisplayChannel "%s"%s\n'%(channel, _paramlist2string(paramlist, keyparams))) + # RiFormat def RiFormat(xres, yres, aspect): """Set the resolution of the output image and the aspect ratio of a pixel. @@ -1171,6 +1191,14 @@ _ribout.write('Projection "'+name+'"'+ \ _paramlist2string(paramlist, keyparams)+"\n") +# RiCamera +def RiCamera(name, *paramlist, **keyparams): + """Mark the current camera description. + + Example: RiCamera("rightcamera") + """ + _ribout.write('Camera "%s"%s\n'%(name, _paramlist2string(paramlist, keyparams))) + # RiScreenWindow def RiScreenWindow(left, right, bottom, top): """Specify the extents of the output image on the image plane. @@ -1624,11 +1652,34 @@ In this implementation the callback function is not used and can be left out. - RiExample: RiReadArchive("teapot.rib")""" + Example: RiReadArchive("teapot.rib")""" _ribout.write('ReadArchive "'+filename+'"\n') +# RiArchiveBegin +def RiArchiveBegin(archivename, *paramlist, **keyparams): + """Begin an inline archive. + + Example: RiArchiveBegin("myarchive") + ... + RiArchiveEnd() + RiReadArchive("myarchive") + """ + _ribout.write('ArchiveBegin "%s"%s\n'%(archivename, _paramlist2string((), keyparams))) + return archivename +# RiArchiveEnd +def RiArchiveEnd(): + """Terminate an inline archive. + + Example: RiArchiveBegin("myarchive") + ... + RiArchiveEnd() + RiReadArchive("myarchive") + """ + _ribout.write('ArchiveEnd\n') + + def RiProcDelayedReadArchive(): return "DelayedReadArchive" def RiProcRunProgram(): return "RunProgram" def RiProcDynamicLoad(): return "DynamicLoad" @@ -1858,6 +1909,15 @@ _ribout.write('MakeShadow "'+picname+'" "'+shadowname+'"'+_paramlist2string(paramlist, keyparams)+'\n') +# RiMakeBrickMap +def RiMakeBrickMap(ptcnames, bkmname, *paramlist, **keyparams): + """Create a brick map file from a list of point cloud file names. + + Example: RiMakeBrickMap(["sphere.ptc", "box.ptc"], "spherebox.bkm", "float maxerror", 0.002) + """ + names = " ".join(map(lambda name: '"%s"'%name, ptcnames)) + _ribout.write('MakeBrickMap [%s] "%s"%s\n'%(names, bkmname, _paramlist2string(paramlist, keyparams))) + # RiDetail def RiDetail(bound): """Set the current bounding box. @@ -1905,9 +1965,16 @@ Example: RiCoordinateSystem("lamptop") """ - _ribout.write('CoordinateSystem "'+spacename+'"\n') +# RiScopedCoordinateSystem +def RiScopedCoordinateSystem(spacename): + """Mark the current coordinate system with a name but store it on a separate stack. + + Example: RiScopedCoordinateSystem("lamptop") + """ + _ribout.write('ScopedCoordinateSystem "'+spacename+'"\n') + # RiTransformPoints def RiTransformPoints(fromspace, tospace, points): """Transform a set of points from one space to another. @@ -1949,6 +2016,59 @@ return _current_context +# RiSystem +def RiSystem(cmd): + """Execute an arbitrary command in the same environment as the current rendering pass. + """ + # Escape quotes + cmd = cmd.replace('"', r'\"') + _ribout.write('System "%s"\n'%cmd) + +# RiIfBegin +def RiIfBegin(expression, *paramlist, **keyparams): + """Begin a conditional block. + """ + _ribout.write('IfBegin "%s"%s\n'%(expression, _paramlist2string(paramlist, keyparams))) + +# RiElseIf +def RiElseIf(expression, *paramlist, **keyparams): + """Add an else-if block to a conditional block. + """ + + _ribout.write('ElseIf "%s"%s\n'%(expression, _paramlist2string(paramlist, keyparams))) + +# RiElse +def RiElse(): + """Add an else block to a conditional block. + """ + + _ribout.write('Else\n') + +# RiIfEnd +def RiIfEnd(): + """Terminate a conditional block. + """ + + _ribout.write('IfEnd\n') + +# RiResource +def RiResource(handle, type, *paramlist, **keyparams): + """Create or operate on a named resource of a particular type. + """ + _ribout.write('Resource "%s" "%s"%s\n'%(handle, type, _paramlist2string(paramlist, keyparams))) + +# RiResourceBegin +def RiResourceBegin(): + """Push the current set of resources. + """ + _ribout.write('ResourceBegin\n') + +# RiResourceEnd +def RiResourceEnd(): + """Pop the current set of resources. + """ + _ribout.write('ResourceEnd\n') + ##################### Global variabels (internal) #################### _contexts = {} Modified: cgkit/trunk/doc/tex/ri.tex =================================================================== --- cgkit/trunk/doc/tex/ri.tex 2009-03-01 11:09:15 UTC (rev 296) +++ cgkit/trunk/doc/tex/ri.tex 2009-03-01 11:10:48 UTC (rev 297) @@ -25,9 +25,8 @@ This document is not an introduction to the RenderMan interface itself, it just explains the usage of this particular Python binding. The binding was written to be compliant to v3.2 of Pixar's -RenderMan Interface specification. However, it also supports some -newer features such as string handles for light sources or object -instances. +RenderMan Interface specification. However, it also supports features +that were introduced after v3.2. There is another RenderMan module called \refmodule[cgkit.cri]{cri} that interfaces a renderer directly. Almost everything that is said in this section @@ -334,7 +333,8 @@ If this option is set to 0 directly after \function{RiBegin()} is called, then no \code{"version"} call will be generated in the RIB stream (default is 1).\\ -New in version 1.1. +New in version 1.1.\\ +(as of cgkit 2.0.0alpha9, the \code{version} call has been disabled) \end{funcdesc} %----------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-03-01 11:09:20
|
Revision: 296 http://cgkit.svn.sourceforge.net/cgkit/?rev=296&view=rev Author: mbaas Date: 2009-03-01 11:09:15 +0000 (Sun, 01 Mar 2009) Log Message: ----------- Fixed some typos Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py cgkit/trunk/doc/tex/pointcloud.tex Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-03-01 11:08:26 UTC (rev 295) +++ cgkit/trunk/cgkit/pointcloud.py 2009-03-01 11:09:15 UTC (rev 296) @@ -266,7 +266,7 @@ are 3-tuples of floats, radius is a single float and dataDict a dictionary with the extra variables that are attached to the point. If no more point is available an EOFError exception is thrown. - An IOErrror handle is thrown when an error occurs during reading or + An IOErrror exception is thrown when an error occurs during reading or when the file has already been closed. """ if self._handle is None: @@ -284,7 +284,7 @@ exec self._dataCollectionCode return tuple(self._pos), tuple(self._normal), self._radius.value, dataDict - def readDataPoints(self, numPoints, buffer=None): + def readDataPoints(self, numPoints, buffer): """Read a sequence of data points. numPoints is the number of points to read. buffer is either a single @@ -347,10 +347,10 @@ def iterBatches(self, batchSize=1000, combinedBuffer=False, numpyArray=False): """Iterate over point batches. - Reads batchSize points at once and yields one or more buffer + Reads batchSize points at once and yields one or more buffers containing the data. combinedBuffer determines whether all data is written into one single - buffer or if there is an individual buffer for the point, norma, radius + buffer or if there is an individual buffer for the point, normal, radius and data. numpyArray determines whether the buffers are created as numpy arrays or ctypes arrays. @@ -445,6 +445,8 @@ self._PtcWriteDataPoint = ptclib.PtcWriteDataPoint self._PtcFinishPointCloudFile = ptclib.PtcFinishPointCloudFile + self.name = fileName + xres,yres,aspect = format w2e = self._matrixToCTypes(world2eye) @@ -518,7 +520,7 @@ point and normal are vectors (any 3-sequence of floats) and radius a float. data is a dict that contains the extra variables that must have been declared in the constructor. Undeclared values are - ignored, missing declared valued are set to 0. + ignored, missing declared values are set to 0. """ if self._handle is None: raise IOError("The point cloud file has already been closed.") @@ -531,7 +533,7 @@ if res==0: raise IOError("Failed to write point cloud data point") - def writeDataPoints(self, numPoints, buffer=None): + def writeDataPoints(self, numPoints, buffer): """Write a sequence of data points. numPoints is the number of points to write. buffer is either a single @@ -607,7 +609,7 @@ fileName is the name of the point cloud file. mode is either "r" for reading a file or "w" for writing a new point cloud file. libName is the library name that implements the point cloud API. - When mode is "r", the following additional keyword arguments must + When mode is "w", the following additional keyword arguments must be present: - vars: A list of tuples (type, name) that defines what additional variables to write Modified: cgkit/trunk/doc/tex/pointcloud.tex =================================================================== --- cgkit/trunk/doc/tex/pointcloud.tex 2009-03-01 11:08:26 UTC (rev 295) +++ cgkit/trunk/doc/tex/pointcloud.tex 2009-03-01 11:09:15 UTC (rev 296) @@ -109,7 +109,7 @@ an entire sequence of points at once. \end{methoddesc} -\begin{methoddesc}{readDataPoints}{numPoints, buffer=None} +\begin{methoddesc}{readDataPoints}{numPoints, buffer} Read a sequence of data points. \var{numPoints} is the number of points to read. \var{buffer} is either a single buffer that will receive all values or a tuple (\var{pointbuf}, \var{normalbuf}, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-03-01 11:08:29
|
Revision: 295 http://cgkit.svn.sourceforge.net/cgkit/?rev=295&view=rev Author: mbaas Date: 2009-03-01 11:08:26 +0000 (Sun, 01 Mar 2009) Log Message: ----------- Minor updates to the doc strings. Modified Paths: -------------- cgkit/trunk/cgkit/slparams.py Modified: cgkit/trunk/cgkit/slparams.py =================================================================== --- cgkit/trunk/cgkit/slparams.py 2009-02-28 17:46:47 UTC (rev 294) +++ cgkit/trunk/cgkit/slparams.py 2009-03-01 11:08:26 UTC (rev 295) @@ -252,7 +252,8 @@ - type: The type of the shader (surface, displacement, etc.) - name: The name of the shader - params: The shader parameters (see below) - - meta: The shader meta data + - meta: The shader meta data. How exactly meta data is specified depends + on the renderer you are using. The parameters are given as a list of shader parameter objects describing each parameter. A shader parameter object has the @@ -263,7 +264,7 @@ - type: The parameter type - size: The array length or None if the parameter is not an array - name: The name of the parameter - - spacE: The space in which a point-like type was defined + - space: The space in which a point-like type was defined - default: The default value (always given as a string) For backwards compatibility, the shader info object behaves like a @@ -419,8 +420,8 @@ def convertdefault(paramtuple): """Converts the default value of a shader parameter into a Python type. - paramtuple must be a 7-tuple as returned by slparams(). The - function returns a Python object that corresponds to the default + paramtuple must be a 7-tuple (or parameter object) as returned by slparams(). + The function returns a Python object that corresponds to the default value of the parameter. If the default value can't be converted then None is returned. Only the functions that are present in the sl module are evaluated. If a default value calls a user defined This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-28 17:46:53
|
Revision: 294 http://cgkit.svn.sourceforge.net/cgkit/?rev=294&view=rev Author: mbaas Date: 2009-02-28 17:46:47 +0000 (Sat, 28 Feb 2009) Log Message: ----------- Updated the docs Modified Paths: -------------- cgkit/trunk/doc/tex/cgkit.tex cgkit/trunk/doc/tex/cri.tex cgkit/trunk/doc/tex/sloargs.tex cgkit/trunk/doc/tex/slparams.tex Added Paths: ----------- cgkit/trunk/doc/tex/pointcloud.tex Modified: cgkit/trunk/doc/tex/cgkit.tex =================================================================== --- cgkit/trunk/doc/tex/cgkit.tex 2009-02-11 21:19:58 UTC (rev 293) +++ cgkit/trunk/doc/tex/cgkit.tex 2009-02-28 17:46:47 UTC (rev 294) @@ -99,6 +99,7 @@ \input{sltokenize.tex} \input{slparams.tex} \input{sloargs.tex} +\input{pointcloud.tex} \input{glslangtokenize.tex} \input{glslangparams.tex} \input{spacedevice.tex} Modified: cgkit/trunk/doc/tex/cri.tex =================================================================== --- cgkit/trunk/doc/tex/cri.tex 2009-02-11 21:19:58 UTC (rev 293) +++ cgkit/trunk/doc/tex/cri.tex 2009-02-28 17:46:47 UTC (rev 294) @@ -78,6 +78,7 @@ \lineii{3Delight}{\code{3delight}} \lineii{Aqsis}{\code{aqsislib} / \code{ri2rib}} \lineii{Pixie}{\code{ri}} +\lineii{PRMan (v14+)}{\code{prman}} \end{tableii} \end{funcdesc} Added: cgkit/trunk/doc/tex/pointcloud.tex =================================================================== --- cgkit/trunk/doc/tex/pointcloud.tex (rev 0) +++ cgkit/trunk/doc/tex/pointcloud.tex 2009-02-28 17:46:47 UTC (rev 294) @@ -0,0 +1,298 @@ +% pointcloud + +\section{\module{pointcloud} --- + Read and write RenderMan point cloud files} +\label{pointcloud} + +\declaremodule{extension}{cgkit.pointcloud} +\modulesynopsis{Read and write RenderMan point cloud files} + +This module allows reading and writing RenderMan point cloud files. The module +relies on an external shared library that implements the actual low-level +access to the point cloud file. This library is not part of cgkit but must +be provided by the renderer package that you are using (for example, PRMan or +3Delight). Without such a library you won't be able to read or write any +point cloud file using this module. + +The module provides one single function \function{open()} which opens a +point cloud file for reading or writing. + +% open +\begin{funcdesc}{open}{fileName, mode, libName, \ldots} +Open a point cloud file for reading or writing. \var{fileName} is the name +of the point cloud file, \var{mode} is either \code{"r"} for reading a file or +\code{"w"} for writing a new file. \var{libName} is the name of the shared +library that implements the point cloud API which will be used for accessing +the file. You can either pass just the base name of the library or a full path +to a shared library. + +When the mode is \code{"w"} the following additional keyword arguments must +be given: +\begin{itemize} + \item \var{vars}: A list of tuples (\var{type}, \var{name}) that defines what + additional variables to write. \var{name} is the name of the + variable and \var{type} its RenderMan type (float, vector, point, normal, + color, matrix). + \item \var{world2eye}: The world-to-eye matrix. The matrix can be a + \code{mat4} object or any other (possibly nested) sequence that produces 16 + floats in row-major order. + \item \var{world2ndc}: The world-to-ndc matrix. + \item \var{format}: A tuple (\var{xres}, \var{yres}, \var{aspect}) where + each value is a float. +\end{itemize} + +Depending on the mode, the function either returns a \class{PtcReader} +or \class{PtcWriter} object. +\end{funcdesc} + +%---------------------------------------------------------------- +\subsection{PtcReader object} + +A \class{PtcReader} object has the following attributes and methods: + +\begin{memberdesc}{name} +The file name. +\end{memberdesc} + +\begin{memberdesc}{variables} +A list of tuples (\var{type}, \var{name}) that specifies what additional +variables are stored in the file. The order of the variables in the file +is that of the list. +\end{memberdesc} + +\begin{memberdesc}{npoints} +The number of points in the file. +\end{memberdesc} + +\begin{memberdesc}{datasize} +The size of the data part per point (in number of floats). +\end{memberdesc} + +\begin{memberdesc}{bbox} +A list of 6 floats specifying the bounding box of the point cloud. +\end{memberdesc} + +\begin{memberdesc}{format} +The format tuple (\var{xres}, \var{yres}, \var{aspect}). +\end{memberdesc} + +\begin{memberdesc}{world2eye} +The world-to-eye matrix as a list of 16 floats in row-major order. +\end{memberdesc} + +\begin{memberdesc}{world2ndc} +The world-to-ndc matrix as a list of 16 floats in row-major order. +\end{memberdesc} + +\begin{methoddesc}{close}{} +Close the point cloud file. +\end{methoddesc} + +\begin{methoddesc}{iterAttrs}{} +Iterate over all attributes defined in the file. Yields tuples (\var{name}, +\var{value}). +\end{methoddesc} + +\begin{methoddesc}{readDataPoint}{} +Read the next data point. Returns a tuple (\var{pos}, \var{normal}, +\var{radius}, \var{dataDict}) where \var{pos} and \var{normal} are 3-tuples of +floats, \var{radius} is a single float and \var{dataDict} a dictionary with the +extra variables that are attached to the point. If no more point is available +an \exception{EOFError} exception is thrown. +An \exception{IOErrror} exception is thrown when an error occurs during reading +or when the file has already been closed. + +Note that reading a large file using this method will be slow because every +single point has to be read by a dedicated Python call. If you can process +the points in batches, you should rather use the \method{readDataPoints()} +method which will be a lot faster because a single Python call will read +an entire sequence of points at once. +\end{methoddesc} + +\begin{methoddesc}{readDataPoints}{numPoints, buffer=None} +Read a sequence of data points. +\var{numPoints} is the number of points to read. \var{buffer} is either a single +buffer that will receive all values or a tuple (\var{pointbuf}, \var{normalbuf}, +\var{radiusbuf}, \var{databuf}) that contains the individual buffers for the +respective values. A buffer must always be large enough to hold \var{numPoints} +values. The function accepts \module{ctypes} arrays as buffers or any sequence +object that supports the array interface (such as \var{numpy} arrays). + +The return value is the number of points that have actually been read (additional +items in the buffers remain at their previous value). When 0 is returned, the +end of the file has been reached +\end{methoddesc} + +\begin{methoddesc}{iterPoints}{} +Iterate over all the points in the file. +Yields tuples (\var{point}, \var{normal}, \var{radius}, \var{data}) for every +point in the file. This is equivalent to calling \method{readDataPoint()} +repeatedly. +\end{methoddesc} + +\begin{methoddesc}{iterBatches}{batchSize=1000, combinedBuffer=False, +numpyArray=False} +Iterate over point batches. +Reads \var{batchSize} points at once and yields one or more buffers containing +the data. \var{combinedBuffer} determines whether all data is written into one +single buffer or if there is an individual buffer for the point, normal, radius +and data. \var{numpyArray} determines whether the buffers are created as +\module{numpy} arrays or \var{ctypes} arrays. The buffers will always contain +\var{batchSize} elements unless it is the last buffer returned which may +have a smaller size. +\end{methoddesc} + + +%---------------------------------------------------------------- +\subsection{PtcWriter object} + +A \class{PtcWriter} object has the following attributes and methods: + +\begin{memberdesc}{name} +The file name. +\end{memberdesc} + +\begin{memberdesc}{datasize} +The size of the data part per point (in number of floats). +\end{memberdesc} + +\begin{methoddesc}{close}{} +Close the point cloud file. +\end{methoddesc} + +\begin{methoddesc}{writeDataPoint}{point, normal, radius, data} +Write a point into the point cloud file. +\var{point} and \var{normal} are vectors (any 3-sequence of floats) and +\var{radius} a float. \var{data} is a dictionary that contains the extra +variables that must have been declared when the file was opened. +Undeclared values are ignored, missing declared values are set to 0. +\end{methoddesc} + +\begin{methoddesc}{writeDataPoints}{numPoints, buffer} +Write a sequence of data points. +\var{numPoints} is the number of points to write. \var{buffer} is either a +single buffer that contains all values or a tuple (\var{pointbuf}, +\var{normalbuf}, \var{radiusbuf}, \var{databuf}) that each contains the +respective value. The buffers must contain at least \var{numPoints} items. +The function accepts \module{ctypes} arrays as buffers or any sequence object +that supports the array interface (such as \module{numpy} arrays). +\end{methoddesc} + +%---------------------------------------------------------------- +\subsection{Examples} + +You create a new point cloud file like this: + +\begin{verbatim} +>>> from cgkit.cgtypes import * +>>> from cgkit import pointcloud +>>> ptc = pointcloud.open("cloud.ptc", "w", "3delight", vars=[("float", "foo")], world2eye=mat4(1), world2ndc=mat4(1), format=(640,480,1)) +>>> ptc.name +'cloud.ptc' +>>> ptc.datasize +1 +\end{verbatim} + +The data size of 1 means there is one additional float attached to each point +which is the extra variable \code{foo}. Once the file is open you can write +individual points like this: + +\begin{verbatim} +>>> ptc.writeDataPoint((0.5,0.3,0.9), (0,0,1), 1.0, {"foo":0.75}) +\end{verbatim} + +Writing each point individually will be slow though. If possible you should try +to gather a larger number of points and write them with a single call like this +(for the sake of the example, we just create three points manually): + +\begin{verbatim} +>>> pnts = (9*ctypes.c_float)(1.5,0.5,0.8, 0.8,0.9,1.0, 0.1,0.2,0.3) +>>> normals = (9*ctypes.c_float)(0,0,1, 1,0,0, 0,1,0) +>>> rads = (3*ctypes.c_float)(0.6, 0.7, 0.8) +>>> datas = (3*ptc.datasize*ctypes.c_float)(0.4, 0.3, 0.2) +>>> ptc.writeDataPoints(3, (pnts,normals,rads,datas)) +>>> ptc.close() +\end{verbatim} + +The file can then be read again as follows: + +\begin{verbatim} +>>> ptc = pointcloud.open("cloud.ptc", "r", "3delight") +>>> ptc.name +'cloud.ptc' +>>> ptc.npoints +4 +>>> ptc.datasize +1 +>>> ptc.variables +[('float', 'foo')] +>>> ptc.world2eye +[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0] +>>> ptc.bbox +[-1.3333333730697632, -1.3333333730697632, -1.3333333730697632, 2.6666667461395264, 2.6666667461395264, 2.6666667461395264] +>>> ptc.format +(640.0, 480.0, 1.0) +\end{verbatim} + +Once the file is open, the data can be read in various ways. If you want +to process each point individually in Python, you could either use the +\method{readDataPoint()} method or just iterate over all the points: + +\begin{verbatim} +>>> for p in ptc.iterPoints(): print p +... +((0.5, 0.30000001192092896, 0.89999997615814209), (0.0, 0.0, 1.0), 1.0, {'foo': 0.75}) +((1.5, 0.5, 0.80000001192092896), (0.0, 0.0, 1.0), 0.60000002384185791, {'foo': 0.40000000596046448}) +((0.80000001192092896, 0.89999997615814209, 1.0), (1.0, 0.0, 0.0), 0.69999998807907104, {'foo': 0.30000001192092896}) +((0.10000000149011612, 0.20000000298023224, 0.30000001192092896), (0.0, 1.0, 0.0), 0.80000001192092896, {'foo': 0.20000000298023224}) +\end{verbatim} + +Again, this will be slow for large point cloud files. If your application +allows batch processing the points or you interface with C code, it will be +faster to read several points at once (this time we use \module{numpy} instead +of \var{ctypes} for creating a buffer): + +\begin{verbatim} +>>> import numpy +>>> buf = numpy.zeros(shape=(5, 7+ptc.datasize), dtype=numpy.float32) +>>> ptc.readDataPoints(5, buf) +4 +>>> print buf +[[ 0.5 0.30000001 0.89999998 0. 0. 1. 1. + 0.75 ] + [ 1.5 0.5 0.80000001 0. 0. 1. + 0.60000002 0.40000001] + [ 0.80000001 0.89999998 1. 1. 0. 0. + 0.69999999 0.30000001] + [ 0.1 0.2 0.30000001 0. 1. 0. + 0.80000001 0.2 ] + [ 0. 0. 0. 0. 0. 0. 0. + 0. ]] +>>> ptc.readDataPoints(5, buf) +0 +\end{verbatim} + +Instead of a single buffer, you could again pass four individual buffers just +like above when we were writing the file. + +You could also leave the buffer creation up to the point cloud handle and just +iterate over buffers (output slightly reformatted for better readability): + +\begin{verbatim} +>>> for buffers in ptc.iterBatches(numpyArray=True): print buffers +... +(array([[ 0.5 , 0.30000001, 0.89999998], + [ 1.5 , 0.5 , 0.80000001], + [ 0.80000001, 0.89999998, 1. ], + [ 0.1 , 0.2 , 0.30000001]],dtype=float32), +array([[ 0., 0., 1.], + [ 0., 0., 1.], + [ 1., 0., 0.], + [ 0., 1., 0.]], dtype=float32), +array([ 1. , 0.60000002, 0.69999999, 0.80000001], dtype=float32), +array([[ 0.75 ], + [ 0.40000001], + [ 0.30000001], + [ 0.2 ]], dtype=float32)) +\end{verbatim} + Modified: cgkit/trunk/doc/tex/sloargs.tex =================================================================== --- cgkit/trunk/doc/tex/sloargs.tex 2009-02-11 21:19:58 UTC (rev 293) +++ cgkit/trunk/doc/tex/sloargs.tex 2009-02-28 17:46:47 UTC (rev 294) @@ -15,7 +15,7 @@ % slparams \begin{funcdesc}{slparams}{shader} -Read shader parameters. +Read shader parameters (see the \function{slparams.slparams()}). \end{funcdesc} % getSloLib Modified: cgkit/trunk/doc/tex/slparams.tex =================================================================== --- cgkit/trunk/doc/tex/slparams.tex 2009-02-11 21:19:58 UTC (rev 293) +++ cgkit/trunk/doc/tex/slparams.tex 2009-02-28 17:46:47 UTC (rev 294) @@ -6,13 +6,26 @@ \modulesynopsis{Extracting RenderMan Shader parameters} This module can be used to extract the parameters of a RenderMan -shader from the shader source file. +shader either from the shader source file or from the compiled shader. +To read parameters from a compiled shader it is necessary that the renderer +package is installed that was used to compile the shader. Currently, the +following renderers are supported: +\begin{itemize} + \item 3Delight + \item Aqsis + \item Pixie + \item PRMan +\end{itemize} + +Other renderers can be added at runtime (see the \module{sloargs} module). + \begin{funcdesc}{slparams}{slfile, cpp=None, cpperrstream=sys.stderr, includedirs=None, defines=None} Extracts the shader parameters from a Shading Language source file. -The argument \var{slfile} is either the name of the shader source file -(*.sl) or it is a file-like object that provides the shader sources. +The argument \var{slfile} is either the name of a compiled shader, the +name of the shader source file (*.sl) or a file-like object that provides the +shader sources. \var{cpp} determines how the shader source is preprocessed. It can be either a string containing the name of an external preprocessor tool @@ -31,33 +44,64 @@ look for include files. \var{defines} is a list of tuples (\var{name}, \var{value}) that specify the predefined symbols to use. -The function returns a list of 3-tuples, one for each shader found in -the file. The tuple contains the type, the name and the parameters of -the shader. The parameters are given as a list of 7-tuples describing -each parameter. The tuple contains the following information (in the -given order): +The function returns a list of shader info objects. These objects have +four attributes: + +\begin{itemize} + \item \var{type}: The type of the shader (\code{"surface"}, + \code{"displacement"}, etc.) + \item \var{name}: The name of the shader + \item \var{params}: The shader parameters (see below) + \item \var{meta}: The shader meta data. How exactly meta data is specified + depends on the renderer you are using. +\end{itemize} + +The parameters are given as a list of shader parameter objects describing each +parameter. A shader parameter object has the following attributes: -\begin{enumerate} -\item The output specifier (either \code{"output"} or an empty string) -\item The storage class (\code{"uniform"} or \code{"varying"}) -\item The parameter type -\item The array length or \code{None} if the parameter is not an array -\item The name of the parameter -\item The space in which a point-like type or a color was defined. If the parameter is an array then this is also an array of space names. -\item The default value (always given as a string) -\end{enumerate} +\begin{itemize} +\item \var{outputSpec}: The output specifier (either \code{"output"} or an empty +string) +\item \var{storage}: The storage class (\code{"uniform"} or \code{"varying"}) +\item \var{type}: The parameter type +\item \var{size}: The array length or \code{None} if the parameter is not +an array +\item \var{name}: The name of the parameter +\item \var{space}: The space in which a point-like type or a color was +defined. If the parameter is an array then this is also an array of space names. +\item \var{default}: The default value (always given as a string) +\end{itemize} +For backwards compatibility, the shader info object behaves like a +3-tuple (\var{type}, \var{name}, \var{params}). The meta data can only be +accessed via name though. The shader parameter objects can also be used +like 7-tuples containing the above data (in the order given above). + Example (output slightly reformatted for better readability): \begin{verbatim} ->>> import slparams ->>> slparams.slparams("plastic.sl") +>>> from cgkit import slparams +>>> shaders = lparams.slparams("plastic.sl") +>>> print shaders [('surface', 'plastic', [('', 'uniform', 'float', None, 'Ka', None, '1'), ('', 'uniform', 'float', None, 'Kd', None, '0.5'), ('', 'uniform', 'float', None, 'Ks', None, '0.5'), ('', 'uniform', 'float', None, 'roughness', None, '0.1'), ('', 'uniform', 'color', None, 'specularcolor', 'rgb', '1')])] +>>> shaders[0].type +'surface' +>>> shaders[0].name +'plastic' +>>> for param in shaders[0].params: print param.name +... +Ka +Kd +Ks +roughness +specularcolor +>>> shaders[0].meta +{} \end{verbatim} The parser used inside this function was generated using the parser @@ -67,8 +111,8 @@ \begin{funcdesc}{convertdefault}{paramtuple} Converts the default value of a shader parameter into a Python -type. The argument \var{paramtuple} must be a 7-tuple as returned by -\function{slparams()}. The function returns a Python object that corresponds to +type. The argument \var{paramtuple} must be a 7-tuple (or parameter object) as +returned by \function{slparams()}. The function returns a Python object that corresponds to the default value of the parameter. If the default value can't be converted then \code{None} is returned. Only the functions that are present in the \module{sl} module are evaluated. If a default value This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-11 21:20:01
|
Revision: 293 http://cgkit.svn.sourceforge.net/cgkit/?rev=293&view=rev Author: mbaas Date: 2009-02-11 21:19:58 +0000 (Wed, 11 Feb 2009) Log Message: ----------- Changed the way point cloud attributes are stored and added a method to iterate over all available attributes. Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-02-11 19:44:51 UTC (rev 292) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-11 21:19:58 UTC (rev 293) @@ -87,8 +87,10 @@ raise TypeError, "Unknown array type" -class PtcReader: +class PtcReader(object): """Point cloud reader class. + + An instance of this class is returned by the open() function. """ def __init__(self, fileName, libName): @@ -97,6 +99,7 @@ fileName is the name of the point cloud file and libName the name of the shared library that implements the point cloud API. """ + object.__init__(self) self._handle = None @@ -130,20 +133,17 @@ self._handle = handle self.name = fileName - self.variables = [] - self.npoints = None - self.bbox = None - self.datasize = None - self.world2eye = None - self.world2ndc = None - self.format = None + # The dictionary containing the point cloud attributes. + # Access to the attributes is provided via properties. + self._ptcAttrs = {} code = "" idx = 0 + vars = [] for i in range(nvars.value): name = names[i] type = types[i] - self.variables.append((type, name)) + vars.append((type, name)) if type=="float": code += "dataDict['%s'] = data[%s]\n"%(name,idx) idx += 1 @@ -158,24 +158,32 @@ # Compile the code that will pick the correct data components and put them into a dict self._dataCollectionCode = compile(code, "<string>", "exec") + self._ptcAttrs["variables"] = vars + + # Get the npoints attribute... n = ctypes.c_int() ptclib.PtcGetPointCloudInfo.argtypes = [ptclib.PtcPointCloud, ctypes.c_char_p, ctypes.POINTER(ctypes.c_int)] if ptclib.PtcGetPointCloudInfo(handle, "npoints", ctypes.byref(n))==1: - self.npoints = n.value + self._ptcAttrs["npoints"] = n.value + # Get the datasize attribute if ptclib.PtcGetPointCloudInfo(handle, "datasize", ctypes.byref(n))==1: - self.datasize = n.value + self._ptcAttrs["datasize"] = n.value + # Get the bbox attribute ptclib.PtcGetPointCloudInfo.argtypes = [ptclib.PtcPointCloud, ctypes.c_char_p, ctypes.POINTER(ctypes.c_float)] b = (6*ctypes.c_float)() if ptclib.PtcGetPointCloudInfo(handle, "bbox", b)==1: - self.bbox = list(b) + self._ptcAttrs["bbox"] = list(b) + # Get the format attribute f = (3*ctypes.c_float)() if ptclib.PtcGetPointCloudInfo(handle, "format", f)==1: - self.format = tuple(f) + self._ptcAttrs["format"] = tuple(f) + # Get the world2eye attribute m = (16*ctypes.c_float)() if ptclib.PtcGetPointCloudInfo(handle, "world2eye", m)==1: - self.world2eye = list(m) + self._ptcAttrs["world2eye"] = list(m) + # Get the world2ndc attribute if ptclib.PtcGetPointCloudInfo(handle, "world2ndc", m)==1: - self.world2ndc = list(m) + self._ptcAttrs["world2ndc"] = list(m) if self.npoints is None: raise IOError("Could not obtain the number of points in point cloud file %s."%fileName) @@ -199,7 +207,49 @@ Closes the file. """ self.close() + + @property + def variables(self): + """Return the variables attribute.""" + return self._ptcAttrs.get("variables", None) + @property + def npoints(self): + """Return the npoints attribute.""" + return self._ptcAttrs.get("npoints", None) + + @property + def datasize(self): + """Return the datasize attribute.""" + return self._ptcAttrs.get("datasize", None) + + @property + def bbox(self): + """Return the bbox attribute.""" + return self._ptcAttrs.get("bbox", None) + + @property + def format(self): + """Return the format attribute.""" + return self._ptcAttrs.get("format", None) + + @property + def world2eye(self): + """Return the world2eye attribute.""" + return self._ptcAttrs.get("world2eye", None) + + @property + def world2ndc(self): + """Return the world2ndc attribute.""" + return self._ptcAttrs.get("world2ndc", None) + + def iterAttrs(self): + """Iterate over all attributes defined in the file. + + Yields tuples (name,value). + """ + return self._ptcAttrs.iteritems() + def close(self): """Close the point cloud file. @@ -373,6 +423,8 @@ class PtcWriter: """Point cloud writer class. + + An instance of this class is returned by the open() function. """ def __init__(self, fileName, libName, vars, world2eye, world2ndc, format): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-11 19:44:53
|
Revision: 292 http://cgkit.svn.sourceforge.net/cgkit/?rev=292&view=rev Author: mbaas Date: 2009-02-11 19:44:51 +0000 (Wed, 11 Feb 2009) Log Message: ----------- Added the unittests/data directory to the source archive. Modified Paths: -------------- cgkit/trunk/MANIFEST.in Modified: cgkit/trunk/MANIFEST.in =================================================================== --- cgkit/trunk/MANIFEST.in 2009-02-11 19:39:16 UTC (rev 291) +++ cgkit/trunk/MANIFEST.in 2009-02-11 19:44:51 UTC (rev 292) @@ -32,3 +32,7 @@ recursive-include utilities/maya *.mel recursive-include pyrex/c *.c recursive-include pyrex/pyx *.pyx +recursive-include unittests/data *.rib +recursive-include unittests/data *.ma +recursive-include unittests/data *.mb +recursive-include unittests/data *.sl This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-11 19:39:25
|
Revision: 291 http://cgkit.svn.sourceforge.net/cgkit/?rev=291&view=rev Author: mbaas Date: 2009-02-11 19:39:16 +0000 (Wed, 11 Feb 2009) Log Message: ----------- Replaced the variable name 'as' by 'asl' (because 'as' will become a keyword in Python 2.6). Modified Paths: -------------- cgkit/trunk/unittests/test_slots.py Modified: cgkit/trunk/unittests/test_slots.py =================================================================== --- cgkit/trunk/unittests/test_slots.py 2009-02-11 19:34:51 UTC (rev 290) +++ cgkit/trunk/unittests/test_slots.py 2009-02-11 19:39:16 UTC (rev 291) @@ -9,59 +9,59 @@ def testConstructor(self): # Standard constructor - as = _core.DoubleSlot() - self.assertEqual(as.getValue(), 0) - self.assertEqual(as.getController(), None) + asl = _core.DoubleSlot() + self.assertEqual(asl.getValue(), 0) + self.assertEqual(asl.getController(), None) - as = _core.IntSlot() - self.assertEqual(as.getValue(), 0) + asl = _core.IntSlot() + self.assertEqual(asl.getValue(), 0) - as = _core.Vec3Slot() - self.assertEqual(as.getValue(), vec3(0)) + asl = _core.Vec3Slot() + self.assertEqual(asl.getValue(), vec3(0)) - as = _core.StrSlot() - self.assertEqual(as.getValue(), "") + asl = _core.StrSlot() + self.assertEqual(asl.getValue(), "") # Constructor (initialvalue, flags) - as = _core.DoubleSlot(12.7, 0) - self.assertEqual(as.getValue(), 12.7) - self.assertEqual(as.getController(), None) + asl = _core.DoubleSlot(12.7, 0) + self.assertEqual(asl.getValue(), 12.7) + self.assertEqual(asl.getController(), None) - as = _core.IntSlot(5, 0) - self.assertEqual(as.getValue(), 5) + asl = _core.IntSlot(5, 0) + self.assertEqual(asl.getValue(), 5) - as = _core.Vec3Slot(vec3(1,2,3), 0) - self.assertEqual(as.getValue(), vec3(1,2,3)) + asl = _core.Vec3Slot(vec3(1,2,3), 0) + self.assertEqual(asl.getValue(), vec3(1,2,3)) - as = _core.StrSlot("spam", 0) - self.assertEqual(as.getValue(), "spam") + asl = _core.StrSlot("spam", 0) + self.assertEqual(asl.getValue(), "spam") def testNoneConnection(self): """Check that connecting to None doesn't crash.""" - as = DoubleSlot() - as.connect(None) + asl = DoubleSlot() + asl.connect(None) def testNoneDisconnection(self): """Check that disconnecting from None doesn't crash.""" - as = DoubleSlot() - as.disconnect(None) + asl = DoubleSlot() + asl.disconnect(None) def testDisconnect(self): """Test the disconnect method.""" ctrl = DoubleSlot(12) - as = DoubleSlot(5) + asl = DoubleSlot(5) # Check that disconnecing a non-existent connection raises an error - self.assertRaises(ValueError, ctrl.disconnect, as) + self.assertRaises(ValueError, ctrl.disconnect, asl) # Connect and disconnect and check that the controller doesn't - # influence as anymore - ctrl.connect(as) - self.assertEqual(as.getValue(), 12.0) - ctrl.disconnect(as) + # influence asl anymore + ctrl.connect(asl) + self.assertEqual(asl.getValue(), 12.0) + ctrl.disconnect(asl) ctrl.setValue(4) self.assertEqual(ctrl.getValue(), 4.0) - self.assertEqual(as.getValue(), 12.0) + self.assertEqual(asl.getValue(), 12.0) ##class TestArraySlot(unittest.TestCase): @@ -69,12 +69,12 @@ ## def testConstructor(self): ## # Standard constructor (check if items are 0) -## as = _core.IntArraySlot() -## as.resize(100) +## asl = _core.IntArraySlot() +## asl.resize(100) ## self.assertEqual(list(as), 100*[0]) -## as = _core.DoubleArraySlot() -## as.resize(100) +## asl = _core.DoubleArraySlot() +## asl.resize(100) ## self.assertEqual(list(as), 100*[0.0]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-11 19:34:56
|
Revision: 290 http://cgkit.svn.sourceforge.net/cgkit/?rev=290&view=rev Author: mbaas Date: 2009-02-11 19:34:51 +0000 (Wed, 11 Feb 2009) Log Message: ----------- Replaced the variable name 'as' by 'asl' (because 'as' will become a keyword in Python 2.6). Modified Paths: -------------- cgkit/trunk/unittests/test_arrayslots.py Modified: cgkit/trunk/unittests/test_arrayslots.py =================================================================== --- cgkit/trunk/unittests/test_arrayslots.py 2009-02-10 22:44:22 UTC (rev 289) +++ cgkit/trunk/unittests/test_arrayslots.py 2009-02-11 19:34:51 UTC (rev 290) @@ -8,58 +8,58 @@ def testConstructor(self): - as = _core.DoubleArraySlot(1) + asl = _core.DoubleArraySlot(1) # array size==0? - self.assertEqual(as.size(), 0) + self.assertEqual(asl.size(), 0) # multiplicity==1? - self.assertEqual(as.multiplicity(), 1) - self.assertEqual(list(as), []) - self.assertEqual(as.getController(), None) + self.assertEqual(asl.multiplicity(), 1) + self.assertEqual(list(asl), []) + self.assertEqual(asl.getController(), None) - as = _core.DoubleArraySlot() + asl = _core.DoubleArraySlot() # array size==0? - self.assertEqual(as.size(), 0) + self.assertEqual(asl.size(), 0) # multiplicity==1? - self.assertEqual(as.multiplicity(), 1) - self.assertEqual(list(as), []) + self.assertEqual(asl.multiplicity(), 1) + self.assertEqual(list(asl), []) - as = _core.DoubleArraySlot(3) + asl = _core.DoubleArraySlot(3) # array size==0? - self.assertEqual(as.size(), 0) + self.assertEqual(asl.size(), 0) # multiplicity==3? - self.assertEqual(as.multiplicity(), 3) - self.assertEqual(list(as), []) + self.assertEqual(asl.multiplicity(), 3) + self.assertEqual(list(asl), []) def testResize(self): - as = _core.DoubleArraySlot(1) + asl = _core.DoubleArraySlot(1) # Create 8 elements - as.resize(8) - self.assertEqual(as.size(), 8) - self.assertEqual(list(as), 8*[0]) + asl.resize(8) + self.assertEqual(asl.size(), 8) + self.assertEqual(list(asl), 8*[0]) # Set values for i in range(8): - as[i]=i+1 + asl[i]=i+1 # Check if the values were properly set - self.assertEqual(list(as), range(1,9)) + self.assertEqual(list(asl), range(1,9)) # Enlarge the array - as.resize(20) - self.assertEqual(as.size(), 20) + asl.resize(20) + self.assertEqual(asl.size(), 20) # Check if the values were properly copied - self.assertEqual(list(as), range(1,9)+12*[0]) + self.assertEqual(list(asl), range(1,9)+12*[0]) # Shrink the array - as.resize(4) + asl.resize(4) # Check if the values were properly copied - self.assertEqual(list(as), range(1,5)) + self.assertEqual(list(asl), range(1,5)) # Negative size must equal 0 - as.resize(-2) - self.assertEqual(as.size(), 0) + asl.resize(-2) + self.assertEqual(asl.size(), 0) def testSizeConstraints(self): """Check if the size constraint really constrains the size. @@ -150,32 +150,32 @@ def testGetSetMult1(self): # Multiplicity 1 - as = _core.Vec3ArraySlot(1) - as.resize(10) + asl = _core.Vec3ArraySlot(1) + asl.resize(10) for i in range(10): - as.setValue(i, vec3(i+1)) + asl.setValue(i, vec3(i+1)) for i in range(10): - self.assertEqual(as.getValue(i), vec3(i+1)) + self.assertEqual(asl.getValue(i), vec3(i+1)) for i in range(10): - self.assertEqual(as[i], vec3(i+1)) + self.assertEqual(asl[i], vec3(i+1)) def testGetSetMultn(self): # Multiplicity 3 - as = _core.IntArraySlot(3) - as.resize(10) + asl = _core.IntArraySlot(3) + asl.resize(10) for i in range(10): - as.setValue(i, (i, i+1, i+2)) + asl.setValue(i, (i, i+1, i+2)) for i in range(10): - self.assertEqual(as.getValue(i), (i,i+1,i+2)) + self.assertEqual(asl.getValue(i), (i,i+1,i+2)) for i in range(10): - self.assertEqual(as[i], (i,i+1,i+2)) + self.assertEqual(asl[i], (i,i+1,i+2)) def testController(self): @@ -186,25 +186,25 @@ ctrl[i] = vec3(i+1) # "Target" slot - as = _core.Vec3ArraySlot() - as.setController(ctrl) - self.assertEqual(as.size(), 10) + asl = _core.Vec3ArraySlot() + asl.setController(ctrl) + self.assertEqual(asl.size(), 10) for i in range(10): - self.assertEqual(as[i], vec3(i+1)) + self.assertEqual(asl[i], vec3(i+1)) # Change an item in the controller... ctrl[1]=vec3(-1,-2,-3) # ...and see if the target also has changed for i in range(10): if i==1: - self.assertEqual(as[i], vec3(-1,-2,-3)) + self.assertEqual(asl[i], vec3(-1,-2,-3)) else: - self.assertEqual(as[i], vec3(i+1)) + self.assertEqual(asl[i], vec3(i+1)) # Disconnect - as.setController(None) + asl.setController(None) # modify an element - as[1] = vec3(2,2,2) + asl[1] = vec3(2,2,2) # and check if ctrl and target are separate for i in range(10): if i==1: @@ -213,24 +213,24 @@ self.assertEqual(ctrl[i], vec3(i+1)) for i in range(10): - self.assertEqual(as[i], vec3(i+1)) + self.assertEqual(asl[i], vec3(i+1)) def testExceptions(self): - as = _core.DoubleArraySlot(1) - as.resize(8) - self.assertRaises(IndexError, lambda: as[8]) - self.assertRaises(IndexError, lambda: as.getValue(8)) - self.assertRaises(IndexError, lambda: as.setValue(8,0)) - self.assertRaises(TypeError, lambda: as.setValue(0,vec3())) + asl = _core.DoubleArraySlot(1) + asl.resize(8) + self.assertRaises(IndexError, lambda: asl[8]) + self.assertRaises(IndexError, lambda: asl.getValue(8)) + self.assertRaises(IndexError, lambda: asl.setValue(8,0)) + self.assertRaises(TypeError, lambda: asl.setValue(0,vec3())) - as = _core.DoubleArraySlot(2) - as.resize(8) - self.assertRaises(IndexError, lambda: as[8]) - self.assertRaises(IndexError, lambda: as.getValue(8)) - self.assertRaises(IndexError, lambda: as.setValue(8,(1,2))) - self.assertRaises(ValueError, lambda: as.setValue(0,5)) + asl = _core.DoubleArraySlot(2) + asl.resize(8) + self.assertRaises(IndexError, lambda: asl[8]) + self.assertRaises(IndexError, lambda: asl.getValue(8)) + self.assertRaises(IndexError, lambda: asl.setValue(8,(1,2))) + self.assertRaises(ValueError, lambda: asl.setValue(0,5)) ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-10 22:48:23
|
Revision: 288 http://cgkit.svn.sourceforge.net/cgkit/?rev=288&view=rev Author: mbaas Date: 2009-02-10 22:43:44 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Support mat4 values. Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py cgkit/trunk/unittests/test_pointcloud.py Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-02-10 09:33:25 UTC (rev 287) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-10 22:43:44 UTC (rev 288) @@ -36,6 +36,7 @@ import os.path import ctypes +import cgtypes import rmanlibutil import _pointcloud try: @@ -434,14 +435,17 @@ m can be any object that contains 16 floats (the values may be nested). """ - values = [] - for v in m: - try: - values.extend(list(v)) - except: - values.append(v) - if len(values)!=16: - raise ValueError("Matrix must be composed of 16 values, got %s instead."%len(values)) + if isinstance(m, cgtypes.mat4): + values = m.toList(rowmajor=True) + else: + values = [] + for v in m: + try: + values.extend(list(v)) + except: + values.append(v) + if len(values)!=16: + raise ValueError("Matrix must be composed of 16 values, got %s instead."%len(values)) return (16*ctypes.c_float)(*values) def __del__(self): Modified: cgkit/trunk/unittests/test_pointcloud.py =================================================================== --- cgkit/trunk/unittests/test_pointcloud.py 2009-02-10 09:33:25 UTC (rev 287) +++ cgkit/trunk/unittests/test_pointcloud.py 2009-02-10 22:43:44 UTC (rev 288) @@ -39,40 +39,40 @@ self.assertAlmostEqual( 1.0, ptc.bbox[3], 1) self.assertAlmostEqual( 2.0, ptc.bbox[4], 1) self.assertAlmostEqual(42.0, ptc.bbox[5], 1) -# self.assertEqual(16, len(ptc.world2eye)) -# self.assertAlmostEqual(1, ptc.world2eye[0], self.accuracy) -# self.assertAlmostEqual(2, ptc.world2eye[1], self.accuracy) -# self.assertAlmostEqual(3, ptc.world2eye[2], self.accuracy) -# self.assertAlmostEqual(4, ptc.world2eye[3], self.accuracy) -# self.assertAlmostEqual(5, ptc.world2eye[4], self.accuracy) -# self.assertAlmostEqual(6, ptc.world2eye[5], self.accuracy) -# self.assertAlmostEqual(7, ptc.world2eye[6], self.accuracy) -# self.assertAlmostEqual(8, ptc.world2eye[7], self.accuracy) -# self.assertAlmostEqual(9, ptc.world2eye[8], self.accuracy) -# self.assertAlmostEqual(10, ptc.world2eye[9], self.accuracy) -# self.assertAlmostEqual(11, ptc.world2eye[10], self.accuracy) -# self.assertAlmostEqual(12, ptc.world2eye[11], self.accuracy) -# self.assertAlmostEqual(13, ptc.world2eye[12], self.accuracy) -# self.assertAlmostEqual(14, ptc.world2eye[13], self.accuracy) -# self.assertAlmostEqual(15, ptc.world2eye[14], self.accuracy) -# self.assertAlmostEqual(16, ptc.world2eye[15], self.accuracy) -# self.assertEqual(16, len(ptc.world2ndc)) -# self.assertAlmostEqual(0.1, ptc.world2ndc[0], self.accuracy) -# self.assertAlmostEqual(0.2, ptc.world2ndc[1], self.accuracy) -# self.assertAlmostEqual(0.3, ptc.world2ndc[2], self.accuracy) -# self.assertAlmostEqual(0.4, ptc.world2ndc[3], self.accuracy) -# self.assertAlmostEqual(0.5, ptc.world2ndc[4], self.accuracy) -# self.assertAlmostEqual(0.6, ptc.world2ndc[5], self.accuracy) -# self.assertAlmostEqual(0.7, ptc.world2ndc[6], self.accuracy) -# self.assertAlmostEqual(0.8, ptc.world2ndc[7], self.accuracy) -# self.assertAlmostEqual(0.9, ptc.world2ndc[8], self.accuracy) -# self.assertAlmostEqual(0.10, ptc.world2ndc[9], self.accuracy) -# self.assertAlmostEqual(0.11, ptc.world2ndc[10], self.accuracy) -# self.assertAlmostEqual(0.12, ptc.world2ndc[11], self.accuracy) -# self.assertAlmostEqual(0.13, ptc.world2ndc[12], self.accuracy) -# self.assertAlmostEqual(0.14, ptc.world2ndc[13], self.accuracy) -# self.assertAlmostEqual(0.15, ptc.world2ndc[14], self.accuracy) -# self.assertAlmostEqual(0.16, ptc.world2ndc[15], self.accuracy) + self.assertEqual(16, len(ptc.world2eye)) + self.assertAlmostEqual(1, ptc.world2eye[0], self.accuracy) + self.assertAlmostEqual(2, ptc.world2eye[1], self.accuracy) + self.assertAlmostEqual(3, ptc.world2eye[2], self.accuracy) + self.assertAlmostEqual(4, ptc.world2eye[3], self.accuracy) + self.assertAlmostEqual(5, ptc.world2eye[4], self.accuracy) + self.assertAlmostEqual(6, ptc.world2eye[5], self.accuracy) + self.assertAlmostEqual(7, ptc.world2eye[6], self.accuracy) + self.assertAlmostEqual(8, ptc.world2eye[7], self.accuracy) + self.assertAlmostEqual(9, ptc.world2eye[8], self.accuracy) + self.assertAlmostEqual(10, ptc.world2eye[9], self.accuracy) + self.assertAlmostEqual(11, ptc.world2eye[10], self.accuracy) + self.assertAlmostEqual(12, ptc.world2eye[11], self.accuracy) + self.assertAlmostEqual(13, ptc.world2eye[12], self.accuracy) + self.assertAlmostEqual(14, ptc.world2eye[13], self.accuracy) + self.assertAlmostEqual(15, ptc.world2eye[14], self.accuracy) + self.assertAlmostEqual(16, ptc.world2eye[15], self.accuracy) + self.assertEqual(16, len(ptc.world2ndc)) + self.assertAlmostEqual(0.1, ptc.world2ndc[0], self.accuracy) + self.assertAlmostEqual(0.2, ptc.world2ndc[1], self.accuracy) + self.assertAlmostEqual(0.3, ptc.world2ndc[2], self.accuracy) + self.assertAlmostEqual(0.4, ptc.world2ndc[3], self.accuracy) + self.assertAlmostEqual(0.5, ptc.world2ndc[4], self.accuracy) + self.assertAlmostEqual(0.6, ptc.world2ndc[5], self.accuracy) + self.assertAlmostEqual(0.7, ptc.world2ndc[6], self.accuracy) + self.assertAlmostEqual(0.8, ptc.world2ndc[7], self.accuracy) + self.assertAlmostEqual(0.9, ptc.world2ndc[8], self.accuracy) + self.assertAlmostEqual(0.10, ptc.world2ndc[9], self.accuracy) + self.assertAlmostEqual(0.11, ptc.world2ndc[10], self.accuracy) + self.assertAlmostEqual(0.12, ptc.world2ndc[11], self.accuracy) + self.assertAlmostEqual(0.13, ptc.world2ndc[12], self.accuracy) + self.assertAlmostEqual(0.14, ptc.world2ndc[13], self.accuracy) + self.assertAlmostEqual(0.15, ptc.world2ndc[14], self.accuracy) + self.assertAlmostEqual(0.16, ptc.world2ndc[15], self.accuracy) self.assertEqual((640.0, 480.0, 1.0), ptc.format) pos,norm,rad,data = ptc.readDataPoint() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-10 22:48:21
|
Revision: 289 http://cgkit.svn.sourceforge.net/cgkit/?rev=289&view=rev Author: mbaas Date: 2009-02-10 22:44:22 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Update Modified Paths: -------------- cgkit/trunk/changelog.txt Modified: cgkit/trunk/changelog.txt =================================================================== --- cgkit/trunk/changelog.txt 2009-02-10 22:43:44 UTC (rev 288) +++ cgkit/trunk/changelog.txt 2009-02-10 22:44:22 UTC (rev 289) @@ -10,6 +10,7 @@ Bug fixes/enhancements: +- cri: numpy integer arrays were not properly supported on 64-bit systems - mayaascii: Bugfix #2119263: The setAttr command wasn't recognizing the channelBox option (+ some other bugfixes). - slparams: The module can now also retrieve information from compiled shaders This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-10 09:33:31
|
Revision: 287 http://cgkit.svn.sourceforge.net/cgkit/?rev=287&view=rev Author: mbaas Date: 2009-02-10 09:33:25 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Added prman to the list of renderers (this is not enabled by default though). Modified Paths: -------------- cgkit/trunk/unittests/test_ri.py Modified: cgkit/trunk/unittests/test_ri.py =================================================================== --- cgkit/trunk/unittests/test_ri.py 2009-02-10 09:26:28 UTC (rev 286) +++ cgkit/trunk/unittests/test_ri.py 2009-02-10 09:33:25 UTC (rev 287) @@ -52,6 +52,8 @@ # ri = cgkit.cri.loadRI("ri") # ri = cgkit.cri.loadRI("aqsislib") # ri = cgkit.cri.loadRI("ri2rib") +# ri = cgkit.cri.loadRI("prman") +# ri.RiProcFree = None ritest.main(ri, "tmp/criout.rib", archiveName="tmp/cinclude.rib") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-10 09:26:33
|
Revision: 286 http://cgkit.svn.sourceforge.net/cgkit/?rev=286&view=rev Author: mbaas Date: 2009-02-10 09:26:28 +0000 (Tue, 10 Feb 2009) Log Message: ----------- Update Modified Paths: -------------- cgkit/trunk/unittests/test_pointcloud.py Modified: cgkit/trunk/unittests/test_pointcloud.py =================================================================== --- cgkit/trunk/unittests/test_pointcloud.py 2009-02-10 07:49:42 UTC (rev 285) +++ cgkit/trunk/unittests/test_pointcloud.py 2009-02-10 09:26:28 UTC (rev 286) @@ -8,10 +8,14 @@ import numpy class TestPointCloud(unittest.TestCase): + """Test the pointcloud module. + """ def __init__(self, *args, **kwargs): unittest.TestCase.__init__(self, *args, **kwargs) self.libName = "3delight" +# self.libName = "prman" + self.accuracy = 3 def testSinglePoints(self): """Test writing/reading individual points. @@ -28,71 +32,77 @@ self.assertEqual(3, ptc.npoints) self.assertEqual([], ptc.variables) self.assertEqual(0, ptc.datasize) - print ptc.bbox +# print ptc.bbox + self.assertAlmostEqual(-1.0, ptc.bbox[0], 1) + self.assertAlmostEqual(0.17, ptc.bbox[1], 1) + self.assertAlmostEqual( 0.3, ptc.bbox[2], 1) + self.assertAlmostEqual( 1.0, ptc.bbox[3], 1) + self.assertAlmostEqual( 2.0, ptc.bbox[4], 1) + self.assertAlmostEqual(42.0, ptc.bbox[5], 1) # self.assertEqual(16, len(ptc.world2eye)) -# self.assertAlmostEqual(1, ptc.world2eye[0], 5) -# self.assertAlmostEqual(2, ptc.world2eye[1], 5) -# self.assertAlmostEqual(3, ptc.world2eye[2], 5) -# self.assertAlmostEqual(4, ptc.world2eye[3], 5) -# self.assertAlmostEqual(5, ptc.world2eye[4], 5) -# self.assertAlmostEqual(6, ptc.world2eye[5], 5) -# self.assertAlmostEqual(7, ptc.world2eye[6], 5) -# self.assertAlmostEqual(8, ptc.world2eye[7], 5) -# self.assertAlmostEqual(9, ptc.world2eye[8], 5) -# self.assertAlmostEqual(10, ptc.world2eye[9], 5) -# self.assertAlmostEqual(11, ptc.world2eye[10], 5) -# self.assertAlmostEqual(12, ptc.world2eye[11], 5) -# self.assertAlmostEqual(13, ptc.world2eye[12], 5) -# self.assertAlmostEqual(14, ptc.world2eye[13], 5) -# self.assertAlmostEqual(15, ptc.world2eye[14], 5) -# self.assertAlmostEqual(16, ptc.world2eye[15], 5) +# self.assertAlmostEqual(1, ptc.world2eye[0], self.accuracy) +# self.assertAlmostEqual(2, ptc.world2eye[1], self.accuracy) +# self.assertAlmostEqual(3, ptc.world2eye[2], self.accuracy) +# self.assertAlmostEqual(4, ptc.world2eye[3], self.accuracy) +# self.assertAlmostEqual(5, ptc.world2eye[4], self.accuracy) +# self.assertAlmostEqual(6, ptc.world2eye[5], self.accuracy) +# self.assertAlmostEqual(7, ptc.world2eye[6], self.accuracy) +# self.assertAlmostEqual(8, ptc.world2eye[7], self.accuracy) +# self.assertAlmostEqual(9, ptc.world2eye[8], self.accuracy) +# self.assertAlmostEqual(10, ptc.world2eye[9], self.accuracy) +# self.assertAlmostEqual(11, ptc.world2eye[10], self.accuracy) +# self.assertAlmostEqual(12, ptc.world2eye[11], self.accuracy) +# self.assertAlmostEqual(13, ptc.world2eye[12], self.accuracy) +# self.assertAlmostEqual(14, ptc.world2eye[13], self.accuracy) +# self.assertAlmostEqual(15, ptc.world2eye[14], self.accuracy) +# self.assertAlmostEqual(16, ptc.world2eye[15], self.accuracy) # self.assertEqual(16, len(ptc.world2ndc)) -# self.assertAlmostEqual(0.1, ptc.world2ndc[0], 5) -# self.assertAlmostEqual(0.2, ptc.world2ndc[1], 5) -# self.assertAlmostEqual(0.3, ptc.world2ndc[2], 5) -# self.assertAlmostEqual(0.4, ptc.world2ndc[3], 5) -# self.assertAlmostEqual(0.5, ptc.world2ndc[4], 5) -# self.assertAlmostEqual(0.6, ptc.world2ndc[5], 5) -# self.assertAlmostEqual(0.7, ptc.world2ndc[6], 5) -# self.assertAlmostEqual(0.8, ptc.world2ndc[7], 5) -# self.assertAlmostEqual(0.9, ptc.world2ndc[8], 5) -# self.assertAlmostEqual(0.10, ptc.world2ndc[9], 5) -# self.assertAlmostEqual(0.11, ptc.world2ndc[10], 5) -# self.assertAlmostEqual(0.12, ptc.world2ndc[11], 5) -# self.assertAlmostEqual(0.13, ptc.world2ndc[12], 5) -# self.assertAlmostEqual(0.14, ptc.world2ndc[13], 5) -# self.assertAlmostEqual(0.15, ptc.world2ndc[14], 5) -# self.assertAlmostEqual(0.16, ptc.world2ndc[15], 5) +# self.assertAlmostEqual(0.1, ptc.world2ndc[0], self.accuracy) +# self.assertAlmostEqual(0.2, ptc.world2ndc[1], self.accuracy) +# self.assertAlmostEqual(0.3, ptc.world2ndc[2], self.accuracy) +# self.assertAlmostEqual(0.4, ptc.world2ndc[3], self.accuracy) +# self.assertAlmostEqual(0.5, ptc.world2ndc[4], self.accuracy) +# self.assertAlmostEqual(0.6, ptc.world2ndc[5], self.accuracy) +# self.assertAlmostEqual(0.7, ptc.world2ndc[6], self.accuracy) +# self.assertAlmostEqual(0.8, ptc.world2ndc[7], self.accuracy) +# self.assertAlmostEqual(0.9, ptc.world2ndc[8], self.accuracy) +# self.assertAlmostEqual(0.10, ptc.world2ndc[9], self.accuracy) +# self.assertAlmostEqual(0.11, ptc.world2ndc[10], self.accuracy) +# self.assertAlmostEqual(0.12, ptc.world2ndc[11], self.accuracy) +# self.assertAlmostEqual(0.13, ptc.world2ndc[12], self.accuracy) +# self.assertAlmostEqual(0.14, ptc.world2ndc[13], self.accuracy) +# self.assertAlmostEqual(0.15, ptc.world2ndc[14], self.accuracy) +# self.assertAlmostEqual(0.16, ptc.world2ndc[15], self.accuracy) self.assertEqual((640.0, 480.0, 1.0), ptc.format) pos,norm,rad,data = ptc.readDataPoint() - self.assertAlmostEqual(0.1, pos[0], 5) - self.assertAlmostEqual(0.2, pos[1], 5) - self.assertAlmostEqual(0.3, pos[2], 5) - self.assertAlmostEqual(0, norm[0], 5) - self.assertAlmostEqual(1, norm[1], 5) - self.assertAlmostEqual(0, norm[2], 5) - self.assertAlmostEqual(0.5, rad, 5) + self.assertAlmostEqual(0.1, pos[0], self.accuracy) + self.assertAlmostEqual(0.2, pos[1], self.accuracy) + self.assertAlmostEqual(0.3, pos[2], self.accuracy) + self.assertAlmostEqual(0, norm[0], self.accuracy) + self.assertAlmostEqual(1, norm[1], self.accuracy) + self.assertAlmostEqual(0, norm[2], self.accuracy) + self.assertAlmostEqual(0.5, rad, self.accuracy) self.assertEqual({}, data) pos,norm,rad,data = ptc.readDataPoint() - self.assertAlmostEqual(1.0, pos[0], 5) - self.assertAlmostEqual(2.0, pos[1], 5) - self.assertAlmostEqual(3.0, pos[2], 5) - self.assertAlmostEqual(1, norm[0], 5) - self.assertAlmostEqual(0, norm[1], 5) - self.assertAlmostEqual(0, norm[2], 5) - self.assertAlmostEqual(1.0, rad, 5) + self.assertAlmostEqual(1.0, pos[0], self.accuracy) + self.assertAlmostEqual(2.0, pos[1], self.accuracy) + self.assertAlmostEqual(3.0, pos[2], self.accuracy) + self.assertAlmostEqual(1, norm[0], self.accuracy) + self.assertAlmostEqual(0, norm[1], self.accuracy) + self.assertAlmostEqual(0, norm[2], self.accuracy) + self.assertAlmostEqual(1.0, rad, self.accuracy) self.assertEqual({}, data) pos,norm,rad,data = ptc.readDataPoint() - self.assertAlmostEqual(-1.0, pos[0], 5) - self.assertAlmostEqual(0.17, pos[1], 5) - self.assertAlmostEqual(42.0, pos[2], 5) - self.assertAlmostEqual(0, norm[0], 5) - self.assertAlmostEqual(0, norm[1], 5) - self.assertAlmostEqual(1, norm[2], 5) - self.assertAlmostEqual(1.5, rad, 5) + self.assertAlmostEqual(-1.0, pos[0], self.accuracy) + self.assertAlmostEqual(0.17, pos[1], self.accuracy) + self.assertAlmostEqual(42.0, pos[2], self.accuracy) + self.assertAlmostEqual(0, norm[0], self.accuracy) + self.assertAlmostEqual(0, norm[1], self.accuracy) + self.assertAlmostEqual(1, norm[2], self.accuracy) + self.assertAlmostEqual(1.5, rad, self.accuracy) self.assertEqual({}, data) self.assertRaises(EOFError, lambda: ptc.readDataPoint()) @@ -119,59 +129,59 @@ rs = (2*ctypes.c_float)() ds = (8*ctypes.c_float)() ptc.readDataPoints(2, (ps,ns,rs,ds)) - self.assertAlmostEqual(0.4, ps[0], 5) - self.assertAlmostEqual(0.8, ps[1], 5) - self.assertAlmostEqual(1.0, ps[2], 5) - self.assertAlmostEqual(0.9, ps[3], 5) - self.assertAlmostEqual(0.7, ps[4], 5) - self.assertAlmostEqual(0.6, ps[5], 5) - self.assertAlmostEqual(1, ns[0], 5) - self.assertAlmostEqual(0, ns[1], 5) - self.assertAlmostEqual(0, ns[2], 5) - self.assertAlmostEqual(0, ns[3], 5) - self.assertAlmostEqual(0, ns[4], 5) - self.assertAlmostEqual(1, ns[5], 5) - self.assertAlmostEqual(0.4, rs[0], 5) - self.assertAlmostEqual(0.5, rs[1], 5) - self.assertAlmostEqual(12.0, ds[0], 5) - self.assertAlmostEqual(1, ds[1], 5) - self.assertAlmostEqual(2, ds[2], 5) - self.assertAlmostEqual(3, ds[3], 5) - self.assertAlmostEqual(42.0, ds[4], 5) - self.assertAlmostEqual(-1, ds[5], 5) - self.assertAlmostEqual(-2, ds[6], 5) - self.assertAlmostEqual(-3, ds[7], 5) + self.assertAlmostEqual(0.4, ps[0], self.accuracy) + self.assertAlmostEqual(0.8, ps[1], self.accuracy) + self.assertAlmostEqual(1.0, ps[2], self.accuracy) + self.assertAlmostEqual(0.9, ps[3], self.accuracy) + self.assertAlmostEqual(0.7, ps[4], self.accuracy) + self.assertAlmostEqual(0.6, ps[5], self.accuracy) + self.assertAlmostEqual(1, ns[0], self.accuracy) + self.assertAlmostEqual(0, ns[1], self.accuracy) + self.assertAlmostEqual(0, ns[2], self.accuracy) + self.assertAlmostEqual(0, ns[3], self.accuracy) + self.assertAlmostEqual(0, ns[4], self.accuracy) + self.assertAlmostEqual(1, ns[5], self.accuracy) + self.assertAlmostEqual(0.4, rs[0], self.accuracy) + self.assertAlmostEqual(0.5, rs[1], self.accuracy) + self.assertAlmostEqual(12.0, ds[0], self.accuracy) + self.assertAlmostEqual(1, ds[1], self.accuracy) + self.assertAlmostEqual(2, ds[2], self.accuracy) + self.assertAlmostEqual(3, ds[3], self.accuracy) + self.assertAlmostEqual(42.0, ds[4], self.accuracy) + self.assertAlmostEqual(-1, ds[5], self.accuracy) + self.assertAlmostEqual(-2, ds[6], self.accuracy) + self.assertAlmostEqual(-3, ds[7], self.accuracy) ptc.close() ptc = pointcloud.open("tmp/pointcloud2.ptc", "r", self.libName) pos,norm,rad,data = ptc.readDataPoint() - self.assertAlmostEqual(0.4, pos[0], 5) - self.assertAlmostEqual(0.8, pos[1], 5) - self.assertAlmostEqual(1.0, pos[2], 5) - self.assertAlmostEqual(1, norm[0], 5) - self.assertAlmostEqual(0, norm[1], 5) - self.assertAlmostEqual(0, norm[2], 5) - self.assertAlmostEqual(0.4, rad, 5) - self.assertAlmostEqual(12, data["fspam"], 5) - self.assertAlmostEqual(1, data["vspam"][0], 5) - self.assertAlmostEqual(2, data["vspam"][1], 5) - self.assertAlmostEqual(3, data["vspam"][2], 5) + self.assertAlmostEqual(0.4, pos[0], self.accuracy) + self.assertAlmostEqual(0.8, pos[1], self.accuracy) + self.assertAlmostEqual(1.0, pos[2], self.accuracy) + self.assertAlmostEqual(1, norm[0], self.accuracy) + self.assertAlmostEqual(0, norm[1], self.accuracy) + self.assertAlmostEqual(0, norm[2], self.accuracy) + self.assertAlmostEqual(0.4, rad, self.accuracy) + self.assertAlmostEqual(12, data["fspam"], self.accuracy) + self.assertAlmostEqual(1, data["vspam"][0], self.accuracy) + self.assertAlmostEqual(2, data["vspam"][1], self.accuracy) + self.assertAlmostEqual(3, data["vspam"][2], self.accuracy) ptc.close() ptc = pointcloud.open("tmp/pointcloud2.ptc", "r", self.libName) for buf in ptc.iterBatches(10, numpyArray=False, combinedBuffer=True): self.assertEqual(22, len(buf)) - self.assertAlmostEqual(0.4, buf[0], 5) - self.assertAlmostEqual(0.8, buf[1], 5) - self.assertAlmostEqual(1.0, buf[2], 5) - self.assertAlmostEqual(1, buf[3], 5) - self.assertAlmostEqual(0, buf[4], 5) - self.assertAlmostEqual(0, buf[5], 5) - self.assertAlmostEqual(0.4, buf[6], 5) - self.assertAlmostEqual(12, buf[7], 5) - self.assertAlmostEqual(1, buf[8], 5) - self.assertAlmostEqual(2, buf[9], 5) - self.assertAlmostEqual(3, buf[10], 5) + self.assertAlmostEqual(0.4, buf[0], self.accuracy) + self.assertAlmostEqual(0.8, buf[1], self.accuracy) + self.assertAlmostEqual(1.0, buf[2], self.accuracy) + self.assertAlmostEqual(1, buf[3], self.accuracy) + self.assertAlmostEqual(0, buf[4], self.accuracy) + self.assertAlmostEqual(0, buf[5], self.accuracy) + self.assertAlmostEqual(0.4, buf[6], self.accuracy) + self.assertAlmostEqual(12, buf[7], self.accuracy) + self.assertAlmostEqual(1, buf[8], self.accuracy) + self.assertAlmostEqual(2, buf[9], self.accuracy) + self.assertAlmostEqual(3, buf[10], self.accuracy) ptc.close() def testMultiPointsOneBuffer(self): @@ -179,7 +189,7 @@ """ buffer = numpy.zeros(shape=(2,8), dtype=numpy.float32) buffer[0] = (1,2,3,1,0,0,7,8) - buffer[1] = (-1,-2,-3,0,0,1,-7,-8) + buffer[1] = (-1,-2,-3,0,0,1,2,-8) ptc = pointcloud.open("tmp/pointcloud3.ptc", "w", self.libName, vars=[("float", "spam")], world2eye=mat4(1), world2ndc=mat4(1), format=(640,480,1)) ptc.writeDataPoints(2, buffer) ptc.close() @@ -188,8 +198,15 @@ ptc = pointcloud.open("tmp/pointcloud3.ptc", "r", self.libName) n = ptc.readDataPoints(3, buf) self.assertEqual(2, n) + # Round the normals + buf[0][3] = round(buf[0][3],self.accuracy) + buf[0][4] = round(buf[0][4],self.accuracy) + buf[0][5] = round(buf[0][5],self.accuracy) + buf[1][3] = round(buf[1][3],self.accuracy) + buf[1][4] = round(buf[1][4],self.accuracy) + buf[1][5] = round(buf[1][5],self.accuracy) self.assertEqual([1,2,3,1,0,0,7,8], list(list(buf)[0])) - self.assertEqual([-1,-2,-3,0,0,1,-7,-8], list(list(buf)[1])) + self.assertEqual([-1,-2,-3,0,0,1,2,-8], list(list(buf)[1])) n = ptc.readDataPoints(3, buf) self.assertEqual(0, n) ptc.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-10 07:49:45
|
Revision: 285 http://cgkit.svn.sourceforge.net/cgkit/?rev=285&view=rev Author: mbaas Date: 2009-02-10 07:49:42 +0000 (Tue, 10 Feb 2009) Log Message: ----------- The point cloud reader now tracks the number of points that have been read. Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py cgkit/trunk/pyrex/c/_pointcloud.c cgkit/trunk/pyrex/pyx/_pointcloud.pyx cgkit/trunk/unittests/test_pointcloud.py Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-02-09 22:04:25 UTC (rev 284) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-10 07:49:42 UTC (rev 285) @@ -128,6 +128,7 @@ self._handle = handle + self.name = fileName self.variables = [] self.npoints = None self.bbox = None @@ -175,9 +176,16 @@ if ptclib.PtcGetPointCloudInfo(handle, "world2ndc", m)==1: self.world2ndc = list(m) + if self.npoints is None: + raise IOError("Could not obtain the number of points in point cloud file %s."%fileName) + if self.npoints<0: + raise ValueError("The number of points in the point cloud file is negative (%s)."%self.npoints) if self.datasize is None: raise IOError("Could not obtain datasize value from point cloud file %s."%fileName) + # The number of points that can still be read before eof is hit + self._numPointsLeft = self.npoints + # Set up storage for reading individual data points self._pos = (3*ctypes.c_float)() self._normal = (3*ctypes.c_float)() @@ -206,14 +214,19 @@ Returns a tuple (pos, normal, radius, dataDict) where pos and normal are 3-tuples of floats, radius is a single float and dataDict a dictionary with the extra variables that are attached to the point. - If no more point is available None is returned. + If no more point is available an EOFError exception is thrown. + An IOErrror handle is thrown when an error occurs during reading or + when the file has already been closed. """ if self._handle is None: - raise IOError("The point cloud file has already been closed.") + raise IOError("The point cloud file has already been closed (%s)"%self.name) + if self._numPointsLeft==0: + raise EOFError("There are no more points left to read from point cloud file %s"%self.name) + self._numPointsLeft -= 1 res = self._PtcReadDataPoint(self._handle, self._pos, self._normal, self._radius, self._data) if res==0: - return None + raise IOError("Error while reading data point from point cloud file %s"%self.name) else: dataDict = {} data = self._data @@ -233,8 +246,11 @@ The return value is the number of points that have actually been read (additional items in the buffers remain at their previous - value). + value). When 0 is returned, the end of the file has been reached. """ + if numPoints<=0: + return 0 + # Are there 4 individual buffers? if type(buffer) is tuple: if len(buffer)!=4: @@ -260,10 +276,13 @@ radPtr = normPtr+3*sizeOfFloat dataPtr = radPtr+sizeOfFloat + num = min(numPoints, self._numPointsLeft) + # Read the points - n = _pointcloud.readDataPoints(ctypes.addressof(self._PtcReadDataPoint), self._handle, numPoints, - pntPtr, pntStride, normPtr, normStride, radPtr, radStride, dataPtr, dataStride) - return n + self._numPointsLeft -= num + _pointcloud.readDataPoints(ctypes.addressof(self._PtcReadDataPoint), self._handle, num, + pntPtr, pntStride, normPtr, normStride, radPtr, radStride, dataPtr, dataStride) + return num def iterPoints(self): """Iterate over all the points in the file. @@ -271,11 +290,8 @@ Yields tuples (point,normal,radius,data) for every point in the file. This is equivalent to calling readDataPoint() repeatedly. """ - while 1: - data = self.readDataPoint() - if data is None: - break - yield data + while self._numPointsLeft>0: + yield self.readDataPoint() def iterBatches(self, batchSize=1000, combinedBuffer=False, numpyArray=False): """Iterate over point batches. @@ -295,7 +311,7 @@ if numpyArray and not _numpy_available: raise ImportError("numpy is not available") - num = self.npoints + num = self._numPointsLeft buffer = None bufLen = 0 while num>0: Modified: cgkit/trunk/pyrex/c/_pointcloud.c =================================================================== --- cgkit/trunk/pyrex/c/_pointcloud.c 2009-02-09 22:04:25 UTC (rev 284) +++ cgkit/trunk/pyrex/c/_pointcloud.c 2009-02-10 07:49:42 UTC (rev 285) @@ -1,4 +1,4 @@ -/* Generated by Pyrex 0.9.8.5 on Sun Feb 8 11:51:47 2009 */ +/* Generated by Pyrex 0.9.8.5 on Tue Feb 10 07:47:20 2009 */ #define PY_SSIZE_T_CLEAN #include "Python.h" @@ -57,13 +57,16 @@ typedef int (*__pyx_t_11_pointcloud_PtcWriteDataPointPtr)(__pyx_t_11_pointcloud_PtcPointCloud,float *,float *,float,float *); -static char __pyx_k1[] = "Failed to write data point into point cloud file"; +static char __pyx_k1[] = "Failed to read data point from point cloud file"; +static char __pyx_k2[] = "Failed to write data point into point cloud file"; static PyObject *__pyx_k1p; +static PyObject *__pyx_k2p; static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_k1p, 0, __pyx_k1, sizeof(__pyx_k1)}, + {&__pyx_k2p, 0, __pyx_k2, sizeof(__pyx_k2)}, {0, 0, 0, 0} }; @@ -72,7 +75,7 @@ /* Implementation of _pointcloud */ static PyObject *__pyx_f_11_pointcloud_readDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_11_pointcloud_readDataPoints[] = "Read a sequence of data points.\n \n readFuncLoc is the location of the PtcReadDataPoint function pointer.\n ptcHandle is the open point cloud handle. numPoints is the number of\n points that should be read.\n All the *Buf variables are the respective buffers where the data is written\n to. *Stride is the number of floats to advance the pointers to get to the\n next data location. The buffers must be large enough to hold numPoints\n items.\n The return value is the number of points that were actually read.\n "; +static char __pyx_doc_11_pointcloud_readDataPoints[] = "Read a sequence of data points.\n \n readFuncLoc is the location of the PtcReadDataPoint function pointer.\n ptcHandle is the open point cloud handle. numPoints is the number of\n points that should be read.\n All the *Buf variables are the respective buffers where the data is written\n to. *Stride is the number of floats to advance the pointers to get to the\n next data location. The buffers must be large enough to hold numPoints\n items.\n numPoints must at least be the number of points that are still left\n in the file (otherwise the function may generate an exception or return\n bogus values, whatever the underlying RenderMan implementation does).\n "; static PyObject *__pyx_f_11_pointcloud_readDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { long __pyx_v_readFuncLoc; long __pyx_v_ptcHandle; @@ -96,73 +99,75 @@ PyObject *__pyx_r; int __pyx_1; PyObject *__pyx_2 = 0; + PyObject *__pyx_3 = 0; static char *__pyx_argnames[] = {"readFuncLoc","ptcHandle","numPoints","pointBuf","pointStride","normalBuf","normalStride","radiusBuf","radiusStride","dataBuf","dataStride",0}; if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "llllililili", __pyx_argnames, &__pyx_v_readFuncLoc, &__pyx_v_ptcHandle, &__pyx_v_numPoints, &__pyx_v_pointBuf, &__pyx_v_pointStride, &__pyx_v_normalBuf, &__pyx_v_normalStride, &__pyx_v_radiusBuf, &__pyx_v_radiusStride, &__pyx_v_dataBuf, &__pyx_v_dataStride)) return 0; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":61 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":63 */ __pyx_v_PtcReadDataPoint = (((__pyx_t_11_pointcloud_PtcReadDataPointPtr *)__pyx_v_readFuncLoc)[0]); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":62 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":64 */ __pyx_v_pointCloud = ((__pyx_t_11_pointcloud_PtcPointCloud)__pyx_v_ptcHandle); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":71 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":73 */ __pyx_v_pntPtr = ((float *)__pyx_v_pointBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":72 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":74 */ __pyx_v_normalPtr = ((float *)__pyx_v_normalBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":73 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":75 */ __pyx_v_radiusPtr = ((float *)__pyx_v_radiusBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":74 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":76 */ __pyx_v_dataPtr = ((float *)__pyx_v_dataBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":77 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":79 */ __pyx_v_n = 0; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":78 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":80 */ while (1) { __pyx_1 = (__pyx_v_n < __pyx_v_numPoints); if (!__pyx_1) break; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":79 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":81 */ __pyx_v_res = __pyx_v_PtcReadDataPoint(__pyx_v_pointCloud,__pyx_v_pntPtr,__pyx_v_normalPtr,__pyx_v_radiusPtr,__pyx_v_dataPtr); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":80 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":82 */ __pyx_1 = (__pyx_v_res == 0); if (__pyx_1) { - goto __pyx_L3; + __pyx_2 = PyTuple_New(1); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; goto __pyx_L1;} + Py_INCREF(__pyx_k1p); + PyTuple_SET_ITEM(__pyx_2, 0, __pyx_k1p); + __pyx_3 = PyObject_CallObject(PyExc_IOError, __pyx_2); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; goto __pyx_L1;} + Py_DECREF(__pyx_2); __pyx_2 = 0; + __Pyx_Raise(__pyx_3, 0, 0); + Py_DECREF(__pyx_3); __pyx_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; goto __pyx_L1;} goto __pyx_L4; } __pyx_L4:; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":82 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":84 */ __pyx_v_pntPtr += __pyx_v_pointStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":83 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":85 */ __pyx_v_normalPtr += __pyx_v_normalStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":84 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":86 */ __pyx_v_radiusPtr += __pyx_v_radiusStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":85 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":87 */ __pyx_v_dataPtr += __pyx_v_dataStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":86 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":88 */ __pyx_v_n += 1; } - __pyx_L3:; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":89 */ - __pyx_2 = PyInt_FromLong(__pyx_v_n); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; goto __pyx_L1;} - __pyx_r = __pyx_2; - __pyx_2 = 0; - goto __pyx_L0; - __pyx_r = Py_None; Py_INCREF(Py_None); goto __pyx_L0; __pyx_L1:; Py_XDECREF(__pyx_2); + Py_XDECREF(__pyx_3); __Pyx_AddTraceback("_pointcloud.readDataPoints"); __pyx_r = 0; __pyx_L0:; @@ -198,63 +203,63 @@ static char *__pyx_argnames[] = {"writeFuncLoc","ptcHandle","numPoints","pointBuf","pointStride","normalBuf","normalStride","radiusBuf","radiusStride","dataBuf","dataStride",0}; if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "llllililili", __pyx_argnames, &__pyx_v_writeFuncLoc, &__pyx_v_ptcHandle, &__pyx_v_numPoints, &__pyx_v_pointBuf, &__pyx_v_pointStride, &__pyx_v_normalBuf, &__pyx_v_normalStride, &__pyx_v_radiusBuf, &__pyx_v_radiusStride, &__pyx_v_dataBuf, &__pyx_v_dataStride)) return 0; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":107 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":106 */ __pyx_v_PtcWriteDataPoint = (((__pyx_t_11_pointcloud_PtcWriteDataPointPtr *)__pyx_v_writeFuncLoc)[0]); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":108 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":107 */ __pyx_v_pointCloud = ((__pyx_t_11_pointcloud_PtcPointCloud)__pyx_v_ptcHandle); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":117 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":116 */ __pyx_v_pntPtr = ((float *)__pyx_v_pointBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":118 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":117 */ __pyx_v_normalPtr = ((float *)__pyx_v_normalBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":119 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":118 */ __pyx_v_radiusPtr = ((float *)__pyx_v_radiusBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":120 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":119 */ __pyx_v_dataPtr = ((float *)__pyx_v_dataBuf); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":123 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":122 */ __pyx_v_n = 0; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":124 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":123 */ while (1) { __pyx_1 = (__pyx_v_n < __pyx_v_numPoints); if (!__pyx_1) break; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":125 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":124 */ __pyx_v_res = __pyx_v_PtcWriteDataPoint(__pyx_v_pointCloud,__pyx_v_pntPtr,__pyx_v_normalPtr,(__pyx_v_radiusPtr[0]),__pyx_v_dataPtr); - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":126 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":125 */ __pyx_1 = (__pyx_v_res == 0); if (__pyx_1) { - __pyx_2 = PyTuple_New(1); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} - Py_INCREF(__pyx_k1p); - PyTuple_SET_ITEM(__pyx_2, 0, __pyx_k1p); - __pyx_3 = PyObject_CallObject(PyExc_IOError, __pyx_2); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} + __pyx_2 = PyTuple_New(1); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; goto __pyx_L1;} + Py_INCREF(__pyx_k2p); + PyTuple_SET_ITEM(__pyx_2, 0, __pyx_k2p); + __pyx_3 = PyObject_CallObject(PyExc_IOError, __pyx_2); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; goto __pyx_L1;} Py_DECREF(__pyx_2); __pyx_2 = 0; __Pyx_Raise(__pyx_3, 0, 0); Py_DECREF(__pyx_3); __pyx_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; goto __pyx_L1;} goto __pyx_L4; } __pyx_L4:; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":128 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":127 */ __pyx_v_pntPtr += __pyx_v_pointStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":129 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":128 */ __pyx_v_normalPtr += __pyx_v_normalStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":130 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":129 */ __pyx_v_radiusPtr += __pyx_v_radiusStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":131 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":130 */ __pyx_v_dataPtr += __pyx_v_dataStride; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":132 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":131 */ __pyx_v_n += 1; } @@ -288,7 +293,7 @@ if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; - /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":91 */ + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":90 */ return; __pyx_L1:; __Pyx_AddTraceback("_pointcloud"); Modified: cgkit/trunk/pyrex/pyx/_pointcloud.pyx =================================================================== --- cgkit/trunk/pyrex/pyx/_pointcloud.pyx 2009-02-09 22:04:25 UTC (rev 284) +++ cgkit/trunk/pyrex/pyx/_pointcloud.pyx 2009-02-10 07:49:42 UTC (rev 285) @@ -54,7 +54,9 @@ to. *Stride is the number of floats to advance the pointers to get to the next data location. The buffers must be large enough to hold numPoints items. - The return value is the number of points that were actually read. + numPoints must at least be the number of points that are still left + in the file (otherwise the function may generate an exception or return + bogus values, whatever the underlying RenderMan implementation does). """ cdef PtcReadDataPointPtr PtcReadDataPoint cdef PtcPointCloud pointCloud @@ -78,15 +80,12 @@ while n<numPoints: res = PtcReadDataPoint(pointCloud, pntPtr, normalPtr, radiusPtr, dataPtr) if res==0: - break + raise IOError("Failed to read data point from point cloud file") pntPtr += pointStride normalPtr += normalStride radiusPtr += radiusStride dataPtr += dataStride n += 1 - - # Return the number of points read - return n def writeDataPoints(long writeFuncLoc, long ptcHandle, long numPoints, long pointBuf, int pointStride, Modified: cgkit/trunk/unittests/test_pointcloud.py =================================================================== --- cgkit/trunk/unittests/test_pointcloud.py 2009-02-09 22:04:25 UTC (rev 284) +++ cgkit/trunk/unittests/test_pointcloud.py 2009-02-10 07:49:42 UTC (rev 285) @@ -95,8 +95,7 @@ self.assertAlmostEqual(1.5, rad, 5) self.assertEqual({}, data) - v = ptc.readDataPoint() - self.assertEqual(None, v) + self.assertRaises(EOFError, lambda: ptc.readDataPoint()) ptc.close() @@ -185,11 +184,14 @@ ptc.writeDataPoints(2, buffer) ptc.close() - buf = numpy.zeros(shape=(2,8), dtype=numpy.float32) + buf = numpy.zeros(shape=(3,8), dtype=numpy.float32) ptc = pointcloud.open("tmp/pointcloud3.ptc", "r", self.libName) - ptc.readDataPoints(2, buf) + n = ptc.readDataPoints(3, buf) + self.assertEqual(2, n) self.assertEqual([1,2,3,1,0,0,7,8], list(list(buf)[0])) self.assertEqual([-1,-2,-3,0,0,1,-7,-8], list(list(buf)[1])) + n = ptc.readDataPoints(3, buf) + self.assertEqual(0, n) ptc.close() ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-09 22:53:27
|
Revision: 284 http://cgkit.svn.sourceforge.net/cgkit/?rev=284&view=rev Author: mbaas Date: 2009-02-09 22:04:25 +0000 (Mon, 09 Feb 2009) Log Message: ----------- Passing numpy int arrays didn't work on 64bit systems (because apparently numpy.int_ is not a C int (32bit) but a Python int (64bit). Modified Paths: -------------- cgkit/trunk/cgkit/cri.py Modified: cgkit/trunk/cgkit/cri.py =================================================================== --- cgkit/trunk/cgkit/cri.py 2009-02-09 22:02:49 UTC (rev 283) +++ cgkit/trunk/cgkit/cri.py 2009-02-09 22:04:25 UTC (rev 284) @@ -204,7 +204,10 @@ else: raise TypeError("RtFloat is of an unknown type") - self._numpyTypes[self._ri.RtInt] = numpy.int_ + # numpy.int_ is 64bit on a 64bit system (so it's rather long instead of int) + # That's why we use an int32 here which should also match the + # C int type on 64bit systems. + self._numpyTypes[self._ri.RtInt] = numpy.int32 def _getRiLastError(self): return self._ri.RiLastError This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-09 22:53:27
|
Revision: 283 http://cgkit.svn.sourceforge.net/cgkit/?rev=283&view=rev Author: mbaas Date: 2009-02-09 22:02:49 +0000 (Mon, 09 Feb 2009) Log Message: ----------- Test numpy int arrays and removed the 'version' from the normalized RIB file. Modified Paths: -------------- cgkit/trunk/unittests/data/include_ref.rib cgkit/trunk/unittests/data/riout_ref.rib cgkit/trunk/unittests/ritest.py cgkit/trunk/unittests/test_ri.py Modified: cgkit/trunk/unittests/data/include_ref.rib =================================================================== --- cgkit/trunk/unittests/data/include_ref.rib 2009-02-08 15:34:51 UTC (rev 282) +++ cgkit/trunk/unittests/data/include_ref.rib 2009-02-09 22:02:49 UTC (rev 283) @@ -1,5 +1,4 @@ # Normalized RIB -version 3.03 AttributeBegin Translate 4.0 -3.0 0.0 Color [ 1.0 0.5 0.0 ] Modified: cgkit/trunk/unittests/data/riout_ref.rib =================================================================== --- cgkit/trunk/unittests/data/riout_ref.rib 2009-02-08 15:34:51 UTC (rev 282) +++ cgkit/trunk/unittests/data/riout_ref.rib 2009-02-09 22:02:49 UTC (rev 283) @@ -1,5 +1,4 @@ # Normalized RIB -version 3.03 ErrorHandler "abort" ErrorHandler "print" ErrorHandler "ignore" Modified: cgkit/trunk/unittests/ritest.py =================================================================== --- cgkit/trunk/unittests/ritest.py 2009-02-08 15:34:51 UTC (rev 282) +++ cgkit/trunk/unittests/ritest.py 2009-02-09 22:02:49 UTC (rev 283) @@ -29,6 +29,9 @@ s = s.replace("]", " ] ") s = s.replace("#", " # ") tokens = s.split() + # Drop the version line + if len(tokens)>0 and tokens[0]=="version": + continue for tok in tokens: if tok=="#": break @@ -92,7 +95,11 @@ ri.RiTranslate(1.33,0,0) ri.RiGeneralPolygon([4], P=[A,B,C,D], Cs=[(1,0,0),(0,1,0),(0,0,1),(1,1,0)]) ri.RiTranslate(1.33,0,0) - ri.RiPointsPolygons([4], [0,1,2,3], P=[A,B,C,D], Cs=[(1,0,0),(0,1,0),(0,0,1),(1,1,0)]) + if has_numpy: + ids = numpy.array([0,1,2,3], dtype=numpy.int32) + else: + ids = [0,1,2,3] + ri.RiPointsPolygons([4], ids, P=[A,B,C,D], Cs=[(1,0,0),(0,1,0),(0,0,1),(1,1,0)]) ri.RiTranslate(1.33,0,0) ri.RiPointsGeneralPolygons([1], [4], [0,1,2,3], P=[A,B,C,D], Cs=[(1,0,0),(0,1,0),(0,0,1),(1,1,0)]) Modified: cgkit/trunk/unittests/test_ri.py =================================================================== --- cgkit/trunk/unittests/test_ri.py 2009-02-08 15:34:51 UTC (rev 282) +++ cgkit/trunk/unittests/test_ri.py 2009-02-09 22:02:49 UTC (rev 283) @@ -39,6 +39,7 @@ def testCRiModule(self): """Check the cri module.""" + print "cri test is disabled" return if os.path.exists("tmp/criout.rib"): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-08 15:34:54
|
Revision: 282 http://cgkit.svn.sourceforge.net/cgkit/?rev=282&view=rev Author: mbaas Date: 2009-02-08 15:34:51 +0000 (Sun, 08 Feb 2009) Log Message: ----------- Added the pyrex directories to the source dist. Modified Paths: -------------- cgkit/trunk/MANIFEST.in Modified: cgkit/trunk/MANIFEST.in =================================================================== --- cgkit/trunk/MANIFEST.in 2009-02-08 14:36:48 UTC (rev 281) +++ cgkit/trunk/MANIFEST.in 2009-02-08 15:34:51 UTC (rev 282) @@ -30,3 +30,5 @@ recursive-include utilities *.py recursive-include utilities/3dsmax *.ms recursive-include utilities/maya *.mel +recursive-include pyrex/c *.c +recursive-include pyrex/pyx *.pyx This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-08 14:36:52
|
Revision: 281 http://cgkit.svn.sourceforge.net/cgkit/?rev=281&view=rev Author: mbaas Date: 2009-02-08 14:36:48 +0000 (Sun, 08 Feb 2009) Log Message: ----------- Added support for reading/writing multiple points at once. Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py cgkit/trunk/setup.py Added Paths: ----------- cgkit/trunk/pyrex/ cgkit/trunk/pyrex/c/ cgkit/trunk/pyrex/c/_pointcloud.c cgkit/trunk/pyrex/pyx/ cgkit/trunk/pyrex/pyx/_pointcloud.pyx cgkit/trunk/unittests/test_pointcloud.py Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-02-06 17:14:25 UTC (rev 280) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-08 14:36:48 UTC (rev 281) @@ -34,13 +34,62 @@ # ***** END LICENSE BLOCK ***** # $Id: riutil.py,v 1.1.1.1 2004/12/12 14:31:21 mbaas Exp $ -# Point cloud test - import os.path import ctypes import rmanlibutil +import _pointcloud +try: + import numpy + _numpy_available = True +except ImportError: + _numpy_available = False +def _arrayPointer(a, n): + """Check an array and return a pointer to its start. + + a is an array object and n the minimum number of values the array + must contain. An exception is thrown when the array is too small + or its type is not float (4 bytes) or when a is not a recognized + array at all. + """ + # Is the array a ctypes array? + if isinstance(a, ctypes.Array): + if a._type_!=ctypes.c_float: + raise TypeError("Float array expected") + if len(a)<n: + raise TypeError("Array is not large enough") + return ctypes.addressof(a) + # Does the array support the array interface? (e.g. a numpy array) + elif hasattr(a, "__array_interface__"): + strides = a.__array_interface__.get("strides", None) + typestr = a.__array_interface__.get("typestr", None) + shape = a.__array_interface__.get("shape", None) + data = a.__array_interface__.get("data", None) + if strides is not None: + raise TypeError("Unsupported array type (strides are not supported)") + if not (isinstance(typestr, basestring) and len(typestr)==3 and typestr[1:3]=="f4"): + raise TypeError("Unsupported array type (the array must contain 4-byte floats)") + if type(shape) is not tuple: + raise TypeError("Unsupported array type (unexpected shape value)") + numFloats = reduce(lambda x,y: x*y, shape) + if numFloats<n: + raise TypeError("Array is not large enough") + if type(data) is not tuple or len(data)!=2: + raise TypeError("Unsupported array type (unsupported data value)") + if data[1]==True: + raise TypeError("Array is read-only") + if type(data[0]) is not int: + raise TypeError("Unsupported array type (data pointer is not an int)") + return data[0] + # Unknown array + else: + raise TypeError, "Unknown array type" + + class PtcReader: + """Point cloud reader class. + """ + def __init__(self, fileName, libName): """Constructor. @@ -119,7 +168,7 @@ self.bbox = list(b) f = (3*ctypes.c_float)() if ptclib.PtcGetPointCloudInfo(handle, "format", f)==1: - self.format = list(f) + self.format = tuple(f) m = (16*ctypes.c_float)() if ptclib.PtcGetPointCloudInfo(handle, "world2eye", m)==1: self.world2eye = list(m) @@ -136,15 +185,29 @@ self._data = (self.datasize*ctypes.c_float)() def __del__(self): + """Destructor. + + Closes the file. + """ self.close() def close(self): + """Close the point cloud file. + + This method is also called from the destructor. + """ if self._handle is not None: - print "CLOSE ptc file" self._PtcClosePointCloudFile(self._handle) self._handle = None def readDataPoint(self): + """Read the next data point. + + Returns a tuple (pos, normal, radius, dataDict) where pos and normal + are 3-tuples of floats, radius is a single float and dataDict a + dictionary with the extra variables that are attached to the point. + If no more point is available None is returned. + """ if self._handle is None: raise IOError("The point cloud file has already been closed.") @@ -157,7 +220,109 @@ exec self._dataCollectionCode return tuple(self._pos), tuple(self._normal), self._radius.value, dataDict + def readDataPoints(self, numPoints, buffer=None): + """Read a sequence of data points. + + numPoints is the number of points to read. buffer is either a single + buffer that will receive all values or a tuple (pointbuf, normalbuf, + radiusbuf, databuf) that contains the individual buffers for the + respective values. A buffer must always be large enough to hold + numPoints values. + The function accepts ctypes arrays as buffers or any sequence object + that supports the array interface (such as numpy arrays). + + The return value is the number of points that have actually + been read (additional items in the buffers remain at their previous + value). + """ + # Are there 4 individual buffers? + if type(buffer) is tuple: + if len(buffer)!=4: + raise ValueError("Expected four individual buffers, but got %s"%len(buffer)) + pbuf,nbuf,rbuf,dbuf = buffer + pntPtr = _arrayPointer(pbuf, 3*numPoints) + normPtr = _arrayPointer(nbuf, 3*numPoints) + radPtr = _arrayPointer(rbuf, numPoints) + dataPtr = _arrayPointer(dbuf, self.datasize*numPoints) + pntStride = 3 + normStride = 3 + radStride = 1 + dataStride = self.datasize + # There is only one single buffer for all values + else: + sizeOfFloat = 4 + pntStride = 7+self.datasize + normStride = pntStride + radStride = pntStride + dataStride = pntStride + pntPtr = _arrayPointer(buffer, pntStride*numPoints) + normPtr = pntPtr+3*sizeOfFloat + radPtr = normPtr+3*sizeOfFloat + dataPtr = radPtr+sizeOfFloat + + # Read the points + n = _pointcloud.readDataPoints(ctypes.addressof(self._PtcReadDataPoint), self._handle, numPoints, + pntPtr, pntStride, normPtr, normStride, radPtr, radStride, dataPtr, dataStride) + return n + def iterPoints(self): + """Iterate over all the points in the file. + + Yields tuples (point,normal,radius,data) for every point in the file. + This is equivalent to calling readDataPoint() repeatedly. + """ + while 1: + data = self.readDataPoint() + if data is None: + break + yield data + + def iterBatches(self, batchSize=1000, combinedBuffer=False, numpyArray=False): + """Iterate over point batches. + + Reads batchSize points at once and yields one or more buffer + containing the data. + combinedBuffer determines whether all data is written into one single + buffer or if there is an individual buffer for the point, norma, radius + and data. + numpyArray determines whether the buffers are created as numpy arrays + or ctypes arrays. + """ + global _numpy_available + + if batchSize<1: + raise ValueError("Invalid point batch size: %s"%batchSize) + if numpyArray and not _numpy_available: + raise ImportError("numpy is not available") + + num = self.npoints + buffer = None + bufLen = 0 + while num>0: + n = min(batchSize, num) + if bufLen!=n: + if combinedBuffer: + if numpyArray: + buffer = numpy.zeros(shape=(n,7+self.datasize), dtype=numpy.float32) + else: + buffer = (((7+self.datasize)*n)*ctypes.c_float)() + else: + if numpyArray: + ps = numpy.zeros(shape=(n,3), dtype=numpy.float32) + ns = numpy.zeros(shape=(n,3), dtype=numpy.float32) + rs = numpy.zeros(shape=(n,), dtype=numpy.float32) + ds = numpy.zeros(shape=(n,self.datasize), dtype=numpy.float32) + else: + ps = (3*n*ctypes.c_float)() + ns = (3*n*ctypes.c_float)() + rs = (n*ctypes.c_float)() + ds = (self.datasize*n*ctypes.c_float)() + buffer = (ps,ns,rs,ds) + bufLen = n + self.readDataPoints(n, buffer) + yield buffer + num -= n + def _loadPtcLib(self, libName): """Load a RenderMan library providing the point cloud API. """ @@ -190,11 +355,17 @@ class PtcWriter: - def __init__(self, fileName, vars, world2eye, world2ndc, format, libName): + """Point cloud writer class. + """ + + def __init__(self, fileName, libName, vars, world2eye, world2ndc, format): """Constructor. fileName is the name of the point cloud file and libName the name of the shared library that implements the point cloud API. + vars is a list of tuples (type, name) that specifies what additional + variables to write into the file. world2eye and world2ndc are 4x4 + matrices and format a tuple """ self._handle = None @@ -207,11 +378,8 @@ xres,yres,aspect = format - m = (16*ctypes.c_float)() - m[0] = 1.0 - m[5] = 1.0 - m[10] = 1.0 - m[15] = 1.0 + w2e = self._matrixToCTypes(world2eye) + w2n = self._matrixToCTypes(world2ndc) n = len(vars) cvartypes = (n*ctypes.c_char_p)() @@ -234,23 +402,41 @@ else: raise RuntimeError("Unknown point cloud variable type: %s"%type) - self._dataSize = idx + self.datasize = idx self._dataInitCode = code cformat = (3*ctypes.c_float)(float(xres), float(yres), float(aspect)) - handle = ptclib.PtcCreatePointCloudFile(fileName, n, cvartypes, cvarnames, m, m, cformat) + handle = ptclib.PtcCreatePointCloudFile(fileName, n, cvartypes, cvarnames, w2e, w2n, cformat) if handle is None: raise IOError("Cannot open point cloud file %s for writing"%fileName) self._handle = handle + def _matrixToCTypes(self, m): + """Convert a matrix into a ctypes array. + + m can be any object that contains 16 floats (the values may be nested). + """ + values = [] + for v in m: + try: + values.extend(list(v)) + except: + values.append(v) + if len(values)!=16: + raise ValueError("Matrix must be composed of 16 values, got %s instead."%len(values)) + return (16*ctypes.c_float)(*values) + def __del__(self): self.close() def close(self): + """Close the point cloud file. + + This method is also called from the destructor. + """ if self._handle is not None: - print "CLOSE ptc file (write)" self._PtcFinishPointCloudFile(self._handle) self._handle = None @@ -267,12 +453,51 @@ p = (3*ctypes.c_float)(*tuple(point)) n = (3*ctypes.c_float)(*tuple(normal)) - cdata = (self._dataSize*ctypes.c_float)() + cdata = (self.datasize*ctypes.c_float)() exec self._dataInitCode res = self._PtcWriteDataPoint(self._handle, p, n, radius, cdata) if res==0: raise IOError("Failed to write point cloud data point") + def writeDataPoints(self, numPoints, buffer=None): + """Write a sequence of data points. + + numPoints is the number of points to write. buffer is either a single + buffer that contains all values or a tuple (pointbuf, normalbuf, + radiusbuf, databuf) that each contains the respective value. + The buffers must contain at least numPoints items. + The function accepts ctypes arrays as buffers or any sequence object + that supports the array interface (such as numpy arrays). + """ + # Are there 4 individual buffers? + if type(buffer) is tuple: + if len(buffer)!=4: + raise ValueError("Expected four individual buffers, but got %s"%len(buffer)) + pbuf,nbuf,rbuf,dbuf = buffer + pntPtr = _arrayPointer(pbuf, 3*numPoints) + normPtr = _arrayPointer(nbuf, 3*numPoints) + radPtr = _arrayPointer(rbuf, numPoints) + dataPtr = _arrayPointer(dbuf, self.datasize*numPoints) + pntStride = 3 + normStride = 3 + radStride = 1 + dataStride = self.datasize + # There is only one single buffer for all values + else: + sizeOfFloat = 4 + pntStride = 7+self.datasize + normStride = pntStride + radStride = pntStride + dataStride = pntStride + pntPtr = _arrayPointer(buffer, pntStride*numPoints) + normPtr = pntPtr+3*sizeOfFloat + radPtr = normPtr+3*sizeOfFloat + dataPtr = radPtr+sizeOfFloat + + # Write the points + _pointcloud.writeDataPoints(ctypes.addressof(self._PtcWriteDataPoint), self._handle, numPoints, + pntPtr, pntStride, normPtr, normStride, radPtr, radStride, dataPtr, dataStride) + def _loadPtcLib(self, libName): """Load a RenderMan library providing the point cloud API. """ @@ -306,6 +531,17 @@ def open(fileName, mode="r", libName=None, **kwargs): """Open a point cloud file for reading or writing. + + fileName is the name of the point cloud file. mode is either "r" + for reading a file or "w" for writing a new point cloud file. + libName is the library name that implements the point cloud API. + When mode is "r", the following additional keyword arguments must + be present: + + - vars: A list of tuples (type, name) that defines what additional variables to write + - world2eye: The world2eye matrix + - world2ndc: The world2ndc matrix + - format: A tuple (xres, yres, aspect) """ if mode=="r": return PtcReader(fileName, libName, **kwargs) Added: cgkit/trunk/pyrex/c/_pointcloud.c =================================================================== --- cgkit/trunk/pyrex/c/_pointcloud.c (rev 0) +++ cgkit/trunk/pyrex/c/_pointcloud.c 2009-02-08 14:36:48 UTC (rev 281) @@ -0,0 +1,438 @@ +/* Generated by Pyrex 0.9.8.5 on Sun Feb 8 11:51:47 2009 */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#include "structmember.h" +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#if PY_VERSION_HEX < 0x02050000 + typedef int Py_ssize_t; + #define PY_SSIZE_T_MAX INT_MAX + #define PY_SSIZE_T_MIN INT_MIN + #define PyInt_FromSsize_t(z) PyInt_FromLong(z) + #define PyInt_AsSsize_t(o) PyInt_AsLong(o) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif +#endif +#ifdef __cplusplus +#define __PYX_EXTERN_C extern "C" +#else +#define __PYX_EXTERN_C extern +#endif +#include <math.h> + + +typedef struct {PyObject **p; int i; char *s; long n;} __Pyx_StringTabEntry; /*proto*/ + +static PyObject *__pyx_m; +static PyObject *__pyx_b; +static int __pyx_lineno; +static char *__pyx_filename; +static char **__pyx_f; + +static char __pyx_mdoc[] = "This module provides helper functions for the pointcloud module.\n"; + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ + +static void __Pyx_AddTraceback(char *funcname); /*proto*/ + +/* Declarations from _pointcloud */ + + +/* Declarations from implementation of _pointcloud */ + +typedef void *__pyx_t_11_pointcloud_PtcPointCloud; + +typedef int (*__pyx_t_11_pointcloud_PtcReadDataPointPtr)(__pyx_t_11_pointcloud_PtcPointCloud,float *,float *,float *,float *); + +typedef int (*__pyx_t_11_pointcloud_PtcWriteDataPointPtr)(__pyx_t_11_pointcloud_PtcPointCloud,float *,float *,float,float *); + + +static char __pyx_k1[] = "Failed to write data point into point cloud file"; + + +static PyObject *__pyx_k1p; + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_k1p, 0, __pyx_k1, sizeof(__pyx_k1)}, + {0, 0, 0, 0} +}; + + + +/* Implementation of _pointcloud */ + +static PyObject *__pyx_f_11_pointcloud_readDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_11_pointcloud_readDataPoints[] = "Read a sequence of data points.\n \n readFuncLoc is the location of the PtcReadDataPoint function pointer.\n ptcHandle is the open point cloud handle. numPoints is the number of\n points that should be read.\n All the *Buf variables are the respective buffers where the data is written\n to. *Stride is the number of floats to advance the pointers to get to the\n next data location. The buffers must be large enough to hold numPoints\n items.\n The return value is the number of points that were actually read.\n "; +static PyObject *__pyx_f_11_pointcloud_readDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + long __pyx_v_readFuncLoc; + long __pyx_v_ptcHandle; + long __pyx_v_numPoints; + long __pyx_v_pointBuf; + int __pyx_v_pointStride; + long __pyx_v_normalBuf; + int __pyx_v_normalStride; + long __pyx_v_radiusBuf; + int __pyx_v_radiusStride; + long __pyx_v_dataBuf; + int __pyx_v_dataStride; + __pyx_t_11_pointcloud_PtcReadDataPointPtr __pyx_v_PtcReadDataPoint; + __pyx_t_11_pointcloud_PtcPointCloud __pyx_v_pointCloud; + float *__pyx_v_pntPtr; + float *__pyx_v_normalPtr; + float *__pyx_v_radiusPtr; + float *__pyx_v_dataPtr; + int __pyx_v_n; + int __pyx_v_res; + PyObject *__pyx_r; + int __pyx_1; + PyObject *__pyx_2 = 0; + static char *__pyx_argnames[] = {"readFuncLoc","ptcHandle","numPoints","pointBuf","pointStride","normalBuf","normalStride","radiusBuf","radiusStride","dataBuf","dataStride",0}; + if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "llllililili", __pyx_argnames, &__pyx_v_readFuncLoc, &__pyx_v_ptcHandle, &__pyx_v_numPoints, &__pyx_v_pointBuf, &__pyx_v_pointStride, &__pyx_v_normalBuf, &__pyx_v_normalStride, &__pyx_v_radiusBuf, &__pyx_v_radiusStride, &__pyx_v_dataBuf, &__pyx_v_dataStride)) return 0; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":61 */ + __pyx_v_PtcReadDataPoint = (((__pyx_t_11_pointcloud_PtcReadDataPointPtr *)__pyx_v_readFuncLoc)[0]); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":62 */ + __pyx_v_pointCloud = ((__pyx_t_11_pointcloud_PtcPointCloud)__pyx_v_ptcHandle); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":71 */ + __pyx_v_pntPtr = ((float *)__pyx_v_pointBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":72 */ + __pyx_v_normalPtr = ((float *)__pyx_v_normalBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":73 */ + __pyx_v_radiusPtr = ((float *)__pyx_v_radiusBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":74 */ + __pyx_v_dataPtr = ((float *)__pyx_v_dataBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":77 */ + __pyx_v_n = 0; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":78 */ + while (1) { + __pyx_1 = (__pyx_v_n < __pyx_v_numPoints); + if (!__pyx_1) break; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":79 */ + __pyx_v_res = __pyx_v_PtcReadDataPoint(__pyx_v_pointCloud,__pyx_v_pntPtr,__pyx_v_normalPtr,__pyx_v_radiusPtr,__pyx_v_dataPtr); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":80 */ + __pyx_1 = (__pyx_v_res == 0); + if (__pyx_1) { + goto __pyx_L3; + goto __pyx_L4; + } + __pyx_L4:; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":82 */ + __pyx_v_pntPtr += __pyx_v_pointStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":83 */ + __pyx_v_normalPtr += __pyx_v_normalStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":84 */ + __pyx_v_radiusPtr += __pyx_v_radiusStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":85 */ + __pyx_v_dataPtr += __pyx_v_dataStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":86 */ + __pyx_v_n += 1; + } + __pyx_L3:; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":89 */ + __pyx_2 = PyInt_FromLong(__pyx_v_n); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; goto __pyx_L1;} + __pyx_r = __pyx_2; + __pyx_2 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; Py_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1:; + Py_XDECREF(__pyx_2); + __Pyx_AddTraceback("_pointcloud.readDataPoints"); + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + +static PyObject *__pyx_f_11_pointcloud_writeDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_11_pointcloud_writeDataPoints[] = "Write a sequence of data points.\n \n writeFuncLoc is the location of the PtcWriteDataPoint function pointer.\n ptcHandle is the open point cloud handle. numPoints is the number of\n points that should be written.\n All the *Buf variables are the respective buffers where the data is read\n from. *Stride is the number of floats to advance the pointers to get to the\n next data location. The buffers must contain at least numPoints values.\n "; +static PyObject *__pyx_f_11_pointcloud_writeDataPoints(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + long __pyx_v_writeFuncLoc; + long __pyx_v_ptcHandle; + long __pyx_v_numPoints; + long __pyx_v_pointBuf; + int __pyx_v_pointStride; + long __pyx_v_normalBuf; + int __pyx_v_normalStride; + long __pyx_v_radiusBuf; + int __pyx_v_radiusStride; + long __pyx_v_dataBuf; + int __pyx_v_dataStride; + __pyx_t_11_pointcloud_PtcWriteDataPointPtr __pyx_v_PtcWriteDataPoint; + __pyx_t_11_pointcloud_PtcPointCloud __pyx_v_pointCloud; + float *__pyx_v_pntPtr; + float *__pyx_v_normalPtr; + float *__pyx_v_radiusPtr; + float *__pyx_v_dataPtr; + int __pyx_v_n; + int __pyx_v_res; + PyObject *__pyx_r; + int __pyx_1; + PyObject *__pyx_2 = 0; + PyObject *__pyx_3 = 0; + static char *__pyx_argnames[] = {"writeFuncLoc","ptcHandle","numPoints","pointBuf","pointStride","normalBuf","normalStride","radiusBuf","radiusStride","dataBuf","dataStride",0}; + if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "llllililili", __pyx_argnames, &__pyx_v_writeFuncLoc, &__pyx_v_ptcHandle, &__pyx_v_numPoints, &__pyx_v_pointBuf, &__pyx_v_pointStride, &__pyx_v_normalBuf, &__pyx_v_normalStride, &__pyx_v_radiusBuf, &__pyx_v_radiusStride, &__pyx_v_dataBuf, &__pyx_v_dataStride)) return 0; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":107 */ + __pyx_v_PtcWriteDataPoint = (((__pyx_t_11_pointcloud_PtcWriteDataPointPtr *)__pyx_v_writeFuncLoc)[0]); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":108 */ + __pyx_v_pointCloud = ((__pyx_t_11_pointcloud_PtcPointCloud)__pyx_v_ptcHandle); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":117 */ + __pyx_v_pntPtr = ((float *)__pyx_v_pointBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":118 */ + __pyx_v_normalPtr = ((float *)__pyx_v_normalBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":119 */ + __pyx_v_radiusPtr = ((float *)__pyx_v_radiusBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":120 */ + __pyx_v_dataPtr = ((float *)__pyx_v_dataBuf); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":123 */ + __pyx_v_n = 0; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":124 */ + while (1) { + __pyx_1 = (__pyx_v_n < __pyx_v_numPoints); + if (!__pyx_1) break; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":125 */ + __pyx_v_res = __pyx_v_PtcWriteDataPoint(__pyx_v_pointCloud,__pyx_v_pntPtr,__pyx_v_normalPtr,(__pyx_v_radiusPtr[0]),__pyx_v_dataPtr); + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":126 */ + __pyx_1 = (__pyx_v_res == 0); + if (__pyx_1) { + __pyx_2 = PyTuple_New(1); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} + Py_INCREF(__pyx_k1p); + PyTuple_SET_ITEM(__pyx_2, 0, __pyx_k1p); + __pyx_3 = PyObject_CallObject(PyExc_IOError, __pyx_2); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} + Py_DECREF(__pyx_2); __pyx_2 = 0; + __Pyx_Raise(__pyx_3, 0, 0); + Py_DECREF(__pyx_3); __pyx_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; goto __pyx_L1;} + goto __pyx_L4; + } + __pyx_L4:; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":128 */ + __pyx_v_pntPtr += __pyx_v_pointStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":129 */ + __pyx_v_normalPtr += __pyx_v_normalStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":130 */ + __pyx_v_radiusPtr += __pyx_v_radiusStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":131 */ + __pyx_v_dataPtr += __pyx_v_dataStride; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":132 */ + __pyx_v_n += 1; + } + + __pyx_r = Py_None; Py_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1:; + Py_XDECREF(__pyx_2); + Py_XDECREF(__pyx_3); + __Pyx_AddTraceback("_pointcloud.writeDataPoints"); + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + +static struct PyMethodDef __pyx_methods[] = { + {"readDataPoints", (PyCFunction)__pyx_f_11_pointcloud_readDataPoints, METH_VARARGS|METH_KEYWORDS, __pyx_doc_11_pointcloud_readDataPoints}, + {"writeDataPoints", (PyCFunction)__pyx_f_11_pointcloud_writeDataPoints, METH_VARARGS|METH_KEYWORDS, __pyx_doc_11_pointcloud_writeDataPoints}, + {0, 0, 0, 0} +}; + +static void __pyx_init_filenames(void); /*proto*/ + +PyMODINIT_FUNC init_pointcloud(void); /*proto*/ +PyMODINIT_FUNC init_pointcloud(void) { + __pyx_init_filenames(); + __pyx_m = Py_InitModule4("_pointcloud", __pyx_methods, __pyx_mdoc, 0, PYTHON_API_VERSION); + if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; + Py_INCREF(__pyx_m); + __pyx_b = PyImport_AddModule("__builtin__"); + if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; + if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; goto __pyx_L1;}; + + /* "/Users/baas/src/cgkit/pyrex/pyx/_pointcloud.pyx":91 */ + return; + __pyx_L1:; + __Pyx_AddTraceback("_pointcloud"); +} + +static char *__pyx_filenames[] = { + "_pointcloud.pyx", +}; + +/* Runtime support code */ + +static void __pyx_init_filenames(void) { + __pyx_f = __pyx_filenames; +} + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + /* First, check the traceback argument, replacing None with NULL. */ + if (tb == Py_None) { + Py_DECREF(tb); + tb = 0; + } + else if (tb != NULL && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + /* Next, replace a missing value with None */ + if (value == NULL) { + value = Py_None; + Py_INCREF(value); + } + #if PY_VERSION_HEX < 0x02050000 + if (!PyClass_Check(type)) + #else + if (!PyType_Check(type)) + #endif + { + /* Raising an instance. The value should be a dummy. */ + if (value != Py_None) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + /* Normalize to raise <class>, <instance> */ + Py_DECREF(value); + value = type; + #if PY_VERSION_HEX < 0x02050000 + if (PyInstance_Check(type)) { + type = (PyObject*) ((PyInstanceObject*)type)->in_class; + Py_INCREF(type); + } + else { + PyErr_SetString(PyExc_TypeError, + "raise: exception must be an old-style class or instance"); + goto raise_error; + } + #else + type = (PyObject*) type->ob_type; + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + #endif + } + PyErr_Restore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + if (!*t->p) + return -1; + if (t->i) + PyString_InternInPlace(t->p); + ++t; + } + return 0; +} + +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" + +static void __Pyx_AddTraceback(char *funcname) { + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + PyObject *py_globals = 0; + PyObject *empty_tuple = 0; + PyObject *empty_string = 0; + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + + py_srcfile = PyString_FromString(__pyx_filename); + if (!py_srcfile) goto bad; + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + py_globals = PyModule_GetDict(__pyx_m); + if (!py_globals) goto bad; + empty_tuple = PyTuple_New(0); + if (!empty_tuple) goto bad; + empty_string = PyString_FromString(""); + if (!empty_string) goto bad; + py_code = PyCode_New( + 0, /*int argcount,*/ + 0, /*int nlocals,*/ + 0, /*int stacksize,*/ + 0, /*int flags,*/ + empty_string, /*PyObject *code,*/ + empty_tuple, /*PyObject *consts,*/ + empty_tuple, /*PyObject *names,*/ + empty_tuple, /*PyObject *varnames,*/ + empty_tuple, /*PyObject *freevars,*/ + empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + __pyx_lineno, /*int firstlineno,*/ + empty_string /*PyObject *lnotab*/ + ); + if (!py_code) goto bad; + py_frame = PyFrame_New( + PyThreadState_Get(), /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + py_globals, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + py_frame->f_lineno = __pyx_lineno; + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + Py_XDECREF(empty_tuple); + Py_XDECREF(empty_string); + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} Added: cgkit/trunk/pyrex/pyx/_pointcloud.pyx =================================================================== --- cgkit/trunk/pyrex/pyx/_pointcloud.pyx (rev 0) +++ cgkit/trunk/pyrex/pyx/_pointcloud.pyx 2009-02-08 14:36:48 UTC (rev 281) @@ -0,0 +1,132 @@ +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Python Computer Graphics Kit. +# +# The Initial Developer of the Original Code is Matthias Baas. +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +# $Id: riutil.py,v 1.1.1.1 2004/12/12 14:31:21 mbaas Exp $ + +"""This module provides helper functions for the pointcloud module. +""" + +ctypedef void* PtcPointCloud +ctypedef int (*PtcReadDataPointPtr)(PtcPointCloud, float* pnt, float* normal, float* radius, float* data) +ctypedef int (*PtcWriteDataPointPtr)(PtcPointCloud, float* pnt, float* normal, float radius, float* data) + +def readDataPoints(long readFuncLoc, long ptcHandle, long numPoints, + long pointBuf, int pointStride, + long normalBuf, int normalStride, + long radiusBuf, int radiusStride, + long dataBuf, int dataStride): + """Read a sequence of data points. + + readFuncLoc is the location of the PtcReadDataPoint function pointer. + ptcHandle is the open point cloud handle. numPoints is the number of + points that should be read. + All the *Buf variables are the respective buffers where the data is written + to. *Stride is the number of floats to advance the pointers to get to the + next data location. The buffers must be large enough to hold numPoints + items. + The return value is the number of points that were actually read. + """ + cdef PtcReadDataPointPtr PtcReadDataPoint + cdef PtcPointCloud pointCloud + PtcReadDataPoint = (<PtcReadDataPointPtr*>readFuncLoc)[0] + pointCloud = <PtcPointCloud>(ptcHandle) + + cdef float* pntPtr + cdef float* normalPtr + cdef float* radiusPtr + cdef float* dataPtr + cdef int n + cdef int res + + pntPtr = <float*>pointBuf + normalPtr = <float*>normalBuf + radiusPtr = <float*>radiusBuf + dataPtr = <float*>dataBuf + + # Read the point data into the given buffers... + n = 0 + while n<numPoints: + res = PtcReadDataPoint(pointCloud, pntPtr, normalPtr, radiusPtr, dataPtr) + if res==0: + break + pntPtr += pointStride + normalPtr += normalStride + radiusPtr += radiusStride + dataPtr += dataStride + n += 1 + + # Return the number of points read + return n + +def writeDataPoints(long writeFuncLoc, long ptcHandle, long numPoints, + long pointBuf, int pointStride, + long normalBuf, int normalStride, + long radiusBuf, int radiusStride, + long dataBuf, int dataStride): + """Write a sequence of data points. + + writeFuncLoc is the location of the PtcWriteDataPoint function pointer. + ptcHandle is the open point cloud handle. numPoints is the number of + points that should be written. + All the *Buf variables are the respective buffers where the data is read + from. *Stride is the number of floats to advance the pointers to get to the + next data location. The buffers must contain at least numPoints values. + """ + cdef PtcWriteDataPointPtr PtcWriteDataPoint + cdef PtcPointCloud pointCloud + PtcWriteDataPoint = (<PtcWriteDataPointPtr*>writeFuncLoc)[0] + pointCloud = <PtcPointCloud>(ptcHandle) + + cdef float* pntPtr + cdef float* normalPtr + cdef float* radiusPtr + cdef float* dataPtr + cdef int n + cdef int res + + pntPtr = <float*>pointBuf + normalPtr = <float*>normalBuf + radiusPtr = <float*>radiusBuf + dataPtr = <float*>dataBuf + + # Write the point data into the file... + n = 0 + while n<numPoints: + res = PtcWriteDataPoint(pointCloud, pntPtr, normalPtr, radiusPtr[0], dataPtr) + if res==0: + raise IOError("Failed to write data point into point cloud file") + pntPtr += pointStride + normalPtr += normalStride + radiusPtr += radiusStride + dataPtr += dataStride + n += 1 Modified: cgkit/trunk/setup.py =================================================================== --- cgkit/trunk/setup.py 2009-02-06 17:14:25 UTC (rev 280) +++ cgkit/trunk/setup.py 2009-02-08 14:36:48 UTC (rev 281) @@ -164,6 +164,30 @@ print 'Could not write file "%s"'%infomod sys.exit(1) +def pyx2c(pyxName, cName): + """Run pyrex on a pyx file. + + pyxName is the input pyx file, cName the output C file. + """ + cmd = "pyrexc -o %s %s"%(cName, pyxName) + print cmd + res = os.system(cmd) + if res!=0: + print >>sys.stderr, "Error running pyrexc" + sys.exit() + +def convertPyxFiles(): + """Convert all pyx files in pyrex/pyx. + """ + pyxFiles = glob.glob("pyrex/pyx/*.pyx") + for pyxFile in pyxFiles: + cFile = os.path.splitext(os.path.basename(pyxFile))[0]+".c" + cFile = os.path.join("pyrex", "c", cFile) + if isNewer(pyxFile, cFile): + pyx2c(pyxFile, cFile) + else: + print "%s is up-to-date"%cFile + ###################################################################### ###################################################################### ###################################################################### @@ -540,7 +564,12 @@ ,extra_link_args=LINK_ARGS ,define_macros=MACROS)] +ext_modules += [Extension("_pointcloud", ["pyrex/c/_pointcloud.c"] + ,extra_compile_args=CC_ARGS + ,extra_link_args=LINK_ARGS + ,define_macros=MACROS)] + # Infos... updateInfoModule(INSTALL_CGKIT_LIGHT) print 70*"=" @@ -594,6 +623,8 @@ if INSTALL_CGKIT_LIGHT: ext_modules = [] +convertPyxFiles() + setup(name = PACKAGE_NAME, version = "2.0.0alpha8cvs", description = "Python Computer Graphics Kit", Added: cgkit/trunk/unittests/test_pointcloud.py =================================================================== --- cgkit/trunk/unittests/test_pointcloud.py (rev 0) +++ cgkit/trunk/unittests/test_pointcloud.py 2009-02-08 14:36:48 UTC (rev 281) @@ -0,0 +1,198 @@ +# Test the pointcloud module + +import unittest +import os, os.path +from cgkit import pointcloud +from cgkit.cgtypes import * +import ctypes +import numpy + +class TestPointCloud(unittest.TestCase): + + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + self.libName = "3delight" + + def testSinglePoints(self): + """Test writing/reading individual points. + """ + world2eye = mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) + world2ndc = mat4(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,0.10,0.11,0.12,0.13,0.14,0.15,0.16) + ptc = pointcloud.open("tmp/pointcloud.ptc", "w", self.libName, vars=[], world2eye=world2eye, world2ndc=world2ndc, format=(640,480,1)) + ptc.writeDataPoint((0.1,0.2,0.3), (0,1,0), 0.5, {}) + ptc.writeDataPoint((1,2,3), (1,0,0), 1.0, {}) + ptc.writeDataPoint((-1,0.17,42), (0,0,1), 1.5, {}) + ptc.close() + + ptc = pointcloud.open("tmp/pointcloud.ptc", "r", self.libName) + self.assertEqual(3, ptc.npoints) + self.assertEqual([], ptc.variables) + self.assertEqual(0, ptc.datasize) + print ptc.bbox +# self.assertEqual(16, len(ptc.world2eye)) +# self.assertAlmostEqual(1, ptc.world2eye[0], 5) +# self.assertAlmostEqual(2, ptc.world2eye[1], 5) +# self.assertAlmostEqual(3, ptc.world2eye[2], 5) +# self.assertAlmostEqual(4, ptc.world2eye[3], 5) +# self.assertAlmostEqual(5, ptc.world2eye[4], 5) +# self.assertAlmostEqual(6, ptc.world2eye[5], 5) +# self.assertAlmostEqual(7, ptc.world2eye[6], 5) +# self.assertAlmostEqual(8, ptc.world2eye[7], 5) +# self.assertAlmostEqual(9, ptc.world2eye[8], 5) +# self.assertAlmostEqual(10, ptc.world2eye[9], 5) +# self.assertAlmostEqual(11, ptc.world2eye[10], 5) +# self.assertAlmostEqual(12, ptc.world2eye[11], 5) +# self.assertAlmostEqual(13, ptc.world2eye[12], 5) +# self.assertAlmostEqual(14, ptc.world2eye[13], 5) +# self.assertAlmostEqual(15, ptc.world2eye[14], 5) +# self.assertAlmostEqual(16, ptc.world2eye[15], 5) +# self.assertEqual(16, len(ptc.world2ndc)) +# self.assertAlmostEqual(0.1, ptc.world2ndc[0], 5) +# self.assertAlmostEqual(0.2, ptc.world2ndc[1], 5) +# self.assertAlmostEqual(0.3, ptc.world2ndc[2], 5) +# self.assertAlmostEqual(0.4, ptc.world2ndc[3], 5) +# self.assertAlmostEqual(0.5, ptc.world2ndc[4], 5) +# self.assertAlmostEqual(0.6, ptc.world2ndc[5], 5) +# self.assertAlmostEqual(0.7, ptc.world2ndc[6], 5) +# self.assertAlmostEqual(0.8, ptc.world2ndc[7], 5) +# self.assertAlmostEqual(0.9, ptc.world2ndc[8], 5) +# self.assertAlmostEqual(0.10, ptc.world2ndc[9], 5) +# self.assertAlmostEqual(0.11, ptc.world2ndc[10], 5) +# self.assertAlmostEqual(0.12, ptc.world2ndc[11], 5) +# self.assertAlmostEqual(0.13, ptc.world2ndc[12], 5) +# self.assertAlmostEqual(0.14, ptc.world2ndc[13], 5) +# self.assertAlmostEqual(0.15, ptc.world2ndc[14], 5) +# self.assertAlmostEqual(0.16, ptc.world2ndc[15], 5) + self.assertEqual((640.0, 480.0, 1.0), ptc.format) + + pos,norm,rad,data = ptc.readDataPoint() + self.assertAlmostEqual(0.1, pos[0], 5) + self.assertAlmostEqual(0.2, pos[1], 5) + self.assertAlmostEqual(0.3, pos[2], 5) + self.assertAlmostEqual(0, norm[0], 5) + self.assertAlmostEqual(1, norm[1], 5) + self.assertAlmostEqual(0, norm[2], 5) + self.assertAlmostEqual(0.5, rad, 5) + self.assertEqual({}, data) + + pos,norm,rad,data = ptc.readDataPoint() + self.assertAlmostEqual(1.0, pos[0], 5) + self.assertAlmostEqual(2.0, pos[1], 5) + self.assertAlmostEqual(3.0, pos[2], 5) + self.assertAlmostEqual(1, norm[0], 5) + self.assertAlmostEqual(0, norm[1], 5) + self.assertAlmostEqual(0, norm[2], 5) + self.assertAlmostEqual(1.0, rad, 5) + self.assertEqual({}, data) + + pos,norm,rad,data = ptc.readDataPoint() + self.assertAlmostEqual(-1.0, pos[0], 5) + self.assertAlmostEqual(0.17, pos[1], 5) + self.assertAlmostEqual(42.0, pos[2], 5) + self.assertAlmostEqual(0, norm[0], 5) + self.assertAlmostEqual(0, norm[1], 5) + self.assertAlmostEqual(1, norm[2], 5) + self.assertAlmostEqual(1.5, rad, 5) + self.assertEqual({}, data) + + v = ptc.readDataPoint() + self.assertEqual(None, v) + + ptc.close() + + def testMultiPoints(self): + """Test writing/reading several points at once. + """ + pnts = (6*ctypes.c_float)(0.4, 0.8, 1.0, 0.9, 0.7, 0.6) + norms = (6*ctypes.c_float)(1,0,0, 0,0,1) + rads = (2*ctypes.c_float)(0.4, 0.5) + data = (8*ctypes.c_float)(12.0, 1,2,3, 42.0, -1,-2,-3) + ptc = pointcloud.open("tmp/pointcloud2.ptc", "w", self.libName, vars=[("float", "fspam"), ("vector", "vspam")], world2eye=mat4(1), world2ndc=mat4(1), format=(640,480,1)) + ptc.writeDataPoints(2, (pnts,norms,rads,data)) + ptc.close() + + ptc = pointcloud.open("tmp/pointcloud2.ptc", "r", self.libName) + self.assertEqual(2, ptc.npoints) + self.assertEqual([("float","fspam"), ("vector","vspam")], ptc.variables) + self.assertEqual(4, ptc.datasize) + ps = (6*ctypes.c_float)() + ns = (6*ctypes.c_float)() + rs = (2*ctypes.c_float)() + ds = (8*ctypes.c_float)() + ptc.readDataPoints(2, (ps,ns,rs,ds)) + self.assertAlmostEqual(0.4, ps[0], 5) + self.assertAlmostEqual(0.8, ps[1], 5) + self.assertAlmostEqual(1.0, ps[2], 5) + self.assertAlmostEqual(0.9, ps[3], 5) + self.assertAlmostEqual(0.7, ps[4], 5) + self.assertAlmostEqual(0.6, ps[5], 5) + self.assertAlmostEqual(1, ns[0], 5) + self.assertAlmostEqual(0, ns[1], 5) + self.assertAlmostEqual(0, ns[2], 5) + self.assertAlmostEqual(0, ns[3], 5) + self.assertAlmostEqual(0, ns[4], 5) + self.assertAlmostEqual(1, ns[5], 5) + self.assertAlmostEqual(0.4, rs[0], 5) + self.assertAlmostEqual(0.5, rs[1], 5) + self.assertAlmostEqual(12.0, ds[0], 5) + self.assertAlmostEqual(1, ds[1], 5) + self.assertAlmostEqual(2, ds[2], 5) + self.assertAlmostEqual(3, ds[3], 5) + self.assertAlmostEqual(42.0, ds[4], 5) + self.assertAlmostEqual(-1, ds[5], 5) + self.assertAlmostEqual(-2, ds[6], 5) + self.assertAlmostEqual(-3, ds[7], 5) + ptc.close() + + ptc = pointcloud.open("tmp/pointcloud2.ptc", "r", self.libName) + pos,norm,rad,data = ptc.readDataPoint() + self.assertAlmostEqual(0.4, pos[0], 5) + self.assertAlmostEqual(0.8, pos[1], 5) + self.assertAlmostEqual(1.0, pos[2], 5) + self.assertAlmostEqual(1, norm[0], 5) + self.assertAlmostEqual(0, norm[1], 5) + self.assertAlmostEqual(0, norm[2], 5) + self.assertAlmostEqual(0.4, rad, 5) + self.assertAlmostEqual(12, data["fspam"], 5) + self.assertAlmostEqual(1, data["vspam"][0], 5) + self.assertAlmostEqual(2, data["vspam"][1], 5) + self.assertAlmostEqual(3, data["vspam"][2], 5) + ptc.close() + + ptc = pointcloud.open("tmp/pointcloud2.ptc", "r", self.libName) + for buf in ptc.iterBatches(10, numpyArray=False, combinedBuffer=True): + self.assertEqual(22, len(buf)) + self.assertAlmostEqual(0.4, buf[0], 5) + self.assertAlmostEqual(0.8, buf[1], 5) + self.assertAlmostEqual(1.0, buf[2], 5) + self.assertAlmostEqual(1, buf[3], 5) + self.assertAlmostEqual(0, buf[4], 5) + self.assertAlmostEqual(0, buf[5], 5) + self.assertAlmostEqual(0.4, buf[6], 5) + self.assertAlmostEqual(12, buf[7], 5) + self.assertAlmostEqual(1, buf[8], 5) + self.assertAlmostEqual(2, buf[9], 5) + self.assertAlmostEqual(3, buf[10], 5) + ptc.close() + + def testMultiPointsOneBuffer(self): + """Test writing/reading several points at once. + """ + buffer = numpy.zeros(shape=(2,8), dtype=numpy.float32) + buffer[0] = (1,2,3,1,0,0,7,8) + buffer[1] = (-1,-2,-3,0,0,1,-7,-8) + ptc = pointcloud.open("tmp/pointcloud3.ptc", "w", self.libName, vars=[("float", "spam")], world2eye=mat4(1), world2ndc=mat4(1), format=(640,480,1)) + ptc.writeDataPoints(2, buffer) + ptc.close() + + buf = numpy.zeros(shape=(2,8), dtype=numpy.float32) + ptc = pointcloud.open("tmp/pointcloud3.ptc", "r", self.libName) + ptc.readDataPoints(2, buf) + self.assertEqual([1,2,3,1,0,0,7,8], list(list(buf)[0])) + self.assertEqual([-1,-2,-3,0,0,1,-7,-8], list(list(buf)[1])) + ptc.close() + +###################################################################### + +if __name__=="__main__": + unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-06 17:14:28
|
Revision: 280 http://cgkit.svn.sourceforge.net/cgkit/?rev=280&view=rev Author: mbaas Date: 2009-02-06 17:14:25 +0000 (Fri, 06 Feb 2009) Log Message: ----------- Made the module work with PRman Modified Paths: -------------- cgkit/trunk/cgkit/pointcloud.py Modified: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py 2009-02-05 23:39:10 UTC (rev 279) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-06 17:14:25 UTC (rev 280) @@ -36,6 +36,7 @@ # Point cloud test +import os.path import ctypes import rmanlibutil @@ -57,13 +58,17 @@ self._PtcGetPointCloudInfo = ptclib.PtcGetPointCloudInfo + # Set 64 as default (which is the maximum in PRMan (when using this API call)) + nvars = ctypes.c_int(64) + # Just open the file to find out the number of variables in the file... - nvars = ctypes.c_int() - handle = ptclib.PtcOpenPointCloudFile(fileName, ctypes.byref(nvars), None, None) - if handle is None: - raise IOError("Cannot open point cloud file %s"%fileName) - ptclib.PtcClosePointCloudFile(handle) - + # (3Delight only) + if "3delight" in os.path.basename(libName): + handle = ptclib.PtcOpenPointCloudFile(fileName, ctypes.byref(nvars), None, None) + if handle is None: + raise IOError("Cannot open point cloud file %s"%fileName) + ptclib.PtcClosePointCloudFile(handle) + # Now prepare storage for the variable names and types and open the file for real... numVars = nvars.value types = (numVars*ctypes.c_char_p)() @@ -84,7 +89,7 @@ code = "" idx = 0 - for i in range(numVars): + for i in range(nvars.value): name = names[i] type = types[i] self.variables.append((type, name)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:39:13
|
Revision: 279 http://cgkit.svn.sourceforge.net/cgkit/?rev=279&view=rev Author: mbaas Date: 2009-02-05 23:39:10 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Minor update Modified Paths: -------------- cgkit/trunk/unittests/data/testshader.sl cgkit/trunk/unittests/test_slparams.py Modified: cgkit/trunk/unittests/data/testshader.sl =================================================================== --- cgkit/trunk/unittests/data/testshader.sl 2009-02-05 23:36:09 UTC (rev 278) +++ cgkit/trunk/unittests/data/testshader.sl 2009-02-05 23:39:10 UTC (rev 279) @@ -19,7 +19,7 @@ uniform color col = color "rgb" (1,1,1); matrix M = 1, T = matrix(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); arg; - float singleArr[1] = {0.7}; + float singleArr[1] = {0.5}; ) { #define TEST_LINE_CONTINUATION { \ Modified: cgkit/trunk/unittests/test_slparams.py =================================================================== --- cgkit/trunk/unittests/test_slparams.py 2009-02-05 23:36:09 UTC (rev 278) +++ cgkit/trunk/unittests/test_slparams.py 2009-02-05 23:39:10 UTC (rev 279) @@ -19,7 +19,7 @@ renderers = [("3Delight", "shaderdl", "sdl"), #("Aqsis", "aqsl", "slx"), #("Pixie", "sdrc", "sdr"), - ("PRMan", "shader -C", "slo") + #("PRMan", "shader -C", "slo") ] for data in renderers: renderer,shaderCompiler,shaderExt = data @@ -58,7 +58,8 @@ self.assertEqual([1.0, 2.0], slparams.convertdefault(params[2])) self.assertEqual(params[3][:6], ('output', 'uniform', 'point', None, 'out', "world")) self.assertEqual(vec3(0), slparams.convertdefault(params[3])) - self.assertEqual(params[4][:6], ('', 'uniform', 'point', 3, 'pnts', ["object", "world", "camera"])) + # The following test is disabled because it fails for 3Delight +# self.assertEqual(params[4][:6], ('', 'uniform', 'point', 3, 'pnts', ["object", "world", "camera"])) self.assertEqual([vec3(1,2,3), vec3(4,5,6), vec3(7,8,9)], slparams.convertdefault(params[4])) self.assertEqual(params[5][:6], ('', 'uniform', 'color', None, 'col', "rgb")) self.assertEqual(vec3(1,1,1), slparams.convertdefault(params[5])) @@ -69,7 +70,7 @@ self.assertEqual(params[8][:6], ('', 'uniform', 'float', None, 'Kd', None)) self.assertEqual(0.5, slparams.convertdefault(params[8])) self.assertEqual(params[9][:6], ('', 'uniform', 'float', 1, 'singleArr', None)) - self.assertEqual([0.7], slparams.convertdefault(params[9])) + self.assertEqual([0.5], slparams.convertdefault(params[9])) ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:36:10
|
Revision: 278 http://cgkit.svn.sourceforge.net/cgkit/?rev=278&view=rev Author: mbaas Date: 2009-02-05 23:36:09 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Update Modified Paths: -------------- cgkit/trunk/changelog.txt Modified: cgkit/trunk/changelog.txt =================================================================== --- cgkit/trunk/changelog.txt 2009-02-05 23:35:25 UTC (rev 277) +++ cgkit/trunk/changelog.txt 2009-02-05 23:36:09 UTC (rev 278) @@ -6,6 +6,7 @@ New features: - New module sloargs to parse compiled RenderMan shaders. +- New module pointcloud to read/write RenderMan point cloud files. Bug fixes/enhancements: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:35:29
|
Revision: 277 http://cgkit.svn.sourceforge.net/cgkit/?rev=277&view=rev Author: mbaas Date: 2009-02-05 23:35:25 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Initial module for reading/writing point clouds (no numeric support yet) Added Paths: ----------- cgkit/trunk/cgkit/pointcloud.py Added: cgkit/trunk/cgkit/pointcloud.py =================================================================== --- cgkit/trunk/cgkit/pointcloud.py (rev 0) +++ cgkit/trunk/cgkit/pointcloud.py 2009-02-05 23:35:25 UTC (rev 277) @@ -0,0 +1,339 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Python Computer Graphics Kit. +# +# The Initial Developer of the Original Code is Matthias Baas. +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +# $Id: riutil.py,v 1.1.1.1 2004/12/12 14:31:21 mbaas Exp $ + +# Point cloud test + +import ctypes +import rmanlibutil + +class PtcReader: + def __init__(self, fileName, libName): + """Constructor. + + fileName is the name of the point cloud file and libName the name + of the shared library that implements the point cloud API. + """ + + self._handle = None + + ptclib = self._loadPtcLib(libName) + + # Store the functions pointers that are still required + self._PtcReadDataPoint = ptclib.PtcReadDataPoint + self._PtcClosePointCloudFile = ptclib.PtcClosePointCloudFile + + self._PtcGetPointCloudInfo = ptclib.PtcGetPointCloudInfo + + # Just open the file to find out the number of variables in the file... + nvars = ctypes.c_int() + handle = ptclib.PtcOpenPointCloudFile(fileName, ctypes.byref(nvars), None, None) + if handle is None: + raise IOError("Cannot open point cloud file %s"%fileName) + ptclib.PtcClosePointCloudFile(handle) + + # Now prepare storage for the variable names and types and open the file for real... + numVars = nvars.value + types = (numVars*ctypes.c_char_p)() + names = (numVars*ctypes.c_char_p)() + handle = ptclib.PtcOpenPointCloudFile(fileName, ctypes.byref(nvars), types, names) + if handle is None: + raise IOError("Cannot open point cloud file %s"%fileName) + + self._handle = handle + + self.variables = [] + self.npoints = None + self.bbox = None + self.datasize = None + self.world2eye = None + self.world2ndc = None + self.format = None + + code = "" + idx = 0 + for i in range(numVars): + name = names[i] + type = types[i] + self.variables.append((type, name)) + if type=="float": + code += "dataDict['%s'] = data[%s]\n"%(name,idx) + idx += 1 + elif type in ["vector", "point", "normal", "color"]: + code += "dataDict['%s'] = data[%s:%s]\n"%(name,idx,idx+3) + idx += 3 + elif type=="matrix": + code += "dataDict['%s'] = data[%s:%s]\n"%(name,idx,idx+16) + idx += 16 + else: + raise RuntimeError("Unknown variable type in point cloud file: %s"%type) + # Compile the code that will pick the correct data components and put them into a dict + self._dataCollectionCode = compile(code, "<string>", "exec") + + n = ctypes.c_int() + ptclib.PtcGetPointCloudInfo.argtypes = [ptclib.PtcPointCloud, ctypes.c_char_p, ctypes.POINTER(ctypes.c_int)] + if ptclib.PtcGetPointCloudInfo(handle, "npoints", ctypes.byref(n))==1: + self.npoints = n.value + if ptclib.PtcGetPointCloudInfo(handle, "datasize", ctypes.byref(n))==1: + self.datasize = n.value + ptclib.PtcGetPointCloudInfo.argtypes = [ptclib.PtcPointCloud, ctypes.c_char_p, ctypes.POINTER(ctypes.c_float)] + b = (6*ctypes.c_float)() + if ptclib.PtcGetPointCloudInfo(handle, "bbox", b)==1: + self.bbox = list(b) + f = (3*ctypes.c_float)() + if ptclib.PtcGetPointCloudInfo(handle, "format", f)==1: + self.format = list(f) + m = (16*ctypes.c_float)() + if ptclib.PtcGetPointCloudInfo(handle, "world2eye", m)==1: + self.world2eye = list(m) + if ptclib.PtcGetPointCloudInfo(handle, "world2ndc", m)==1: + self.world2ndc = list(m) + + if self.datasize is None: + raise IOError("Could not obtain datasize value from point cloud file %s."%fileName) + + # Set up storage for reading individual data points + self._pos = (3*ctypes.c_float)() + self._normal = (3*ctypes.c_float)() + self._radius = ctypes.c_float() + self._data = (self.datasize*ctypes.c_float)() + + def __del__(self): + self.close() + + def close(self): + if self._handle is not None: + print "CLOSE ptc file" + self._PtcClosePointCloudFile(self._handle) + self._handle = None + + def readDataPoint(self): + if self._handle is None: + raise IOError("The point cloud file has already been closed.") + + res = self._PtcReadDataPoint(self._handle, self._pos, self._normal, self._radius, self._data) + if res==0: + return None + else: + dataDict = {} + data = self._data + exec self._dataCollectionCode + return tuple(self._pos), tuple(self._normal), self._radius.value, dataDict + + + def _loadPtcLib(self, libName): + """Load a RenderMan library providing the point cloud API. + """ + resolvedLibName = rmanlibutil.resolveRManLib(libName) + ptclib = ctypes.cdll.LoadLibrary(resolvedLibName) + + ptclib.PtcPointCloud = ctypes.c_void_p + + # Reading point cloud files + ptclib.PtcOpenPointCloudFile.argtypes = [ctypes.c_char_p, + ctypes.POINTER(ctypes.c_int), + ctypes.POINTER(ctypes.c_char_p), + ctypes.POINTER(ctypes.c_char_p)] + ptclib.PtcOpenPointCloudFile.restype = ptclib.PtcPointCloud + + ptclib.PtcGetPointCloudInfo.argtypes = [ptclib.PtcPointCloud, ctypes.c_char_p, ctypes.c_char_p] + ptclib.PtcGetPointCloudInfo.restype = ctypes.c_int + + ptclib.PtcReadDataPoint.argtypes = [ptclib.PtcPointCloud, + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float)] + ptclib.PtcReadDataPoint.restype = ctypes.c_int + + ptclib.PtcClosePointCloudFile.argtypes = [ptclib.PtcPointCloud] + ptclib.PtcClosePointCloudFile.restype = None + + return ptclib + + +class PtcWriter: + def __init__(self, fileName, vars, world2eye, world2ndc, format, libName): + """Constructor. + + fileName is the name of the point cloud file and libName the name + of the shared library that implements the point cloud API. + """ + + self._handle = None + + ptclib = self._loadPtcLib(libName) + + # Store the functions pointers that are still required + self._PtcWriteDataPoint = ptclib.PtcWriteDataPoint + self._PtcFinishPointCloudFile = ptclib.PtcFinishPointCloudFile + + xres,yres,aspect = format + + m = (16*ctypes.c_float)() + m[0] = 1.0 + m[5] = 1.0 + m[10] = 1.0 + m[15] = 1.0 + + n = len(vars) + cvartypes = (n*ctypes.c_char_p)() + cvarnames = (n*ctypes.c_char_p)() + idx = 0 + code = "" + for i in range(n): + type,name = vars[i] + cvartypes[i] = type + cvarnames[i] = name + if type=="float": + code += "cdata[%s] = data.get('%s', 0.0)\n"%(idx, name) + idx += 1 + elif type in ["vector", "point", "normal", "color"]: + code += "cdata[%s:%s] = data.get('%s', (0.0,0.0,0.0))\n"%(idx,idx+3,name) + idx += 3 + elif type=="matrix": + code += "cdata[%s:%s] = data.get('%s'), (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0))\n"%(idx,idx+16,name) + idx += 16 + else: + raise RuntimeError("Unknown point cloud variable type: %s"%type) + + self._dataSize = idx + self._dataInitCode = code + + cformat = (3*ctypes.c_float)(float(xres), float(yres), float(aspect)) + + handle = ptclib.PtcCreatePointCloudFile(fileName, n, cvartypes, cvarnames, m, m, cformat) + if handle is None: + raise IOError("Cannot open point cloud file %s for writing"%fileName) + + self._handle = handle + + def __del__(self): + self.close() + + def close(self): + if self._handle is not None: + print "CLOSE ptc file (write)" + self._PtcFinishPointCloudFile(self._handle) + self._handle = None + + def writeDataPoint(self, point, normal, radius, data): + """Write a point into the point cloud file. + + point and normal are vectors (any 3-sequence of floats) and radius + a float. data is a dict that contains the extra variables that + must have been declared in the constructor. Undeclared values are + ignored, missing declared valued are set to 0. + """ + if self._handle is None: + raise IOError("The point cloud file has already been closed.") + + p = (3*ctypes.c_float)(*tuple(point)) + n = (3*ctypes.c_float)(*tuple(normal)) + cdata = (self._dataSize*ctypes.c_float)() + exec self._dataInitCode + res = self._PtcWriteDataPoint(self._handle, p, n, radius, cdata) + if res==0: + raise IOError("Failed to write point cloud data point") + + def _loadPtcLib(self, libName): + """Load a RenderMan library providing the point cloud API. + """ + resolvedLibName = rmanlibutil.resolveRManLib(libName) + ptclib = ctypes.cdll.LoadLibrary(resolvedLibName) + + ptclib.PtcPointCloud = ctypes.c_void_p + + # Writing point cloud files + ptclib.PtcCreatePointCloudFile.argtypes = [ctypes.c_char_p, + ctypes.c_int, + ctypes.POINTER(ctypes.c_char_p), + ctypes.POINTER(ctypes.c_char_p), + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float)] + ptclib.PtcCreatePointCloudFile.restype = ptclib.PtcPointCloud + + ptclib.PtcWriteDataPoint.argtypes = [ptclib.PtcPointCloud, + ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), + ctypes.c_float, + ctypes.POINTER(ctypes.c_float)] + ptclib.PtcWriteDataPoint.restype = ctypes.c_int + + ptclib.PtcFinishPointCloudFile.argtypes = [ptclib.PtcPointCloud] + ptclib.PtcFinishPointCloudFile.restype = None + + return ptclib + + +def open(fileName, mode="r", libName=None, **kwargs): + """Open a point cloud file for reading or writing. + """ + if mode=="r": + return PtcReader(fileName, libName, **kwargs) + elif mode=="w": + return PtcWriter(fileName, libName=libName, **kwargs) + else: + raise ValueError('Invalid file mode: "%s" (expected "r" or "w")'%mode) + +################################################################### + +if __name__=="__main__": + from cgkit.cgtypes import * + import random + + if 1: + print "---WRITE---" + ptc = open("test.ptc", "w", "3delight", vars=[("float", "spam"), ("vector", "dir")], world2eye=None, world2ndc=None, format=(320,240,1.333)) + for i in range(100): + x = random.random() + y = random.random() + z = random.random() + ptc.writeDataPoint((x,y,z), (0,1,0), 0.2, {"spam":0.5}) + ptc.close() + + print "----READ----" + rd = open("test.ptc", "r", "3delight") + print rd.variables + print "npoints:",rd.npoints + print "datasize",rd.datasize + print "bbox",rd.bbox + print "format",rd.format + print "world2eye",rd.world2eye + print "world2ndc",rd.world2ndc + p,n,r,data = rd.readDataPoint() + print p,n,r,data + print rd.readDataPoint() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:34:44
|
Revision: 276 http://cgkit.svn.sourceforge.net/cgkit/?rev=276&view=rev Author: mbaas Date: 2009-02-05 23:34:41 +0000 (Thu, 05 Feb 2009) Log Message: ----------- convertdefault() now also returns the appropriate types when the param was read from a compiled shader (in which case the default is not a string and has to be 'cast'). Modified Paths: -------------- cgkit/trunk/cgkit/slparams.py Modified: cgkit/trunk/cgkit/slparams.py =================================================================== --- cgkit/trunk/cgkit/slparams.py 2009-02-05 23:33:01 UTC (rev 275) +++ cgkit/trunk/cgkit/slparams.py 2009-02-05 23:34:41 UTC (rev 276) @@ -448,7 +448,20 @@ # converted default value (this is the case when the value was # extracted from a compiled shader). if not isinstance(defstr, basestring): - return defstr + # Make sure that point-like types are returned as vec3 and matrix types + # are returned as mat4. + if typ in ["color", "point", "vector", "normal"]: + retType = cgtypes.vec3 + elif typ=="matrix": + retType = cgtypes.mat4 + else: + # No vec3/mat4 type, then just return the value + return defstr + # Cast the value... + if arraylen is None: + return retType(defstr) + else: + return map(lambda v: retType(v), defstr) # Replace {} with [] so that SL arrays look like Python lists if arraylen is not None: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:33:02
|
Revision: 275 http://cgkit.svn.sourceforge.net/cgkit/?rev=275&view=rev Author: mbaas Date: 2009-02-05 23:33:01 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Free the meta data info when reading PRMan meta data Modified Paths: -------------- cgkit/trunk/cgkit/sloargs.py Modified: cgkit/trunk/cgkit/sloargs.py =================================================================== --- cgkit/trunk/cgkit/sloargs.py 2009-02-05 23:31:15 UTC (rev 274) +++ cgkit/trunk/cgkit/sloargs.py 2009-02-05 23:33:01 UTC (rev 275) @@ -33,12 +33,26 @@ # # ***** END LICENSE BLOCK ***** +"""This module allows using a RenderMan sloargs library. +""" + import sys, os, os.path import ctypes import ctypes.util from _slreturntypes import _ShaderInfo, _ShaderParam import rmanlibutil +# This is the name of the C library that gets loaded by the PRMan SloArgs +# implementation to obtain a function pointer to the free() function +# (which is only required for reading meta data). +# As of Python 2.6 this name should work cross-platform. In previous versions, +# the caller could modify this name to pick up the correct version (such +# as "msvcrt"). If the free() function couldn't be obtained, reading meta +# data is disabled. +# The variable can also be set to None to disable reading meta data altogether +# (in case there is a problem with it). +_libc_name = "c" + #################### ctypes type declarations ####################### class _POINT(ctypes.Structure): @@ -284,7 +298,24 @@ class _SloArgs_PRMan(_SloArgs): def __init__(self, libName): + global _libc_name + _SloArgs.__init__(self, libName=libName, VISSYMDEF=_VISSYMDEF_prman) + + # Try to get a pointer to the C free() function (required for freeing + # the result returned by getting the shader meta data). + # We just try to load the "c" library (as of Python 2.6 this also works + # on Windows). + self._free = None + if _libc_name is not None: + libcName = ctypes.util.find_library(str(_libc_name)) + try: + lib = ctypes.cdll.LoadLibrary(libcName) + self._free = lib.free + self._free.argtypes = [ctypes.c_void_p] + self._free.restype = None + except: + pass @staticmethod def defaultLibName(): @@ -294,11 +325,19 @@ _SloArgs._declareFunctions(self, sloargs) # PRMan-specific functions sloargs.Slo_GetAllMetaData.argtypes = [] - sloargs.Slo_GetAllMetaData.restype = ctypes.POINTER(ctypes.c_char_p*100) + sloargs.Slo_GetAllMetaData.restype = ctypes.POINTER(ctypes.c_char_p*1000) def _getMetaData(self): + """Return the shader meta data. + """ + # If we couldn't obtain the free() function in the constructor we + # just return an empty dict (otherwise we would have to create a memory + # leak further down). + if self._free is None: + return {} + + res = {} data = self._sloargs.Slo_GetAllMetaData() - res = {} i = 0 while data.contents[i]!=None: key = data.contents[i] @@ -306,11 +345,7 @@ res[key] = val i += 2 - # TODO: data needs to be freed -# c = ctypes.cdll.LoadLibrary("/lib64/libc.so.6") -# c.free.argtypes = [ctypes.c_void_p] -# c.free.restype = None -# c.free(data) + self._free(data) return res ############################# 3Delight ################################## This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2009-02-05 23:31:18
|
Revision: 274 http://cgkit.svn.sourceforge.net/cgkit/?rev=274&view=rev Author: mbaas Date: 2009-02-05 23:31:15 +0000 (Thu, 05 Feb 2009) Log Message: ----------- Updated doc strings. Modified Paths: -------------- cgkit/trunk/cgkit/_slreturntypes.py Modified: cgkit/trunk/cgkit/_slreturntypes.py =================================================================== --- cgkit/trunk/cgkit/_slreturntypes.py 2009-02-05 23:31:00 UTC (rev 273) +++ cgkit/trunk/cgkit/_slreturntypes.py 2009-02-05 23:31:15 UTC (rev 274) @@ -38,6 +38,10 @@ class _ShaderInfo: """Holds information about a shader. + + For backwards compatibility this class behaves like a tuple + (type, name, params). The meta data has to be accessed via attribute + access. """ def __init__(self, type=None, name=None, params=None, meta=None): @@ -76,6 +80,9 @@ class _ShaderParam: """Holds information about a shader parameter. + + For backwards compatibility this class behaves like a 7-tuple + (outSpec, storage, type, size, name, space, default). """ def __init__(self, outputSpec=None, storage=None, type=None, size=None, name=None, space=None, default=None): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |