VexPointCloud
From Odwiki
Contents |
What is a point cloud?
Well, to be blunt, a point cloud is simply a bunch of points in space. Points can have arbitrary attributes (or channels if you prefer). Each point has the same set of attributes.
You might imagine a particle system as a point cloud. Each particle has a set of attributes (like velocity or color). You might also imagine scattering points over a surface (or multiple surfaces) kind of like a photon map.
The concept behind Point Clouds in Houdini is to store calculated custom information on each point of the cloud that is cached and available for subsequent processing within the same VEX operation. It can be thought of as a user-defined run-time cache. If used as intended, only the "useful" points have their calculations performed and cached - for example, only unobscured points within the render's view frustum, keeping re-use to the maximum and redundant calculations to the minimum.
Please note that as of Houdini 8.1, the calculations associated with Point Clouds happen on the fly and the resultant point cloud cannot be written out to disk.
What would I use Point Clouds for?
Point clouds allow you to perform some tasks that are hard to do traditionally, like:
- Share computations for things which typically vary slowly in a scene, like lighting.
- Query nearby samples - really important for things like SubsurfaceScattering
Some examples are:
Look in the VexPointCloudGallery for pictures.
How do I access a point cloud in VEX?
Rather than looking at all the points in the point cloud, you typically want to find just a few points which are "important" to your computation. The pcopen function will access the point cloud and determine the most important points for you to look at. This is done by specifying a position (or other attribute) and asking for the "nearest" points to the given position.
For example, to find the nearest 10 points to the origin (within a radius of 0.1 units), we would make the call
vector query_point = {0,0,0};
float radius = 0.1;
int max_points = 10;
int handle = pcopen(mapname, "P", query_point, radius, max_points);
This will query the map and queue up the nearest points for later operations.
It's possible, that the map doesn't have any points within the radius specified, in which case, the query will still succeed, but no points will be queued. Alternatively, it's possible that the map will have thousands of points within the sphere centered at {0,0,0}. In this case, only the closest 10 points will be returned.
Great, now what?
So, now we know how to find the points in the map, but what can we do with them?
The simplest thing you can do is to get the "average" value of a different channel for the point in question.
Cd = vector(pcfilter(handle, "Cd"));
The above code will filter (or average) the "Cd" channel of all the points found in the pcopen and return the filtered color.
Storing Data in a Point Cloud for re-use
There are lots of times when very expensive computations need to be performed, but the results of the computation don't change much over space. We can use point clouds to store some of these expensive computations and then filter the results to get an approximation to the real result.
For example, when computing Irradiance or AmbientOcclusion, the work required to get one shading sample can be significant (i.e. lots of ray-tracing). However, since global illumination tends to change slowly over space, it's possible to filter some surrounding computations to give an approximate solution. This is the theory behind IrradianceCaching. It's also similar (though slightly different) to the way photon maps work when computing global illumination.
Another case where we might want to store computations is when computing volumetric effects. If we have computed the illumination of a cloud for nearby points, we can probably filter those values to get an approximate color for any arbitrary point. Again, this is because the illumination in clouds will change relatively slowly.
For this, look into the pcexport() VEX command. This storage happens in RAM, but you also have the option of writing out point clouds with custom data to disk.
Writing Point Clouds To Disk
Look into the pcwrite() command for writing out a point to disk. There are many reasons to want to export sample data to disk - for example: writing out the sample position of a displaced surface. Especially with a high-order surface, like a SubdivisionSurface.
Gallery
Please see images rendered with Point Clouds in the VexPointCloudGallery
Examples
Example One : Filtering point cloud data
The .hip file reconstruct.hip.gz has a simple VOP network which re-constructs an image based on a point cloud. The example file is self-contained and should be fairly simple to understand.
Here is an annotated version of the code generated by the VOP network (/vex/point_cloud_filter).
// A bunch of pragmas and setup stuff deleted
cop2
point_cloud_filter(vector trans = { 0, 0, 0 };
vector rot = { 0, 0, 0 };
vector scale = { 1, 1, 1 };
vector pivot = { 0, 0, 0 };
string file = "op:/obj/geo1/point_cloud";
float radius = 0.1;
int maxpoints = 10)
{
vector vec;
matrix xform;
vector search_position;
int handle;
vector value;
float fval1;
float fval2;
float fval3;
// Here, we take the pixel UV coordinates and convert them to a
// position. We then can apply a transform (based on the
// parameters) to be able to evaluate a transformed version of the
// texture
vec = vop_floattovec(X, Y, 0);
xform = maketransform(0, 0, trans, rot, scale, pivot);
search_position = vec * xform;
//
// Here, we open the point cloud and query for the number of
// points we want to filter. We query the "P" channel, meaning
// that we're looking for the points closest to the
// "search_position" in space.
//
handle = pcopen(file, "P", search_position, radius, maxpoints);
//
// Once we have the nearest points, we can simply "filter" the
// "Cd" attribute/channel of the points to re-construct the
// approximate color of the map at the given point.
//
value = pcfilter(handle, "Cd");
// Now, we simply convert the filtered color to the RGB value of
// the output pixel.
vop_vectofloat(value, fval1, fval2, fval3);
R = fval1;
G = fval2;
B = fval3;
}
If you download the .hip file, you can play with the parameters in the COP.
It's fairly obvious what the transform parameters are doing.
When you load the example .hip file, you'll note that the COP is only searching for the exact closest point in the point cloud. The resulting image basically fills a whole swatch of color with the closest points color. By increasing the number of points filtered, we get a better (albiet blurrier) approximation to the actual source image.
Now, try changing the radius slider. If you change the search radius to 0.05 or so, you'll see the image is now made up of lots of dots and has large areas where no color is chosen. That's because the search radius isn't big enough to find any nearby points.
If you go to the SOP network, you can increase the number of points in the scatter SOP. This improves the fidelity of the reconstructed image. As the number of points increases, the cooking time will also increase, though it may not be noticable in this example.



