Пример #1
0
    public FABRIKChain(FABRIKChain parent, List <FABRIKEffector> effectors, int layer)
    {
        FABRIKEffector endEffector = effectors[effectors.Count - 1];

        this.isEndChain = endEffector.transform.childCount == 0;

        // If the current endEffector has no children, then the chain is considered an "end chain"
        // Add a NEW end effector that is offset from the CURRENT end effector's position ...
        // ... where the offset reflects its positioning within the CURRENT end effector's bounding box
        // e.g. Vector3.zero is centered in the box
        if (this.isEndChain)
        {
            effectors.Add(CreateEndEffector(endEffector));
        }

        // Now that we have all effectors accounted for, calculate the length of each segment
        for (int i = 1; i < effectors.Count; i++)
        {
            effectors[i - 1].Length = Vector3.Distance(effectors[i].transform.position, effectors[i - 1].transform.position);
        }

        this.effectors = new List <FABRIKEffector>(effectors);

        this.layer = layer;

        // Add this chain to the parent chain's children
        if (parent != null)
        {
            this.parent = parent;

            parent.children.Add(this);
        }
    }
Пример #2
0
        /// <summary>
        /// Performs a FABRIK inverse kinematic solve, modifying the FABRIKChain points array.
        /// </summary>
        public static void Solve(FABRIKChain chain,
                                 int maxIterations   = 8,
                                 float solveDistance = 0.01f)
        {
            var start  = chain.start;
            var target = chain.target;

            var sumLengths      = chain.lengths.Query().Fold((sum, l) => sum + l);
            var sqrDistToTarget = (target - start).sqrMagnitude;

            if (sqrDistToTarget > sumLengths * sumLengths)
            {
                // Target out of reach, straighten towards it.
                var toTarget = (target - start).normalized;
                for (int i = 0; i + 1 < chain.points.Length; i++)
                {
                    chain.points[i + 1] = chain.points[i] + toTarget * chain.lengths[i];
                }
            }
            else
            {
                // Target within reach.
                var iterations       = 0;
                var sqrDistToGoal    = (chain.points[chain.points.Length - 1] - target).sqrMagnitude;
                var solveDistanceSqr = solveDistance * solveDistance;
                while (sqrDistToGoal > solveDistanceSqr && iterations++ < maxIterations)
                {
                    BackwardSolve(chain);
                    ForwardSolve(chain);
                    sqrDistToGoal = (chain.points[chain.points.Length - 1] - target).sqrMagnitude;
                }
            }
        }
Пример #3
0
    private FABRIKChain LoadSystem(Transform transform, FABRIKChain parent = null, int layer = 0)
    {
        List <FABRIKEffector> effectors = new List <FABRIKEffector>();

        // Use parent chain's end effector as our sub-base effector, e.g:
        //                 [D]---[E]
        //        1       /    2        1 = [A, B, C]
        // [A]---[B]---[C]              2 = [C, D, E]
        //                \    3        3 = [C, F, G]
        //                 [F]---[G]
        if (parent != null)
        {
            effectors.Add(parent.EndEffector);
        }

        // childCount > 1 is a new sub-base
        // childCount = 0 is an end chain (added to our list below)
        // childCount = 1 is continuation of chain
        while (transform != null)
        {
            FABRIKEffector effector = transform.gameObject.GetComponent <FABRIKEffector>();

            if (effector == null)
            {
                break;
            }

            effectors.Add(effector);

            if (transform.childCount != 1)
            {
                break;
            }

            transform = transform.GetChild(0);
        }

        FABRIKChain chain = new FABRIKChain(parent, effectors, layer);

        chains.Add(chain);

        // Add to our end chain list if it is an end chain
        if (chain.IsEndChain)
        {
            endChains.Add(transform.gameObject.name, chain);
        }
        // Else iterate over each of the end effector's children to create a new chain in the layer above
        else
        {
            foreach (Transform child in transform)
            {
                LoadSystem(child, chain, layer + 1);
            }
        }

        return(chain);
    }
Пример #4
0
 /// <summary>
 /// Performs a single forward FABRIK solver iteration on the argument chain.
 /// </summary>
 public static void ForwardSolve(FABRIKChain chain)
 {
     // Move the first point to the start and project forward along chain.
     chain.points[0] = chain.start;
     for (int i = 0; i + 1 < chain.points.Length; i++)
     {
         var linkDir = (chain.points[i + 1] - chain.points[i]).normalized;
         chain.points[i + 1] = chain.points[i] + linkDir * chain.lengths[i];
     }
 }
Пример #5
0
    public override void OnFABRIK()
    {
        float speed = 100.0F;
        float step  = Time.deltaTime * speed;

        FABRIKChain right = GetEndChain("mixamorig:RightHand_end_effector");
        FABRIKChain left  = GetEndChain("mixamorig:LeftHand_end_effector");

        right.Target = Vector3.MoveTowards(right.EndEffector.Position, sphere_right.position, step);
        left.Target  = Vector3.MoveTowards(left.EndEffector.Position, sphere_left.position, step);
    }
