It turned out to be pretty much a complete rewrite using the HDK but I did learn a few things along the way.
One of the trickier bits was working out how to utilise Houdini’s GR_RenderHook class to mimic the custom-GL behaviour of Maya’s MPxLocator class. In the end I opted to override the provided GU_Detail in my SOP with a custom GU_Detail-derived class and check against that in the GR_RenderHook using RTTI.
It looks a little bit like…
if( dynamic_cast<MyCustomDetail *>( gdp )){// do custom GL here}
It seems you can call OpenGL freely in the GR_RenderHook draw methods but I had all kinds of trouble clearing the state stack afterwards causing subsequent Houdini draws to get very confused. I’m sure it’s possible but I found a much better bet is to use the RE_OGLRender methods (which exist to mimic most GL calls). Once I moved over to using the RE_OGLRender methods everything worked as expected and Houdini seems to do a decent job avoiding unnecessary calls to the redraw code (I don’t maintain a GL display list).
Correct GL!
Another problem I had was creating Houdini geometry from my SOP with just points and no primitives (as you might get from say, a ScatterSop). When I tried to call GU_Detail::appendPoint() without building a primitive first I’d get a crash.
GU_PrimParticle::build( gdp, nPoints,0);// add points here
gdp->deletePrimitive(0,0);
GU, GEO, GB… are you lost yet?! The Geometry Introduction tries to make it clearer but I still got confused :\
Finally (always save the best till last) the best bit was trying to build the plugin. Unfortunately the hcustom program that ships with Houdini can’t compile more than one source file into a plugin. There is an example Makefile though, and after some dissection I ported the various compilation and linking flags into a CMake module. You can also find that in the source as config/cmake/FindHoudini.cmake.
Oh, and if you doing HDK development always read the header files. There are more comments in there than the doxygen documentation would lead you to believe!
I was thinking about a question over at VFX Overflow when I remembered a section in Advanced RenderMan that describes how to render procedural “nonideal” lenses in RenderMan renderers that support the trace() shadeop. It’s an old idea but can still be fun to play with.
The technique involves rendering though some lens geometry. The lens has a shader attached which gathers light from the other side by tracing rays. Because the shader is responsible for determining the direction the gathered light comes from you can model a wide variety of behaviours.
The book contains an example shader for rendering a panorama, but I liked the idea of a lens that renders a hemispherical latitude-longitude environment map so I put this one together.
surface latlong(){// our ndc-space point
point _Pndc = transform("NDC", P );// our parametric coordinatesfloat _u = xcomp( _Pndc );float _v = ycomp( _Pndc );// our vector componentsfloat rayx =-cos( _u * PI *2)* sin( _v * PI );float rayy = cos( _v * PI );float rayz = sin( _u * PI *2)* sin( _v * PI );// our trace point/vector
point _Pt = point "object"(0,0,0);
vector _It = vector "world"( rayx, rayy, rayz );// trace a colour
Ci = trace( _Pt, _It );
Oi = Os;
Ci *= Oi;}
Here is a test scene. The pink dot marks where the environment will be rendered from.
Here is the render camera and the lens geometry.
The generated lat-long environment map.
Finally, here is a test using the map as a pure reflection environment for a very shiny sphere.
You’ll notice that the reflections are not completely accurate due to the fact that the sphere has a radius and the environment map is rendered from a single point. This makes environment maps better suited to distant reflections like in say… an environment.
Over the holidays Johannes and I were talking about little bits & bobs of vfx development and thought that a Nuke plugin for direct rendering from RenderMan display driver would be useful.
As it turns out, not only does Nuke make a good floating-point framebuffer but doing slap-comps or lookdev builds with interactive rendering works pretty well.
There is also some information about the Client/Server classes that the display driver and plugin utilise. It turns out there are very similar classes in the Cortex library so I’d suggest you give them a gander too.
Last weekend I got to go along to the Google offices in Sydney for the OpenAustralia Hackfest.
I was intending to lurk all weekend but everyone was fired up and hacking away so I couldn’t resist doing something.
After a few ideas which were simply too crazy (mostly involving game engines), Ray and I hatched a plot to map statistical information gathered using the OpenAustralia API to the physical properties of objects in a rigid-body dynamic simulation.
Ray knocked together a python backend which got the various bits of information and I used Houdini to map that information into a simulation. That was as simple as calling the Python module from within Houdini expressions to set the initial state of the RBD object properties, like bounciness.
# get num debates for rbd object $OBJimport vis
return vis.numDebates( lvar("OBJ"))
The Houdini setup was very straight-foward but I did get to play with the new ODE RBD solver which worked great. All the objects were solved as boxes (for speed on my laptop) and we instanced in teapot geometry at render time.
The result was popular with the crowd and we ended up winning 3rd prize!