Softimage SDK Programmer's Guide > Plug-in Development > Modeling >

# Getting at Clusters

This section demonstrates how to create, access, and modify clusters and their elements on 3D objects. All of the code in this section belongs to one large script, but is presented in modules according to usage. The topics covered include:

- Example: Accessing the cluster's elements, parent, and type

- Example: Create a cluster

- Example: Find the cluster in the scene

- Example: Add points to the cluster

- Example: Remove points from the cluster

- Example: Copying clusters

- Example: Deleting clusters

Example:Accessing the cluster's elements, parent, and type

A lot of the tasks when working with cluster involve using the cluster's elements. You can access the elements through the SubComponent object (Cluster.CreateSubComponent). From there, you can access the 3D object that is parenting the cluster (SubComponent.Parent3DObject).

Tip

You can also access the elements through the Cluster.Elements property, which returns the collection of geometry indices as a ClusterElementCollection.

This function prints the name of the cluster's parent, which elements it contains, and the type of elements it contains. The other examples in this section also refer to this function.

    Function printClusterInfo( in_cluster )
    	' Make sure the inbound object is a valid cluster
    	If TypeName( in_cluster ) = "Cluster" Then
    		' Get the cluster's elements
    		Set oMembers = in_cluster.CreateSubComponent
    		aIndices = oMembers.ElementArray

    		' Format its values
    		sElementData = ""
    		For i = 0 To UBound( aIndices )
    			sElementData = sElementData & ", " & in_cluster.Type
    									& "[" & aIndices(i) & "]"
    		Next
    		sElementData = vbTab & vbTab & Right( sElementData, Len(sElementData)-2 )

    		' Print them out
    		LogMessage "Current cluster contains these element(s) under the '" _
    				& oMembers.Parent3DObject.Name & "' object:" & vbLf _
    				& sElementData & vbLf
    		LogMessage "=========================================================="

    		printClusterInfo = True
    	Else
    		LogMessage "Object is not a valid cluster."
    		printClusterInfo = False
    	End If
    End Function

Example:Create a cluster

This example demonstrates how to create a cluster (using the object model) from a 3D object (in this case, a grid).

Note

This code snippet uses the printClusterInfo() function described in Example: Accessing the cluster's elements, parent, and type.

After you create the grid, you can add a point (vertex) cluster on it using the Geometry.AddCluster method. Notice that you have to create the cluster on the Geometry object, not directly on the grid.

    	' Create the grid
    	Set oGrid = ActiveSceneRoot.AddGeometry( "Grid", "MeshSurface", "wall" )

    	' You can use an array variable to save the point indices
    	aPointsForCluster = Array( 21,22,31,40,41 )

    	' The indices used in this method correspond to the indexing order of the
    	' element for the 3D object
    	Set oCluster = oGrid.ActivePrimitive.Geometry.AddCluster( _
    									siVertexCluster, _
    									"wallpaper", _
    									aPointsForCluster _
    								)

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'wall' object:
    		'pnt[21], pnt[23], pnt[29], pnt[31], pnt[33], pnt[39], pnt[41]
    '"
    'INFO : "=========================================================="

Example: Find the cluster in the scene

This step is not necessary if you have already created a cluster, but is provided simply as a demonstration of finding an existing cluster in the scene assuming you know only that you want the point cluster on a polymsh grid object.

Note

This code snippet follows the one in Example: Create a cluster and uses the printClusterInfo() function described in Example: Accessing the cluster's elements, parent, and type.

Just to make it interesting, let's add a couple more clusters.

    	' Add an edge cluster to the grid
    	aEdgesForCluster = Array( 28,31,47,50,66 )
    	Set oECls = oGrid.ActivePrimitive.Geometry.AddCluster( _
    									siEdgeCluster, _
    									"paint", _
    									aEdgesForCluster _
    									)

The printClusterInfo(oECls) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'wall' object:
    		'edge[28], edge[31], edge[47], edge[50], edge[66]
    '"
    'INFO : "=========================================================="

This piece of code adds a cube and makes another point cluster on it. Notice how you can use either an array variable or pass an array directly to the argument.

    	' Create a cube and add another point cluster to it
    	Set oCube = ActiveSceneRoot.AddGeometry( "Cube", "MeshSurface", "chair" )
    	Set oPCls = oCube.ActivePrimitive.Geometry.AddCluster( _
    									siVertexCluster, _
    									"seat", _
    									Array( 1,3,5,7 ) _
    							     )

The printClusterInfo(oPCls) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'chair' object:
    		'pnt[1], pnt[3], pnt[5], pnt[7]
    '"
    'INFO : "=========================================================="