Пример #6
0
    public void Start()
    {
        rootChain = CreateSystem(rootObject.transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return(y.layer.CompareTo(x.layer)); });

        if (initialTarget != null)
        {
            endChains[0].Target = initialTarget.position;
        }
    }
Пример #7
0
    public void Awake()
    {
        // Load our IK system from the root transform
        rootChain = LoadSystem(transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return(y.Layer.CompareTo(x.Layer)); });

        foreach (FABRIKChain chain in chains)
        {
            chain.CalculateSummedWeight();
        }
    }
Пример #8
0
    // this can be expanded to build branching limbs and so return a list of chains.
    // the root chain should be tracked, and in the update function each chain will need backward() called on it
    private FABRIKChain buildLimb(Transform limbOrigin, FABRIKChain parentChain = null, int layer = 0)
    {
        List <FABRIKEffector> sections = new List <FABRIKEffector>(config.sectionCount + (parentChain == null ? 1 : 2));

        if (parentChain != null)
        {
            sections.Add(parentChain.EndEffector);
        }

        buildLimbSection(config.sectionCount, limbOrigin, Vector3.zero, in sections);

        return(new FABRIKChain(parentChain, sections, layer));
    }
Пример #9
0
    public void Awake()
    {
        rootObject = new GameObject("FABRIK-Root-" + transform.name);

        rootObject.transform.position = transform.position;
        rootObject.transform.rotation = transform.rotation;

        transform.parent = rootObject.transform;

        rootChain = CreateSystem(rootObject.transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return(y.layer.CompareTo(x.layer)); });
    }
Пример #10
0
    public void Awake()
    {
        rootObject = new GameObject("FABRIK-Root-" + transform.name);

        rootObject.transform.position = transform.position;
        rootObject.transform.rotation = transform.rotation;

        transform.parent = rootObject.transform;

        rootChain = CreateSystem(rootObject.transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return y.layer.CompareTo(x.layer); } );
    }
Пример #11
0
    public override void OnFABRIK()
    {
        float speed = 10.0F;
        float step  = Time.deltaTime * speed;

        FABRIKChain up_left    = GetEndChain("up_left");
        FABRIKChain down_left  = GetEndChain("down_left");
        FABRIKChain up_right   = GetEndChain("up_right");
        FABRIKChain down_right = GetEndChain("down_right");

        up_left.Target    = Vector3.MoveTowards(up_left.EndEffector.Position, targetTransformA.position, step);
        down_left.Target  = Vector3.MoveTowards(down_left.EndEffector.Position, targetTransformB.position, step);
        up_right.Target   = Vector3.MoveTowards(up_right.EndEffector.Position, targetTransformC.position, step);
        down_right.Target = Vector3.MoveTowards(down_right.EndEffector.Position, targetTransformD.position, step);
    }
Пример #12
0
    public FABRIKChain(int layer, FABRIKChain parent, params FABRIKEffector [] effectors)
    {
        this.layer = layer;

        this.endEffector = effectors.Length - 1;

        this.effectors.AddRange(effectors);

        this.parent = parent;

        if (parent != null)
        {
            parent.children.Add(this);
        }
    }
Пример #13
0
    public override void OnFABRIK()
    {
        target.position = new Vector3(target.position.x, 0, target.position.z);
        FABRIKChain end = GetEndChain("Cylinder (6)_end_effector");

        end.Target = Vector3.MoveTowards(end.EndEffector.Position, target.position, speed * Time.deltaTime);

        UpdateLinks();

        //if (Input.GetKeyDown(KeyCode.P))
        //{
        //	float dist = 0f;
        //	Debug.Log(TargetReachable(ref dist).ToString() + "__" + dist.ToString());
        //}
    }
Пример #14
0
    public FABRIKChain(int layer, FABRIKChain parent, params FABRIKEffector [] effectors)
    {
        this.layer = layer;

        this.endEffector = effectors.Length - 1;

        this.effectors.AddRange(effectors);

        this.parent = parent;

        if(parent != null)
        {
            parent.children.Add(this);
        }
    }
Пример #15
0
    private FABRIKChain CreateSystem(Transform transform, FABRIKChain parent = null, int layer = 0)
    {
        List <FABRIKEffector> effectors = new List <FABRIKEffector>();

        FABRIKEffector effector = null;

        // Use parent chain's end effector as our sub-base effector
        if (parent != null)
        {
            effector = parent.EndEffector;

            effectors.Add(effector);
        }

        // childCount > 1 is a new sub-base, childCount = 0 is an end chain (added to our list below), childCount = 1 is continuation of chain
        while (transform)
        {
            effector = FABRIKEffector.FetchComponent(transform.gameObject).Constructor(effector);

            effectors.Add(effector);

            if (transform.childCount != 1)
            {
                break;
            }

            transform = transform.GetChild(0);
        }

        FABRIKChain chain = new FABRIKChain(layer, parent, effectors.ToArray());

        chains.Add(chain);

        if (transform.childCount == 0)
        {
            endChains.Add(chain);
        }
        else
        {
            foreach (Transform child in transform)
            {
                CreateSystem(child, chain, layer + 1);
            }
        }

        return(chain);
    }
