Provides a read-only API for accessing the data of a geometry object connected to a custom ICE node.
dirty states:checking for geometry changes The following geometry types are supported:
This API can handle single geometries or a composite of multiple, or grouped, geometries. For grouped geometries, CICEGeometry virtually unifies the sub-geometries as one single geometry which allows data to be accessed as if it were actually a single geometry. For instance, calling CICEGeometry::GetPointPositionCount on a grouped geometry returns the total number of points for all sub-geometries.
CICEGeometry is typically used in the cb_ICENode_BeginEvaluate BeginEvaluate callback but can also be used in all custom cb_icenodes ICENode evaluation callbacks . However, it cannot be used from an cb_ICENode_Evaluate Evaluate callback in multi-thread mode with a non-singleton context. Calls to CICEGeometry methods will just return default values in this context. Also, CICEGeometry can only be used with specific geometry ports defined with the following types:
The CICEGeometry class can also be used to interrogate connected geometries about their states. The states supported are:
siTopologyDirtyState
is true, it implies that siPointPositionDirtyState
is also true. CICEGeometry only supports geometry-centric states. Use CICEPortState to query for the low-level port states of connected geometries.
XSIPLUGINCALLBACK CStatus Sample_RegisterNode( ICENodeContext& in_ctxt ) { ICENodeDef nodeDef = Application().GetFactory().CreateICENodeDef(L"Sample",L"Sample"); nodeDef.AddInputPort( ID_IN_GeometryPortID, ID_G_100, siICENodeDataGeometry,siICENodeStructureSingle,siICENodeContextSingleton, L"geometry input", L"geometry input" ); // Rest of the code omitted for brievity ... return CStatus::OK; } XSIPLUGINCALLBACK CStatus Sample_BeginEvaluate( ICENodeContext& in_ctxt ) { CICEGeometry geom( in_ctxt, ID_IN_GeometryPortID ); // Geometry data are provided as a flat list of values CDoubleArray points; geom.GetPointPositions( points ) ; XSI::MATH::CMatrix4f transfo; geom.GetTransformation( transfo ); std::vector< MATH::CVector3f >* pUserData = new std::vector< MATH::CVector3f >; ULONG nCount = geom.GetPolygonCount(); CLongArray sizes; // sizes holds the number of points per polygon CLongArray indices; // indices holds the polygon indices and are used for indexing the point values geom.GetPolygonIndices( sizes, indices ); // Compute the center point of all polygons and save the result in a user data. ULONG nOffset = 0; for (ULONG i=0; i<nCount; i++) { MATH::CVector3f vTotal; for (ULONG j=0; j<(ULONG)sizes[i]; j++, nOffset++) { MATH::CVector3f v( (float)points[ indices[nOffset]*3 ], (float)points[ indices[nOffset]*3+1 ], (float)points[ indices[nOffset]*3+2 ] ); vTotal += v; } vTotal *= 1.0f/sizes[i]; // The points are relative to the geometry and must be converted to global coordinates. vTotal.MulByMatrix4InPlace( transfo ); pUserData->push_back( vTotal ); } return CStatus::OK; } XSIPLUGINCALLBACK CStatus Sample_Evaluate( ICENodeContext& in_ctxt ) { ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( ); switch( out_portID ) { case ID_OUT_Sample_Points: { // Retrieve the points computed in Sample_BeginEvaluate std::vector<MATH::CVector3f>* pUserData = (std::vector<MATH::CVector3f>*)(CValue::siPtrType)in_ctxt.GetUserData( ); CDataArrayVector3f outData( in_ctxt ); CIndexSet indexSet( in_ctxt ); for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next()) { // Note: The output buffer is relative to the 'batch' data therefore the batch can be // indexed with the iterator directly. As for the user data vector, pUSerData must be // indexed with the 'batch' global index i.e. CIndexSet::Iterator::GetAbsoluteIndex() outData[it] = (*pUserData)[ it.GetAbsoluteIndex() ]; } } break; }; return CStatus::OK; } XSIPLUGINCALLBACK CStatus Sample_EndEvaluate( ICENodeContext& in_ctxt ) { // Release the memory allocated for the user data CValue userData = in_ctxt.GetUserData( ); if (userData.IsEmpty()) { return CStatus::OK; } std::vector<MATH::CVector3f>* pUserData = (std::vector<MATH::CVector3f>*)(CValue::siPtrType)userData; if (pUserData) delete pUserData; in_ctxt.PutUserData( CValue() ); return CStatus::OK; }
static void _LogGeometryStates( CICEGeometry& in_geom, const CString& in_portName, double in_dCurrentFrame, bool in_bClearState ) { if ( in_geom.IsDirty( CICEGeometry::siAnyDirtyState ) ) { bool bTypeDirtyState = in_geom.IsDirty( CICEGeometry::siGeometryTypeDirtyState ); bool bTransfoDirtyState = in_geom.IsDirty( CICEGeometry::siTransformationDirtyState ); bool bPointsDirtyState = in_geom.IsDirty( CICEGeometry::siPointPositionDirtyState ); bool bTopologyDirtyState = in_geom.IsDirty( CICEGeometry::siTopologyDirtyState ); if ( in_bClearState ) { in_geom.ClearState(); } Application app; // Don't log redundant information: // bTypeDirtyState always implies bTransfoDirtyState + bPointsDirtyState + bTopologyDirtyState // bTopologyDirtyState always implies bPointsDirtyState if ( bTypeDirtyState) { app.LogMessage( ">>> Port " + in_portName + " siGeometryTypeDirtyState at frame " + CString(in_dCurrentFrame) + " is dirty" ); } else { if ( bTransfoDirtyState) { app.LogMessage( ">>> Port " + in_portName + " siTransformationDirtyState at frame " + CString(in_dCurrentFrame) + " is dirty" ); } if ( bTopologyDirtyState) { app.LogMessage( ">>> Port " + in_portName + " siTopologyDirtyState at frame " + CString(in_dCurrentFrame) + " is dirty" ); } else if ( bPointsDirtyState) { app.LogMessage( ">>> Port " + in_portName + " siPointPositionDirtyState at frame " + CString(in_dCurrentFrame) + " is dirty" ); } } } } static void LogGeometryStates( CICEGeometry& in_geom, const CString& in_portName, double in_dCurrentFrame ) { CICEGeometry::Type geomtype = in_geom.GetGeometryType(); switch( geomtype ) { case CICEGeometry::siGroupType: { // Note: ClearState on sub-geometries will clear the states for the entire group geometry. It's // recommended to call ClearState only on the group geometry to avoid inconsistencies. _LogGeometryStates( in_geom, in_portName, in_dCurrentFrame, false ); for (ULONG i=0; i<in_geom.GetSubGeometryCount(); i++) { CICEGeometry subgeom = in_geom.GetSubGeometry(i); _LogGeometryStates( subgeom, in_portName + CString(i), in_dCurrentFrame, false ); } in_geom.ClearState(); } break; default: { _LogGeometryStates( in_geom, in_portName, in_dCurrentFrame, true ); } } } XSIPLUGINCALLBACK CStatus Port_State_Observer_BeginEvaluate( ICENodeContext& in_ctxt ) { CICEGeometry geomGroup( in_ctxt, ID_IN_GeometryGroup ); CICEGeometry geomCurve( in_ctxt, ID_IN_NurbsCurve ); CICEGeometry geomMesh( in_ctxt, ID_IN_MeshSurf ); CICEGeometry geomNurbsSurf( in_ctxt, ID_IN_NurbsSurf ); CICEGeometry geomCloud( in_ctxt, ID_IN_PointCloud ); double dCurrentFrame = in_ctxt.GetTime(); LogGeometryStates( geomGroup, L"GeometryGroup", dCurrentFrame ); LogGeometryStates( geomCurve, L"NurbsCurve", dCurrentFrame ); LogGeometryStates( geomMesh, L"MeshSurf", dCurrentFrame ); LogGeometryStates( geomNurbsSurf, L"NurbsSurf", dCurrentFrame ); LogGeometryStates( geomCloud, L"PointCloud", dCurrentFrame ); return CStatus::OK; }
#include <xsi_icegeometry.h>
enum Type |
Defines the geometry types supported by CICEGeometry.
enum DirtyState |
Defines the supported dirty geometry state types.
CICEGeometry | ( | ICENodeContext & | in_ctxt, |
ULONG | in_nInputPortID, | ||
ULONG | in_nInstanceIndex = 0 |
||
) |
Constructor for creating and initializing an instance of CICEGeometry.
in_ctxt | ICENode evaluation context. |
in_nInputPortID | Input port identifier. |
in_nInstanceIndex | The group instance of the port. Defaults to 0 . |
CICEGeometry | ( | const CICEGeometry & | in_geom | ) |
Copy Constructor.
CICEGeometry | ( | ) |
Default Constructor. Creates an invalid CICEGeometry object of type Type::siNoneType.
~CICEGeometry | ( | ) |
Destructor.
bool IsValid | ( | ) | const |
Returns true if the object is valid. Unless the object is not set properly, IsValid always return true. IsValid cannot be used to detect if a geometry is connected or not. The rational behind is that it's not guaranteed that all connected geometries have data, therefore having geometries always set as valid allows users to write generic code. For instance, unconnected geometries, empty polygon geometries and empty point clouds will all return 0 for CICEGeometry::GetPointPositionCount.
In general it's not recommended for a custom node to check for valid port connections. For instance, a custom node could be connected to a passthrough node which could be potentially not connected to any node. If you want to optimize things based on the port state then it is recommended to use the CICEPortState class and perform actions based on specific notifications.
Type GetGeometryType | ( | ) | const |
Returns the geometry type. The type is set to Type::siNoneType when the object is not properly defined.
bool operator== | ( | const CICEGeometry & | in_geom | ) | const |
Equality operator. Tests if two geometries are the same; the function is just comparing the internal pointer objects.
in_geom | CICEGeometry instance to compare to this instance. |
bool operator!= | ( | const CICEGeometry & | in_geom | ) | const |
Inequality operator. Tests whether two geometries are different; the function is just comparing the internal pointer objects.
in_geom | CICEGeometry instance to compare to this instance. |
CICEGeometry& operator= | ( | const CICEGeometry & | in_geom | ) |
Assignment operator. Assign this geometry to another geometry. This operation is a simple object assignment. The content of the geometry is not duplicated.
in_geom | CICEGeometry object to assign. |
ULONG GetSubGeometryCount | ( | ) | const |
Returns the number of sub-geometries contained by this geometry.
CICEGeometry GetSubGeometry | ( | ULONG | in_index | ) | const |
Returns the sub-geometry at the position identified by in_index
. The CICEGeometry instance returned is invalid if in_index
is out of bounds.
ULONG GetPointPositionCount | ( | ) | const |
Returns the number of point positions on the current geometry.
CStatus GetPointPositions | ( | CDoubleArray & | out_points | ) | const |
Returns an array of double values containing the point positions (xyz
) of the entire geometry. The positions are stored as a flat list and can be indexed using the indices returned by CICEGeometry::GetPolygonIndices, CICEGeometry::GetTrianglePointIndices or CICEGeometry::GetSegmentIndices.
The array is formatted as:
{x0,y0,z0, ... xN,yN,zN}
out_points | Array of point positions. |
CICEGeometry geom( in_ctxt, ID_IN_geometry ); CDoubleArray points; geom.GetPointPositions( points ) ; ULONG nCount = geom.GetPolygonCount(); CLongArray sizes; CLongArray indices; geom.GetPolygonIndices( sizes, indices ); ULONG nOffset = 0; std::vector< MATH::CVector3f > v3fArray; for (ULONG i=0; i<nCount; i++) { for (ULONG j=0; j<(ULONG)sizes[i]; j++, nOffset++) { MATH::CVector3f v( (float)points[ indices[nOffset]*3 ], (float)points[ indices[nOffset]*3+1 ], (float)points[ indices[nOffset]*3+2 ] ); v3fArray.push_back( v ); } }
ULONG GetTriangleCount | ( | ) | const |
Returns the number of triangles in the geometry.
CStatus GetTrianglePointIndices | ( | CLongArray & | out_indices | ) | const |
Returns an array containing the point indices for each triangulated polygon. The point indices are stored in the array as a flat list of values grouped in triplets, the first triplet being the points of triangle 0
, etc. The triangle indices are numbered based on the order of creation of the triangles.
The array is formatted as:
{t0<p0,p1,p2>, t1<p0,p1,p2>... tN<p0,p1,p2>}
out_indices | Array of triangle point indices. |
CICEGeometry geom( in_ctxt, ID_IN_geometry ); CDoubleArray points; geom.GetPointPositions( points ) ; ULONG nCount = geom.GetTriangleCount(); CLongArray indices; geom.GetTrianglePointIndices( indices ); ULONG nOffset = 0; std::vector< MATH::CVector3f > v3fArray; for (ULONG i=0; i<nCount; i++) { for (ULONG j=0; j<3; j++, nOffset++) { MATH::CVector3f v( (float)points[ indices[nOffset]*3 ], (float)points[ indices[nOffset]*3+1 ], (float)points[ indices[nOffset]*3+2 ] ); v3fArray.push_back( v ); } }
ULONG GetPolygonCount | ( | ) | const |
Returns the number of polygons of the geometry.
CStatus GetPolygonIndices | ( | CLongArray & | out_sizes, |
CLongArray & | out_indices | ||
) | const |
Returns the size and point indices for all polygons on the geometry.
out_sizes | Array containing the point count for each polygon. |
out_indices | Array containing the point indices for each Polygon. The vertices are stored as a flat list and ordered by polygons, the first group being the points for polygon 0 , etc. The array is formatted as: {poly0<v0,v1..vN>, poly1<v0,v1..vN>... polyN<v0,v1..vN>} |
CICEGeometry geom( in_ctxt, ID_IN_geometry ); CDoubleArray points; geom.GetPointPositions( points ) ; ULONG nCount = geom.GetPolygonCount(); CLongArray sizes; CLongArray indices; geom.GetPolygonIndices( sizes, indices ); ULONG nOffset = 0; std::vector< MATH::CVector3f > v3fArray; for (ULONG i=0; i<nCount; i++) { for (ULONG j=0; j<(ULONG)sizes[i]; j++, nOffset++) { MATH::CVector3f v( (float)points[ indices[nOffset]*3 ], (float)points[ indices[nOffset]*3+1 ], (float)points[ indices[nOffset]*3+2 ] ); v3fArray.push_back( v ); } }
ULONG GetSegmentCount | ( | ) | const |
Returns the number of segments for the geometry. Segment is a generic term to describe 1D geometry components such as edges for mesh surfaces and control points for nurbs surfaces.
CStatus GetSegmentIndices | ( | CLongArray & | out_indices | ) | const |
Returns an array of segment indices. Segment is a generic term to describe 1D geometry components such as edges for mesh surfaces and control points for nurbs surfaces. The array contains a sequence of pairs describing the segment indices:
{s0<id0,id1>, ...sN<id0,id1>}
The indices can be used with CICEGeometry::GetPointPositions to get the segment points.
out_indices | Array of edge indices. |
CICEGeometry geom( in_ctxt, ID_IN_geometry ); CDoubleArray points; geom.GetPointPositions( points ) ; ULONG nCount = geom.GetSegmentCount(); CLongArray indices; geom.GetSegmentIndices( sizes, indices ); ULONG nOffset = 0; std::vector< MATH::CVector3f > v3fArray; for (ULONG i=0; i<nCount; i++) { for (ULONG j=0; j<2; j++, nOffset++) { MATH::CVector3f v( (float)points[ indices[nOffset]*3 ], (float)points[ indices[nOffset]*3+1 ], (float)points[ indices[nOffset]*3+2 ] ); v3fArray.push_back( v ); } }
CStatus GetTransformation | ( | XSI::MATH::CMatrix4f & | out_mat44 | ) | const |
Returns the global transformation matrix of this geometry.
out_mat44 | Transformation matrix. |
bool IsDirty | ( | unsigned short | in_flag = siAnyDirtyState | ) | const |
Returns the dirty state of this geometry for a given state type as defined in the CICEGeometry::DirtyState enumerator. By default, IsDirty returns true if at least one of the geometry states is dirty.
in_flag | State type. |
void ClearState | ( | ) |
Clears the geometry states.