public override void Constrain(ActorNode node) { ActorNode target = m_Target as ActorNode; if (target == null) { return; } Mat2D transformA = m_Parent.WorldTransform; Mat2D transformB = new Mat2D(target.WorldTransform); if (m_SourceSpace == TransformSpace.Local) { ActorNode grandParent = target.Parent; if (grandParent != null) { Mat2D inverse = new Mat2D(); if (!Mat2D.Invert(inverse, grandParent.WorldTransform)) { return; } Mat2D.Multiply(transformB, inverse, transformB); } } if (m_DestSpace == TransformSpace.Local) { ActorNode grandParent = m_Parent.Parent; if (grandParent != null) { Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); } } Mat2D.Decompose(transformA, m_ComponentsA); Mat2D.Decompose(transformB, m_ComponentsB); float angleA = m_ComponentsA.Rotation % PI2; float angleB = m_ComponentsB.Rotation % PI2; float diff = angleB - angleA; if (diff > Math.PI) { diff -= PI2; } else if (diff < -Math.PI) { diff += PI2; } float ti = 1.0f - m_Strength; m_ComponentsB.Rotation = angleA + diff * m_Strength; m_ComponentsB.X = m_ComponentsA.X * ti + m_ComponentsB.X * m_Strength; m_ComponentsB.Y = m_ComponentsA.Y * ti + m_ComponentsB.Y * m_Strength; m_ComponentsB.ScaleX = m_ComponentsA.ScaleX * ti + m_ComponentsB.ScaleX * m_Strength; m_ComponentsB.ScaleY = m_ComponentsA.ScaleY * ti + m_ComponentsB.ScaleY * m_Strength; m_ComponentsB.Skew = m_ComponentsA.Skew * ti + m_ComponentsB.Skew * m_Strength; Mat2D.Compose(m_Parent.WorldTransform, m_ComponentsB); }
public void UpdateMount() { if (m_MountNode == null) { return; } //Matrix4x4 world = m_MountTargetObject.transform.localToWorldMatrix; Matrix4x4 localParent = Matrix4x4.identity; if (gameObject.transform.parent) { localParent = gameObject.transform.parent.worldToLocalMatrix; } Matrix4x4 localTransform = localParent * m_ActorGameObject.transform.localToWorldMatrix; // m_MountNode Mat2D world = m_MountNode.WorldTransform; Mat2D m2d = new Mat2D(); m2d[0] = localTransform[0, 0]; m2d[1] = localTransform[1, 0]; m2d[2] = localTransform[0, 1]; m2d[3] = localTransform[1, 1]; m2d[4] = localTransform[0, 3] + world[4] * ActorAsset.NimaToUnityScale * localTransform[0, 0]; m2d[5] = localTransform[1, 3] + world[5] * ActorAsset.NimaToUnityScale * localTransform[1, 1]; if (m_InheritRotation && m_InheritScale) { Vec2D scale = new Vec2D(); float angle = Mat2D.Decompose(world, scale); transform.localEulerAngles = new Vector3(0.0f, 0.0f, angle * Mathf.Rad2Deg); transform.localScale = new Vector3(scale[0] * m_ScaleModifier, scale[1] * m_ScaleModifier, 1.0f); } else if (m_InheritRotation) { float angle = (float)Math.Atan2(world[1], world[0]); transform.localEulerAngles = new Vector3(0.0f, 0.0f, angle * Mathf.Rad2Deg); } else if (m_InheritScale) { Vec2D scale = new Vec2D(); Mat2D.GetScale(world, scale); transform.localScale = new Vector3(scale[0] * m_ScaleModifier, scale[1] * m_ScaleModifier, 1.0f); } transform.localPosition = new Vector3(m2d[4], m2d[5], transform.localPosition.z); }
public override void UpdateTransform() { if (m_ActorCollider == null) { return; } base.UpdateTransform(); m_Collider.enabled = m_ActorCollider.IsCollisionEnabled; Mat2D world = m_ActorNode.WorldTransform; Vec2D scale = new Vec2D(); float angle = Mat2D.Decompose(world, scale); transform.localEulerAngles = new Vector3(0.0f, 0.0f, angle * Mathf.Rad2Deg); transform.localScale = new Vector3(scale[0] * ActorAsset.NimaToUnityScale, scale[1] * ActorAsset.NimaToUnityScale, 1.0f); transform.localPosition = new Vector3(world[4] * ActorAsset.NimaToUnityScale, world[5] * ActorAsset.NimaToUnityScale, 0.0f); }
public override void Constrain(ActorNode node) { ActorNode target = m_Target as ActorNode; ActorNode grandParent = m_Parent.Parent; Mat2D transformA = m_Parent.WorldTransform; Mat2D transformB = new Mat2D(); Mat2D.Decompose(transformA, m_ComponentsA); if (target == null) { Mat2D.Copy(transformB, transformA); m_ComponentsB[0] = m_ComponentsA[0]; m_ComponentsB[1] = m_ComponentsA[1]; m_ComponentsB[2] = m_ComponentsA[2]; m_ComponentsB[3] = m_ComponentsA[3]; m_ComponentsB[4] = m_ComponentsA[4]; m_ComponentsB[5] = m_ComponentsA[5]; } else { Mat2D.Copy(transformB, target.WorldTransform); if (m_SourceSpace == TransformSpace.Local) { ActorNode sourceGrandParent = target.Parent; if (sourceGrandParent != null) { Mat2D inverse = new Mat2D(); if (!Mat2D.Invert(inverse, sourceGrandParent.WorldTransform)) { return; } Mat2D.Multiply(transformB, inverse, transformB); } } Mat2D.Decompose(transformB, m_ComponentsB); if (!m_Copy) { m_ComponentsB.Rotation = m_DestSpace == TransformSpace.Local ? 1.0f : m_ComponentsA.Rotation; } else { m_ComponentsB.Rotation *= m_Scale; if (m_Offset) { m_ComponentsB.Rotation += m_Parent.Rotation; } } if (m_DestSpace == TransformSpace.Local) { // Destination space is in parent transform coordinates. // Recompose the parent local transform and get it in world, then decompose the world for interpolation. if (grandParent != null) { Mat2D.Compose(transformB, m_ComponentsB); Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); Mat2D.Decompose(transformB, m_ComponentsB); } } } bool clampLocal = m_MinMaxSpace == TransformSpace.Local && grandParent != null; if (clampLocal) { // Apply min max in local space, so transform to local coordinates first. Mat2D.Compose(transformB, m_ComponentsB); Mat2D inverse = new Mat2D(); if (!Mat2D.Invert(inverse, grandParent.WorldTransform)) { return; } Mat2D.Multiply(transformB, inverse, transformB); Mat2D.Decompose(transformB, m_ComponentsB); } if (m_EnableMax && m_ComponentsB.Rotation > m_Max) { m_ComponentsB.Rotation = m_Max; } if (m_EnableMin && m_ComponentsB.Rotation < m_Min) { m_ComponentsB.Rotation = m_Min; } if (clampLocal) { // Transform back to world. Mat2D.Compose(transformB, m_ComponentsB); Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); Mat2D.Decompose(transformB, m_ComponentsB); } float angleA = m_ComponentsA.Rotation % PI2; float angleB = m_ComponentsB.Rotation % PI2; float diff = angleB - angleA; if (diff > Math.PI) { diff -= PI2; } else if (diff < -Math.PI) { diff += PI2; } float ti = 1.0f - m_Strength; m_ComponentsB.Rotation = m_ComponentsA.Rotation + diff * m_Strength; m_ComponentsB.X = m_ComponentsA.X; m_ComponentsB.Y = m_ComponentsA.Y; m_ComponentsB.ScaleX = m_ComponentsA.ScaleX; m_ComponentsB.ScaleY = m_ComponentsA.ScaleY; m_ComponentsB.Skew = m_ComponentsA.Skew; Mat2D.Compose(m_Parent.WorldTransform, m_ComponentsB); }
public override void Constrain(ActorNode node) { ActorNode target = m_Target as ActorNode; if (target == null) { return; } Vec2D worldTargetTranslation = new Vec2D(); target.GetWorldTranslation(worldTargetTranslation); if (m_InfluencedBones.Length == 0) { return; } // Decompose the chain. foreach (BoneChain item in m_FKChain) { ActorBone bone = item.m_Bone; Mat2D parentWorld = bone.Parent.WorldTransform; Mat2D.Invert(item.m_ParentWorldInverse, parentWorld); Mat2D.Multiply(bone.Transform, item.m_ParentWorldInverse, bone.WorldTransform); Mat2D.Decompose(bone.Transform, item.m_TransformComponents); } int count = m_BoneData.Count; if (count == 1) { Solve1(m_BoneData[0], worldTargetTranslation); } else if (count == 2) { Solve2(m_BoneData[0], m_BoneData[1], worldTargetTranslation); } else { BoneChain tip = m_BoneData[count - 1]; for (int i = 0; i < count - 1; i++) { BoneChain item = m_BoneData[i]; Solve2(item, tip, worldTargetTranslation); for (int j = item.m_Index + 1; j < m_FKChain.Length - 1; j++) { BoneChain fk = m_FKChain[j]; Mat2D.Invert(fk.m_ParentWorldInverse, fk.m_Bone.Parent.WorldTransform); } } } // At the end, mix the FK angle with the IK angle by strength if (m_Strength != 1.0) { foreach (BoneChain fk in m_FKChain) { if (!fk.m_Included) { ActorBone bone = fk.m_Bone; Mat2D.Multiply(bone.WorldTransform, bone.Parent.WorldTransform, bone.Transform); continue; } float fromAngle = fk.m_TransformComponents.Rotation % PI2; float toAngle = fk.m_Angle % PI2; float diff = toAngle - fromAngle; if (diff > PI) { diff -= PI2; } else if (diff < -PI) { diff += PI2; } float angle = fromAngle + diff * m_Strength; ConstrainRotation(fk, angle); } } }