Example #1
0
        void WriteMeshes(BinaryWriter writer, TextTable text, ref Header header)
        {
            header.MeshOffset = (int)writer.BaseStream.Position;
            header.MeshCount  = Mathf.Max(1, Submeshes.Count);

            if (Submeshes.Count > 0)
            {
                foreach (var mesh in Submeshes)
                {
                    WriteMesh(mesh);
                }
            }
            else
            {
                WriteMesh(new Submesh
                {
                    Name          = "Model",
                    Material      = "Default",
                    TriangleCount = Triangles.Count
                });
            }

            void WriteMesh(Submesh mesh)
            {
                writer.Write(text.GetOrAddIndex(mesh.Name));
                writer.Write(text.GetOrAddIndex(mesh.Material));
                writer.Write(0);
                writer.Write(Vertices.Count);
                writer.Write(mesh.TriangleIndex);
                writer.Write(mesh.TriangleCount);
            }
        }
Example #2
0
        void WriteBones(BinaryWriter writer, TextTable text, ref Header header)
        {
            header.JointOffset = (int)writer.BaseStream.Position;
            header.JointCount  = Bones.Count;

            foreach (var bone in Bones)
            {
                int parent = Bones.IndexOf(bone.Parent);

                if (parent == -1 && bone.Parent != null)
                {
                    throw new Exception("Bone has invalid parent.");
                }

                writer.Write(text.GetOrAddIndex(bone.Name));
                writer.Write(parent);
                writer.Write(CoordinateHelper.UnityToQuake(bone.Translate));
                writer.Write(CoordinateHelper.UnityToQuake(bone.Rotate));
                writer.Write(CoordinateHelper.UnityToQuake(bone.Scale, isScale: true));
            }
        }
Example #3
0
        void WriteAnimations(BinaryWriter writer, TextTable text, ref Header header)
        {
            // todo: make this code nicer

            if (FrameCount <= 0)
            {
                return;
            }

            header.PoseCount  = Bones.Count;
            header.FrameCount = FrameCount;
            var frameData = new List <ushort>();
            var keyFrames = new KeyFrame[Bones.Count];
            var channels  = new PoseChannels[FrameCount, Bones.Count];
            var poses     = new Pose[Bones.Count];

            for (int b = 0; b < Bones.Count; b++)
            {
                keyFrames[b] = new KeyFrame
                {
                    Bone      = Bones[b],
                    Translate = Bones[b].Translate,
                    Rotate    = Bones[b].Rotate,
                    Scale     = Bones[b].Scale
                };
            }

            for (int f = 0; f < FrameCount; f++)
            {
                if (frames.TryGetValue(f, out var keys))
                {
                    foreach (var key in keys)
                    {
                        var bone = Bones.IndexOf(key.Bone);
                        if (bone == -1)
                        {
                            continue;
                        }
                        keyFrames[bone] = key;
                    }
                }

                for (int b = 0; b < Bones.Count; b++)
                {
                    var translate = CoordinateHelper.UnityToQuake(keyFrames[b].Translate);
                    var rotate    = CoordinateHelper.UnityToQuake(keyFrames[b].Rotate);
                    var scale     = CoordinateHelper.UnityToQuake(keyFrames[b].Scale, isScale: true);

                    channels[f, b][0] = translate.x;
                    channels[f, b][1] = translate.y;
                    channels[f, b][2] = translate.z;
                    channels[f, b][3] = rotate.x;
                    channels[f, b][4] = rotate.y;
                    channels[f, b][5] = rotate.z;
                    channels[f, b][6] = rotate.w;
                    channels[f, b][7] = scale.x;
                    channels[f, b][8] = scale.y;
                    channels[f, b][9] = scale.z;

                    for (int c = 0; c < 10; c++)
                    {
                        if (f == 0)
                        {
                            poses[b].Min[c] = poses[b].Max[c] = channels[f, b][c];
                        }
                        else
                        {
                            poses[b].Min[c] = Mathf.Min(poses[b].Min[c], channels[f, b][c]);
                            poses[b].Max[c] = Mathf.Max(poses[b].Max[c], channels[f, b][c]);
                        }
                    }
                }
            }

            for (int b = 0; b < Bones.Count; b++)
            {
                poses[b].Parent = Bones.IndexOf(Bones[b].Parent);

                for (int c = 0; c < 10; c++)
                {
                    poses[b].ChannelOffset[c] = poses[b].Min[c];
                    poses[b].ChannelScale [c] = 0;

                    if (poses[b].Min[c] == poses[b].Max[c])
                    {
                        continue;
                    }

                    poses[b].ChannelMask    |= 1 << c;
                    poses[b].ChannelScale[c] = (poses[b].Max[c] - poses[b].Min[c]) / 65535f;
                    header.FrameChannelCount++;
                }
            }

            for (int f = 0; f < FrameCount; f++)
            {
                for (int b = 0; b < Bones.Count; b++)
                {
                    for (int c = 0; c < 10; c++)
                    {
                        if ((poses[b].ChannelMask & (1 << c)) == 0)
                        {
                            continue;
                        }

                        float frame = (channels[f, b][c] - poses[b].Min[c]) / (poses[b].Max[c] - poses[b].Min[c]);
                        frameData.Add((ushort)Mathf.Min(frame * 65535f, 65535f));
                    }
                }
            }

            header.PoseOffset = (int)writer.BaseStream.Position;
            foreach (var pose in poses)
            {
                pose.Write(writer);
            }

            header.FrameOffset = (int)writer.BaseStream.Position;
            foreach (var frame in frameData)
            {
                writer.Write(frame);
            }

            header.AnimCount  = Mathf.Max(1, Animations.Count);
            header.AnimOffset = (int)writer.BaseStream.Position;

            if (Animations.Count > 0)
            {
                foreach (var range in Animations)
                {
                    WriteAnimation(range);
                }
            }
            else
            {
                WriteAnimation(new AnimationRange
                {
                    Name       = "Sequence",
                    FrameCount = FrameCount,
                    FrameRate  = 24
                });
            }

            void WriteAnimation(AnimationRange range)
            {
                writer.Write(text.GetOrAddIndex(range.Name));
                writer.Write(range.FrameIndex);
                writer.Write(range.FrameCount);
                writer.Write(range.FrameRate);
                writer.Write((int)range.Flags);
            }
        }