예제 #1
0
        // Change standard T-pose to TDA T-pose
        private static void FixTdaBonesAndVertices([NotNull, ItemNotNull] IReadOnlyList <PmxBone> bones, [NotNull, ItemNotNull] IReadOnlyList <PmxVertex> vertices)
        {
            var defRotRight = Quaternion.FromEulerAngles(0, 0, MathHelper.DegreesToRadians(34.5f));
            var defRotLeft  = Quaternion.FromEulerAngles(0, 0, MathHelper.DegreesToRadians(-34.5f));

            var leftArm  = bones.SingleOrDefault(b => b.Name == "左腕");
            var rightArm = bones.SingleOrDefault(b => b.Name == "右腕");

            Debug.Assert(leftArm != null, nameof(leftArm) + " != null");
            Debug.Assert(rightArm != null, nameof(rightArm) + " != null");

            leftArm.AnimatedRotation  = defRotLeft;
            rightArm.AnimatedRotation = defRotRight;

            foreach (var bone in bones)
            {
                if (bone.ParentIndex >= 0)
                {
                    bone.Parent = bones[bone.ParentIndex];
                }
            }

            foreach (var bone in bones)
            {
                bone.SetToVmdPose(true);
            }

            foreach (var vertex in vertices)
            {
                var m = Matrix4.Zero;

                for (var j = 0; j < 4; ++j)
                {
                    var boneWeight = vertex.BoneWeights[j];

                    if (!boneWeight.IsValid)
                    {
                        continue;
                    }

                    m = m + bones[boneWeight.BoneIndex].SkinMatrix * boneWeight.Weight;
                }

                vertex.Position = Vector3.TransformPosition(vertex.Position, m);
                vertex.Normal   = Vector3.TransformNormal(vertex.Normal, m);
            }

            foreach (var bone in bones)
            {
                bone.InitialPosition = bone.CurrentPosition;
            }
        }
예제 #2
0
        private void UpdateVertices(float currentTime)
        {
            var bodyMesh         = _bodyMesh;
            var bodyAvatar       = _bodyAvatar;
            var bodyVertices     = _bodyVertices;
            var headMesh         = _headMesh;
            var headAvatar       = _headAvatar;
            var origBodyVertices = _originalBodyVertices;
            var headVertices     = _headVertices;
            var origHeadVertices = _originalHeadVertices;

            var keyFrames = _animation.KeyFrames;

#if !STATIC_POSE_DEBUG
            var animatedBoneCount      = _animation.BoneCount;
            var firstKeyFrameIndex     = -1;
            var lastFirstKeyFrameIndex = 0;

            for (var i = 0; i < keyFrames.Count; i += animatedBoneCount)
            {
                //if (keyFrames[i].Time >= currentTime) {
                if (keyFrames[i].FrameIndex > _lastFrameIndex)
                {
                    firstKeyFrameIndex = lastFirstKeyFrameIndex;
                    break;
                }

                lastFirstKeyFrameIndex = i;
            }

            if (firstKeyFrameIndex < 0)
            {
                // We are at the end of the whole animation.
                return;
            }

            for (var i = firstKeyFrameIndex; i < firstKeyFrameIndex + animatedBoneCount; ++i)
            {
                var frame   = keyFrames[i];
                var altPath = frame.Path.Contains("BODY_SCALE/") ? frame.Path.Replace("BODY_SCALE/", string.Empty) : frame.Path;
                var bone    = _bodyBoneList.FirstOrDefault(b => b.Path == altPath);

                if (bone == null)
                {
                    throw new ApplicationException($"Invalid bone path: {altPath}");
                }

                BoneNode transferredBone = null;

                foreach (var kv in BoneAttachmentMap)
                {
                    if (kv.Key == altPath)
                    {
                        transferredBone = _headBoneList.SingleOrDefault(b => b.Path == kv.Value);

                        if (transferredBone == null)
                        {
                            throw new ArgumentException();
                        }

                        break;
                    }
                }

                if (frame.HasPositions)
                {
                    var x = frame.PositionX.Value;
                    var y = frame.PositionY.Value;
                    var z = frame.PositionZ.Value;

                    var t = new Vector3(x, y, z);

                    t = t.FixCoordSystem();

                    bone.LocalPosition = t;

                    //if (transferredBone != null) {
                    //    transferredBone.LocalPosition = t;
                    //}
                }

                if (frame.HasRotations)
                {
                    var q = UnityRotation.EulerDeg(frame.AngleX.Value, frame.AngleY.Value, frame.AngleZ.Value);

                    q = q.FixCoordSystem();

                    bone.LocalRotation = q;

                    if (transferredBone != null)
                    {
                        transferredBone.LocalRotation = q;
                    }
                }
            }
#endif

            foreach (var bone in _bodyBoneList)
            {
                bone.UpdateTransform();
            }

            foreach (var bone in _headBoneList)
            {
                bone.UpdateTransform();
            }

            UpdateVertInternal(origBodyVertices, bodyVertices, bodyAvatar, bodyMesh, _bodyBoneList);
            UpdateVertInternal(origHeadVertices, headVertices, headAvatar, headMesh, _headBoneList);

            void UpdateVertInternal(PosNorm[] origVertices, PosNorm[] vertices, Avatar avatar, Mesh mesh, IReadOnlyList <BoneNode> boneList)
            {
                var vertexCount = vertices.Length;

                for (var i = 0; i < vertexCount; ++i)
                {
                    var vertex = origVertices[i];
                    var skin   = mesh.Skin[i];

                    var   m = Matrix4.Zero;
                    var   activeSkinCount = 0;
                    float totalWeight     = 0;

                    for (var j = 0; j < 4; ++j)
                    {
                        if (skin[j].Weight <= 0)
                        {
                            continue;
                        }

                        ++activeSkinCount;

                        var boneNameHash = mesh.BoneNameHashes[skin[j].BoneIndex];
                        var boneIndex    = avatar.FindBoneIndexByNameHash(boneNameHash);
                        var transform    = boneList[boneIndex].SkinMatrix;
                        m            = m + transform * skin[j].Weight;
                        totalWeight += skin[j].Weight;
                    }

                    if (activeSkinCount == 0)
                    {
#if DEBUG
                        Debug.Print("Warning: one skin is not bound to bones.");
#endif
                        continue;
                    }

#if DEBUG
                    if (Math.Abs(totalWeight - 1.0f) > 0.00001f)
                    {
                        Debug.Print("Warning: weights do not sum up.");
                    }
#endif

#if !NO_TRANSFORM_MESH
                    vertex.Position = Vector3.TransformPosition(vertex.Position, m);
                    vertex.Normal   = Vector3.TransformNormal(vertex.Normal, m);
#endif

                    vertices[i] = vertex;
                }
            }

            ++_lastFrameIndex;
        }