Пример #16
0
    public void Awake()
    {
        // Load our IK system from the root transform
        rootChain = LoadSystem(transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return(y.Layer.CompareTo(x.Layer)); });

        foreach (FABRIKChain chain in chains)
        {
            chain.CalculateSummedWeight();
            Debug.Log($"chain.EndEffector {chain.EndEffector} chain.BaseEffector  {chain.BaseEffector}");
        }

        Debug.Log($"rootChain.EndEffector {rootChain.EndEffector} rootChain.BaseEffector  {rootChain.BaseEffector}");
        Debug.Log(endChains.Count);
    }
Пример #17
0
    public FABRIKChain(int layer, FABRIKChain parent, bool constrain, float constrainAngle, params FABRIKEffector[] effectors)
    {
        this.layer          = layer;
        this.Constrain      = constrain;
        this.ConstrainAngle = constrainAngle;

        this.endEffector = effectors.Length - 1;

        this.effectors.AddRange(effectors);

        this.parent = parent;

        if (parent != null)
        {
            parent.children.Add(this);
        }
    }
Пример #18
0
 /// <summary>
 /// Performs a single backwards FABRIK solver iteration on the argument chain.
 /// </summary>
 public static void BackwardSolve(FABRIKChain chain, Vector3?warmStartDir = null)
 {
     // Move the last point to the target and project backwards along chain.
     chain.points[chain.points.Length - 1] = chain.target;
     for (int i = chain.points.Length - 1; i - 1 >= 0; i--)
     {
         Vector3 linkDir;
         if (warmStartDir.HasValue && i == chain.points.Length - 1)
         {
             linkDir = warmStartDir.Value.normalized;
         }
         else
         {
             linkDir = (chain.points[i - 1] - chain.points[i]).normalized;
         }
         chain.points[i - 1] = chain.points[i] + linkDir * chain.lengths[i - 1];
     }
 }
Пример #19
0
    private FABRIKChain CreateSystem(Transform transform, FABRIKChain parent = null, int layer = 0)
    {
        List<FABRIKEffector> effectors = new List<FABRIKEffector>();

        FABRIKEffector effector = null;

        // Use parent chain's end effector as our sub-base effector
        if(parent != null)
        {
            effector = parent.EndEffector;

            effectors.Add(effector);
        }

        // childCount > 1 is a new sub-base, childCount = 0 is an end chain (added to our list below), childCount = 1 is continuation of chain
        while(transform)
        {
            effector = FABRIKEffector.FetchComponent(transform.gameObject).Constructor(effector);

            effectors.Add(effector);

            if(transform.childCount != 1)
            {
                break;
            }

            transform = transform.GetChild(0);
        }

        FABRIKChain chain = new FABRIKChain(layer, parent, effectors.ToArray());

        chains.Add(chain);

        if(transform.childCount == 0)
        {
            endChains.Add(chain);
        }
        else foreach(Transform child in transform)
        {
            CreateSystem(child, chain, layer + 1);
        }

        return chain;
    }
Пример #20
0
    public FABRIKChain(FABRIKChain parent, List <FABRIKEffector> effectors, int layer)
    {
        for (int i = 1; i < effectors.Count; i++)
        {
            effectors[i - 1].Length = Vector3.Distance(effectors[i].transform.position, effectors[i - 1].transform.position);
        }

        this.effectors = new List <FABRIKEffector>(effectors);

        this.layer = layer;

        // Add this chain to the parent chain's children
        if (parent != null)
        {
            this.parent = parent;

            parent.children.Add(this);
        }
    }
Пример #21
0
    public void Awake()
    {
        Quaternion q = Quaternion.LookRotation(Vector3.right, Vector3.up);

        Debug.Log("Forward = " + (q * Vector3.forward));
        Debug.Log("Right = " + (q * Vector3.right));
        Debug.Log("Up = " + (q * Vector3.up));

        // Load our IK system from the root transform
        rootChain = LoadSystem(transform);

        // Inversely sort by layer, greater-first
        chains.Sort(delegate(FABRIKChain x, FABRIKChain y) { return(y.Layer.CompareTo(x.Layer)); });

        foreach (var key in endChains)
        {
            Debug.Log(key);
        }
    }
Пример #22
0
 private void Awake()
 {
     limbChain = buildLimb(transform);
     length    = config.sectionCount * config.limbSectionPrefab.childOffset.z;
 }