Houdini Engine 7.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Objects

Table of Contents

Object (OBJ) nodes are Houdini's transform nodes. They can contain other OBJ nodes or geometry (SOP) nodes (Geos).

Query

Given a HAPI_NodeId that represents an OBJ node, you can get the HAPI_ObjectInfo via HAPI_GetObjectInfo() with that node id.

To get all the object nodes inside another node, usually the asset node, simply call HAPI_ComposeObjectList(). This will create an internal list of OBJ node ids by recursively looking for geometry type OBJ nodes, nodes that contain geometry, or leaf OBJ nodes. This function will return you the object_count which you can use to create an array of HAPI_ObjectInfo and then fill it with HAPI_GetComposedObjectList().

HAPI_GetComposedObjectList() is actually a specialized version of HAPI_ComposeChildNodeList() that is recursive, looks for HAPI_NODETYPE_OBJ, and uses the HAPI_NODEFLAGS_OBJ_GEOMETRY flag.

Here's an example of using these functions:

// Load the library from file.
HAPI_AssetLibraryId library_id = -1;
hapiTestSession, "HAPI_Test_Objects_ObjectTypes.otl",
false, &library_id );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
HAPI_TEST_ASSERT( library_id >= 0 );
HAPI_NodeId node_id = -1;
result = HAPI_CreateNode(
hapiTestSession, -1, "Object/HAPI_Test_Objects_ObjectTypes",
nullptr, true, &node_id );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
// Get the child node count, filtered to geometry OBJ nodes only.
int child_count = 0;
hapiTestSession, node_id, HAPI_NODETYPE_OBJ,
HAPI_NODEFLAGS_OBJ_GEOMETRY, true, &child_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
HAPI_TEST_ASSERT( child_count == 2 );
// Get the node ids of the filtered child nodes.
std::vector< HAPI_NodeId > child_node_ids( child_count );
hapiTestSession, node_id, child_node_ids.data(), child_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
// Get the number of child objects.
int object_count = 0;
hapiTestSession, node_id, nullptr, &object_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
HAPI_TEST_ASSERT( object_count == 2 );
// Get the child objects' HAPI_ObjectInfos.
std::vector< HAPI_ObjectInfo > object_infos( object_count );
hapiTestSession, node_id, object_infos.data(), 0, object_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
// Check to make sure the node ids match between the child nodes and the
// child objects - they should be one and the same.
for ( int i = 0; i < child_count; ++i )
HAPI_TEST_ASSERT( object_infos[ i ].nodeId == child_node_ids[ i ] );

Object Transforms

Since OBJ nodes are really just fancy transforms, we provide special functions to easily get this transform.

You can get the transform on a single object node by calling HAPI_GetObjectTransform(). However, it's usually more efficient to get the transforms on a lot of object nodes at once. To do this, after the same call to HAPI_ComposeObjectList() from above in Query, you can call HAPI_GetComposedObjectTransforms(). Both HAPI_GetComposedObjectList() and HAPI_GetComposedObjectTransforms() use HAPI_ComposeObjectList() to get the internal object list created.

Here's an example of getting transforms on a bunch of object nodes:

// Load the library from file.
HAPI_AssetLibraryId library_id = -1;
hapiTestSession, "HAPI_Test_Objects_Transforms_Simple.otl",
false, &library_id );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
HAPI_TEST_ASSERT( library_id >= 0 );
// Instantiate the asset.
HAPI_NodeId node_id = -1;
result = HAPI_CreateNode(
hapiTestSession, -1, "Object/HAPI_Test_Objects_Transforms_Simple",
nullptr, true, &node_id );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
// Compose list of objects.
int object_count = 0;
hapiTestSession, node_id, nullptr, &object_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
HAPI_TEST_ASSERT( object_count == 1 );
// Get object transforms.
std::vector< HAPI_Transform > transforms( object_count );
hapiTestSession, node_id,
transforms.data(),
0, object_count );
HAPI_TEST_ASSERT( result == HAPI_RESULT_SUCCESS );
// Check values.
const HAPI_Transform & transform = transforms.front();
HAPI_TEST_ASSERT( approx( transform.position[ 0 ], 1.0f ) );
HAPI_TEST_ASSERT( approx( transform.position[ 1 ], 2.0f ) );
HAPI_TEST_ASSERT( approx( transform.position[ 2 ], 3.0f ) );
HAPI_TEST_ASSERT( approx( transform.rotationQuaternion[ 0 ], 0.0325370245f ) );
HAPI_TEST_ASSERT( approx( transform.rotationQuaternion[ 1 ], 0.0453578345f ) );
HAPI_TEST_ASSERT( approx( transform.rotationQuaternion[ 2 ], 0.0507340841f ) );
HAPI_TEST_ASSERT( approx( transform.rotationQuaternion[ 3 ], 0.997150958f ) );
HAPI_TEST_ASSERT( approx( transform.scale[ 0 ], 0.7f ) );
HAPI_TEST_ASSERT( approx( transform.scale[ 1 ], 0.8f ) );
HAPI_TEST_ASSERT( approx( transform.scale[ 2 ], 0.9f ) );
HAPI_TEST_ASSERT( approx( transform.shear[ 0 ], 0.1f ) );
HAPI_TEST_ASSERT( approx( transform.shear[ 1 ], 0.11f ) );
HAPI_TEST_ASSERT( approx( transform.shear[ 2 ], 0.12f ) );