Now the fun begins! This piece gets each object with mesh geometry in the scene and then gets the cluster collection from each using the Geometry.Clusters property. Make sure to trap as many potential errors as you can, since you may be working with empty or invalid objects at some point.

    	' Using the X3DObject.FindChildren method and specifying the mesh family
    	' (3rd argument) returns a collection of all polygon mesh objects that
    	' appear in the hierarchy under the scene root. From there we can find
    	' which one matches our criteria.
    	Set oAllObjects = ActiveSceneRoot.FindChildren( , , siMeshFamily )

    	' Loop through the collection to find any Point clusters
    	For Each obj In oAllObjects
    		' Get all the clusters on the mesh  geometry as a collection
    		Set oAllClusters = obj.ActivePrimitive.Geometry.Clusters

    		' Loop through the collection to find any Point clusters
    		For Each cls In oAllClusters
    			' Only deal with point clusters
    			If cls.Type = "pnt" Then
    				' Get the one whose parent = grid
    				Set oPoint = cls.CreateSubComponent
    				Set oParent = oPoint.Parent3DObject

    				' If it matches, grab it & run
    				If oParent.IsKindOf( "Grid" ) Then
    					Set oCluster = cls
    					Exit For
    				End If
    			End If
    		Next
    	Next

Example: Add points to the cluster

This example demonstrates how to add points to an existing point cluster. In this case, you have to use a mixture of the object model and scripting commands.

Note

This code snippet follows the one in Example: Find the cluster in the scene and uses the printClusterInfo() function described in Example: Accessing the cluster's elements, parent, and type.

    	' Create a new SubComponent object so you can specify which elements to add.
    	Set oSubComp = oCluster.CreateSubComponent

    	' Use the SubComponent.AddElement method to add each point separately
    	' to the subcomponent.
    	oSubComp.AddElement 23
    	oSubComp.AddElement 29
    	oSubComp.AddElement 33
    	oSubComp.AddElement 39

    	' Add the subcomponent to the cluster using the SIAddToCluster command.
    	SIAddToCluster oCluster, oSubComp

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'wall' object:
    		'pnt[21],pnt[22],pnt[23],pnt[29],pnt[31],pnt[33],pnt[39],pnt[40],pnt[41]
    '"
    'INFO : "=========================================================="

Example: Remove points from the cluster

When you want to remove points (or any element) from a cluster, you have to use the SubComponent.RemoveElement method to clear the elements you want to keep from the SubComponent object and then use the SIRemoveFromCluster command to remove the leftover elements from the actual cluster.

Note

This code snippet follows the one in Example: Add points to the cluster and uses the printClusterInfo() function described in Example: Accessing the cluster's elements, parent, and type.

In this case, we want to remove points 22 and 40, so we have to remove "pnt[21,23,29,31,33,39,41]" from the subcomponent and then use it with SIRemoveFromCluster:

    	' Create a new SubComponent object to specify which elements to remove.
    	Set oSubComp = oCluster.CreateSubComponent

    	' Remove the elements you want to keep from the subcomponent
    	oSubComp.RemoveElement 21
    	oSubComp.RemoveElement 23
    	oSubComp.RemoveElement 29
    	oSubComp.RemoveElement 31
    	oSubComp.RemoveElement 33
    	oSubComp.RemoveElement 39
    	oSubComp.RemoveElement 41

    	' Remove the specified subcomponent from the cluster
    	SIRemoveFromCluster oCluster, oSubComp

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'wall' object:
    		'pnt[21], pnt[23], pnt[29], pnt[31], pnt[33], pnt[39], pnt[41]
    '"
    'INFO : "=========================================================="

Example: Copying clusters

When you want to copy an entire cluster from one object to another, you have to use the CopyCluster command

Note

This code snippet follows the one in Example: Remove points from the cluster.

    '
    ' Copying clusters can only be done via the CopyCluster command. This example
    ' demonstrates how to copy clusters between objects.
    Set oTarget = ActiveSceneRoot.AddGeometry( "Grid", "MeshSurface", "floor" )
    CopyCluster oCluster, oTarget

    ' Now you have to find it in the scene again (since the CopyCluster command
    ' doesn't return the newly created cluster). It's probably the first one in
    ' the bunch.
    Set oNewCls = oTarget.ActivePrimitive.Geometry.Clusters(0)

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

    'INFO : "Current cluster contains these element(s) under the 'floor' object:
    		'pnt[21], pnt[23], pnt[29], pnt[31], pnt[33], pnt[39], pnt[41]
    '"
    'INFO : "=========================================================="

Example: Deleting clusters

Now that you've created a copy of the cluster on the new object, delete the old one. For this you need to use the RemoveCluster command:

Note

This code snippet follows the one in Example: Copying clusters.

    RemoveCluster oCluster