A cluster represents a set of components on a Geometry.
For example, the polygons of the left arm of a human model might be grouped together by creating a cluster.
A cluster has a type (see SIObject::GetType) which corresponds to the component type that it contains, (pnt
, knot
, poly
). A geometry can have multiple clusters, including clusters of different types. Any particular component might be included in multiple clusters. The ::ClusterTypes that are supported on a geometry depend on the type of object. For example only NurbsSurface or NurbsCurve can have a siKnotCluster.
Clusters can be created on the geometry of a ParticleCloud. These clusters are of type siVertexCluster but they contain Particles.
A cluster that includes all the components of a particular type is said to be always complete, which you can verify with Cluster::IsAlwaysComplete. An always-complete cluster always covers all components of the geometry, even when components are added by a modeling operation; however, notice that a cluster which covers all components of a geometry is not necessarily always-complete. Other clusters may contain a subset of components. In all cases the indices of the components in the cluster do not directly match the indices of the component on the geometry. The mapping between cluster indices and geometry indices is available through Cluster::GetElements and Cluster::FindIndices.
Clusters are useful for storing per-component data with a ClusterProperty or UserDataMap. Clusters can also have their own CustomProperty objects. All these properties can be created with SceneItem::AddProperty and enumerated with SceneItem::GetLocalProperties. Notice that some types of ClusterProperty require the cluster to be always complete.
using namespace XSI; Application app; Model root = app.GetActiveSceneRoot(); X3DObject myGrid; root.AddGeometry( L"Grid", L"MeshSurface", L"", myGrid ); Cluster myCls; CLongArray indices(9); indices[0] = 8; indices[1] = 16; indices[2] = 24; indices[3] = 32; indices[4] = 40; indices[5] = 48; indices[6] = 56; indices[7] = 64; indices[8] = 72; myGrid.GetActivePrimitive().GetGeometry().AddCluster(siVertexCluster, L"", indices, myCls ); app.LogMessage( L"Cluster type: " + myCls.GetClassIDName() );
#include <xsi_cluster.h>
Public Member Functions | |
Cluster () | |
~Cluster () | |
Cluster (const CRef &in_ref) | |
Cluster (const Cluster &in_obj) | |
bool | IsA (siClassID in_ClassID) const |
siClassID | GetClassID () const |
Cluster & | operator= (const Cluster &in_obj) |
Cluster & | operator= (const CRef &in_ref) |
CClusterElementArray | GetElements () const |
X3DObject | GetCenterReference () const |
CStatus | PutCenterReference (const X3DObject &in_centerObj) |
bool | HasStaticKinematicState () const |
CRefArray | GetStaticKinematicStates () const |
SubComponent | CreateSubComponent () |
CStatus | FindIndex (LONG in_geometryIndex, LONG &out_clusterIndex) const |
CStatus | FindIndices (const CLongArray &in_geometryIndices, CLongArray &out_clusterIndices) const |
bool | IsAlwaysComplete () const |
CStatus | GetGeometryElementFlags (CBitArray &out_flags) const |
Cluster | ( | ) |
Default constructor.
~Cluster | ( | ) |
Default destructor.
bool IsA | ( | siClassID | in_ClassID | ) | const [virtual] |
Returns true if a given class type is compatible with this API class.
in_ClassID | class type. |
Reimplemented from SceneItem.
siClassID GetClassID | ( | ) | const [virtual] |
Creates an object from another object. The newly created object is set to empty if the input object is not compatible.
in_obj | constant class object. |
CClusterElementArray GetElements | ( | ) | const |
Returns an array of geometry indices represented by the cluster.
X3DObject GetCenterReference | ( | ) | const |
Returns the cluster center reference.
Sets the cluster center reference. If the reference is empty, the ClusterCenter operator is deleted.
in_centerObj | Object to be used as the center reference. |
bool HasStaticKinematicState | ( | ) | const |
Returns true if the cluster has a base pose. The base pose is represented by a StaticKinematicState property.
CRefArray GetStaticKinematicStates | ( | ) | const |
Returns an array containing all StaticKinematicState properties on the cluster.
SubComponent CreateSubComponent | ( | ) |
Creates a SubComponent from the cluster type.
CStatus FindIndex | ( | LONG | in_geometryIndex, |
LONG & | out_clusterIndex | ||
) | const |
Returns the cluster index corresponding to the specified geometry component index.
in_geometryIndex | Geometry component index. |
out_clusterIndex | Cluster index corresponding to the geometry index or -1 if the geometry index is not part of the cluster. |
CStatus FindIndices | ( | const CLongArray & | in_geometryIndices, |
CLongArray & | out_clusterIndices | ||
) | const |
Returns the cluster indices corresponding to the specified geometry component indices.
in_geometryIndices | Array of geometry component indices. |
out_clusterIndices | Array of cluster indices corresponding to the geometry indices or -1 if the geometry index is not part of the cluster. |
using namespace XSI; Application app; Model root = app.GetActiveSceneRoot(); X3DObject myGrid; root.AddGeometry( L"Grid", L"MeshSurface", L"", myGrid ); CLongArray indices(3); indices[0] = 0; indices[1] = 3; indices[2] = 22; Geometry myMesh(myGrid.GetActivePrimitive().GetGeometry()); Cluster myCls; myMesh.AddCluster(siVertexCluster, L"", indices, myCls ); Facet myFacet(myMesh.GetFacets().GetItem(0)); CLongArray aPointIndices = myFacet.GetPoints().GetIndexArray(); CLongArray aClusterIndices; myCls.FindIndices(aPointIndices, aClusterIndices); for (LONG i=0; i<(LONG)aClusterIndices.GetCount(); ++i) { if ( aClusterIndices[i] == -1 ) app.LogMessage( L"The point index " + CValue(aPointIndices[i]).GetAsText() + L" is not part of the cluster."); else app.LogMessage(L"Cluster index for point index " + CValue(aPointIndices[i]).GetAsText() + L"= " + CValue(aClusterIndices[i]).GetAsText()); }
bool IsAlwaysComplete | ( | ) | const |
Returns true if the cluster is maintained as always complete. If so, the cluster will always cover all geometry's components even under modeling operations.
Returns an array of flags containing the geometry elements set on this cluster. The array size matches the number of elements on the geometry for this cluster type. A true flag indicates a cluster element, the position of the flag in the array corresponds to the cluster element.
If the cluster was generated by an instance of CGeometryAccessor initialized with a subdivision level > 0, the array matches the number of subdivided elements on the underlying geometry.
out_flags | The element flags for this cluster |
using namespace XSI; Application app; Model root = app.GetActiveSceneRoot(); X3DObject myCone; root.AddGeometry( L"Cone", L"MeshSurface", L"", myCone ); PolygonMesh myMesh(myCone.GetActivePrimitive().GetGeometry()); CClusterPropertyBuilder cpBuilder = myMesh.GetClusterPropertyBuilder(); // add a vertex color property on the geometry, this creates a complete node // cluster on the geometry ClusterProperty color = cpBuilder.AddVertexColor(); // add a weight map property on the geometry, this creates an empty vertex // cluster ClusterProperty wmap = cpBuilder.AddWeightMap(false); // set the color vertex values LONG indices[] = {0, 3, 22}; float colors[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; color.SetValues( indices, colors, 3 ); // set the weight map values float weights[] = { 1.0f, 0.5f, 0.75f }; wmap.SetValues( indices, weights, 3 ); // get a geometry accessor initialized with a subdivision level of 1 CGeometryAccessor ga = myMesh.GetGeometryAccessor(siConstructionModeModeling, siCatmullClark, 1); // get the node and vertex clusters created with CClusterPropertyBuilder CRefArray clusters = ga.GetAllClusters(); // log the clusters element ids for (LONG i=0; i<clusters.GetCount(); i++) { Cluster cls = clusters[i]; CBitArray flags; CStatus st = cls.GetGeometryElementFlags( flags ); st.AssertSucceeded(); app.LogMessage( L"Cluster name: " + cls.GetName() ); app.LogMessage( L"Nb geometry elements: " + CString(flags.GetCount()) ); app.LogMessage( L"Nb cluster elements: " + CString(flags.GetTrueCount()) ); LONG idx = flags.GetIterator(); while( flags.GetNextTrueBit( idx ) ) { app.LogMessage( CString(idx) + L":" + CString( flags[idx] ) ); } }