Exemple #1
0
        public H3D ToH3D(string TextureAndMtlSearchPath = null)
        {
            H3D Output = new H3D();

            Dictionary <string, OBJMaterial> Materials = new Dictionary <string, OBJMaterial>();

            if (TextureAndMtlSearchPath != null)
            {
                string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile);

                if (File.Exists(MaterialFile))
                {
                    string MaterialName = null;

                    OBJMaterial Material = default(OBJMaterial);

                    TextReader Reader = new StreamReader(MaterialFile);

                    for (string Line; (Line = Reader.ReadLine()) != null;)
                    {
                        string[] Params = Line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                        if (Params.Length == 0)
                        {
                            continue;
                        }

                        switch (Params[0])
                        {
                        case "newmtl":
                            if (Params.Length > 1)
                            {
                                if (MaterialName != null && Material.DiffuseTexture != null)
                                {
                                    Materials.Add(MaterialName, Material);
                                }

                                Material = new OBJMaterial();

                                MaterialName = Line.Substring(Line.IndexOf(" ")).Trim();
                            }
                            break;

                        case "map_Kd":
                            if (Params.Length > 1)
                            {
                                string Name = Line.Substring(Line.IndexOf(Params[1]));

                                string TextureFile = Path.Combine(TextureAndMtlSearchPath, Name);
                                string TextureName = Path.GetFileNameWithoutExtension(TextureFile);

                                if (File.Exists(TextureFile) && !Output.Textures.Contains(TextureName))
                                {
                                    Output.Textures.Add(new H3DTexture(TextureFile));
                                }

                                Material.DiffuseTexture = Path.GetFileNameWithoutExtension(TextureName);
                            }
                            break;

                        case "Ka":
                        case "Kd":
                        case "Ks":
                            if (Params.Length >= 4)
                            {
                                Vector4 Color = new Vector4(
                                    float.Parse(Params[1], CultureInfo.InvariantCulture),
                                    float.Parse(Params[2], CultureInfo.InvariantCulture),
                                    float.Parse(Params[3], CultureInfo.InvariantCulture), 1);

                                switch (Params[0])
                                {
                                case "Ka": Material.Ambient = Color; break;

                                case "Kd": Material.Diffuse = Color; break;

                                case "Ks": Material.Specular = Color; break;
                                }
                            }
                            break;
                        }
                    }

                    Reader.Dispose();

                    if (MaterialName != null && Material.DiffuseTexture != null)
                    {
                        Materials.Add(MaterialName, Material);
                    }
                }
            }

            H3DModel Model = new H3DModel();

            Model.Name = "Model";

            ushort MaterialIndex = 0;

            Model.Flags       = H3DModelFlags.HasSkeleton;
            Model.BoneScaling = H3DBoneScaling.Maya;
            Model.MeshNodesVisibility.Add(true);

            float Height = 0;

            foreach (OBJMesh Mesh in Meshes)
            {
                Vector3 MinVector = new Vector3();
                Vector3 MaxVector = new Vector3();

                Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>();

                List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>();

                Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>();

                foreach (PICAVertex Vertex in Mesh.Vertices)
                {
                    VerticesQueue.Enqueue(Vertex);
                }

                while (VerticesQueue.Count > 2)
                {
                    List <ushort> Indices = new List <ushort>();

                    while (VerticesQueue.Count > 0)
                    {
                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = VerticesQueue.Dequeue();

                            if (Vertices.ContainsKey(Vertex))
                            {
                                Indices.Add((ushort)Vertices[Vertex]);
                            }
                            else
                            {
                                Indices.Add((ushort)Vertices.Count);

                                if (Vertex.Position.X < MinVector.X)
                                {
                                    MinVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y < MinVector.Y)
                                {
                                    MinVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z < MinVector.Z)
                                {
                                    MinVector.Z = Vertex.Position.Z;
                                }

                                if (Vertex.Position.X > MaxVector.X)
                                {
                                    MaxVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y > MaxVector.Y)
                                {
                                    MaxVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z > MaxVector.Z)
                                {
                                    MaxVector.Z = Vertex.Position.Z;
                                }

                                Vertices.Add(Vertex, Vertices.Count);
                            }
                        }
                    }

                    H3DSubMesh SM = new H3DSubMesh();

                    SM.BoneIndices = new ushort[] { 0 };
                    SM.Skinning    = H3DSubMeshSkinning.Smooth;
                    SM.Indices     = Indices.ToArray();

                    SubMeshes.Add(SM);
                }

                //Mesh
                List <PICAAttribute> Attributes = PICAAttribute.GetAttributes(
                    PICAAttributeName.Position,
                    PICAAttributeName.Normal,
                    PICAAttributeName.TexCoord0,
                    PICAAttributeName.Color,
                    PICAAttributeName.BoneIndex,
                    PICAAttributeName.BoneWeight);

                H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes)
                {
                    Skinning      = H3DMeshSkinning.Smooth,
                    MeshCenter    = (MinVector + MaxVector) * 0.5f,
                    MaterialIndex = MaterialIndex
                };

                if (Height < MaxVector.Y)
                {
                    Height = MaxVector.Y;
                }

                //Material
                string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{Mesh.MaterialName}";

                H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, MatName, null);

                if (Materials.ContainsKey(Mesh.MaterialName))
                {
                    Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture;
                }
                else
                {
                    Material.Texture0Name = "NoTexture";
                }

                Model.Materials.Add(Material);

                M.UpdateBoolUniforms(Material);

                Model.AddMesh(M);
            }

            /*
             * On Pokémon, the root bone (on the animaiton file) is used by the game to move
             * characters around, and all rigged bones are parented to this bone.
             * It's usually the Waist bone, that points upward and is half the character height.
             */
            Model.Skeleton.Add(new H3DBone(
                                   new Vector3(0, Height * 0.5f, 0),
                                   new Vector3(0, 0, (float)(Math.PI * 0.5)),
                                   Vector3.One,
                                   "Waist",
                                   -1));

            Model.Skeleton[0].CalculateTransform(Model.Skeleton);

            Output.Models.Add(Model);

            Output.CopyMaterials();

            return(Output);
        }