The Point Cloud API
The Point Cloud API
March 2008
1 Introduction
Point cloud files can be read and written using the point cloud API. Manipulating point cloud files has many applications - for example: merging point clouds, decimating point clouds, subsurface scattering simulation, ambient occlusion computation, and so on.
Note: unorganized point clouds can be read even if they are gzipped, but organized point clouds cannot be read if they are gzipped.
1.1 API Definition
From an application program's point of view, a point cloud is just a void pointer:
typedef void *PtcPointCloud;
RMAN_POINTCLOUD_API_VERSION is #define'd in pointcloud.h and can be used to distinguish between different versions of the point cloud file API. The current version is 4.
The following procedures are used for writing point cloud files:
PtcPointCloud PtcCreatePointCloudFile (char *filename, int nvars, char **vartypes, char **varnames, float *world2eye, float *world2ndc, float *format);
PtcPointCloud PtcCreateOrgPointCloudFile (char *filename, int npvars, char **pvartypes, char **pvarnames, int ntvars, char **tvartypes, char **tvarnames, float *world2eye, float *world2ndc, float *format);
int PtcWriteDataPoint (PtcPointCloud pointcloud, float *point, float *normal, float radius, float *data);
int PtcWriteTreeNode (PtcPointCloud pointcloud, int firstpoint, int npoints, float *data, PtcFilePos childpos[8], PtcFilePos *filepos);
void PtcFinishPointCloudFile (PtcPointCloud pointcloud);
The following procedures are available for reading an existing point cloud file:
PtcPointCloud PtcSafeOpenPointCloudFile (char *filename);
int PtcGetPointCloudInfo (PtcPointCloud pointcloud, char *request, void *result);
This function is used to get various information from the point cloud. pointcloud is a pointer returned from a call to PtcSafeOpenPointCloudFile() (or PtcOpenPointCloudFile()). The possible requests and corresponding results are:
- "npoints": the number of points in the point cloud file (an int).
- "bbox": the bounding box of the point cloud (an array of six floats: Xmin, Ymin, Zmin, Xmax, Ymax, Zmax).
- "nnodes": the number of octree nodes in the point cloud file (an int); 0 if the point cloud file is not organized.
- "rootpos": the file position of the octree root node (a PtcFilePos).
- "npointvars" or "nvars": the number of variables in points (an int).
- "pointvartypes" or "vartypes": the types of the variables in points (an array of strings).
- "pointvarnames" or "varnames": the names of the variables in points (an array of strings).
- "pointdatasize" or "datasize": the number of float data in each data point (an int).
- "ntreevars": the number of variables in octree nodes (an int).
- "treevartypes": the types of the variables in octree nodes (an array of strings).
- "treevarnames": the names of the variables in octree nodes (an array of strings).
- "treedatasize": the number of float data in each octree node (an int).
- "world2eye": the world-to-eye transformation matrix when the point cloud was created (16 floats).
- "world2ndc": the world-to-NDC transformation matrix when the point cloud was created (16 floats).
- "format": the image x resolution, y resolution, and pixel aspect ratio when the point cloud was created.
int PtcReadDataPoint (PtcPointCloud pointcloud, float *point, float *normal, float *radius, float *data);
int PtcReadDataPoints (PtcPointCloud pointcloud, int firstpoint, int npoints, PtcDataPoint *datapoints);
int PtcReadTreeNode (PtcPointCloud pointcloud, PtcFilePos filepos, int *firstpoint, int *npoints, float bbox[6], float *data, PtcFilePos childpos[8]);
int PtcReadTreeNodes (PtcPointCloud pointcloud, PtcFilePos filepos[8], PtcTreeNode nodes[8]);
int PtcGetNearestPointsData (PtcPointCloud pointcloud, float *point, float *normal, float maxdist, int numpoints, float *data);
void PtcClosePointCloudFile (PtcPointCloud pointcloud);
All these API function prototypes are defined in the header file pointcloud.h. Compile and link with the following library (in PRMan 14.0 and higher):
libprman.so/.dylib/.dll
Platform-specific linking instructions can be found in the RenderMan SDK documentation.
2 API Examples
2.1 ptmerge.c
To illustrate the point cloud API, we show a program that uses it. The program reads one or more point cloud files (with the same data types) and writes their content out as a single point cloud file.
/* * ptmerge.c * This program demonstrates how to use the pointcloud API to read * and write points from/to point cloud files. * * The program reads some point cloud files and writes their content * out as a single point cloud file. */ #include "stdlib.h" #include "stdio.h" #include "string.h" #include "math.h" #include "assert.h" #include "pointcloud.h" int main(int argc, char *argv[]) { PtcPointCloud *inptcs = NULL; /* an array of PtcPointClouds (pointers) */ PtcPointCloud outptc = NULL; float w2e[16], w2n[16], format[3]; float point[3], normal[3]; float radius, ``*data``; int nInFiles = argc-2, f, v; int datasize, nvars, nv; int npoints, p; char **vartypes = NULL, **varnames = NULL, **vt = NULL, **vn = NULL; // arrays of strings char *inname, *outname; if (argc < 3) { fprintf(stderr, "ptmerge error: needs at least one input file and an output\n"); exit(1); } inptcs = (PtcPointCloud *) malloc(nInFiles * sizeof(PtcPointCloud)); /* Open the first input files to determine data types */ inname = argv[1]; inptcs[0] = PtcSafeOpenPointCloudFile(inname); if (!inptcs[0]) { fprintf(stderr, "ptmerge error: unable to open input file %s\n", inname); exit(1); } PtcGetPointCloudInfo(inptcs[0], "nvars", &nvars); PtcGetPointCloudInfo(inptcs[0], "vartypes", &vartypes); PtcGetPointCloudInfo(inptcs[0], "varnames", &varnames); /* Open following input files (if any) and make sure they have the same data types as the first */ for (f = 1; f < nInFiles; f++) { inname = argv[f+1]; inptcs[f] = PtcSafeOpenPointCloudFile(inname); if (!inptcs[f]) { fprintf(stderr, "ptmerge error: unable to open input file %s, skipping it.\n", inname); continue; } PtcGetPointCloudInfo(inptcs[f], "nvars", &nv); PtcGetPointCloudInfo(inptcs[f], "vartypes", &vt); PtcGetPointCloudInfo(inptcs[f], "varnames", &vn); if (nv != nvars) { fprintf(stderr, "ptmerge error: input files differ number of vars\n"); exit(1); } for (v = 0; v < nvars; v++) { if (strcmp(vartypes[v], vt[v])) { fprintf(stderr, "ptmerge error: input files differ in data types: %s vs %s\n", vartypes[v], vt[v]); exit(1); } if (strcmp(varnames[v], vn[v])) { fprintf(stderr, "ptmerge error: input files differ in data names: %s vs %s\n", varnames[v], vn[v]); exit(1); } } } /* Get transformation matrices and image format from first file */ PtcGetPointCloudInfo(inptcs[0], "world2eye", w2e); PtcGetPointCloudInfo(inptcs[0], "world2ndc", w2n); PtcGetPointCloudInfo(inptcs[0], "format", format); /* Create output file with the same data types as input file(s) */ outname = argv[argc - 1]; outptc = PtcCreatePointCloudFile(outname, nvars, vartypes, varnames, w2e, w2n, format); if (!outptc) { fprintf(stderr, "Unable to open output file %s.\n", outname); exit(1); } PtcGetPointCloudInfo(inptcs[0], "datasize", &datasize); data = (float *) malloc(datasize * sizeof(float)); /* Loop over the input files, reading all points and writing them to the output file. */ for (f = 0; f < nInFiles; ++f) { PtcGetPointCloudInfo(inptcs[f], "npoints", &npoints); inname = argv[f+1]; printf("input file '%s' has %i points\n", inname, npoints); for (p = 0; p < npoints; p++) { PtcReadDataPoint(inptcs[f], point, normal, &radius, data); PtcWriteDataPoint(outptc, point, normal, radius, data); } PtcClosePointCloudFile(inptcs[f]); } free(inptcs); free(data); /* Finish writing the point cloud data and close files */ PtcFinishPointCloudFile(outptc); printf("merged file '%s' written\n", outname); return 0; /* success */ }
The ptmerge program can be invoked with:
ptmerge infile1.ptc infile2.ptc ... outfile.ptc
2.2 Subsurface Scattering
As another example of how to use the point cloud API, we are here providing source code for subsurface scattering simulation. (This is the same computation done by ptfilter -filter ssdiffusion and the subsurface() function.)
The main entry point is the function SSDiffusion(), which does the following:
- Reads in the points in the input point cloud file(s).
- Builds an octree.
- Computes the diffusion approximation for each point.
- Writes out a new point cloud.
The source code in C++ is listed here: ssdiffusion.cpp. This code is provided "as is"; use at your own risk. For an explanation of the algorithm, data structures, greek symbols, etc., please refer to the Translucency and Subsurface Scattering application note and the three papers listed in it.