using UnityEngine; using System.Collections.Generic; namespace BioIK { public class Model { //Reference to the character private BioIK Character; //Reference to root private BioSegment Root; //Offset to world private double OPX, OPY, OPZ; //Offset rosition to world frame private double ORX, ORY, ORZ, ORW; //Offset rotation to world frame private double OSX, OSY, OSZ; //Offset scale to world Frame //Linked list of nodes in the model public Node[] Nodes = new Node[0]; //Global pointers to the IK setup public MotionPtr[] MotionPtrs = new MotionPtr[0]; public ObjectivePtr[] ObjectivePtrs = new ObjectivePtr[0]; //Assigned Configuraton private double[] Configuration; private double[] Gradient; private double[] Losses; //Simulated Configuration private double[] PX,PY,PZ,RX,RY,RZ,RW; private double[] SimulatedLosses; //Degree of Freedom private int DoF; public Model(BioIK character) { Character = character; //Set Root Root = Character.FindSegment(Character.transform); //Create Root AddNode(Root); //Build Model BioObjective[] objectives = CollectObjectives(Root, new List()); for(int i=0; i chain = Character.GetChain(Root, objectives[i].Segment); for(int j=1; j objectives) { for(int i=0; i reverseChain = new List(); reverseChain.Add(Transform); Node p = parent; while(p != null) { reverseChain.Add(p.Transform); p = p.Parent; } reverseChain.Reverse(); Chain = reverseChain.ToArray(); } //Adds a child to this node public void AddChild(Node child) { System.Array.Resize(ref Childs, Childs.Length+1); Childs[Childs.Length-1] = child; } //Recursively refreshes the current transform data public void Refresh() { //Local if(Joint == null) { Vector3 lp = Transform.localPosition; Quaternion lr = Transform.localRotation; LPX = lp.x; LPY = lp.y; LPZ = lp.z; LRX = lr.x; LRY = lr.y; LRZ = lr.z; LRW = lr.w; } else { XValue = Joint.X.GetTargetValue(true); YValue = Joint.Y.GetTargetValue(true); ZValue = Joint.Z.GetTargetValue(true); Joint.ComputeLocalTransformation(XValue, YValue, ZValue, out LPX, out LPY, out LPZ, out LRX, out LRY, out LRZ, out LRW); } Vector3 ws = Transform.lossyScale; WSX = ws.x; WSY = ws.y; WSZ = ws.z; //World ComputeWorldTransformation(); //Feed Forward foreach(Node child in Childs) { child.Refresh(); } } //Updates local and world transform, and feeds the joint variable configuration forward to all childs public void FeedForwardConfiguration(double[] configuration, bool updateWorld = false) { //Assume no local update is required bool updateLocal = false; if(XEnabled && configuration[XIndex] != XValue) { XValue = configuration[XIndex]; updateLocal = true; } if(YEnabled && configuration[YIndex] != YValue) { YValue = configuration[YIndex]; updateLocal = true; } if(ZEnabled && configuration[ZIndex] != ZValue) { ZValue = configuration[ZIndex]; updateLocal = true; } //Only update local transformation if a joint value has changed if(updateLocal) { Joint.ComputeLocalTransformation(XValue, YValue, ZValue, out LPX, out LPY, out LPZ, out LRX, out LRY, out LRZ, out LRW); updateWorld = true; } //Only update world transformation if local transformation (in this or parent node) has changed if(updateWorld) { ComputeWorldTransformation(); } //Feed forward the joint variable configuration foreach(Node child in Childs) { child.FeedForwardConfiguration(configuration, updateWorld); } } //Simulates a single transform modification while leaving the whole data structure unchanged //Returns the resulting Cartesian posture transformations in the out values public void SimulateModification( double[] configuration ) { double[] px=Model.PX; double[] py=Model.PY; double[] pz=Model.PZ; double[] rx=Model.RX; double[] ry=Model.RY; double[] rz=Model.RZ; double[] rw=Model.RW; for(int i=0; i