/// <summary> /// Defines what to do when processing the animation. /// </summary> /// <param name="stream">The animation stream to work on.</param> public void ProcessAnimation(AnimationStream stream) { jobWeight.Set(stream, 1f); var lRot = driven.GetLocalRotation(stream); var offset = drivenOffset.Get(stream); if (Vector3.Dot(offset, offset) > 0f) { lRot *= Quaternion.Inverse(Quaternion.Euler(offset)); } var wRot = lRot; if (drivenParent.IsValid(stream)) { wRot = drivenParent.GetRotation(stream) * wRot; } for (int i = 0; i < sourceTransforms.Length; ++i) { sourceWeights[i].SetFloat(stream, 1f); ReadWriteTransformHandle sourceTransform = sourceTransforms[i]; sourceTransform.SetRotation(stream, wRot * sourceOffsets[i]); // Required to update handles with binding info. sourceTransforms[i] = sourceTransform; } }
public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); if (w > 0f) { var sliderPos = Slider.GetLocalPosition(stream); var t = Mathf.Clamp01(sliderPos.y); Slider.SetLocalPosition(stream, new Vector3(0, t, 0)); if (Rotation) { var rot = Quaternion.Lerp( SourceA.GetRotation(stream), SourceB.GetRotation(stream), t ); var targetRot = Target.GetRotation(stream); Target.SetRotation(stream, Quaternion.Lerp(targetRot, rot, w)); } if (Position) { var pos = Vector3.Lerp( SourceA.GetPosition(stream), SourceB.GetPosition(stream), t ); var targetPos = Target.GetPosition(stream); Target.SetPosition(stream, Vector3.Lerp(targetPos, pos, w)); } } }
public void ProcessAnimation(AnimationStream stream) { jobWeight.Set(stream, 1f); var lRot = driven.GetLocalRotation(stream); var offset = drivenOffset.Get(stream); if (Vector3.Dot(offset, offset) > 0f) { lRot *= Quaternion.Inverse(Quaternion.Euler(offset)); } var localToWorld = Quaternion.identity; var wPos = driven.GetPosition(stream); if (drivenParent.IsValid(stream)) { localToWorld = drivenParent.GetRotation(stream); } for (int i = 0; i < sourceTransforms.Length; ++i) { sourceWeights[i].SetFloat(stream, 1f); var sourceTransform = sourceTransforms[i]; sourceTransform.SetPosition(stream, wPos + localToWorld * sourceOffsets[i] * lRot * aimAxis); // Required to update handles with binding info. sourceTransforms[i] = sourceTransform; } }
public void ProcessAnimation(AnimationStream stream) { jobWeight.Set(stream, 1f); rootTarget.SetPosition(stream, root.GetPosition(stream)); rootTarget.SetRotation(stream, root.GetRotation(stream)); tipTarget.SetPosition(stream, tip.GetPosition(stream)); tipTarget.SetRotation(stream, tip.GetRotation(stream)); }
/// <summary> /// Defines what to do when processing the animation. /// </summary> /// <param name="stream">The animation stream to work on.</param> public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); if (w > 0f) { if (blendPosition.Get(stream)) { Vector3 posBlend = Vector3.Lerp( sourceA.GetPosition(stream) + sourceAOffset.translation, sourceB.GetPosition(stream) + sourceBOffset.translation, positionWeight.Get(stream) ); driven.SetPosition(stream, Vector3.Lerp(driven.GetPosition(stream), posBlend, w)); } else { driven.SetLocalPosition(stream, driven.GetLocalPosition(stream)); } if (blendRotation.Get(stream)) { Quaternion rotBlend = Quaternion.Lerp( sourceA.GetRotation(stream) * sourceAOffset.rotation, sourceB.GetRotation(stream) * sourceBOffset.rotation, rotationWeight.Get(stream) ); driven.SetRotation(stream, Quaternion.Lerp(driven.GetRotation(stream), rotBlend, w)); } else { driven.SetLocalRotation(stream, driven.GetLocalRotation(stream)); } } else { AnimationRuntimeUtils.PassThrough(stream, driven); } }
public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); var sliderPos = Slider.GetLocalPosition(stream); var t = Mathf.Clamp01(sliderPos.y); Slider.SetLocalPosition(stream, new Vector3(0, t, 0)); if (w > 0f) { var rootRot = Root.GetRotation(stream); var midRot = Mid.GetRotation(stream); var tipRot = Tip.GetRotation(stream); var rootRotFK = Quaternion.Lerp(rootRot, FK_Root.GetRotation(stream), w); var midRotFK = Quaternion.Lerp(midRot, FK_Mid.GetRotation(stream), w); var tipRotFK = tipRot; AnimationRuntimeUtils.SolveTwoBoneIK( stream, Root, Mid, Tip, IK_Target, IK_Hint, posWeight: 1f * w, rotWeight: 0 * w, hintWeight: 1f * w, limbLengths: LinkLengths, targetOffset: AffineTransform.identity ); var rootRotIK = Root.GetRotation(stream); var midRotIK = Mid.GetRotation(stream); var tipRotIK = Tip.GetRotation(stream); Root.SetRotation(stream, Quaternion.Lerp(rootRotFK, rootRotIK, t)); Mid.SetRotation(stream, Quaternion.Lerp(midRotFK, midRotIK, t)); Tip.SetRotation(stream, Quaternion.Lerp(tipRotFK, tipRotIK, t)); } }
public void ProcessAnimation(AnimationStream stream) { var w = jobWeight.Get(stream); if (w == 0f) { return; } var offset = ikOffset.Get(stream); var leftToePos = leftToe.GetPosition(stream); var rightToePos = rightToe.GetPosition(stream); var leftIkOffset = offset.x * w; var rightIkOffset = offset.y * w; leftToePos += new Vector3(0f, leftIkOffset, 0f); rightToePos += new Vector3(0f, rightIkOffset, 0f); var leftAnklePos = leftAnkle.GetPosition(stream); var rightAnklePos = rightAnkle.GetPosition(stream); var leftAnkleRot = leftAnkle.GetRotation(stream); var rightAnkleRot = rightAnkle.GetRotation(stream); var leftAnkleIkPos = new Vector3(leftAnklePos.x, leftAnklePos.y + leftIkOffset, leftAnklePos.z); var rightAnkleIkPos = new Vector3(rightAnklePos.x, rightAnklePos.y + rightIkOffset, rightAnklePos.z); var hipHeightOffset = (leftIkOffset + rightIkOffset) * 0.5f; var forwardBackBias = (leftIkOffset - rightIkOffset) * weightShiftHorizontal.Get(stream); float maxRotationOffset = maxFootRotationOffset.Get(stream); // TODO: (sunek) Rework weight shift to move towards actual lower foot? hipHeightOffset += Mathf.Abs(leftIkOffset - rightIkOffset) * weightShiftVertical.Get(stream); var standAngle = Quaternion.AngleAxis(weightShiftAngle.Get(stream), Vector3.up) * Vector3.forward; hips.SetPosition(stream, hips.GetPosition(stream) + new Vector3(standAngle.x * forwardBackBias, hipHeightOffset, standAngle.z * forwardBackBias)); // Figure out the normal rotation var leftNormalRot = Quaternion.LookRotation(Vector3.forward, normalLeftFoot.Get(stream)); var rightNormalRot = Quaternion.LookRotation(Vector3.forward, normalRightFoot.Get(stream)); // Clamp normal rotation var leftAngle = Quaternion.Angle(Quaternion.identity, leftNormalRot); var rightAngle = Quaternion.Angle(Quaternion.identity, rightNormalRot); if (leftAngle > maxRotationOffset && maxRotationOffset > 0f) { var fraction = maxRotationOffset / leftAngle; leftNormalRot = Quaternion.Lerp(Quaternion.identity, leftNormalRot, fraction); } if (rightAngle > maxRotationOffset && maxRotationOffset > 0f) { var fraction = maxRotationOffset / rightAngle; rightNormalRot = Quaternion.Lerp(Quaternion.identity, rightNormalRot, fraction); } // Apply rotation to ankle var leftToesMatrix = Matrix4x4.TRS(leftToePos, Quaternion.identity, Vector3.one); var rightToesMatrix = Matrix4x4.TRS(rightToePos, Quaternion.identity, Vector3.one); var leftToesNormalDeltaMatrix = Matrix4x4.TRS(leftToePos, leftNormalRot, Vector3.one) * leftToesMatrix.inverse; var rightToesNormalDeltaMatrix = Matrix4x4.TRS(rightToePos, rightNormalRot, Vector3.one) * rightToesMatrix.inverse; var leftAnkleMatrix = Matrix4x4.TRS(leftAnkleIkPos, leftAnkleRot, Vector3.one) * leftToesMatrix.inverse; var rightAnkleMatrix = Matrix4x4.TRS(rightAnkleIkPos, rightAnkleRot, Vector3.one) * rightToesMatrix.inverse; leftAnkleMatrix = leftToesNormalDeltaMatrix * leftAnkleMatrix * leftToesMatrix; rightAnkleMatrix = rightToesNormalDeltaMatrix * rightAnkleMatrix * rightToesMatrix; leftAnkleIkPos = leftAnkleMatrix.GetColumn(3); rightAnkleIkPos = rightAnkleMatrix.GetColumn(3); leftAnkleRot = Quaternion.Lerp(leftAnkleRot, leftAnkleMatrix.rotation, w); rightAnkleRot = Quaternion.Lerp(rightAnkleRot, rightAnkleMatrix.rotation, w); // Update ik position // TODO: (sunek) Consider combating leg overstretch var leftPosition = Vector3.Lerp(leftAnklePos, leftAnkleIkPos, w); var rightPosition = Vector3.Lerp(rightAnklePos, rightAnkleIkPos, w); leftEffector.SetPosition(stream, leftPosition); rightEffector.SetPosition(stream, rightPosition); leftEffector.SetRotation(stream, leftAnkleRot); rightEffector.SetRotation(stream, rightAnkleRot); }
public void ProcessAnimation(AnimationStream stream) { var jointCount = boneChain.Length; var boneCount = jointCount - 1; var tipPosition = tipTarget.GetPosition(stream); var weight = jobWeight.Get(stream); var positions = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var tangents = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var normals = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var v0 = boneChain[0].GetRotation(stream) * Vector3.up; // fill the local buffer of positions for (var i = 0; i < jointCount; i++) { positions[i] = boneChain[i].GetPosition(stream); } // perform solver iterations for (var i = 0; i < iterationCount; i++) { // force final position to the tip target... unsure if this is the best... positions[positions.Length - 1] = tipPosition; // project distance constraints for (var j = 0; j < boneCount; j++) { var invMass0 = j == 0 ? 0f : 1f; var invMass1 = j == boneCount - 1 ? 0 : 1f; var p0 = positions[j + 0]; var p1 = positions[j + 1]; var d = restLengths[j]; var C = distance(p0, p1) - d; if (C < float.Epsilon && C > -float.Epsilon) { continue; } var direction = normalize(p0 - p1); var lambda = C * direction; positions[j + 0] -= invMass0 / (invMass0 + invMass1) * lambda; positions[j + 1] += invMass1 / (invMass0 + invMass1) * lambda; } // project collisions for (var j = 0; j < jointCount; j++) { var p = positions[j]; p.y = max(p.y, minimumHeight); positions[j] = p; } } // Set the new bone rotations for (var i = 0; i < boneCount; i++) { var prevDir = boneChain[i + 1].GetPosition(stream) - boneChain[i + 0].GetPosition(stream); var newDir = positions[i + 1] - positions[i]; var currentRotation = boneChain[i].GetRotation(stream); var additionalRotation = QuaternionExt.FromToRotation(prevDir, newDir); boneChain[i].SetRotation(stream, Quaternion.Lerp(currentRotation, additionalRotation * currentRotation, weight)); } boneChain[jointCount - 1].SetRotation(stream, tipTarget.GetRotation(stream)); positions.Dispose(); tangents.Dispose(); normals.Dispose(); }
public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); if (w > 0f) { var cursorPos = FootRollCursor.GetLocalPosition(stream); FootRollCursor.SetLocalPosition(stream, new Vector3(cursorPos.x, cursorPos.y, 0)); var pos = FootControllerBase.GetPosition(stream); var rot = FootControllerBase.GetRotation(stream); if (cursorPos.x < 0f) { var footRightSidePos = FootRightSide.GetPosition(stream); var axisZ = rot * Vector3.forward; var rotZ = Quaternion.AngleAxis(180 * cursorPos.x, axisZ); pos = footRightSidePos + rotZ * (pos - footRightSidePos); rot = rotZ * rot; if (cursorPos.y >= 0f) { var toePos = footRightSidePos + rotZ * (ToeEnd.GetPosition(stream) - footRightSidePos); var axisX = rot * Vector3.right; var rotX = Quaternion.AngleAxis(180 * cursorPos.y, axisX); pos = toePos + rotX * (pos - toePos); rot = rotX * rot; } else { var heelPos = footRightSidePos + rotZ * (FootHeel.GetPosition(stream) - footRightSidePos); var axisX = rot * Vector3.right; var rotX = Quaternion.AngleAxis(180 * cursorPos.y, axisX); pos = heelPos + rotX * (pos - heelPos); rot = rotX * rot; } } else { var footLeftSidePos = FootLeftSide.GetPosition(stream); var axisZ = rot * Vector3.forward; var rotZ = Quaternion.AngleAxis(180 * cursorPos.x, axisZ); pos = footLeftSidePos + rotZ * (pos - footLeftSidePos); rot = rotZ * rot; if (cursorPos.y >= 0f) { var toePos = footLeftSidePos + rotZ * (ToeEnd.GetPosition(stream) - footLeftSidePos); var axisX = rot * Vector3.right; var rotX = Quaternion.AngleAxis(180 * cursorPos.y, axisX); pos = toePos + rotX * (pos - toePos); rot = rotX * rot; } else { var heelPos = footLeftSidePos + rotZ * (FootHeel.GetPosition(stream) - footLeftSidePos); var axisX = rot * Vector3.right; var rotX = Quaternion.AngleAxis(180 * cursorPos.y, axisX); pos = heelPos + rotX * (pos - heelPos); rot = rotX * rot; } } var footIKTargetPos = FootIKTarget.GetPosition(stream); var footIKTargetRot = FootIKTarget.GetRotation(stream); FootIKTarget.SetPosition(stream, Vector3.Lerp(footIKTargetPos, pos, w)); FootIKTarget.SetRotation(stream, Quaternion.Lerp(footIKTargetRot, rot, w)); } }