Files
2025-09-29 00:52:08 +02:00

172 lines
5.9 KiB
Plaintext
Executable File

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 = #()
)
)