Inheritance: MonoBehaviour
Example #1
0
    private IEnumerator StopSolver(FABRIK solver)
    {
        yield return(new WaitForSeconds(FABRIKSolveTimeSeconds));

        solver.enabled = false;

        SetEnd(fromCap, rootLink);
        SetEnd(toCap, lastLink);

        Rigidbody         parentRigid = rootLink.GetComponent <Rigidbody>();
        ConfigurableJoint parentJoint = parentRigid.GetComponent <ConfigurableJoint>();

        for (int i = 0; i < numLinks; i++)
        {
            parentRigid.isKinematic = false;
            parentRigid.transform.SetParent(rootLink.parent);

            Transform childT = parentRigid.transform.GetChild(0);
            if (childT.CompareTag("joint"))
            {
                Rigidbody child = childT.GetComponent <Rigidbody>();
                parentJoint.connectedBody = child;
                parentJoint = child.GetComponent <ConfigurableJoint>();
                parentRigid = child;
            }
        }

        //set the FABRIK root to under this for easier cleanup
        rootLink.parent.SetParent(this.transform);
    }
Example #2
0
        public IkModifier(ModifierInfo mi, Entity casterEntity, Entity targetEntity,
                          Environment environment,
                          CollectionOfInteractions modifierInteractionCollection) : base(mi, casterEntity, targetEntity, environment, modifierInteractionCollection)
        {
            this.environment = environment;
            this.info        = (IkInfo)mi;
            mapCollider      = environment.MapColliders();

            caster = casterEntity.GetComponent <SkillComponent>().Character;
            FrameAndSecondsConverter fasc = FrameAndSecondsConverter._30Fps;

            aimAt                    = 0;
            aimDuration              = fasc.FramesToSeconds(info.Config.aimDuration);
            aimLogicDuration         = fasc.FramesToSeconds(info.Config.aimLogicDuration);
            aimInterpolationDuration = fasc.FramesToSeconds(info.Config.aimInterpolationDuration);
            startupAt                = aimAt + aimDuration;
            startupDuration          = fasc.FramesToSeconds(info.Config.startupDuration);
            activeAt                 = startupAt + startupDuration;
            activeDuration           = fasc.FramesToSeconds(info.Config.activeDuration);
            recoveryAt               = activeAt + activeDuration;
            recoveryDuration         = fasc.FramesToSeconds(info.Config.recoveryDuration);
            totalDuration            = recoveryAt + recoveryDuration;
            target                   = environment.FindNearbyCharacters(
                caster, Vector3.zero, 999,
                new[] { FindingFilter.ExcludeMe, FindingFilter.ExcludeDead, FindingFilter.ExcludeAllies }
                )[0];
            fabrik = caster.GameObject().GetComponent <FABRIK>();
            IKSolverFABRIK solverFabrik = (IKSolverFABRIK)fabrik.GetIKSolver();

            ikJoint       = solverFabrik.bones[solverFabrik.bones.Length - 1].transform;
            ikJointParent = solverFabrik.bones[solverFabrik.bones.Length - 2].transform;
        }
Example #3
0
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        FABRIK fabrik = target as FABRIK;

        if (GUILayout.Button("Generate FABRIK Effector System"))
        {
            fabrik.CreateSystem();
        }
    }
Example #4
0
    public static void Solve(HandState[] states, IKPointTarget[] pointTargets, IKGapTarget[] gapTargets)
    {
        if (!states[0].active && !states[1].active)
        {
            return;
        }

        FABRIK data = new FABRIK(states, pointTargets, gapTargets);

        for (int i = 0; i < 5; i++)
        {
            data.SolveStep();
        }
        data.Apply(states);
    }
