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

About Houdini Groups

Houdini groups can contain primitives and points. Edge groups are also supported but Houdini Engine does not currently expose that functionality. Primitives can be whole polygon meshes, single polygons, volumes, curves, spheres, and so on. It is possible, for example, to have a single group contain some of the ploygons from one mesh, some of the polygons from another mesh, a volume, and a curve, all at the same time.

It is up to the asset maker to use groups as they see fit but the most common use case for primitive groups is assigning multiple textures to the same polygon mesh. This is the reason why we by default split polygon meshes by group. See Parts for more information on this splitting.

Query Group Information

Get Group Names

You query information on groups by first getting a list of group names per Geo and per HAPI_GroupType, using HAPI_GetGroupNames(). The number of groups on a geo can be found by calling HAPI_GeoInfo_GetGroupCountByType() on it's HAPI_GeoInfo or directly from:

Here's an example of getting group names:

// Load the library from file.
HAPI_AssetLibraryId library_id = -1;
HAPI_Result result =
hapiTestSession, "HAPI_Test_Groups_AllTypes.otl",
false, &library_id );
assert( result == HAPI_RESULT_SUCCESS );
// Instantiate the asset.
HAPI_NodeId node_id = -1;
result = HAPI_CreateNode(
hapiTestSession, -1, "Object/HAPI_Test_Groups_AllTypes",
nullptr, true, &node_id );
assert( result == HAPI_RESULT_SUCCESS );
{ // Point Groups
// Get our object info.
HAPI_ObjectInfo object_info;
assert( HAPIgetObjectInfoOnNode(
node_id, "PointsOnly", &object_info ) );
// Get geo info.
HAPI_GeoInfo geo_info;
hapiTestSession, object_info.nodeId, &geo_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get group names.
std::vector< HAPI_StringHandle > group_names(
geo_info.pointGroupCount );
hapiTestSession,
geo_info.nodeId,
group_names.data(),
geo_info.pointGroupCount );
assert( result == HAPI_RESULT_SUCCESS );
// Test them.
bool foundX = false;
bool foundZ = false;
for ( auto name : group_names )
{
if ( HAPItestGetString( name ) == "positiveX" )
foundX = true;
if ( HAPItestGetString( name ) == "positiveZ" )
foundZ = true;
}
assert( foundX );
assert( foundZ );
}
{ // Primitive Groups
// Get our object info.
HAPI_ObjectInfo object_info;
assert( HAPIgetObjectInfoOnNode(
node_id, "PrimitivesAndPoints", &object_info ) );
// Get geo info.
HAPI_GeoInfo geo_info;
hapiTestSession, object_info.nodeId, &geo_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get group names.
std::vector< HAPI_StringHandle > group_names(
geo_info.primitiveGroupCount );
hapiTestSession,
geo_info.nodeId,
group_names.data(),
geo_info.primitiveGroupCount );
assert( result == HAPI_RESULT_SUCCESS );
// Test them.
bool found = false;
for ( auto name : group_names )
if ( HAPItestGetString( name ) == "positiveZprim" )
{
found = true;
break;
}
assert( found );
}

Get Group Membership

You then get the membership information for the groups you're interested in, per Part this time, using HAPI_GetGroupMembership(). The membership information is a list of integers, one for each element (according to HAPI_GroupType), where 1 means the element is contained in the group while 0 means the element is not contained in the group. The size of this array is the same as HAPI_PartInfo_GetElementCountByGroupType() given the HAPI_PartInfo of the part you queried and the HAPI_GroupType.

As a helper flag, you can pass a bool pointer membership_array_all_equal to HAPI_GetGroupMembership() to see whether all the membership values are 1 or all of them are 0 without checking each one yourself.

Here's an example of getting group membership:

