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 TransformBind(Mat2D xform) { if (m_BoneConnections != null) { foreach (BoneConnection bc in m_BoneConnections) { Mat2D.Multiply(bc.m_Bind, xform, bc.m_Bind); Mat2D.Invert(bc.m_InverseBind, bc.m_Bind); } } }
public static ActorImage Read(Actor actor, BinaryReader reader, ActorImage node = null) { if (node == null) { node = new ActorImage(); } ActorNode.Read(actor, reader, node); bool isVisible = reader.ReadByte() != 0; if (isVisible) { node.m_BlendMode = (BlendModes)reader.ReadByte(); node.m_DrawOrder = (int)reader.ReadUInt16(); node.m_TextureIndex = (int)reader.ReadByte(); int numConnectedBones = (int)reader.ReadByte(); if (numConnectedBones != 0) { node.m_BoneConnections = new BoneConnection[numConnectedBones]; for (int i = 0; i < numConnectedBones; i++) { BoneConnection bc = new BoneConnection(); bc.m_BoneIdx = reader.ReadUInt16(); Actor.ReadFloat32Array(reader, bc.m_Bind.Values); Mat2D.Invert(bc.m_InverseBind, bc.m_Bind); node.m_BoneConnections[i] = bc; } Mat2D worldOverride = new Mat2D(); Actor.ReadFloat32Array(reader, worldOverride.Values); node.WorldTransformOverride = worldOverride; } uint numVertices = reader.ReadUInt32(); int vertexStride = numConnectedBones > 0 ? 12 : 4; node.m_VertexCount = (int)numVertices; node.m_Vertices = new float[numVertices * vertexStride]; Actor.ReadFloat32Array(reader, node.m_Vertices); uint numTris = reader.ReadUInt32(); node.m_Triangles = new ushort[numTris * 3]; node.m_TriangleCount = (int)numTris; Actor.ReadUInt16Array(reader, node.m_Triangles); } return(node); }
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 Update(byte dirt) { ActorBone bone = m_Parent as ActorBone; ActorBone parentBone = bone.Parent as ActorBone; JellyComponent parentBoneJelly = parentBone == null ? null : parentBone.m_Jelly; Mat2D inverseWorld = new Mat2D(); if (!Mat2D.Invert(inverseWorld, bone.WorldTransform)) { return; } if (m_InTarget != null) { Vec2D translation = m_InTarget.GetWorldTranslation(new Vec2D()); Vec2D.TransformMat2D(m_InPoint, translation, inverseWorld); Vec2D.Normalize(m_InDirection, m_InPoint); } else if (parentBone != null) { if (parentBone.FirstBone == bone && parentBoneJelly != null && parentBoneJelly.m_OutTarget != null) { Vec2D translation = parentBoneJelly.m_OutTarget.GetWorldTranslation(new Vec2D()); Vec2D localParentOut = Vec2D.TransformMat2D(new Vec2D(), translation, inverseWorld); Vec2D.Normalize(localParentOut, localParentOut); Vec2D.Negate(m_InDirection, localParentOut); } else { Vec2D d1 = new Vec2D(1.0f, 0.0f); Vec2D d2 = new Vec2D(1.0f, 0.0f); Vec2D.TransformMat2(d1, d1, parentBone.WorldTransform); Vec2D.TransformMat2(d2, d2, bone.WorldTransform); Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2); Vec2D.TransformMat2(m_InDirection, sum, inverseWorld); Vec2D.Normalize(m_InDirection, m_InDirection); } m_InPoint[0] = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant; m_InPoint[1] = m_InDirection[1] * m_EaseIn * bone.Length * CurveConstant; } else { m_InDirection[0] = 1.0f; m_InDirection[1] = 0.0f; m_InPoint[0] = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant; } if (m_OutTarget != null) { Vec2D translation = m_OutTarget.GetWorldTranslation(new Vec2D()); Vec2D.TransformMat2D(m_OutPoint, translation, inverseWorld); Vec2D tip = new Vec2D(bone.Length, 0.0f); Vec2D.Subtract(m_OutDirection, m_OutPoint, tip); Vec2D.Normalize(m_OutDirection, m_OutDirection); } else if (bone.FirstBone != null) { ActorBone firstBone = bone.FirstBone; JellyComponent firstBoneJelly = firstBone.m_Jelly; if (firstBoneJelly != null && firstBoneJelly.m_InTarget != null) { Vec2D translation = firstBoneJelly.m_InTarget.GetWorldTranslation(new Vec2D()); Vec2D worldChildInDir = Vec2D.Subtract(new Vec2D(), firstBone.GetWorldTranslation(new Vec2D()), translation); Vec2D.TransformMat2(m_OutDirection, worldChildInDir, inverseWorld); } else { Vec2D d1 = new Vec2D(1.0f, 0.0f); Vec2D d2 = new Vec2D(1.0f, 0.0f); Vec2D.TransformMat2(d1, d1, firstBone.WorldTransform); Vec2D.TransformMat2(d2, d2, bone.WorldTransform); Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2); Vec2D.Negate(sum, sum); Vec2D.TransformMat2(m_OutDirection, sum, inverseWorld); Vec2D.Normalize(m_OutDirection, m_OutDirection); } Vec2D.Normalize(m_OutDirection, m_OutDirection); Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant); m_OutPoint[0] = bone.Length; m_OutPoint[1] = 0.0f; Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut); } else { m_OutDirection[0] = -1.0f; m_OutDirection[1] = 0.0f; Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant); m_OutPoint[0] = bone.Length; m_OutPoint[1] = 0.0f; Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut); } UpdateJellies(); }
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); } } }
public override void Constrain(ActorNode node) { ActorNode target = m_Target as ActorNode; ActorNode grandParent = m_Parent.Parent; Mat2D transformA = m_Parent.WorldTransform; Vec2D translationA = new Vec2D(transformA[4], transformA[5]); Vec2D translationB = new Vec2D(); if (target == null) { Vec2D.Copy(translationB, translationA); } else { Mat2D transformB = new Mat2D(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); } } translationB[0] = transformB[4]; translationB[1] = transformB[5]; if (!m_CopyX) { translationB[0] = m_DestSpace == TransformSpace.Local ? 0.0f : translationA[0]; } else { translationB[0] *= m_ScaleX; if (m_Offset) { translationB[0] += m_Parent.X; } } if (!m_CopyY) { translationB[1] = m_DestSpace == TransformSpace.Local ? 0.0f : translationA[1]; } else { translationB[1] *= m_ScaleY; if (m_Offset) { translationB[1] += m_Parent.Y; } } if (m_DestSpace == TransformSpace.Local) { // Destination space is in parent transform coordinates. if (grandParent != null) { Vec2D.TransformMat2D(translationB, translationB, grandParent.WorldTransform); } } } bool clampLocal = m_MinMaxSpace == TransformSpace.Local && grandParent != null; if (clampLocal) { // Apply min max in local space, so transform to local coordinates first. Mat2D invert = new Mat2D(); if (!Mat2D.Invert(invert, grandParent.WorldTransform)) { return; } // Get our target world coordinates in parent local. Vec2D.TransformMat2D(translationB, translationB, invert); } if (m_EnableMaxX && translationB[0] > m_MaxX) { translationB[0] = m_MaxX; } if (m_EnableMinX && translationB[0] < m_MinX) { translationB[0] = m_MinX; } if (m_EnableMaxY && translationB[1] > m_MaxY) { translationB[1] = m_MaxY; } if (m_EnableMinY && translationB[1] < m_MinY) { translationB[1] = m_MinY; } if (clampLocal) { // Transform back to world. Vec2D.TransformMat2D(translationB, translationB, grandParent.WorldTransform); } float ti = 1.0f - m_Strength; // Just interpolate world translation transformA[4] = translationA[0] * ti + translationB[0] * m_Strength; transformA[5] = translationA[1] * ti + translationB[1] * m_Strength; }