struct SkinnedObject_Bone_VertexWeight ( VertID, Weight ) struct SkinnedObject_Bone ( --Node = Point AxisTripod:True Cross:False Size:1.0 WireColor:Blue , Node = Dummy(), VertexWeightTable = #(), --This just stores the references to any children nodes. Mainly used for keeping track of particle helpers and lights etc.. ChildNodeArray = #(), --Clones and return This. VertexIDs are offset by passed VertexIDOffset value. fn Clone VertIDOffset:0 = ( ClonedBone = SkinnedObject_Bone() ClonedBone.CreateFromNode This.Node ClonedBone.CopyVertexWeightTable This.VertexWeightTable VertIDOffset:VertIDOffset ClonedBone.ChildNodeArray = This.ChildNodeArray --Return the new cloned bone Return ClonedBone ), /*-------------------------------------------------- Sets up this bone to mirror the animation of the passed node */--------------------------------------------------- fn CreateFromNode InputNode = ( --Logic for making dummys match the bounds of the passed object. Doesn't work that well atm NodeBoundingBox = NodeGetBoundingBox InputNode InputNode.Transform NodeBoundingBox = NodeBoundingBox[2] - NodeBoundingBox[1] This.Node.Boxsize = [NodeBoundingBox.x, NodeBoundingBox.y, NodeBoundingBox.z] --This.Node.ObjectOffsetPos = (InputNode.Center - This.Node.Pivot) --This.Node.Pivot = InputNode.Center for Child in InputNode.Children do ( Append ChildNodeArray Child ) --First we must move the bone node to the input nodes position so that auto key doesn't create a really weird interpolation to the origin if the animation time frame doesn't start at zero. This.Node.Transform = InputNode.Transform --Get the timespan of the max scene StartFrame = AnimationRange.Start.Frame as integer EndFrame = AnimationRange.End.Frame as integer --For each frame key the bone node against the input node for CurrentFrame = StartFrame to EndFrame do ( animate on, at time CurrentFrame ( This.Node.Transform = InputNode.Transform ) ) --Copy other required tracks across --[R.G] Removing this for now --RSCopyTrack InputNode This.Node "Visibility" --Clean up the keys. Not needed for time being. --ReduceKeys This.Node.Transform.Controller 0.5 1f ), /*-------------------------------------------------- Copies the passed vertex weight table into this bone instance. If passed the VertIDOffset will offset the VertIDs */--------------------------------------------------- fn CopyVertexWeightTable InputVertexWeightTable VertIDOffset:0 = ( This.VertexWeightTable = #() for VertexWeight in InputVertexWeightTable do ( CopiedVertexWeight = SkinnedObject_Bone_VertexWeight() CopiedVertexWeight.VertID = VertexWeight.VertID + VertIDOffset CopiedVertexWeight.Weight = VertexWeight.Weight Append This.VertexWeightTable CopiedVertexWeight ) ), /*-------------------------------------------------- Processes the weights from the passed table creating a vertex weight table. All weights that are 0.0 are ignored to save heap memory. The distinction between a vertex weight table and a normal weight table is that the vertex weight table stores the VertID rather than it being implicit by the position (within the array) of the value in a normal weight table. */--------------------------------------------------- fn MapWeightTable InputWeightTable = ( This.VertexWeightTable = #() VertID = 1 for Weight in InputWeightTable do ( --If the weight is greater than 0.0 then add it, else we don't bother. Saves on heap memory if( Weight > 0 ) then ( Append This.VertexWeightTable (SkinnedObject_Bone_VertexWeight VertID:VertID Weight:Weight) ) VertID += 1 ) ), /*-------------------------------------------------- Reorganises the weights of the bone so that they are order correctly */--------------------------------------------------- fn CondenseWeights = ( --First we reorder all the weights by VertID fn SortFunction LeftVertexWeight RightVertexWeight = ( if( LeftVertexWeight.VertID < RightVertexWeight.VertID ) then return -1 if( LeftVertexWeight.VertID == RightVertexWeight.VertID ) then return 0 if( LeftVertexWeight.VertID > RightVertexWeight.VertID ) then return 1 ) QSort VertexWeightTable SortFunction --Then set the VertID to ascend linearlly 1..2... for i = 1 to VertexWeightTable.Count do ( VertexWeightTable[i].VertID = i ) ), /*-------------------------------------------------- Returns all the verts that this bone affects */--------------------------------------------------- fn GetVertIDArray = ( return (for VertexWeight in This.VertexWeightTable collect VertexWeight.VertID) ), /*--------------------------------------------------- Reorders the VertexWeights of the bones with the passed remap table */--------------------------------------------------- fn ReorderVertIDs VertIDRemapTable = ( for VertexWeight in VertexWeightTable do ( VertexWeight.VertID = VertIDRemapTable.GetNewVertID( VertexWeight.VertID ) ) ), /*-------------------------------------------------- Checks if this bone has any VertexWeights that affect any matching verts in the passed array */--------------------------------------------------- fn HasConflictingWeights InputVertIDArray = ( for VertexWeight in This.VertexWeightTable do ( if ( FindItem InputVertIDArray VertexWeight.VertID ) != 0 then ( return True --A conflict has been found ) ) return False --No conflict was found ), /*--------------------------------------------------- Destroys everything related to this bone ready for GC */--------------------------------------------------- fn Destroy = ( Delete This.Node This.ChildNodeArray = #() This.VertexWeightTable = #() ) )