// Load the library from file.
HAPI_AssetLibraryId library_id = -1;
HAPI_Result result =
hapiTestSession, "HAPI_Test_Groups_AllTypes.otl",
false, &library_id );
assert( result == HAPI_RESULT_SUCCESS );
// Instantiate the asset.
HAPI_NodeId node_id = -1;
result = HAPI_CreateNode(
hapiTestSession, -1, "Object/HAPI_Test_Groups_AllTypes",
nullptr, true, &node_id );
assert( result == HAPI_RESULT_SUCCESS );
{ // Point Groups
// Get our object info.
HAPI_ObjectInfo object_info;
assert( HAPIgetObjectInfoOnNode(
node_id, "PointsOnly", &object_info ) );
// Get display sop.
HAPI_GeoInfo geo_info;
hapiTestSession, object_info.nodeId, &geo_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get part info.
HAPI_PartInfo part_info;
result = HAPI_GetPartInfo(
hapiTestSession, geo_info.nodeId, 0, &part_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get group partial membership.
std::vector< int > partial_group_membership( part_info.pointCount );
bool membership_array_all_equal = true;
hapiTestSession, geo_info.nodeId, 0,
HAPI_GROUPTYPE_POINT, "positiveX",
&membership_array_all_equal,
partial_group_membership.data(),
0, part_info.pointCount );
assert( result == HAPI_RESULT_SUCCESS );
assert( membership_array_all_equal == false );
// Check membership.
for ( int i = 0; i < partial_group_membership.size(); ++i )
{
if ( i == 2 || i == 3 || i == 6 || i == 7 ||
i == 10 || i == 11 || i == 14 || i == 15 )
{
assert( partial_group_membership[ i ] == 1 );
}
else
assert( partial_group_membership[ i ] == 0 );
}
// Get group full membership.
std::vector< int > full_group_membership( part_info.pointCount );
membership_array_all_equal = false;
hapiTestSession, geo_info.nodeId, 0,
HAPI_GROUPTYPE_POINT, "pointsAll",
&membership_array_all_equal,
full_group_membership.data(),
0, part_info.pointCount );
assert( result == HAPI_RESULT_SUCCESS );
assert( membership_array_all_equal == true );
// Check membership.
for ( auto m : full_group_membership )
assert( m == 1 );
}
{ // Primitive Groups
// Get our object info.
HAPI_ObjectInfo object_info;
assert( HAPIgetObjectInfoOnNode(
node_id, "PrimitivesAndPoints", &object_info ) );
// Get display sop.
HAPI_GeoInfo geo_info;
hapiTestSession, object_info.nodeId, &geo_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get part info.
HAPI_PartInfo part_info;
result = HAPI_GetPartInfo(
hapiTestSession, geo_info.nodeId, 0, &part_info );
assert( result == HAPI_RESULT_SUCCESS );
// Get group partial membership.
std::vector< int > partial_group_membership( part_info.faceCount );
bool membership_array_all_equal = true;
hapiTestSession, geo_info.nodeId, 0,
HAPI_GROUPTYPE_PRIM, "positiveZprim",
&membership_array_all_equal,
partial_group_membership.data(),
0, part_info.faceCount );
assert( result == HAPI_RESULT_SUCCESS );
assert( membership_array_all_equal == false );
// Check membership.
for ( int i = 0; i < partial_group_membership.size(); ++i )
{
if ( i == 7 || i == 9 || i >= 11 )
assert( partial_group_membership[ i ] == 1 );
else
assert( partial_group_membership[ i ] == 0 );
}
// Get group full membership.
std::vector< int > full_group_membership( part_info.faceCount );
membership_array_all_equal = false;
hapiTestSession, geo_info.nodeId, 0,
HAPI_GROUPTYPE_PRIM, "primAll",
&membership_array_all_equal,
full_group_membership.data(),
0, part_info.faceCount );
assert( result == HAPI_RESULT_SUCCESS );
assert( membership_array_all_equal == true );
// Check membership.
for ( auto m : full_group_membership )
assert( m == 1 );
}

Adding Groups

You can only add groups and set group memberships on input nodes. See Marshalling Geometry Into Houdini.

To add a group to an input node call HAPI_AddGroup() and give it the desired HAPI_GroupType and group name. Then, set the group's membership using HAPI_SetGroupMembership(), with the same HAPI_GroupType and group name as well as an integer array containing the memberships. This array should be the size given by HAPI_PartInfo_GetElementCountByGroupType() on the HAPI_PartInfo you used with HAPI_SetPartInfo() and your HAPI_GroupType.