Example #5
0
    protected override void ShowVisuals(IPowerable g1, IPowerable g2)
    {
        if (g1 is RoverStation && g2 is RoverInput)
        {
            station = g1 as RoverStation;
            station.OnRoverAttachedChange(g2 as RoverInput);
        }
        else if (g2 is RoverStation && g1 is RoverInput)
        {
            station = g2 as RoverStation;
            station.OnRoverAttachedChange(g1 as RoverInput);
        }

        fromCap = CreateCap(Data.fromPos, Data.fromRot, Data.fromScale);
        toCap   = CreateCap(Data.toPos, Data.toRot, Data.toScale);

        Vector3 fromPos = fromCap.position,
                toPos   = toCap.position;

        float distanceBetween = Vector3.Distance(fromPos, toPos);

        numLinks = Mathf.RoundToInt(distanceBetween / linkSeparation) + LinkNumberAdjustment;

        rootLink = GameObject.Instantiate <Transform>(UmbilicalLinkPrefab);
        rootLink.SetParent(this.transform);
        rootLink.position = fromPos;
        rootLink.rotation = Data.fromRot;

        Transform parent = rootLink;

        for (int i = 0; i < numLinks - 1; i++)
        {
            Transform link = GameObject.Instantiate <Transform>(UmbilicalLinkPrefab);
            link.position = parent.position + Vector3.forward * linkSeparation;
            link.SetParent(parent);
            link.SetAsFirstSibling();
            parent = link;
        }

        lastLink = parent;

        solver                = rootLink.gameObject.AddComponent <FABRIK>();
        solver.Constrain      = true;
        solver.ConstrainAngle = FABRIKAngleConstraint;
        solver.initialTarget  = toCap;

        StartCoroutine(StopSolver(solver));
    }
        public void Execute(Entity entity, int index, ref ArmComponent armComponent,
                            [ReadOnly] ref Translation translation, [ReadOnly] ref Rotation rotation)
        {
            float  armBoneLength   = armComponent.armBoneLength;
            float3 handUp          = armComponent.handUp;
            float  armBendStrength = armComponent.armBendStrength;

            Matrix4x4[] matrices = new Matrix4x4[17];

            DynamicBuffer <ArmChainsBuffer>    armChainsBuffer    = armChainsBufferLookup[entity];
            DynamicBuffer <FingerChainsBuffer> fingerChainsBuffer = fingerChainsBufferLookup[entity];
            DynamicBuffer <ThumbChainsBuffer>  thumbChainsBuffer  = thumbChainsBufferLookup[entity];

            ///////////////////////////
            // Resting position for hand
            float time = worldTime + armComponent.timeOffset;

            // solve the arm IK chain first
            float3 anchor = translation.Value;

            //float3 anchor = new float3();
            FABRIK.SolveViaBuffer(armChainsBuffer.Reinterpret <float3>(), armBoneLength, anchor, armComponent.handTarget, handUp * armBendStrength);

            Quaternion q = rotation.Value;
            float3     transformRight = math.normalize(math.mul(q, directions.right));

            // figure out our current "hand vectors" from our arm orientation
            float3 handForward = math.normalize(util.Last(armChainsBuffer.Reinterpret <float3>(), 0) - util.Last(armChainsBuffer.Reinterpret <float3>(), 1));

            handUp = math.normalize(math.cross(handForward, transformRight));
            float3 handRight = math.cross(handUp, handForward);

            // create handspace-to-worldspace matrix
            armComponent.handMatrix = Matrix4x4.TRS(util.Last(armChainsBuffer.Reinterpret <float3>(), 0), Quaternion.LookRotation(handForward, handUp), directions.one);

            // how much are our fingers gripping?
            // (during a reach, this is based on the reach timer)
            float fingerGrabT = armComponent.savedGrabT;

            if (armComponent.heldRock != Entity.Null)
            {
                //Translation heldRockTrans = translationsFromEntity[armComponent.heldRock];
                fingerGrabT = 1.0f; //When holding the rock, we're fully gripped.

                var held = new RockHeldComponent();
                held.rockInHandPosition = armComponent.handMatrix.MultiplyPoint3x4(armComponent.heldRockOffset);
                ecb.AddComponent(index, armComponent.heldRock, held);
                //   armComponent.lastIntendedRockPos =
            }

            // create rendering matrices for arm bones
            util.UpdateMatrices(matrices, armChainsBuffer.Reinterpret <float3>(), 0, armComponent.armBoneThickness, handUp);
            int matrixIndex = armChainsBuffer.Reinterpret <float3>().Length - 1;

            // next:  fingers
            float3 handPos = util.Last(armChainsBuffer.Reinterpret <float3>(), 0);
            // fingers spread out during a throw
            float openPalm = throwCurve.Evaluate(armComponent.throwTimer);

            //TODO add these to arm component?
            float fingerXOffset = -0.12f;
            float fingerSpacing = 0.08f;

            float[] fingerBoneLengths  = { 0.2f, 0.22f, 0.2f, 0.16f };
            float[] fingerThicknesses  = { 0.05f, 0.05f, 0.05f, 0.05f };
            float   fingerBendStrength = 0.2f;

            for (int i = 0; i < 4; i++)
            {
                float3 handRightTemp = handRight * (fingerXOffset + i * fingerSpacing);

                // find knuckle position for this finger
                float3 fingerPos = handPos + handRightTemp;

                // find resting position for this fingertip
                float3 fingerTarget = fingerPos + handForward * (.5f - .1f * fingerGrabT);

                // spooky finger wiggling while we're idle
                fingerTarget += handUp * Mathf.Sin((time + i * .2f) * 3f) * .2f * (1f - fingerGrabT);

                // if we're gripping, move this fingertip onto the surface of our rock
                float3 rockFingerDelta = fingerTarget - armComponent.lastIntendedRockPos;
                float3 rockFingerPos   = armComponent.lastIntendedRockPos + math.normalize(rockFingerDelta) * (armComponent.lastIntendedRockSize * .5f + fingerThicknesses[i]);
                fingerTarget = math.lerp(fingerTarget, rockFingerPos, fingerGrabT);

                // apply finger-spreading during throw animation
                fingerTarget += (handUp * .3f + handForward * .1f + handRight * (i - 1.5f) * .1f) * openPalm;

                // solve this finger's IK chain
                // FABRIK.Solve(fingerChains[i],fingerBoneLengths[i],fingerPos,fingerTarget,handUp*fingerBendStrength);
                int startIdx = i * 4;
                int stopIdx  = startIdx + 4;
                FABRIK.SolveViaBufferSliced(fingerChainsBuffer.Reinterpret <float3>(), fingerBoneLengths[i], fingerPos, fingerTarget, handUp * fingerBendStrength, startIdx, stopIdx);

                // update this finger's rendering matrices
                util.UpdateMatricesSliced(matrices, fingerChainsBuffer.Reinterpret <float3>(), matrixIndex, fingerThicknesses[i], handUp, startIdx, stopIdx);
                matrixIndex += 4 - 1;
            }

            // the thumb is pretty much the same as the fingers
            // (but pointing in a strange direction)
            float thumbXOffset      = -0.05f;
            float thumbThickness    = 0.06f;
            float thumbBendStrength = 0.1f;
            float thumbBoneLength   = 0.13f;

            float3 thumbPos    = handPos + handRight * thumbXOffset;
            float3 thumbTarget = thumbPos - handRight * .15f + handForward * (.2f + .1f * fingerGrabT) - handUp * .1f;

            thumbTarget += handRight * Mathf.Sin(time * 3f + .5f) * .1f * (1f - fingerGrabT);
            // thumb bends away from the palm, instead of "upward" like the fingers
            float3 thumbBendHint = (-handRight - handForward * .5f);

            float3 rockThumbDelta = thumbTarget - armComponent.lastIntendedRockPos;
            float3 rockThumbPos   = armComponent.lastIntendedRockPos + math.normalize(rockThumbDelta) * (armComponent.lastIntendedRockSize * .5f);

            thumbTarget = math.lerp(thumbTarget, rockThumbPos, fingerGrabT);

            FABRIK.SolveViaBuffer(thumbChainsBuffer.Reinterpret <float3>(), thumbBoneLength, thumbPos, thumbTarget, thumbBendHint * thumbBendStrength);
            util.UpdateMatrices(matrices, thumbChainsBuffer.Reinterpret <float3>(), matrixIndex, thumbThickness, thumbBendHint);

            DynamicBuffer <ArmMatrixBuffer> buffer = matrixBufferLookup[entity];

            buffer.Clear();
            for (int i = 0; i < matrices.Length; i++)
            {
                buffer.Add(new ArmMatrixBuffer()
                {
                    Value = matrices[i]
                });
            }
        }
