Rotating Geometry using transform nodes

Hello all,

I am struggling with a rotation of a geometry in a scene based on the MeshViewer class given from the SDK (Sample 6). I added a member TransformObj m_transform and initialize it after initializing the whole scene, to make sure that the acceleration structure and the geometrygroup + geometry is set properly. Like follows:

void MeshViewer::initTransform()
    m_transform = m_context->createTransform();
    const float alpha = 0.785398163f;
    // Rotation around (world) x-axis 
    float m[16] = { sinf(alpha),cosf(alpha),0,0,
                    0,0,0,1 };
    m_transform->setMatrix( false, m, NULL );


This scene hierarchy should be valid right?

And everytime I press the key ‘x’, the geometry should rotate around the x-axis a bit by doing so:

bool MeshViewer::keyPressed(unsigned char key, int x, int y)
    static float t = 0.0f;
    float m[16];
    switch (key)
    case 'e':       // ....
    case 'E':       // ....
    case 'x':

        t += 0.1;
        float m[16] = { sinf(t),cosf(t),0,0,
                        0,0,0,1 };
        m_transform->setMatrix( false, m, NULL );
        // mark dirty so that the acceleration structure gets refit
        return true;

    return false;

But somehow, i don’t notice any changes. Of course, the matrix of the transform node changes, but that’s it, the acceleration structure is marked dirty in order to refit but doesn’t do anything.

Did I miss something considering the scene hierarchy?

I could do it the dirty way and read out the vertice and normal buffer and transform all vectors by myself, but this would probably kill the perfomance, wouldn’t it?

Here are some debug prints just in case if they are useful

child of geometry group: 1
accelaration datasize: 1671
accelaration builder: Sbvh
transform child type: 514 ==  RT_OBJECTTYPE_GEOMETRY_GROUP;

Thanks in advance!


1.) If those have been all your changes to the sampl6.cpp, that won’t work because the ray traversal starts at the object variable named “top_object” inside the device code and that has been initialized inside MeshViewer::initGeometry() with

m_context[ "top_object" ]->set( m_geometry_group );
m_context[ "top_shadower" ]->set( m_geometry_group );

You would need to make your transform node be the root of the scene traversal to see any effect.

2.) Your rotation matrices look incorrect. You would normally have the cosines on the diagonal, you have the sines there. This is a rotation around the z-axis:

cos  sin 0 0 
-sin cos 0 0
  0   0  1 0
  0   0  0 1

Note that for a zero angle you get the identity matrix which is not the case in your code. Yours would exchange x- and y-coordinates.

3.) To increase performance it makes sense to calculate the inverse matrix as well and send it in setMatrix() so that OptiX doesn’t need to calculate it, esp. if it’s super easy to do that yourself, which is the case for a rotation. The inverse is simply the rotation with the negative angle, which equals the transpose matrix for a rotation.

4.) Line 4 and 12 in the second code block are just debug code. They don’t affect the result and only cost performance.

Thanks for your reply! Everything works fine now :)

im new in optix and i followed the example above with the corrections included but i have two problems that occurred.

The first one is, if i press ‘x’ then im having a break point of
Unhandled exception at 0x00007FF7A11DBAA2 in sample6.exe: 0xC000041D: An unhandled exception was encountered during a user callback.

inline void TransformObj::setMatrix(bool transpose, const float* matrix, const float* inverse_matrix)
    rtTransformSetMatrix( m_transform, transpose, matrix, inverse_matrix );

The second one is that i dont know how to make transform node be the root of the scene traversal.

Thank you in advance.

If you’re new to OptiX, I would recommend to start learning it by following the steps in my posts here:

I can’t say what went wrong in your code if it worked for the original poster.
Please single step through that in your debugger and analyze the data you sent.

You did remove the needless debug code float m[16]; in line 4 and m_transform->getMatrix(false,m,NULL); in line 12 in that posted code?

The answer to your second question is:

// Old:
// m_context[ "top_object" ]->set( m_geometry_group );
// m_context[ "top_shadower" ]->set( m_geometry_group );
// New: m_transform as traversal root object. Look at how optix::Ray definitions inside the device code use it.
m_context[ "top_object" ]->set( m_transform );
m_context[ "top_shadower" ]->set( m_transform );

Thanks for your quick response!

I’ve removed the needless debug code on line 4 and 12, but i think it has to do with my object m_transform initialization.

Transform m_transform;

I’m going to follow your advise tho and follow the steps in your post.

Thank you again for the help

That Transform m_transform; declaration belongs into the same class where the m_geometry_group is.

The function MeshViewer::initTransform() in the first code block of this thread initializes it by creating the actual OptiX object, putting the former root m_geometry_group under it as the single child a transform can have, and sets some default matrix.

That new MeshViewer::initTransform() function needs to be called somewhere after the m_geometry_group has been created. Maybe that’s missing in your code.

m_geometry_group is created in MeshViewer::initGeometry() and you could also just put the body of the MeshViewer::initTransform() inside that initGeometry() function before the original “top_object” is set and change that to your new m_transform there.

Everything is working fine now. Thanks a lot for your help :)