public Quaternion TrackDampingRatio(Vector4 targetValueVec, float angularFrequency, float dampingRatio, float deltaTime) { if (angularFrequency < MathUtil.Epsilon) { VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity); return(QuaternionUtil.FromVector4(ValueVec)); } // keep in same hemisphere for shorter track delta if (Vector4.Dot(ValueVec, targetValueVec) < 0.0f) { targetValueVec = -targetValueVec; } Vector4 delta = targetValueVec - ValueVec; float f = 1.0f + 2.0f * deltaTime * dampingRatio * angularFrequency; float oo = angularFrequency * angularFrequency; float hoo = deltaTime * oo; float hhoo = deltaTime * hoo; float detInv = 1.0f / (f + hhoo); Vector4 detX = f * ValueVec + deltaTime * VelocityVec + hhoo * targetValueVec; Vector4 detV = VelocityVec + hoo * delta; VelocityVec = detV * detInv; ValueVec = detX * detInv; if (VelocityVec.magnitude < MathUtil.Epsilon && delta.magnitude < MathUtil.Epsilon) { VelocityVec = Vector4.zero; ValueVec = targetValueVec; } return(QuaternionUtil.FromVector4(ValueVec)); }
// for BoingBehavior & BoingReactor public void PrepareExecute(ref Params p, Vector3 position, Quaternion rotation, float scale, bool accumulateEffectors) { PositionTarget = PositionOrigin = position; RotationTarget = RotationOrigin = QuaternionUtil.ToVector4(rotation); if (accumulateEffectors) { // make relative PositionTarget = Vector3.zero; RotationTarget = Vector4.zero; m_numEffectors = 0; m_upWs = p.Bits.IsBitSet(ReactorFlags.GlobalReactionUpVector) ? p.RotationReactionUp : rotation *VectorUtil.NormalizeSafe(p.RotationReactionUp, Vector3.up); m_scale = scale; } else { m_numEffectors = -1; m_upWs = Vector3.zero; } }
// master sterp function public static Quaternion Sterp ( Quaternion a, Quaternion b, Vector3 twistAxis, float tSwing, float tTwist, out Quaternion swing, out Quaternion twist, SterpMode mode ) { Quaternion q = b * Quaternion.Inverse(a); Quaternion swingFull; Quaternion twistFull; QuaternionUtil.DecomposeSwingTwist(q, twistAxis, out swingFull, out twistFull); switch (mode) { default: case SterpMode.Nlerp: swing = Quaternion.Lerp(Quaternion.identity, swingFull, tSwing); twist = Quaternion.Lerp(Quaternion.identity, twistFull, tTwist); break; case SterpMode.Slerp: swing = Quaternion.Slerp(Quaternion.identity, swingFull, tSwing); twist = Quaternion.Slerp(Quaternion.identity, twistFull, tTwist); break; } return(twist * swing); }
public Quaternion TrackExponential(Quaternion targetValue, float halfLife, float deltaTime) { if (halfLife < MathUtil.Epsilon) { VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity); ValueVec = QuaternionUtil.ToVector4(targetValue); return(targetValue); } float angularFrequency = 0.6931472f / halfLife; float dampingRatio = 1.0f; return(TrackDampingRatio(targetValue, angularFrequency, dampingRatio, deltaTime)); }
public Quaternion TrackExponential(Vector4 targetValueVec, float halfLife, float deltaTime) { if (halfLife < MathUtil.Epsilon) { VelocityVec = Vector4.zero; ValueVec = targetValueVec; return(QuaternionUtil.FromVector4(targetValueVec)); } float angularFrequency = 0.6931472f / halfLife; float dampingRatio = 1.0f; return(TrackDampingRatio(targetValueVec, angularFrequency, dampingRatio, deltaTime)); }
public Quaternion TrackHalfLife(Quaternion targetValue, float frequencyHz, float halfLife, float deltaTime) { if (halfLife < MathUtil.Epsilon) { VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity); ValueVec = QuaternionUtil.ToVector4(targetValue); return(targetValue); } float angularFrequency = frequencyHz * MathUtil.TwoPi; float dampingRatio = 0.6931472f / (angularFrequency * halfLife); return(TrackDampingRatio(targetValue, angularFrequency, dampingRatio, deltaTime)); }
public Quaternion TrackHalfLife(Vector4 targetValueVec, float frequencyHz, float halfLife, float deltaTime) { if (halfLife < MathUtil.Epsilon) { VelocityVec = Vector4.zero; ValueVec = targetValueVec; return(QuaternionUtil.FromVector4(targetValueVec)); } float angularFrequency = frequencyHz * MathUtil.TwoPi; float dampingRatio = 0.6931472f / (angularFrequency * halfLife); return(TrackDampingRatio(targetValueVec, angularFrequency, dampingRatio, deltaTime)); }
public void SampleFromField() { m_objPosition = transform.position; m_objRotation = transform.rotation; if (ReactorField == null) { return; } var comp = ReactorField.GetComponent <BoingReactorField>(); if (comp == null) { #if UNITY_EDITOR if (!s_warnedComponent) { Debug.LogWarning("The assigned ReactorField game object must have a BoingReactorField component for BoingReactorFieldCpuSampler components to sample from."); s_warnedComponent = true; } #endif return; } if (comp.HardwareMode != BoingReactorField.HardwareModeEnum.CPU) { #if UNITY_EDITOR if (!s_warnedHardwareMode) { Debug.LogWarning("The BoingReactorField component needs to be set to CPU hardware mode for BoingReactorFieldCpuSampler components to sample from."); s_warnedHardwareMode = true; } #endif return; } Vector3 positionOffset; Vector4 rotationOffset; if (!comp.SampleCpuGrid(transform.position, out positionOffset, out rotationOffset)) { return; } transform.position = m_objPosition + positionOffset * PositionSampleMultiplier; transform.rotation = QuaternionUtil.Pow(QuaternionUtil.FromVector4(rotationOffset), RotationSampleMultiplier) * m_objRotation; }
public void EndAccumulateTargets(ref Params p) { if (m_numEffectors > 0) { PositionTarget *= m_scale / m_numEffectors; PositionTarget += PositionOrigin; RotationTarget /= m_numEffectors; RotationTarget = QuaternionUtil.ToVector4(QuaternionUtil.FromVector4(RotationTarget) * QuaternionUtil.FromVector4(RotationOrigin)); } else { PositionTarget = PositionOrigin; RotationTarget = RotationOrigin; } }
// for BoingReactorFied public void PrepareExecute(ref Params p, Vector3 gridCenter, Quaternion gridRotation, Vector3 cellOffset) { PositionOrigin = gridCenter + cellOffset; RotationOrigin = QuaternionUtil.ToVector4(Quaternion.identity); // make relative PositionTarget = Vector3.zero; RotationTarget = Vector4.zero; m_numEffectors = 0; m_upWs = p.Bits.IsBitSet(ReactorFlags.GlobalReactionUpVector) ? p.RotationReactionUp : gridRotation *VectorUtil.NormalizeSafe(p.RotationReactionUp, Vector3.up); m_scale = 1.0f; }
public static Vector3 ClampBend(Vector3 vector, Vector3 reference, float maxBendAngle) { float vLenSqr = vector.sqrMagnitude; if (vLenSqr < MathUtil.Epsilon) { return(vector); } float rLenSqr = reference.sqrMagnitude; if (rLenSqr < MathUtil.Epsilon) { return(vector); } Vector3 vUnit = vector / Mathf.Sqrt(vLenSqr); Vector3 rUnit = reference / Mathf.Sqrt(rLenSqr); Vector3 cross = Vector3.Cross(rUnit, vUnit); float dot = Vector3.Dot(rUnit, vUnit); Vector3 axis = cross.sqrMagnitude > MathUtil.Epsilon ? cross.normalized : FindOrthogonal(rUnit); float angle = Mathf.Acos(Mathf.Clamp01(dot)); if (angle <= maxBendAngle) { return(vector); } Quaternion clampedBendRot = QuaternionUtil.AxisAngle(axis, maxBendAngle); Vector3 result = clampedBendRot * reference; result *= Mathf.Sqrt(vLenSqr) / Mathf.Sqrt(rLenSqr); return(result); }
public void Restore() { if (Application.isEditor) { // transforms can be manually modified in editor between post-update and pre-update // we respect that by skipping restoration of cached transforms if ((transform.position - RenderPosition).sqrMagnitude < MathUtil.Epsilon) { transform.position = CachedPosition; } if (QuaternionUtil.GetAngle(transform.rotation * Quaternion.Inverse(RenderRotation)) < MathUtil.Epsilon) { transform.rotation = CachedRotation; } } else { transform.position = CachedPosition; transform.rotation = CachedRotation; } }
public void AccumulateTarget(ref Params p, ref BoingEffector.Params effector) { Vector3 effectRefPos = effector.Bits.IsBitSet(BoingWork.EffectorFlags.ContinuousMotion) ? VectorUtil.GetClosestPointOnSegment(PositionOrigin, effector.PrevPosition, effector.CurrPosition) : effector.CurrPosition; Vector3 deltaPos = PositionOrigin - effectRefPos; Vector3 deltaPos3D = deltaPos; if (p.Bits.IsBitSet(ReactorFlags.TwoDDistanceCheck)) { switch (p.TwoDPlane) { case TwoDPlaneEnum.XY: deltaPos.z = 0.0f; break; case TwoDPlaneEnum.XZ: deltaPos.y = 0.0f; break; case TwoDPlaneEnum.YZ: deltaPos.x = 0.0f; break; } } bool inRange = Mathf.Abs(deltaPos.x) <= effector.Radius && Mathf.Abs(deltaPos.y) <= effector.Radius && Mathf.Abs(deltaPos.z) <= effector.Radius && deltaPos.sqrMagnitude <= effector.Radius * effector.Radius; if (!inRange) { return; } float deltaDist = deltaPos.magnitude; float tDeltaDist = effector.Radius - effector.FullEffectRadius > MathUtil.Epsilon ? 1.0f - Mathf.Clamp01((deltaDist - effector.FullEffectRadius) / (effector.Radius - effector.FullEffectRadius)) : 1.0f; Vector3 upWsPos = m_upWs; Vector3 upWsRot = m_upWs; Vector3 deltaDirPos = VectorUtil.NormalizeSafe(deltaPos3D, m_upWs); Vector3 deltaDirRot = deltaDirPos; if (p.Bits.IsBitSet(ReactorFlags.TwoDPositionInfluence)) { switch (p.TwoDPlane) { case TwoDPlaneEnum.XY: deltaDirPos.z = 0.0f; upWsPos.z = 0.0f; break; case TwoDPlaneEnum.XZ: deltaDirPos.y = 0.0f; upWsPos.y = 0.0f; break; case TwoDPlaneEnum.YZ: deltaDirPos.x = 0.0f; upWsPos.x = 0.0f; break; } if (upWsPos.sqrMagnitude < MathUtil.Epsilon) { switch (p.TwoDPlane) { case TwoDPlaneEnum.XY: upWsPos = Vector3.up; break; case TwoDPlaneEnum.XZ: upWsPos = Vector3.forward; break; case TwoDPlaneEnum.YZ: upWsPos = Vector3.up; break; } } else { upWsPos.Normalize(); } deltaDirPos = VectorUtil.NormalizeSafe(deltaDirPos, upWsPos); } if (p.Bits.IsBitSet(ReactorFlags.TwoDRotationInfluence)) { switch (p.TwoDPlane) { case TwoDPlaneEnum.XY: deltaDirRot.z = 0.0f; upWsRot.z = 0.0f; break; case TwoDPlaneEnum.XZ: deltaDirRot.y = 0.0f; upWsRot.y = 0.0f; break; case TwoDPlaneEnum.YZ: deltaDirRot.x = 0.0f; upWsRot.x = 0.0f; break; } if (upWsRot.sqrMagnitude < MathUtil.Epsilon) { switch (p.TwoDPlane) { case TwoDPlaneEnum.XY: upWsRot = Vector3.up; break; case TwoDPlaneEnum.XZ: upWsRot = Vector3.forward; break; case TwoDPlaneEnum.YZ: upWsRot = Vector3.up; break; } } else { upWsRot.Normalize(); } deltaDirRot = VectorUtil.NormalizeSafe(deltaDirRot, upWsRot); } if (p.Bits.IsBitSet(ReactorFlags.EnablePositionEffect)) { Vector3 moveVec = tDeltaDist * p.MoveReactionMultiplier * effector.MoveDistance * deltaDirPos; PositionTarget += moveVec; PositionSpring.Velocity += tDeltaDist * p.LinearImpulseMultiplier * effector.LinearImpulse * effector.LinearVelocityDir; } if (p.Bits.IsBitSet(ReactorFlags.EnableRotationEffect)) { Vector3 rotAxis = VectorUtil.NormalizeSafe(Vector3.Cross(upWsRot, deltaDirRot), VectorUtil.FindOrthogonal(upWsRot)); Vector3 rotVec = tDeltaDist * p.RotationReactionMultiplier * effector.RotateAngle * rotAxis; RotationTarget += QuaternionUtil.ToVector4(QuaternionUtil.FromAngularVector(rotVec)); Vector3 angularImpulseDir = VectorUtil.NormalizeSafe(Vector3.Cross(effector.LinearVelocityDir, deltaDirRot - 0.01f * Vector3.up), rotAxis); float angularImpulseMag = tDeltaDist * p.AngularImpulseMultiplier * effector.AngularImpulse; Vector4 angularImpulseDirQuat = QuaternionUtil.ToVector4(QuaternionUtil.FromAngularVector(angularImpulseDir)); RotationSpring.VelocityVec += angularImpulseMag * angularImpulseDirQuat; } ++m_numEffectors; }
public void Reset() { ValueVec = QuaternionUtil.ToVector4(Quaternion.identity); VelocityVec = Vector4.zero; }
public void OnDrawGizmos() { if (BoneData == null) { return; } bool selected = false; foreach (var selectedGo in UnityEditor.Selection.gameObjects) { if (gameObject == selectedGo) { selected = true; break; } foreach (var collider in BoingColliders) { if (collider == null) { continue; } if (collider.gameObject == selectedGo) { selected = true; break; } } if (selected) { break; } } if (!selected) { return; } for (int iChain = 0; iChain < BoneData.Length; ++iChain) { var chain = BoneChains[iChain]; var aBone = BoneData[iChain]; if (aBone == null) { continue; } foreach (var bone in aBone) { var parentBone = bone.ParentIndex >= 0 ? aBone[bone.ParentIndex] : null; Vector3 boneAnimPos = Application.isPlaying ? bone.CachedPositionWs : bone.Transform.position; Vector3 boneTargetPos = bone.Instance.PositionTarget; Vector3 boneSpringPos = bone.Instance.PositionSpring.Value; Vector3 boneBlendedPos = bone.BlendedPositionWs; Quaternion boneAnimRot = Application.isPlaying ? bone.CachedRotationWs : bone.Transform.rotation; Quaternion boneTargetRot = QuaternionUtil.FromVector4(bone.Instance.RotationTarget); Quaternion boneSpringRot = bone.Instance.RotationSpring.ValueQuat; Quaternion boneBlendedRot = bone.BlendedRotationWs; float boneRadius = (chain.EnableBoingKitCollision || chain.EnableUnityCollision || chain.EnableInterChainCollision) ? MinScale * bone.CollisionRadius : 0.02f; Gizmos.color = Color.white; if (DebugDrawRawBones) { Gizmos.matrix = Matrix4x4.TRS(boneAnimPos, boneAnimRot, Vector3.one); Gizmos.DrawWireSphere(Vector3.zero, boneRadius); Gizmos.matrix = Matrix4x4.identity; if (parentBone != null) { Vector3 parentAnimPos = Application.isPlaying ? parentBone.CachedPositionWs : parentBone.Transform.position; Gizmos.DrawLine(boneAnimPos, parentAnimPos); } if (DebugDrawBoneNames) { Handles.Label(boneAnimPos, bone.Transform.name); } if (DebugDrawLengthFromRoot) { float tBone = Mathf.Clamp01(bone.LengthFromRoot * MathUtil.InvSafe(chain.MaxLengthFromRoot)); Handles.Label(boneAnimPos, bone.LengthFromRoot.ToString("n3") + " (t: " + tBone.ToString("n2") + ")"); } } Gizmos.color = Color.yellow; if (DebugDrawBoingBones && Application.isPlaying) { Gizmos.matrix = Matrix4x4.TRS(boneSpringPos, boneSpringRot, Vector3.one); Gizmos.DrawWireSphere(Vector3.zero, boneRadius); Gizmos.matrix = Matrix4x4.identity; if (parentBone != null) { Vector3 parentSpringPos = parentBone.Instance.PositionSpring.Value; Gizmos.DrawLine(boneSpringPos, parentSpringPos); } if (DebugDrawBoneNames) { Handles.Label(boneSpringPos, bone.Transform.name); } } Gizmos.color = Color.red; if (DebugDrawTargetBones && Application.isPlaying) { Gizmos.matrix = Matrix4x4.TRS(boneTargetPos, boneTargetRot, Vector3.one); Gizmos.DrawWireSphere(Vector3.zero, boneRadius); Gizmos.matrix = Matrix4x4.identity; if (parentBone != null) { Vector3 parentTargetPos = parentBone.Instance.PositionTarget; Gizmos.DrawLine(boneTargetPos, parentTargetPos); } if (DebugDrawBoneNames) { Handles.Label(boneTargetPos, bone.Transform.name); } } Gizmos.color = Color.green; if (DebugDrawFinalBones && Application.isPlaying) { Gizmos.matrix = Matrix4x4.TRS(boneBlendedPos, boneBlendedRot, Vector3.one); Gizmos.DrawWireSphere(Vector3.zero, boneRadius); Gizmos.matrix = Matrix4x4.identity; if (parentBone != null) { Vector3 blendedParentBone = Vector3.Lerp(parentBone.Instance.PositionSpring.Value, parentBone.CachedPositionWs, parentBone.AnimationBlend); Gizmos.DrawLine(boneBlendedPos, blendedParentBone); } if (DebugDrawBoneNames) { Handles.Label(boneBlendedPos, bone.Transform.name); } } } Gizmos.color = Color.cyan; if (DebugDrawChainBounds && (chain.EnableBoingKitCollision || chain.EnableUnityCollision)) { Gizmos.matrix = Matrix4x4.Translate(chain.Bounds.center); Gizmos.DrawWireCube(Vector3.zero, chain.Bounds.size); Gizmos.matrix = Matrix4x4.identity; } } if (DebugDrawColliders) { foreach (var collider in BoingColliders) { if (collider == null) { continue; } collider.DrawGizmos(); } } }
public void Reset(Quaternion initValue) { ValueVec = QuaternionUtil.ToVector4(initValue); VelocityVec = Vector4.zero; }
public Quaternion TrackDampingRatio(Quaternion targetValue, float angularFrequency, float dampingRatio, float deltaTime) { return(TrackDampingRatio(QuaternionUtil.ToVector4(targetValue), angularFrequency, dampingRatio, deltaTime)); }
public void Execute(ref Params p, float dt) { bool useAccumulatedEffectors = (m_numEffectors >= 0); bool positionSpringNeedsUpdate = useAccumulatedEffectors ? (PositionSpring.Velocity.sqrMagnitude > MathUtil.Epsilon || (PositionSpring.Value - PositionTarget).sqrMagnitude > MathUtil.Epsilon) : p.Bits.IsBitSet(ReactorFlags.EnablePositionEffect); bool rotationSpringNeedsUpdate = useAccumulatedEffectors ? (RotationSpring.VelocityVec.sqrMagnitude > MathUtil.Epsilon || (RotationSpring.ValueVec - RotationTarget).sqrMagnitude > MathUtil.Epsilon) : p.Bits.IsBitSet(ReactorFlags.EnableRotationEffect); if (m_numEffectors == 0) { bool earlyOut = true; if (positionSpringNeedsUpdate) { earlyOut = false; } else { PositionSpring.Reset(PositionTarget); } if (rotationSpringNeedsUpdate) { earlyOut = false; } else { RotationSpring.Reset(QuaternionUtil.FromVector4(RotationTarget)); } if (earlyOut) { return; } } if (m_instantAccumulation != 0) { PositionSpring.Value = PositionTarget; RotationSpring.ValueVec = RotationTarget; m_instantAccumulation = 0; } else { if (positionSpringNeedsUpdate) { switch (p.PositionParameterMode) { case ParameterMode.Exponential: PositionSpring.TrackExponential(PositionTarget, p.PositionExponentialHalfLife, dt); break; case ParameterMode.OscillationByHalfLife: PositionSpring.TrackHalfLife(PositionTarget, p.PositionOscillationFrequency, p.PositionOscillationHalfLife, dt); break; case ParameterMode.OscillationByDampingRatio: PositionSpring.TrackDampingRatio(PositionTarget, p.PositionOscillationFrequency * MathUtil.TwoPi, p.PositionOscillationDampingRatio, dt); break; } } if (rotationSpringNeedsUpdate) { switch (p.RotationParameterMode) { case ParameterMode.Exponential: RotationSpring.TrackExponential(RotationTarget, p.RotationExponentialHalfLife, dt); break; case ParameterMode.OscillationByHalfLife: RotationSpring.TrackHalfLife(RotationTarget, p.RotationOscillationFrequency, p.RotationOscillationHalfLife, dt); break; case ParameterMode.OscillationByDampingRatio: RotationSpring.TrackDampingRatio(RotationTarget, p.RotationOscillationFrequency * MathUtil.TwoPi, p.RotationOscillationDampingRatio, dt); break; } } } if (!useAccumulatedEffectors) { if (!positionSpringNeedsUpdate) { PositionSpring.Reset(PositionTarget); } if (!rotationSpringNeedsUpdate) { RotationSpring.Reset(RotationTarget); } } }
void FixedUpdate() { float dt = Time.fixedDeltaTime; Vector3 linearInputVec = Vector3.zero; if (Input.GetKey(KeyCode.W)) { linearInputVec += Vector3.forward; } if (Input.GetKey(KeyCode.S)) { linearInputVec += Vector3.back; } if (Input.GetKey(KeyCode.A)) { linearInputVec += Vector3.left; } if (Input.GetKey(KeyCode.D)) { linearInputVec += Vector3.right; } if (Input.GetKey(KeyCode.R)) { linearInputVec += Vector3.up; } if (Input.GetKey(KeyCode.F)) { linearInputVec += Vector3.down; } bool linearThrustOn = linearInputVec.sqrMagnitude > MathUtil.Epsilon; if (linearThrustOn) { linearInputVec = linearInputVec.normalized * LinearThrust; m_linearVelocity += linearInputVec * dt; m_linearVelocity = VectorUtil.ClampLength(m_linearVelocity, 0.0f, MaxLinearSpeed); } else { m_linearVelocity = VectorUtil.ClampLength(m_linearVelocity, 0.0f, Mathf.Max(0.0f, m_linearVelocity.magnitude - LinearDrag * dt)); } float speed = m_linearVelocity.magnitude; float tSpeed = speed * MathUtil.InvSafe(MaxLinearSpeed); Quaternion tiltRot = Quaternion.identity; float tHorizontal = 1.0f; float tHorizontalSpeed = 0.0f; if (speed > MathUtil.Epsilon) { Vector3 flatVel = m_linearVelocity; flatVel.y = 0.0f; tHorizontal = m_linearVelocity.magnitude > 0.01f ? 1.0f - Mathf.Clamp01(Mathf.Abs(m_linearVelocity.y) / m_linearVelocity.magnitude) : 0.0f; tHorizontalSpeed = Mathf.Min(1.0f, speed / Mathf.Max(MathUtil.Epsilon, MaxLinearSpeed)) * tHorizontal; Vector3 tiltAxis = Vector3.Cross(Vector3.up, flatVel).normalized; float tiltAngle = Tilt * MathUtil.Deg2Rad * tHorizontalSpeed; tiltRot = QuaternionUtil.AxisAngle(tiltAxis, tiltAngle); } float angularInput = 0.0f; if (Input.GetKey(KeyCode.Q)) { angularInput -= 1.0f; } if (Input.GetKey(KeyCode.E)) { angularInput += 1.0f; } bool largerMaxAngularSpeed = Input.GetKey(KeyCode.LeftControl); bool angularThurstOn = Mathf.Abs(angularInput) > MathUtil.Epsilon; if (angularThurstOn) { float maxAngularSpeed = MaxAngularSpeed * (largerMaxAngularSpeed ? 2.5f : 1.0f); angularInput *= AngularThrust * MathUtil.Deg2Rad; m_angularVelocity += angularInput * dt; m_angularVelocity = Mathf.Clamp(m_angularVelocity, -maxAngularSpeed * MathUtil.Deg2Rad, maxAngularSpeed * MathUtil.Deg2Rad); } else { m_angularVelocity -= Mathf.Sign(m_angularVelocity) * Mathf.Min(Mathf.Abs(m_angularVelocity), AngularDrag * MathUtil.Deg2Rad * dt); } m_yawAngle += m_angularVelocity * dt; Quaternion yawRot = QuaternionUtil.AxisAngle(Vector3.up, m_yawAngle); m_hoverCenter += m_linearVelocity * dt; m_hoverPhase += Time.deltaTime; Vector3 hoverVec = 0.05f * Mathf.Sin(1.37f * m_hoverPhase) * Vector3.right + 0.05f * Mathf.Sin(1.93f * m_hoverPhase + 1.234f) * Vector3.forward + 0.04f * Mathf.Sin(0.97f * m_hoverPhase + 4.321f) * Vector3.up; hoverVec *= Hover; Quaternion hoverQuat = Quaternion.FromToRotation(Vector3.up, hoverVec + Vector3.up); transform.position = m_hoverCenter + hoverVec; transform.rotation = tiltRot * yawRot * hoverQuat; if (Motor != null) { float motorAngularSpeedDeg = Mathf.Lerp(MotorBaseAngularSpeed, MotorMaxAngularSpeed, tHorizontalSpeed); m_motorAngle += motorAngularSpeedDeg * MathUtil.Deg2Rad * dt; Motor.localRotation = QuaternionUtil.AxisAngle(Vector3.up, m_motorAngle - m_yawAngle); } if (BubbleEmitter != null) { var emission = BubbleEmitter.emission; emission.rateOverTime = Mathf.Lerp(BubbleBaseEmissionRate, BubbleMaxEmissionRate, tSpeed); } if (Eyes != null) { m_blinkTimer -= dt; if (m_blinkTimer <= 0.0f) { bool doubleBlink = !m_lastBlinkWasDouble && Random.Range(0.0f, 1.0f) > 0.75f; m_blinkTimer = doubleBlink ? 0.2f : BlinkInterval + Random.Range(1.0f, 2.0f); m_lastBlinkWasDouble = doubleBlink; m_eyeScaleSpring.Value.y = 0.0f; m_eyePositionLsSpring.Value.y -= 0.025f; } Eyes.localScale = m_eyeScaleSpring.TrackDampingRatio(m_eyeInitScale, 30.0f, 0.8f, dt); Eyes.localPosition = m_eyePositionLsSpring.TrackDampingRatio(m_eyeInitPositionLs, 30.0f, 0.8f, dt); } }
public void PullResults(BoingBones bones) { for (int iChain = 0; iChain < bones.BoneData.Length; ++iChain) { var chain = bones.BoneChains[iChain]; var aBone = bones.BoneData[iChain]; if (aBone == null) { continue; } // must cache before manipulating bone transforms // otherwise, we'd cache delta propagated down from parent bones foreach (var bone in aBone) { bone.CachedPositionWs = bone.Transform.position; bone.CachedPositionLs = bone.Transform.localPosition; bone.CachedRotationWs = bone.Transform.rotation; bone.CachedRotationLs = bone.Transform.localRotation; } // blend bone position for (int iBone = 0; iBone < aBone.Length; ++iBone) { var bone = aBone[iBone]; // skip fixed root if (iBone == 0 && !chain.LooseRoot) { bone.BlendedPositionWs = bone.CachedPositionWs; continue; } bone.BlendedPositionWs = Vector3.Lerp ( bone.Instance.PositionSpring.Value, bone.CachedPositionWs, bone.AnimationBlend ); } // rotation delta back-propagation if (bones.EnableRotationEffect) { for (int iBone = 0; iBone < aBone.Length; ++iBone) { var bone = aBone[iBone]; // skip fixed root if (iBone == 0 && !chain.LooseRoot) { bone.BlendedRotationWs = bone.CachedRotationWs; continue; } if (bone.ChildIndices == null) { if (bone.ParentIndex >= 0) { var parentBone = aBone[bone.ParentIndex]; bone.BlendedRotationWs = parentBone.BlendedRotationWs * (parentBone.RotationInverseWs * bone.CachedRotationWs); } continue; } Vector3 bonePos = bone.CachedPositionWs; Vector3 boneBlendedPos = bone.BlendedPositionWs; Quaternion boneRot = bone.CachedRotationWs; Quaternion boneRotInv = Quaternion.Inverse(boneRot); Vector4 childRotDeltaPsVecAccumulator = Vector3.zero; float totalWeight = 0.0f; foreach (int iChild in bone.ChildIndices) { var childBone = aBone[iChild]; Vector3 childPos = childBone.CachedPositionWs; Vector3 childPosDelta = childPos - bonePos; Vector3 childPosDeltaDir = VectorUtil.NormalizeSafe(childPosDelta, Vector3.zero); Vector3 childBlendedPos = childBone.BlendedPositionWs; Vector3 childBlendedPosDelta = childBlendedPos - boneBlendedPos; Vector3 childBlendedPosDeltaDir = VectorUtil.NormalizeSafe(childBlendedPosDelta, Vector3.zero); Quaternion childRotDelta = Quaternion.FromToRotation(childPosDeltaDir, childBlendedPosDeltaDir); Quaternion childRotDeltaPs = boneRotInv * childRotDelta; Vector4 childRotDeltaPsVec = QuaternionUtil.ToVector4(childRotDeltaPs); float weight = Mathf.Max(MathUtil.Epsilon, chain.MaxLengthFromRoot - childBone.LengthFromRoot); childRotDeltaPsVecAccumulator += weight * childRotDeltaPsVec; totalWeight += weight; } if (totalWeight > 0.0f) { Vector4 avgChildRotDeltaPsVec = childRotDeltaPsVecAccumulator / totalWeight; bone.RotationBackPropDeltaPs = QuaternionUtil.FromVector4(avgChildRotDeltaPsVec); bone.BlendedRotationWs = (boneRot * bone.RotationBackPropDeltaPs) * boneRot; } else if (bone.ParentIndex >= 0) { var parentBone = aBone[bone.ParentIndex]; bone.BlendedRotationWs = parentBone.BlendedRotationWs * (parentBone.RotationInverseWs * bone.CachedRotationWs); } } } // write blended position & adjusted rotation into final transforms for (int iBone = 0; iBone < aBone.Length; ++iBone) { var bone = aBone[iBone]; // skip fixed root if (iBone == 0 && !chain.LooseRoot) { bone.Instance.PositionSpring.Reset(bone.CachedPositionWs); bone.Instance.RotationSpring.Reset(bone.CachedRotationWs); continue; } bone.Transform.position = bone.BlendedPositionWs; bone.Transform.rotation = bone.BlendedRotationWs; bone.Transform.localScale = bone.BlendedScaleLs; } } }
public void Reset(Quaternion initValue, Quaternion initVelocity) { ValueVec = QuaternionUtil.ToVector4(initValue); VelocityVec = QuaternionUtil.ToVector4(initVelocity); }