Esempio n. 1
0
        private Bone LoadBone(GmdFile.BoneTransform boneTransform, Bone parent, GmdFile file, Bone[] boneTable)
        {
            var bone = new Bone();

            bone.Id       = boneTransform.BoneNo;
            bone.Name     = file.BoneNames[boneTransform.BoneNameIndex].ToString();
            bone.Position = boneTransform.LocalPosition;
            bone.Rotation = boneTransform.LocalRotation;
            bone.Scale    = boneTransform.Scale;
            bone.Parent   = parent;
            boneTable[boneTransform.BoneNo] = bone;

            bone.Children.AddRange(GmdUtils.GetChildren(boneTransform, file.BoneTransforms).Select(bt => LoadBone(bt, bone, file, boneTable)));

            return(bone);
        }
Esempio n. 2
0
        public static GmdFile.BoneTransform[] GetChildren(GmdFile.BoneTransform bt, GmdFile.BoneTransform[] boneTransforms)
        {
            var children = new List <GmdFile.BoneTransform>();

            if (bt.NextChildIndex >= 0)
            {
                var siblingIndex = bt.NextChildIndex;

                while (siblingIndex >= 0)
                {
                    children.Add(boneTransforms[siblingIndex]);
                    siblingIndex = boneTransforms[siblingIndex].NextSiblingIndex;
                }
            }

            return(children.ToArray());
        }
Esempio n. 3
0
        public static GmdFile.BoneTransform?GetParentBone(GmdFile.BoneTransform bt, GmdFile.BoneTransform[] boneTransforms)
        {
            var searchIdx = bt.BoneNo;

            for (int i = 0; i < boneTransforms.Length; i++)
            {
                if (boneTransforms[i].NextChildIndex == searchIdx)
                {
                    return(boneTransforms[i]);
                }

                if (boneTransforms[i].NextSiblingIndex == searchIdx)
                {
                    searchIdx = boneTransforms[i].BoneNo;
                    i         = 0;
                }
            }

            return(null);
        }
