Orthographic Rendering

   5623   5   1
User Avatar
Member
30 posts
Joined: July 2007
Offline
Hey all,

I am currently creating a plugin that defines a custom SOP. It also has a MSS (overloaded from MSS_SingleOpBaseState) defined so that the user can do painting-like operations. However, I need to draw 2D lines and other orthographic operations that draw over all objects in the viewport. What is the best approach to doing this?

Right now I'm overloading the doRender function (in the overloaded SingleOpBaseState class) and resetting the projection matrix with ortho2DW. It does draw correctly when doing this. I am doing the correct push and pop operations to save the matrices, but there are a few problems with this approach. For one thing, all the in-viewport UI elements are no longer displaying. Another problem is that it is not getting refreshed correctly. When the current frame changes, I need the viewport to completely refresh. I could use the XOR drawing functions, but the results are not that good.

Furthermore, it would be nice if it would continue drawing when you are not in that operator's “mode”, so that the drawing code would be called even in a different context as long as the SOP's visibility was set to true. It would be great if it could just be done using setVisualizeCallback or if I could create geometry that was overlayed onto the viewport as a UI element, but I haven't found a way to do this.

Any suggestions?

–Joel
Joel Van Eenwyk
Programmer and FX Artist
Homepage: VFX Journal [vfxjournal.net]
User Avatar
Member
8106 posts
Joined: July 2005
Offline
If you're pushing/popping the matrices correctly, I don't see how your doRender function could affect anything else. Perhaps you could try narrowing down what you're doing and posting? There might be some RE_OGLRender quirk that you're not expecting. Note that ortho2DW() modifies the projection matrix and then puts you back into the original matrix stack.

As for handling time changes, that's a bit hard right now in the HDK. I think your best bet is to fake time changes by telling your SOP to set ourFlags().setTimeDep(true).
User Avatar
Member
30 posts
Joined: July 2007
Offline
Thanks for the response! Here is what I have right now:

r->matrixMode(RE_MATRIX_PROJECTION);
r->pushMatrix();
r->loadIdentityMatrix();

int pl, pr, pb, pt;
r->getViewport2DS(&pl, &pr, &pb, &pt);
r->ortho2DW(pl, pr, pb, pt);

r->matrixMode(RE_MATRIX_VIEWING);
r->pushMatrix();
r->loadIdentityMatrix();

r->pushLineWidth(radius);
r->pushSmoothLines();

// Drawing code goes here

r->popSmoothLines();
r->popLineWidth();

r->matrixMode(RE_MATRIX_VIEWING);
r->popMatrix();

r->matrixMode(RE_MATRIX_PROJECTION);
r->popMatrix();

Some of this code is a bit redundant (or at least it should be), but I am just trying to cover all the bases and make sure the state is correct. Also, when you resize the viewport after it renders once, the viewport will go black, which is a bit strange. There must be something going on behind the scenes that is doing something unusual.

Since the SOP doesn't have a doRender function call, where can the render be done? The visualization callback really doesn't seem to be called at the right time. I set a breakpoint on the function, and it gets called at times I wouldn't expect–and definitely not enough.

Any thoughts on how to approach this? Thanks again for the response!

–Joel
Joel Van Eenwyk
Programmer and FX Artist
Homepage: VFX Journal [vfxjournal.net]
User Avatar
Member
8106 posts
Joined: July 2005
Offline
It looks like you're not restoring the matrix mode to what it was previously to me? SOP_Node's don't render. The visualization callback is called whenever the SOP cooks to perform additional operations to the gdp intended for only when it is in it's specific state (ie. set by the state).

Another approach might be to try creating a GR render hook that will allow you to perform your own viewport rendering. To use this approach though, you'll need to choose a geometry primitive to override rendering for.There's an example in the HDK samples.

I was suggesting that you set the time dependency flag in the SOP's cookMySop() method. This ensures that it will be cooked every frame. If the SOP cooks while the state is active, then the viewer should redraw.

Another idea is to create an FS_EventGenerator subclass to create a timer that you can then check to see if the playbar time has changed and then redraw if necessary. To trigger a redraw from your state, you might need to fake it by doing a BM_State::interrupt(this) followed by BM_State::resume(this) though.

To use the FS_EventGenerator class, I think you just need to override getClassName(), getPollTime(), and processEvents(). You would also need call its installGenerator() method on enter() and then uninstallGenerator() on exit().
User Avatar
Member
30 posts
Joined: July 2007
Offline
Hey Edward,

Your suggestions all worked very well! Thanks!

I only ran into one problem that I haven't been able to solve. How do you get access to the SOP node that is being rendered from within the GR render hook member function? I really need that information, because what I need to render is inside the SOP itself. If there isn't a way to do that, can I put custom data inside the GU_Detail—data that Houdini won't attempt to render automatically? It seems like I can (from looking at the samples and header files), but if it is possible, is it the intended/optimal way?

Thanks!

–Joel
Joel Van Eenwyk
Programmer and FX Artist
Homepage: VFX Journal [vfxjournal.net]
User Avatar
Member
8106 posts
Joined: July 2005
Offline
From inside a GR_RenderHook, I don't think you can easily do that. Your idea seems pretty good. Just add your own custom attribute. If it covers the whole GU_Detail, then a detail attribute will be the easiest.
  • Quick Links