コード例 #1
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));
            }
        }
コード例 #2
0
        void WriteVertexArrays(BinaryWriter writer, ref Header header)
        {
            VertexArray[] arrays =
            {
                VertexArray.FromType(VertexArrayType.Position),
                VertexArray.FromType(VertexArrayType.Normal),
                VertexArray.FromType(VertexArrayType.Tangent),
                VertexArray.FromType(VertexArrayType.TexCoord),
                VertexArray.FromType(VertexArrayType.Color),
                VertexArray.FromType(VertexArrayType.BlendIndexes),
                VertexArray.FromType(VertexArrayType.BlendWeights),
            };

            for (int i = 0; i < arrays.Length; i++)
            {
                var array = arrays[i];
                array.Offset = (int)writer.BaseStream.Position;

                for (int v = 0; v < Vertices.Count; v++)
                {
                    switch (arrays[i].Type)
                    {
                    case VertexArrayType.TexCoord:
                        writer.Write(Vertices[v].TexCoord.x);
                        writer.Write(1f - Vertices[v].TexCoord.y);
                        break;

                    case VertexArrayType.Position:
                        writer.Write(CoordinateHelper.UnityToQuake(Vertices[v].Position));
                        break;

                    case VertexArrayType.Normal:
                        writer.Write(CoordinateHelper.UnityToQuake(Vertices[v].Normal));
                        break;

                    case VertexArrayType.Tangent:
                        writer.Write(CoordinateHelper.UnityToQuake(Vertices[v].Tangent));
                        break;

                    case VertexArrayType.BlendIndexes:
                        writer.Write((byte)Vertices[v].Weight.boneIndex0);
                        writer.Write((byte)Vertices[v].Weight.boneIndex1);
                        writer.Write((byte)Vertices[v].Weight.boneIndex2);
                        writer.Write((byte)Vertices[v].Weight.boneIndex3);
                        break;

                    case VertexArrayType.BlendWeights:
                        writer.Write((byte)(Vertices[v].Weight.weight0 * 255f));
                        writer.Write((byte)(Vertices[v].Weight.weight1 * 255f));
                        writer.Write((byte)(Vertices[v].Weight.weight2 * 255f));
                        writer.Write((byte)(Vertices[v].Weight.weight3 * 255f));
                        break;

                    case VertexArrayType.Color:
                        writer.Write(Vertices[v].Color.r);
                        writer.Write(Vertices[v].Color.g);
                        writer.Write(Vertices[v].Color.b);
                        writer.Write(Vertices[v].Color.a);
                        break;
                    }
                }

                arrays[i] = array;
            }

            header.VertexCount       = Vertices.Count;
            header.VertexArrayCount  = arrays.Length;
            header.VertexArrayOffset = (int)writer.BaseStream.Position;
            foreach (var array in arrays)
            {
                array.Write(writer);
            }
        }
コード例 #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);
            }
        }