public void Execute(Entity entity, int index, [ReadOnly] ref ArmHoldingTag tag, ref ArmComponent armComponent, [ReadOnly] ref Translation translation) { float tmpDistance = float.MaxValue; float range = 50.0f; float maxThrowRange = range * range; Entity closestCan = Entity.Null; armComponent.reachingTimer -= deltaTime / armComponent.reachDuration; if (armComponent.targetCan == Entity.Null) { // Find nearest target can to fire at. var targetEntities = EntitiesBucketedByIndex.GetValuesForKey(index); targetEntities.Reset(); while (targetEntities.MoveNext()) { var te = targetEntities.Current; Translation targetPos = translationsFromEntity[te]; float distSq = math.distancesq(translation.Value, targetPos.Value); if ((distSq < maxThrowRange) && (distSq < tmpDistance)) { tmpDistance = distSq; closestCan = te; } } if (closestCan != Entity.Null) { armComponent.targetCan = closestCan; } } if (armComponent.targetCan != Entity.Null) { ecb.AddComponent(index, armComponent.targetCan, new ReservedTag()); ecb.RemoveComponent <ArmHoldingTag>(index, entity); ecb.AddComponent(index, entity, new ArmThrowingTag()); } if (armComponent.heldRock != Entity.Null) { //Hand matrix is set in the animation system, here we tell the rock where we want it to reposition. RockHeldComponent heldComponent = rockHeldCompsFromEntity[armComponent.heldRock]; heldComponent.rockInHandPosition = armComponent.handMatrix.MultiplyPoint3x4(armComponent.heldRockOffset); } }
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] }); } }