Esempio n. 4
0
        public GmdFile ToGmdFile()
        {
            var file = new GmdFile();

            file.Name = Name;
            // TEXTURES

            var textures = Textures.Concat(new string[] { "_dummy_rd", "dummy_nmap", "dummy_black", "dummy_gray", "dummy_white", "default_z", "noise" })
                           .Distinct().ToArray();

            file.Textures = textures
                            .Select(GmdFile.HashedName.FromString)
                            .ToArray();

            var shaders     = Materials.Select(mat => mat.Shader).Distinct().ToArray();
            var hlSubmeshes = Meshes.SelectMany(m => m.Submeshes).OrderBy(sm => sm.Id).ToArray();

            // MATERIALS
            file.Materials = Materials.Select(mat =>
            {
                var material = new GmdFile.Material()
                {
                    Id             = mat.Id,
                    TextureIndices =
                        mat.Textures.Select(tex => (int)(ushort)Array.IndexOf(textures, tex))
                        .Concat(Enumerable.Repeat((int)ushort.MaxValue, 8 - mat.Textures.Length)).ToArray(),
                    ShaderIndex  = (uint)Array.IndexOf(shaders, mat.Shader),
                    SubmeshIndex = (uint)Array.FindIndex(hlSubmeshes, m => m.Material == mat)
                };

                /*
                 * 3 => rd (sd_o1dzt_m2dzt) / tr (skin) / dummy_white
                 *  4 => rm / default_z [can be default_z, strange things happen when null]
                 *  5 => rt / noise [can be noise, too smooth when null]
                 *  6 => rs [can be null]
                 *  7 =>
                 */

                material.TextureIndices[0] = material.TextureIndices[0] >= 255 ? Array.IndexOf(textures, "dummy_black") : material.TextureIndices[0];
                material.TextureIndices[1] = material.TextureIndices[1] >= 255 ? Array.IndexOf(textures, "default_z") : material.TextureIndices[1];
                material.TextureIndices[2] = material.TextureIndices[2] >= 255 ? Array.IndexOf(textures, "dummy_nmap") : material.TextureIndices[2];
                material.TextureIndices[3] = material.TextureIndices[3] >= 255 ? Array.IndexOf(textures, "dummy_white") : material.TextureIndices[3];
                material.TextureIndices[4] = material.TextureIndices[4] >= 255 ? Array.IndexOf(textures, "default_z") : material.TextureIndices[4];
                material.TextureIndices[5] = material.TextureIndices[5] >= 255 ? Array.IndexOf(textures, "noise") : material.TextureIndices[5];
                material.TextureIndices[6] = material.TextureIndices[6] >= 255 ? ushort.MaxValue : material.TextureIndices[6]; //ushort.MaxValue;
                material.TextureIndices[7] = material.TextureIndices[7] >= 255 ? ushort.MaxValue : material.TextureIndices[7]; //ushort.MaxValue;
                // ushort.MaxValue

                material.Initialize(mat.Shader == GmdUtils.TRANSPARENCY_MAT);

                return(material);
            }).ToArray();

            // SHADERS
            file.Shaders = shaders.Select(shader => GmdFile.HashedName.FromString(shader)).ToArray();

            // MESHES
            var meshes        = new List <GmdFile.Mesh>();
            var vertexBuffers = new List <byte[]>();
            var submeshes     = new List <GmdFile.Submesh>();
            var indices       = new List <GmdFile.Index>();
            var boneIndices   = new List <GmdFile.BoneIndex>();

            for (int i = 0; i < Meshes.Length; i++)
            {
                var mesh        = Meshes[i];
                var gmdMesh     = new GmdFile.Mesh();
                var firstVertex = mesh.Submeshes.First().Vertices.First();

                gmdMesh.Initialize();
                gmdMesh.MeshId    = i;
                gmdMesh.Count     = mesh.Submeshes.Sum(m => m.Vertices.Length);
                gmdMesh.Offset    = vertexBuffers.Sum(b => b.Length);
                gmdMesh.UvLayers  = firstVertex.UvLayerCount;
                gmdMesh.HasBones  = firstVertex.BoneIndices != null;
                gmdMesh.FlagCount = GmdUtils.GetFlagCount(mesh.Submeshes.First().Material.Shader);

                using var buffer = new MemoryStream();
                using var writer = new BinaryWriter(buffer);

                Console.WriteLine("m" + i);
                int vertexCount = 0;
                for (int j = 0; j < mesh.Submeshes.Count; j++)
                {
                    var submesh       = mesh.Submeshes[j];
                    var gmdSubmesh    = new GmdFile.Submesh();
                    var boneIndexList = submesh.Vertices.SelectMany(v => v.BoneIndices ?? Enumerable.Empty <int>()).Distinct().ToList();

                    gmdSubmesh.Id              = Array.IndexOf(hlSubmeshes, submesh);
                    gmdSubmesh.MeshIndex       = i;
                    gmdSubmesh.IndicesCount    = submesh.Triangles.GetLength(0) * 3;
                    gmdSubmesh.IndicesOffset   = indices.Count;
                    gmdSubmesh.VertexCount     = submesh.Vertices.Length;
                    gmdSubmesh.MaterialIndex   = (int)submesh.Material.Id;
                    gmdSubmesh.BufferOffset2   = vertexCount;
                    gmdSubmesh.BoneIndexOffset = boneIndices.Count;
                    gmdSubmesh.BoneIndexCount  = boneIndexList.Count;

                    gmdMesh.Stride = WriteVertices(writer, submesh, gmdMesh.FlagCount, boneIndexList);

                    boneIndexList.Insert(0, gmdSubmesh.BoneIndexCount); // Expects count in index list
                    vertexCount += submesh.Vertices.Length;

                    // Fill in indices
                    for (int y = 0; y < submesh.Triangles.GetLength(0); y++)
                    {
                        indices.Add(new GmdFile.Index()
                        {
                            Value = submesh.Triangles[y, 0] + gmdSubmesh.BufferOffset2
                        });
                        indices.Add(new GmdFile.Index()
                        {
                            Value = submesh.Triangles[y, 1] + gmdSubmesh.BufferOffset2
                        });
                        indices.Add(new GmdFile.Index()
                        {
                            Value = submesh.Triangles[y, 2] + gmdSubmesh.BufferOffset2
                        });
                    }

                    boneIndices.AddRange(boneIndexList.Select(idx => new GmdFile.BoneIndex()
                    {
                        Value = idx
                    }));

                    submeshes.Add(gmdSubmesh);
                }

                gmdMesh.Size = (int)buffer.Length;
                vertexBuffers.Add(buffer.ToArray());

                meshes.Add(gmdMesh);
            }

            file.Indices        = indices.ToArray();
            file.Meshes         = meshes.ToArray();
            file.Submeshes      = submeshes.OrderBy(sm => sm.Id).ToArray();
            file.VertexBuffers  = vertexBuffers.ToArray();
            file.BoneIndices    = boneIndices.ToArray();
            file.BoneNames      = Bones.Select(b => GmdFile.HashedName.FromString(b.Name)).ToArray();
            file.BoneTransforms = Bones.Select(bone =>
            {
                var bt           = new GmdFile.BoneTransform();
                bt.Position      = bone.WorldMatrix.Translation;
                bt.LocalPosition = bone.Position;
                bt.LocalRotation = bone.Rotation;
                bt.Scale         = bone.Scale;
                bt.BoneNo        = bt.BoneNo2 = bone.Id;
                bt.BoneNameIndex = bone.Id;

                bt.TransformIndex   = -1;
                bt.NextSiblingIndex = -1;
                bt.NextChildIndex   = -1;
                bt.Footer           = new byte[16];

                if (bone.Name.Contains("[l0]"))
                {
                    bt.TransformIndex = 0;
                    bt.NodeType       = GmdFile.BoneTransform.NODE_TYPE_TRANSFORM;
                }

                // If bone has children, set the nextChildIndex idx
                if (bone.Children.Count > 0)
                {
                    bt.NextChildIndex = bone.Children[0].Id;
                }

                // If bone has another sibling that comes after itself, set NextSiblingIndex
                if (bone.Parent != null)
                {
                    var childIdx = bone.Parent.Children.IndexOf(bone);
                    if (childIdx >= 0 && childIdx + 1 < bone.Parent.Children.Count)
                    {
                        bt.NextSiblingIndex = bone.Parent.Children[childIdx + 1].Id;
                    }
                }

                return(bt);
            }).ToArray();


            return(file);
        }