예제 #1
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;
        }