Example #7
0
 // Start is called before the first frame update
 void Start()
 {
     fabrik = new FABRIK(this.transform, iterationLimit, boneChainLength);
 }
Example #8
0
 void Start()
 {
     fabRik = GetComponent <FABRIK>();
 }
Example #9
0
    void Update()
    {
        float time = Time.time + timeOffset;

        // resting position
        Vector3 idleHandTarget = transform.position + new Vector3(Mathf.Sin(time) * .35f, 1f + Mathf.Cos(time * 1.618f) * .5f, 1.5f);

        if (heldRock == null && windupTimer <= 0f)
        {
            if (intendedRock == null && reachTimer == 0f)
            {
                // we're idle - see if we can grab a rock
                Rock nearestRock = RockManager.NearestConveyorRock(transform.position - Vector3.right * .5f);
                if (nearestRock != null)
                {
                    if ((nearestRock.position - transform.position).sqrMagnitude < maxReachLength * maxReachLength)
                    {
                        // found a rock to grab!
                        // mark it as reserved so other hands don't reach for it
                        intendedRock          = nearestRock;
                        intendedRock.reserved = true;
                        lastIntendedRockSize  = intendedRock.size;
                    }
                }
            }
            else if (intendedRock == null)
            {
                // stop reaching if we've lost our target
                reachTimer -= Time.deltaTime / reachDuration;
            }

            if (intendedRock != null)
            {
                // we're reaching for a rock (but we haven't grabbed it yet)
                Vector3 delta = intendedRock.position - transform.position;
                if (delta.sqrMagnitude < maxReachLength * maxReachLength)
                {
                    // figure out where we want to put our wrist
                    // in order to grab the rock
                    Vector3 flatDelta = delta;
                    flatDelta.y = 0f;
                    flatDelta.Normalize();
                    grabHandTarget      = intendedRock.position + Vector3.up * intendedRock.size * .5f - flatDelta * intendedRock.size * .5f;
                    lastIntendedRockPos = intendedRock.position;

                    reachTimer += Time.deltaTime / reachDuration;
                    if (reachTimer >= 1f)
                    {
                        // we've arrived at the rock - pick it up
                        heldRock = intendedRock;
                        RockManager.RemoveFromConveyor(heldRock);
                        heldRock.state = Rock.State.Held;
                        // remember the rock's position in "hand space"
                        // (so we can position the rock while holding it)
                        heldRockOffset = handMatrix.inverse.MultiplyPoint3x4(heldRock.position);
                        intendedRock   = null;

                        // random minimum delay before starting the windup
                        windupTimer = Random.Range(-1f, 0f);
                        throwTimer  = 0f;
                    }
                }
                else
                {
                    // we didn't grab the rock in time - forget it
                    intendedRock.reserved = false;
                    intendedRock          = null;
                }
            }
        }
        if (heldRock != null)
        {
            // stop reaching after we've successfully grabbed a rock
            reachTimer -= Time.deltaTime / reachDuration;

            if (targetCan == null)
            {
                // find a target
                targetCan = TinCanManager.GetNearestCan(transform.position, true, targetXRange);
            }
            if (targetCan != null)
            {
                // found a target - prepare to throw
                targetCan.reserved = true;
                windupTimer       += Time.deltaTime / windupDuration;
            }
        }

        reachTimer = Mathf.Clamp01(reachTimer);

        // smoothed reach timer
        float grabT = reachTimer;

        grabT = 3f * grabT * grabT - 2f * grabT * grabT * grabT;

        // reaching overrides our idle hand position
        handTarget = Vector3.Lerp(idleHandTarget, grabHandTarget, grabT);

        if (targetCan != null)
        {
            // we've got a target, which means we're currently throwing
            if (windupTimer < 1f)
            {
                // still winding up...
                float windupT = Mathf.Clamp01(windupTimer) - Mathf.Clamp01(throwTimer * 2f);
                windupT    = 3f * windupT * windupT - 2f * windupT * windupT * windupT;
                handTarget = Vector3.Lerp(handTarget, windupHandTarget, windupT);
                Vector3 flatTargetDelta = targetCan.position - transform.position;
                flatTargetDelta.y = 0f;
                flatTargetDelta.Normalize();

                // windup position is "behind us," relative to the target position
                windupHandTarget = transform.position - flatTargetDelta * 2f + Vector3.up * (3f - windupT * 2.5f);
            }
            else
            {
                // done winding up - actual throw, plus resetting to idle
                throwTimer += Time.deltaTime / throwDuration;

                // update our aim until we release the rock
                if (heldRock != null)
                {
                    aimVector = AimAtCan(targetCan, lastIntendedRockPos);
                }

                // we start this animation in our windup position,
                // and end it by returning to our default idle pose
                Vector3 restingPos = Vector3.Lerp(windupHandTarget, handTarget, throwTimer);

                // find the hand's target position to perform the throw
                // (somewhere forward and upward from the windup position)
                Vector3 throwHandTarget = windupHandTarget + aimVector.normalized * 2.5f;

                handTarget = Vector3.LerpUnclamped(restingPos, throwHandTarget, throwCurve.Evaluate(throwTimer));

                if (throwTimer > .15f && heldRock != null)
                {
                    // release the rock
                    heldRock.reserved = false;
                    heldRock.state    = Rock.State.Thrown;
                    heldRock.velocity = aimVector;
                    heldRock          = null;
                }

                if (throwTimer >= 1f)
                {
                    // we've completed the animation - return to idle
                    windupTimer = 0f;
                    throwTimer  = 0f;
                    TinCanManager.UnreserveCanAfterDelay(targetCan, 3f);
                    targetCan = null;
                }
            }
        }

        // solve the arm IK chain first
        FABRIK.Solve(armChain, armBoneLength, transform.position, handTarget, handUp * armBendStrength);

        // figure out our current "hand vectors" from our arm orientation
        handForward = (armChain.Last(0) - armChain.Last(1)).normalized;
        handUp      = Vector3.Cross(handForward, transform.right).normalized;
        handRight   = Vector3.Cross(handUp, handForward);

        // create handspace-to-worldspace matrix
        handMatrix = Matrix4x4.TRS(armChain.Last(), Quaternion.LookRotation(handForward, handUp), Vector3.one);

        // how much are our fingers gripping?
        // (during a reach, this is based on the reach timer)
        float fingerGrabT = grabT;

        if (heldRock != null)
        {
            // move our held rock to match our new hand position
            heldRock.position   = handMatrix.MultiplyPoint3x4(heldRockOffset);
            lastIntendedRockPos = heldRock.position;

            // if we're holding a rock, we're always gripping
            fingerGrabT = 1f;
        }

        // create rendering matrices for arm bones
        UpdateMatrices(armChain, 0, armBoneThickness, handUp);
        int matrixIndex = armChain.Length - 1;

        // next:  fingers

        Vector3 handPos = armChain.Last();
        // fingers spread out during a throw
        float openPalm = throwCurve.Evaluate(throwTimer);

        for (int i = 0; i < fingerChains.Length; i++)
        {
            // find knuckle position for this finger
            Vector3 fingerPos = handPos + handRight * (fingerXOffset + i * fingerSpacing);

            // find resting position for this fingertip
            Vector3 fingerTarget = fingerPos + handForward * (.5f - .1f * fingerGrabT);

            // spooky finger wiggling while we're idle
            fingerTarget += handUp * Mathf.Sin((time + i * .2f) * 3f) * .2f * (1f - fingerGrabT);

            // if we're gripping, move this fingertip onto the surface of our rock
            Vector3 rockFingerDelta = fingerTarget - lastIntendedRockPos;
            Vector3 rockFingerPos   = lastIntendedRockPos + rockFingerDelta.normalized * (lastIntendedRockSize * .5f + fingerThicknesses[i]);
            fingerTarget = Vector3.Lerp(fingerTarget, rockFingerPos, fingerGrabT);

            // apply finger-spreading during throw animation
            fingerTarget += (handUp * .3f + handForward * .1f + handRight * (i - 1.5f) * .1f) * openPalm;

            // solve this finger's IK chain
            FABRIK.Solve(fingerChains[i], fingerBoneLengths[i], fingerPos, fingerTarget, handUp * fingerBendStrength);

            // update this finger's rendering matrices
            UpdateMatrices(fingerChains[i], matrixIndex, fingerThicknesses[i], handUp);
            matrixIndex += fingerChains[i].Length - 1;
        }

        // the thumb is pretty much the same as the fingers
        // (but pointing in a strange direction)
        Vector3 thumbPos    = handPos + handRight * thumbXOffset;
        Vector3 thumbTarget = thumbPos - handRight * .15f + handForward * (.2f + .1f * fingerGrabT) - handUp * .1f;

        thumbTarget += handRight * Mathf.Sin(time * 3f + .5f) * .1f * (1f - fingerGrabT);
        // thumb bends away from the palm, instead of "upward" like the fingers
        Vector3 thumbBendHint = (-handRight - handForward * .5f);

        Vector3 rockThumbDelta = thumbTarget - lastIntendedRockPos;
        Vector3 rockThumbPos   = lastIntendedRockPos + rockThumbDelta.normalized * (lastIntendedRockSize * .5f);

        thumbTarget = Vector3.Lerp(thumbTarget, rockThumbPos, fingerGrabT);

        FABRIK.Solve(thumbChain, thumbBoneLength, thumbPos, thumbTarget, thumbBendHint * thumbBendStrength);

        UpdateMatrices(thumbChain, matrixIndex, thumbThickness, thumbBendHint);

        // draw all of our bones
        Graphics.DrawMeshInstanced(boneMesh, 0, material, matrices);
    }