예제 #1
0
파일: GFModel.cs 프로젝트: Aqua-0/SPICA
        public GFModel(H3DModel mdl, H3DDict <H3DLUT> H3DLUTs) : this()
        {
            Name = mdl.Name;

            foreach (H3DBone Bone in mdl.Skeleton)
            {
                Skeleton.Add(new GFBone(Bone, mdl.Skeleton));
            }

            foreach (H3DMaterial Material in mdl.Materials)
            {
                H3DMesh Mesh = null;
                foreach (H3DMesh M in mdl.Meshes)
                {
                    if (mdl.Materials[M.MaterialIndex] == Material)
                    {
                        Mesh = M;
                        break;
                    }
                }
                Materials.Add(new GFMaterial(Material, Mesh));
            }

            Transform = mdl.WorldTransform;

            PokemonBBoxGen.CreateModelBBox(mdl);
            H3DMetaDataValue BBox       = mdl.MetaData[mdl.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX)];
            List <float>     BBoxMinMax = (List <float>)BBox.Values;

            BBoxMinVector = new Vector4(BBoxMinMax[0], BBoxMinMax[1], BBoxMinMax[2], 1);
            BBoxMaxVector = new Vector4(BBoxMinMax[3], BBoxMinMax[4], BBoxMinMax[5], 1);

            foreach (H3DLUT LUT in H3DLUTs)
            {
                if (LUT.Name.Equals(DefaultLUTName))
                {
                    foreach (H3DLUTSampler Sampler in LUT.Samplers)
                    {
                        LUTs.Add(new GFLUT()
                        {
                            Type  = GetLUTType(Sampler.Name, mdl.Materials),
                            Name  = Sampler.Name,
                            Table = Sampler.Table
                        });
                    }
                }
            }

            foreach (H3DMesh Mesh in mdl.Meshes)
            {
                Meshes.Add(new GFMesh(Mesh, mdl));
            }
        }
예제 #2
0
        public GFSubMesh(H3DSubMesh SubMesh, H3DMesh Parent, List <PICAVertex> Vertices, string Name) : this()
        {
            this.Name        = Name;
            BoneIndicesCount = (byte)SubMesh.BoneIndicesCount;
            BoneIndices      = new byte[SubMesh.BoneIndicesCount];
            for (int i = 0; i < SubMesh.BoneIndicesCount; i++)
            {
                BoneIndices[i] = (byte)SubMesh.BoneIndices[i];
            }

            Indices = SubMesh.Indices;

            PrimitiveMode = SubMesh.PrimitiveMode;
            VertexStride  = Parent.VertexStride;

            Attributes = Parent.Attributes;

            foreach (PICAFixedAttribute Old in Parent.FixedAttributes)
            {
                PICAFixedAttribute New = new PICAFixedAttribute()
                {
                    Name  = Old.Name,
                    Value = Old.Value
                };
                FixedAttributes.Add(New);
            }

            List <PICAVertex>           NewVertices    = new List <PICAVertex>();
            Dictionary <ushort, ushort> OldNewIndexMap = new Dictionary <ushort, ushort>();

            ushort[] NewIndices = new ushort[Indices.Length];

            for (int i = 0; i < NewIndices.Length; i++)
            {
                if (OldNewIndexMap.ContainsKey(Indices[i]))
                {
                    NewIndices[i] = OldNewIndexMap[Indices[i]];
                }
                else
                {
                    PICAVertex Vertex   = Vertices[Indices[i]];
                    ushort     NewIndex = (ushort)NewVertices.Count;
                    NewVertices.Add(Vertex);
                    NewIndices[i] = NewIndex;
                    OldNewIndexMap.Add(Indices[i], NewIndex);
                }
            }

            Indices    = NewIndices;
            IsIdx8Bits = /*NewIndices.Length <= 0x100*/ false;
            RawBuffer  = VerticesConverter.GetBuffer(NewVertices, Attributes);
        }
예제 #3
0
        private static void CreateMetaDataAndAddValue(H3DMesh Mesh, H3DMetaDataValue Value)
        {
            if (Mesh.MetaData == null)
            {
                Mesh.MetaData = new H3DMetaData();
            }
            int Find = Mesh.MetaData.Find(Value.Name);

            if (Find != -1)
            {
                Mesh.MetaData.Remove(Mesh.MetaData[Find]);
            }
            Mesh.MetaData.Add(Value);
        }
예제 #4
0
        public static PICAVertex[] GetWorldSpaceVertices(H3DDict <H3DBone> Skeleton, H3DMesh Mesh)
        {
            PICAVertex[] Vertices = Mesh.GetVertices();

            bool[] TransformedVertices = new bool[Vertices.Length];

            //Smooth meshes are already in World Space, so we don't need to do anything.
            if (Mesh.Skinning != H3DMeshSkinning.Smooth)
            {
                foreach (H3DSubMesh SM in Mesh.SubMeshes)
                {
                    foreach (ushort i in SM.Indices)
                    {
                        if (TransformedVertices[i])
                        {
                            continue;
                        }

                        TransformedVertices[i] = true;

                        PICAVertex v = Vertices[i];

                        if (Skeleton != null &&
                            Skeleton.Count > 0 &&
                            SM.Skinning != H3DSubMeshSkinning.Smooth)
                        {
                            int b = SM.BoneIndices[v.Indices[0]];

                            Matrix4x4 Transform = Skeleton[b].GetWorldTransform(Skeleton);

                            v.Position = Vector4.Transform(new Vector3(
                                                               v.Position.X,
                                                               v.Position.Y,
                                                               v.Position.Z),
                                                           Transform);

                            v.Normal.W = 0;

                            v.Normal = Vector4.Transform(v.Normal, Transform);
                            v.Normal = Vector4.Normalize(v.Normal);
                        }

                        Vertices[i] = v;
                    }
                }
            }

            return(Vertices);
        }
예제 #5
0
        private static void UpdateMeshListItem(H3DMesh mesh, ListViewItem item)
        {
            string materialName = "";

            if (mesh.Parent.Materials.Count > mesh.MaterialIndex)
            {
                materialName = mesh.Parent.Materials[mesh.MaterialIndex].Name;
            }

            item.SubItems.Clear();
            item.Tag  = mesh;
            item.Text = mesh.NodeIndex.ToString();
            item.SubItems.Add(materialName);
            item.SubItems.Add($"mesh_{materialName}");
            item.SubItems.Add(GetLayerString(mesh.Layer));
            item.SubItems.Add(mesh.Priority.ToString());
        }
예제 #6
0
파일: GFSubMesh.cs 프로젝트: Aqua-0/SPICA
        public GFSubMesh(H3DSubMesh SubMesh, H3DMesh Parent, List <PICAVertex> Vertices, string Name)
        {
            this.Name        = Name;
            BoneIndicesCount = (byte)SubMesh.BoneIndicesCount;
            BoneIndices      = new byte[SubMesh.BoneIndicesCount];
            for (int i = 0; i < SubMesh.BoneIndicesCount; i++)
            {
                BoneIndices[i] = (byte)SubMesh.BoneIndices[i];
            }

            Indices    = SubMesh.Indices;
            IsIdx8Bits = true;
            foreach (ushort Index in Indices)
            {
                if (Index > 0xFF)
                {
                    IsIdx8Bits = false;
                    break;
                }
            }

            PrimitiveMode = SubMesh.PrimitiveMode;
            VertexStride  = Parent.VertexStride;

            Attributes      = Parent.Attributes;
            FixedAttributes = Parent.FixedAttributes;

            List <PICAVertex> NewVertices = new List <PICAVertex>();

            ushort[] NewIndices = new ushort[Indices.Length];
            for (int i = 0; i < NewIndices.Length; i++)
            {
                PICAVertex Vertex   = Vertices[Indices[i]];
                int        NewIndex = NewVertices.IndexOf(Vertex);
                if (NewIndex == -1)
                {
                    NewIndex = NewVertices.Count;
                    NewVertices.Add(Vertex);
                }
                NewIndices[i] = (ushort)NewIndex;
            }

            Indices   = NewIndices;
            RawBuffer = VerticesConverter.GetBuffer(NewVertices, Attributes);
        }
예제 #7
0
        public static List <PICAVertex> GetVerticesList(H3DDict <H3DBone> Skeleton, H3DMesh Mesh)
        {
            List <PICAVertex> Output = new List <PICAVertex>();

            PICAVertex[] Vertices = Mesh.GetVertices();

            foreach (H3DSubMesh SM in Mesh.SubMeshes)
            {
                foreach (ushort i in SM.Indices)
                {
                    PICAVertex v = Vertices[i];

                    if (Skeleton != null &&
                        Skeleton.Count > 0 &&
                        SM.Skinning != H3DSubMeshSkinning.Smooth)
                    {
                        int b = SM.BoneIndices[v.Indices[0]];

                        Matrix4x4 Transform = Skeleton[b].GetWorldTransform(Skeleton);

                        v.Position = Vector4.Transform(new Vector3(
                                                           v.Position.X,
                                                           v.Position.Y,
                                                           v.Position.Z),
                                                       Transform);

                        v.Normal.W = 0;

                        v.Normal = Vector4.Transform(v.Normal, Transform);
                        v.Normal = Vector4.Normalize(v.Normal);
                    }

                    for (int b = 0; b < 4 && v.Weights[b] > 0; b++)
                    {
                        v.Indices[b] = SM.BoneIndices[v.Indices[b]];
                    }

                    Output.Add(v);
                }
            }

            return(Output);
        }
예제 #8
0
파일: GFMesh.cs 프로젝트: Aqua-0/SPICA
        public GFMesh(H3DMesh Mesh, H3DModel Parent) : this()
        {
            if (Mesh.NodeIndex >= 0 && Mesh.NodeIndex < Parent.MeshNodesTree.Count)
            {
                Name = Parent.MeshNodesTree.Find(Mesh.NodeIndex);
            }
            else
            {
                Name = "Mesh_" + Parent.Meshes.IndexOf(Mesh);
            }

            if (Mesh.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX) == -1)
            {
                PokemonBBoxGen.CreateModelBBox(Parent);
            }
            H3DMetaDataValue BBox       = Mesh.MetaData[Mesh.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX)];
            List <float>     BBoxMinMax = (List <float>)BBox.Values;

            BBoxMinVector = new Vector4(BBoxMinMax[0], BBoxMinMax[1], BBoxMinMax[2], 1);
            BBoxMaxVector = new Vector4(BBoxMinMax[3], BBoxMinMax[4], BBoxMinMax[5], 1);

            BoneIndicesPerVertex = 4;

            int SubMeshIdx             = 0;
            List <PICAVertex> Vertices = Mesh.GetVertices().ToList();

            foreach (H3DSubMesh SubMesh in Mesh.SubMeshes)
            {
                string MaterialName;
                if (Mesh.MaterialIndex >= 0 && Mesh.MaterialIndex < Parent.Materials.Count)
                {
                    MaterialName = Parent.Materials[Mesh.MaterialIndex].Name;
                }
                else
                {
                    MaterialName = null;
                }
                SubMeshes.Add(new GFSubMesh(SubMesh, Mesh, Vertices, MaterialName));
                SubMeshIdx++;
            }
        }
예제 #9
0
        public DAE(H3D Scene, int MdlIndex, int AnimIndex = -1)
        {
            if (MdlIndex != -1)
            {
                library_visual_scenes = new List <DAEVisualScene>();

                H3DModel Mdl = Scene.Models[MdlIndex];

                DAEVisualScene VN = new DAEVisualScene();

                VN.name = $"{Mdl.Name}_{MdlIndex.ToString("D2")}";
                VN.id   = $"{VN.name}_id";

                //Materials
                if (Mdl.Materials.Count > 0)
                {
                    library_materials = new List <DAEMaterial>();
                    library_effects   = new List <DAEEffect>();
                }

                foreach (H3DMaterial Mtl in Mdl.Materials)
                {
                    string MtlName = $"{MdlIndex.ToString("D2")}_{Mtl.Name}";

                    DAEEffect Effect = new DAEEffect();

                    Effect.name = $"{Mtl.Name}_eff";
                    Effect.id   = $"{Effect.name}_id";

                    DAEEffectParam ImgSurface = new DAEEffectParam();
                    DAEEffectParam ImgSampler = new DAEEffectParam();

                    ImgSurface.surface   = new DAEEffectParamSurfaceElement();
                    ImgSampler.sampler2D = new DAEEffectParamSampler2DElement();

                    ImgSurface.sid               = $"{Mtl.Name}_surf";
                    ImgSurface.surface.type      = "2D";
                    ImgSurface.surface.init_from = Mtl.Texture0Name;
                    ImgSurface.surface.format    = "PNG";

                    ImgSampler.sid = $"{Mtl.Name}_samp";
                    ImgSampler.sampler2D.source    = ImgSurface.sid;
                    ImgSampler.sampler2D.wrap_s    = Mtl.TextureMappers[0].WrapU.ToDAEWrap();
                    ImgSampler.sampler2D.wrap_t    = Mtl.TextureMappers[0].WrapV.ToDAEWrap();
                    ImgSampler.sampler2D.minfilter = Mtl.TextureMappers[0].MinFilter.ToDAEFilter();
                    ImgSampler.sampler2D.magfilter = Mtl.TextureMappers[0].MagFilter.ToDAEFilter();
                    ImgSampler.sampler2D.mipfilter = DAEFilter.LINEAR;

                    Effect.profile_COMMON.newparam.Add(ImgSurface);
                    Effect.profile_COMMON.newparam.Add(ImgSampler);

                    Effect.profile_COMMON.technique.sid = $"{Mtl.Name}_tech";
                    Effect.profile_COMMON.technique.phong.diffuse.texture.texture = ImgSampler.sid;

                    library_effects.Add(Effect);

                    DAEMaterial Material = new DAEMaterial();

                    Material.name = $"{Mtl.Name}_mat";
                    Material.id   = $"{Material.name}_id";

                    Material.instance_effect.url = $"#{Effect.id}";

                    library_materials.Add(Material);
                }

                //Skeleton nodes
                string RootBoneId = string.Empty;

                if ((Mdl.Skeleton?.Count ?? 0) > 0)
                {
                    Queue <Tuple <H3DBone, DAENode> > ChildBones = new Queue <Tuple <H3DBone, DAENode> >();

                    DAENode RootNode = new DAENode();

                    ChildBones.Enqueue(Tuple.Create(Mdl.Skeleton[0], RootNode));

                    RootBoneId = $"#{Mdl.Skeleton[0].Name}_bone_id";

                    while (ChildBones.Count > 0)
                    {
                        Tuple <H3DBone, DAENode> Bone_Node = ChildBones.Dequeue();

                        H3DBone Bone = Bone_Node.Item1;

                        Bone_Node.Item2.id   = $"{Bone.Name}_bone_id";
                        Bone_Node.Item2.name = Bone.Name;
                        Bone_Node.Item2.sid  = Bone.Name;
                        Bone_Node.Item2.type = DAENodeType.JOINT;
                        Bone_Node.Item2.SetBoneEuler(Bone.Translation, Bone.Rotation, Bone.Scale);

                        foreach (H3DBone B in Mdl.Skeleton)
                        {
                            if (B.ParentIndex == -1)
                            {
                                continue;
                            }

                            H3DBone ParentBone = Mdl.Skeleton[B.ParentIndex];

                            if (ParentBone == Bone)
                            {
                                DAENode Node = new DAENode();

                                ChildBones.Enqueue(Tuple.Create(B, Node));

                                if (Bone_Node.Item2.Nodes == null)
                                {
                                    Bone_Node.Item2.Nodes = new List <DAENode>();
                                }

                                Bone_Node.Item2.Nodes.Add(Node);
                            }
                        }
                    }

                    VN.node.Add(RootNode);
                }

                //Mesh
                if (Mdl.Meshes.Count > 0)
                {
                    library_geometries = new List <DAEGeometry>();
                }

                for (int MeshIndex = 0; MeshIndex < Mdl.Meshes.Count; MeshIndex++)
                {
                    if (Mdl.Meshes[MeshIndex].Type == H3DMeshType.Silhouette)
                    {
                        continue;
                    }

                    H3DMesh Mesh = Mdl.Meshes[MeshIndex];

                    PICAVertex[] Vertices = MeshTransform.GetWorldSpaceVertices(Mdl.Skeleton, Mesh);

                    string MtlName = $"Mdl_{MdlIndex}_Mtl_{Mdl.Materials[Mesh.MaterialIndex].Name}";
                    string MtlTgt  = library_materials[Mesh.MaterialIndex].id;

                    for (int SMIndex = 0; SMIndex < Mesh.SubMeshes.Count; SMIndex++)
                    {
                        H3DSubMesh SM = Mesh.SubMeshes[SMIndex];

                        string ShortName = string.Empty;

                        if (Mdl.MeshNodesTree != null && Mesh.NodeIndex < Mdl.MeshNodesTree.Count)
                        {
                            ShortName = Mdl.MeshNodesTree.Find(Mesh.NodeIndex);
                        }

                        string MeshName = $"{ShortName}_{MeshIndex}_{SMIndex}";

                        DAEGeometry Geometry = new DAEGeometry();

                        Geometry.name = MeshName;
                        Geometry.id   = $"{Geometry.name}_geo_id";

                        //Geometry
                        string VertsId = $"{MeshName}_vtx_id";

                        Geometry.mesh.vertices.id        = VertsId;
                        Geometry.mesh.triangles.material = MtlName;
                        Geometry.mesh.triangles.AddInput("VERTEX", $"#{VertsId}");
                        Geometry.mesh.triangles.Set_p(SM.Indices);

                        foreach (PICAAttribute Attr in Mesh.Attributes)
                        {
                            if (Attr.Name >= PICAAttributeName.BoneIndex)
                            {
                                continue;
                            }

                            string[] Values = new string[Vertices.Length];

                            for (int Index = 0; Index < Vertices.Length; Index++)
                            {
                                PICAVertex v = Vertices[Index];

                                switch (Attr.Name)
                                {
                                case PICAAttributeName.Position:  Values[Index] = DAEUtils.Vector3Str(v.Position);  break;

                                case PICAAttributeName.Normal:    Values[Index] = DAEUtils.Vector3Str(v.Normal);    break;

                                case PICAAttributeName.Tangent:   Values[Index] = DAEUtils.Vector3Str(v.Tangent);   break;

                                case PICAAttributeName.Color:     Values[Index] = DAEUtils.Vector4Str(v.Color);     break;

                                case PICAAttributeName.TexCoord0: Values[Index] = DAEUtils.Vector2Str(v.TexCoord0); break;

                                case PICAAttributeName.TexCoord1: Values[Index] = DAEUtils.Vector2Str(v.TexCoord1); break;

                                case PICAAttributeName.TexCoord2: Values[Index] = DAEUtils.Vector2Str(v.TexCoord2); break;
                                }
                            }

                            int Elements = 0;

                            switch (Attr.Name)
                            {
                            case PICAAttributeName.Position:  Elements = 3; break;

                            case PICAAttributeName.Normal:    Elements = 3; break;

                            case PICAAttributeName.Tangent:   Elements = 3; break;

                            case PICAAttributeName.Color:     Elements = 4; break;

                            case PICAAttributeName.TexCoord0: Elements = 2; break;

                            case PICAAttributeName.TexCoord1: Elements = 2; break;

                            case PICAAttributeName.TexCoord2: Elements = 2; break;
                            }

                            DAESource Source = new DAESource();

                            Source.name = $"{MeshName}_{Attr.Name}";
                            Source.id   = $"{Source.name}_id";

                            Source.float_array = new DAEArray()
                            {
                                id    = $"{Source.name}_array_id",
                                count = (uint)(Vertices.Length * Elements),
                                data  = string.Join(" ", Values)
                            };

                            DAEAccessor Accessor = new DAEAccessor()
                            {
                                source = $"#{Source.float_array.id}",
                                count  = (uint)Vertices.Length,
                                stride = (uint)Elements
                            };

                            switch (Elements)
                            {
                            case 2: Accessor.AddParams("float", "S", "T");           break;

                            case 3: Accessor.AddParams("float", "X", "Y", "Z");      break;

                            case 4: Accessor.AddParams("float", "R", "G", "B", "A"); break;
                            }

                            Source.technique_common.accessor = Accessor;

                            Geometry.mesh.source.Add(Source);

                            if (Attr.Name < PICAAttributeName.Color)
                            {
                                string Semantic = string.Empty;

                                switch (Attr.Name)
                                {
                                case PICAAttributeName.Position: Semantic = "POSITION"; break;

                                case PICAAttributeName.Normal:   Semantic = "NORMAL";   break;

                                case PICAAttributeName.Tangent:  Semantic = "TANGENT";  break;
                                }

                                Geometry.mesh.vertices.AddInput(Semantic, $"#{Source.id}");
                            }
                            else if (Attr.Name == PICAAttributeName.Color)
                            {
                                Geometry.mesh.triangles.AddInput("COLOR", $"#{Source.id}", 0);
                            }
                            else
                            {
                                Geometry.mesh.triangles.AddInput("TEXCOORD", $"#{Source.id}", 0, (uint)Attr.Name - 4);
                            }
                        } //Attributes Loop

                        library_geometries.Add(Geometry);

                        //Controller
                        bool HasController = SM.BoneIndicesCount > 0 && (Mdl.Skeleton?.Count ?? 0) > 0;

                        DAEController Controller = new DAEController();

                        if (HasController)
                        {
                            if (library_controllers == null)
                            {
                                library_controllers = new List <DAEController>();
                            }

                            Controller.name = $"{MeshName}_ctrl";
                            Controller.id   = $"{Controller.name}_id";

                            Controller.skin.source = $"#{Geometry.id}";
                            Controller.skin.vertex_weights.count = (uint)Vertices.Length;

                            string[] BoneNames = new string[Mdl.Skeleton.Count];
                            string[] BindPoses = new string[Mdl.Skeleton.Count];

                            for (int Index = 0; Index < Mdl.Skeleton.Count; Index++)
                            {
                                BoneNames[Index] = Mdl.Skeleton[Index].Name;
                                BindPoses[Index] = DAEUtils.MatrixStr(Mdl.Skeleton[Index].InverseTransform);
                            }

                            //4 is the max number of bones per vertex
                            int[] v      = new int[Vertices.Length * 4 * 2];
                            int[] vcount = new int[Vertices.Length];

                            Dictionary <string, int> Weights = new Dictionary <string, int>();

                            int vi = 0, vci = 0;

                            if (SM.Skinning == H3DSubMeshSkinning.Smooth)
                            {
                                foreach (PICAVertex Vertex in Vertices)
                                {
                                    int Count = 0;

                                    for (int Index = 0; Index < 4; Index++)
                                    {
                                        int   BIndex = Vertex.Indices[Index];
                                        float Weight = Vertex.Weights[Index];

                                        if (Weight == 0)
                                        {
                                            break;
                                        }

                                        if (BIndex < SM.BoneIndices.Length && BIndex > -1)
                                        {
                                            BIndex = SM.BoneIndices[BIndex];
                                        }
                                        else
                                        {
                                            BIndex = 0;
                                        }

                                        string WStr = Weight.ToString(CultureInfo.InvariantCulture);

                                        v[vi++] = BIndex;

                                        if (Weights.ContainsKey(WStr))
                                        {
                                            v[vi++] = Weights[WStr];
                                        }
                                        else
                                        {
                                            v[vi++] = Weights.Count;

                                            Weights.Add(WStr, Weights.Count);
                                        }

                                        Count++;
                                    }

                                    vcount[vci++] = Count;
                                }
                            }
                            else
                            {
                                foreach (PICAVertex Vertex in Vertices)
                                {
                                    int BIndex = Vertex.Indices[0];

                                    if (BIndex < SM.BoneIndices.Length && BIndex > -1)
                                    {
                                        BIndex = SM.BoneIndices[BIndex];
                                    }
                                    else
                                    {
                                        BIndex = 0;
                                    }

                                    v[vi++] = BIndex;
                                    v[vi++] = 0;

                                    vcount[vci++] = 1;
                                }

                                Weights.Add("1", 0);
                            }

                            Array.Resize(ref v, vi);

                            Controller.skin.src.Add(new DAESource($"{Controller.name}_names", 1, BoneNames, "JOINT", "Name"));
                            Controller.skin.src.Add(new DAESource($"{Controller.name}_poses", 16, BindPoses, "TRANSFORM", "float4x4"));
                            Controller.skin.src.Add(new DAESource($"{Controller.name}_weights", 1, Weights.Keys.ToArray(), "WEIGHT", "float"));

                            Controller.skin.joints.AddInput("JOINT", $"#{Controller.skin.src[0].id}");
                            Controller.skin.joints.AddInput("INV_BIND_MATRIX", $"#{Controller.skin.src[1].id}");

                            Controller.skin.vertex_weights.AddInput("JOINT", $"#{Controller.skin.src[0].id}", 0);
                            Controller.skin.vertex_weights.AddInput("WEIGHT", $"#{Controller.skin.src[2].id}", 1);

                            Controller.skin.vertex_weights.vcount = string.Join(" ", vcount);
                            Controller.skin.vertex_weights.v      = string.Join(" ", v);

                            library_controllers.Add(Controller);
                        }

                        //Mesh node
                        DAENode Node = new DAENode();

                        Node.name   = $"{MeshName}_node";
                        Node.id     = $"{Node.name}_id";
                        Node.matrix = DAEMatrix.Identity;

                        DAENodeInstance NodeInstance = new DAENodeInstance();

                        NodeInstance.url = $"#{(HasController ? Controller.id : Geometry.id)}";
                        NodeInstance.bind_material.technique_common.instance_material.symbol = MtlName;
                        NodeInstance.bind_material.technique_common.instance_material.target = $"#{MtlTgt}";

                        if (HasController)
                        {
                            NodeInstance.skeleton    = $"#{VN.node[0].id}";
                            Node.instance_controller = NodeInstance;
                        }
                        else
                        {
                            Node.instance_geometry = NodeInstance;
                        }

                        VN.node.Add(Node);
                    } //SubMesh Loop
                }     //Mesh Loop

                library_visual_scenes.Add(VN);

                if (library_visual_scenes.Count > 0)
                {
                    scene.instance_visual_scene.url = $"#{library_visual_scenes[0].id}";
                }

                library_images = new List <DAEImage>();

                foreach (H3DTexture Tex in Scene.Textures)
                {
                    //library_images.Add(new DAEImage()
                    //{
                    //    id        = Tex.Name,
                    //    init_from = $"./{Tex.Name}.png"
                    //});
                }

                foreach (var mat in Scene.Models[MdlIndex].Materials)
                {
                    if (mat.Texture0Name != null && !LibImgContainsThing(mat.Texture0Name))
                    {
                        library_images.Add(new DAEImage()
                        {
                            id        = mat.Texture0Name,
                            init_from = $"./{mat.Texture0Name}.png"
                        });
                    }
                    if (mat.Texture1Name != null && !LibImgContainsThing(mat.Texture1Name))
                    {
                        library_images.Add(new DAEImage()
                        {
                            id        = mat.Texture0Name,
                            init_from = $"./{mat.Texture0Name}.png"
                        });
                    }
                    if (mat.Texture2Name != null && !LibImgContainsThing(mat.Texture2Name))
                    {
                        library_images.Add(new DAEImage()
                        {
                            id        = mat.Texture0Name,
                            init_from = $"./{mat.Texture0Name}.png"
                        });
                    }
                }
            } //MdlIndex != -1

            if (AnimIndex != -1)
            {
                library_animations = new List <DAEAnimation>();

                string[] AnimElemNames = { "translate", "rotateX", "rotateY", "rotateZ", "scale" };

                H3DAnimation SklAnim = Scene.SkeletalAnimations[AnimIndex];

                H3DDict <H3DBone> Skeleton = Scene.Models[0].Skeleton;

                int FramesCount = (int)SklAnim.FramesCount + 1;

                foreach (H3DAnimationElement Elem in SklAnim.Elements)
                {
                    if (Elem.PrimitiveType != H3DPrimitiveType.Transform &&
                        Elem.PrimitiveType != H3DPrimitiveType.QuatTransform)
                    {
                        continue;
                    }

                    H3DBone SklBone = Skeleton.FirstOrDefault(x => x.Name == Elem.Name);
                    H3DBone Parent  = null;

                    if (SklBone != null && SklBone.ParentIndex != -1)
                    {
                        Parent = Skeleton[SklBone.ParentIndex];
                    }

                    for (int i = 0; i < 5; i++)
                    {
                        string[] AnimTimes = new string[FramesCount];
                        string[] AnimPoses = new string[FramesCount];
                        string[] AnimLerps = new string[FramesCount];

                        bool IsRotation = i > 0 && i < 4; //1, 2, 3

                        bool Skip =
                            Elem.PrimitiveType != H3DPrimitiveType.Transform &&
                            Elem.PrimitiveType != H3DPrimitiveType.QuatTransform;

                        if (!Skip)
                        {
                            if (Elem.Content is H3DAnimTransform Transform)
                            {
                                switch (i)
                                {
                                case 0: Skip = !Transform.TranslationExists; break;

                                case 1: Skip = !Transform.RotationX.Exists;  break;

                                case 2: Skip = !Transform.RotationY.Exists;  break;

                                case 3: Skip = !Transform.RotationZ.Exists;  break;

                                case 4: Skip = !Transform.ScaleExists;       break;
                                }
                            }
                            else if (Elem.Content is H3DAnimQuatTransform QuatTransform)
                            {
                                switch (i)
                                {
                                case 0: Skip = !QuatTransform.HasTranslation; break;

                                case 1: Skip = !QuatTransform.HasRotation;    break;

                                case 2: Skip = !QuatTransform.HasRotation;    break;

                                case 3: Skip = !QuatTransform.HasRotation;    break;

                                case 4: Skip = !QuatTransform.HasScale;       break;
                                }
                            }
                        }

                        if (Skip)
                        {
                            continue;
                        }

                        for (int Frame = 0; Frame < FramesCount; Frame++)
                        {
                            string StrTrans = string.Empty;

                            H3DAnimationElement PElem = SklAnim.Elements.FirstOrDefault(x => x.Name == Parent?.Name);

                            Vector3 InvScale = Vector3.One;

                            if (Elem.Content is H3DAnimTransform Transform)
                            {
                                //Compensate parent bone scale (basically, don't inherit scales)
                                if (Parent != null && (SklBone.Flags & H3DBoneFlags.IsSegmentScaleCompensate) != 0)
                                {
                                    if (PElem != null)
                                    {
                                        H3DAnimTransform PTrans = (H3DAnimTransform)PElem.Content;

                                        InvScale /= new Vector3(
                                            PTrans.ScaleX.Exists ? PTrans.ScaleX.GetFrameValue(Frame) : Parent.Scale.X,
                                            PTrans.ScaleY.Exists ? PTrans.ScaleY.GetFrameValue(Frame) : Parent.Scale.Y,
                                            PTrans.ScaleZ.Exists ? PTrans.ScaleZ.GetFrameValue(Frame) : Parent.Scale.Z);
                                    }
                                    else
                                    {
                                        InvScale /= Parent.Scale;
                                    }
                                }

                                switch (i)
                                {
                                //Translation
                                case 0:
                                    StrTrans = DAEUtils.VectorStr(new Vector3(
                                                                      Transform.TranslationX.Exists //X
                                            ? Transform.TranslationX.GetFrameValue(Frame) : SklBone.Translation.X,
                                                                      Transform.TranslationY.Exists //Y
                                            ? Transform.TranslationY.GetFrameValue(Frame) : SklBone.Translation.Y,
                                                                      Transform.TranslationZ.Exists //Z
                                            ? Transform.TranslationZ.GetFrameValue(Frame) : SklBone.Translation.Z));
                                    break;

                                //Scale
                                case 4:
                                    StrTrans = DAEUtils.VectorStr(InvScale * new Vector3(
                                                                      Transform.ScaleX.Exists //X
                                            ? Transform.ScaleX.GetFrameValue(Frame) : SklBone.Scale.X,
                                                                      Transform.ScaleY.Exists //Y
                                            ? Transform.ScaleY.GetFrameValue(Frame) : SklBone.Scale.Y,
                                                                      Transform.ScaleZ.Exists //Z
                                            ? Transform.ScaleZ.GetFrameValue(Frame) : SklBone.Scale.Z));
                                    break;

                                //Rotation
                                case 1: StrTrans = DAEUtils.RadToDegStr(Transform.RotationX.GetFrameValue(Frame)); break;

                                case 2: StrTrans = DAEUtils.RadToDegStr(Transform.RotationY.GetFrameValue(Frame)); break;

                                case 3: StrTrans = DAEUtils.RadToDegStr(Transform.RotationZ.GetFrameValue(Frame)); break;
                                }
                            }
                            else if (Elem.Content is H3DAnimQuatTransform QuatTransform)
                            {
                                //Compensate parent bone scale (basically, don't inherit scales)
                                if (Parent != null && (SklBone.Flags & H3DBoneFlags.IsSegmentScaleCompensate) != 0)
                                {
                                    if (PElem != null)
                                    {
                                        InvScale /= ((H3DAnimQuatTransform)PElem.Content).GetScaleValue(Frame);
                                    }
                                    else
                                    {
                                        InvScale /= Parent.Scale;
                                    }
                                }

                                switch (i)
                                {
                                case 0: StrTrans = DAEUtils.VectorStr(QuatTransform.GetTranslationValue(Frame));            break;

                                case 1: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().X); break;

                                case 2: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().Y); break;

                                case 3: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().Z); break;

                                case 4: StrTrans = DAEUtils.VectorStr(InvScale * QuatTransform.GetScaleValue(Frame));       break;
                                }
                            }

                            //This is the Time in seconds, so we divide by the target FPS
                            AnimTimes[Frame] = (Frame / 30f).ToString(CultureInfo.InvariantCulture);
                            AnimPoses[Frame] = StrTrans;
                            AnimLerps[Frame] = "LINEAR";
                        }

                        DAEAnimation Anim = new DAEAnimation();

                        Anim.name = $"{SklAnim.Name}_{Elem.Name}_{AnimElemNames[i]}";
                        Anim.id   = $"{Anim.name}_id";

                        Anim.src.Add(new DAESource($"{Anim.name}_frame", 1, AnimTimes, "TIME", "float"));
                        Anim.src.Add(new DAESource($"{Anim.name}_interp", 1, AnimLerps, "INTERPOLATION", "Name"));

                        Anim.src.Add(IsRotation
                            ? new DAESource($"{Anim.name}_pose", 1, AnimPoses, "ANGLE", "float")
                            : new DAESource($"{Anim.name}_pose", 3, AnimPoses,
                                            "X", "float",
                                            "Y", "float",
                                            "Z", "float"));

                        Anim.sampler.AddInput("INPUT", $"#{Anim.src[0].id}");
                        Anim.sampler.AddInput("INTERPOLATION", $"#{Anim.src[1].id}");
                        Anim.sampler.AddInput("OUTPUT", $"#{Anim.src[2].id}");

                        Anim.sampler.id     = $"{Anim.name}_samp_id";
                        Anim.channel.source = $"#{Anim.sampler.id}";
                        Anim.channel.target = $"{Elem.Name}_bone_id/{AnimElemNames[i]}";

                        if (IsRotation)
                        {
                            Anim.channel.target += ".ANGLE";
                        }

                        library_animations.Add(Anim);
                    } //Axis 0-5
                }     //SklAnim.Elements
            }         //AnimIndex != -1
        }
예제 #10
0
파일: Mesh.cs 프로젝트: HelloOO7/SPICA
        public Mesh(Model Parent, H3DMesh BaseMesh)
        {
            this.Parent   = Parent;
            this.BaseMesh = BaseMesh;

            Material = Parent.BaseModel.Materials[BaseMesh.MaterialIndex];

            PosOffs = BaseMesh.PositionOffset.ToVector4();

            int VtxCount = 1, FAOffset = 0;

            if (BaseMesh.VertexStride > 0)
            {
                VtxCount = BaseMesh.RawBuffer.Length / BaseMesh.VertexStride;
                FAOffset = BaseMesh.RawBuffer.Length;
            }

            byte[] Buffer;

            using (MemoryStream VertexStream = new MemoryStream())
            {
                BinaryWriter Writer = new BinaryWriter(VertexStream);

                Writer.Write(BaseMesh.RawBuffer);

                VertexStream.Seek(0, SeekOrigin.End);

                foreach (PICAFixedAttribute Attrib in BaseMesh.FixedAttributes)
                {
                    /*
                     * OpenGL doesn't support constant attributes, so we need to write
                     * them as a tight array (waste of space).
                     */
                    for (int i = 0; i < VtxCount; i++)
                    {
                        Writer.Write(Attrib.Value.X);
                        Writer.Write(Attrib.Value.Y);
                        Writer.Write(Attrib.Value.Z);
                        Writer.Write(Attrib.Value.W);
                    }
                }

                Buffer = VertexStream.ToArray();
            }

            IntPtr Length = new IntPtr(Buffer.Length);

            VBOHandle = GL.GenBuffer();
            VAOHandle = GL.GenVertexArray();

            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle);
            GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            GL.BindVertexArray(VAOHandle);

            int Offset = 0;
            int Stride = BaseMesh.VertexStride;

            for (int AttribIndex = 0; AttribIndex < 16; AttribIndex++)
            {
                GL.DisableVertexAttribArray(AttribIndex);
            }

            foreach (PICAAttribute Attrib in BaseMesh.Attributes)
            {
                int Size = Attrib.Elements;

                VertexAttribPointerType Type = VertexAttribPointerType.Byte;

                switch (Attrib.Format)
                {
                case PICAAttributeFormat.Byte:  Type = VertexAttribPointerType.Byte;              break;

                case PICAAttributeFormat.Ubyte: Type = VertexAttribPointerType.UnsignedByte;      break;

                case PICAAttributeFormat.Short: Type = VertexAttribPointerType.Short; Size <<= 1; break;

                case PICAAttributeFormat.Float: Type = VertexAttribPointerType.Float; Size <<= 2; break;
                }

                int AttribIndex = (int)Attrib.Name;

                GL.EnableVertexAttribArray(AttribIndex);

                GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle);

                //Short and Float types needs to be aligned into 2 bytes boundaries.
                if (Attrib.Format != PICAAttributeFormat.Byte &&
                    Attrib.Format != PICAAttributeFormat.Ubyte)
                {
                    Offset += Offset & 1;
                }

                GL.VertexAttribPointer(AttribIndex, Attrib.Elements, Type, false, Stride, Offset);

                SetScale(Attrib.Name, Attrib.Scale);

                Offset += Size;
            }

            foreach (PICAFixedAttribute Attrib in BaseMesh.FixedAttributes)
            {
                int AttribIndex = (int)Attrib.Name;

                GL.EnableVertexAttribArray(AttribIndex);

                GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle);

                GL.VertexAttribPointer(AttribIndex, 4, VertexAttribPointerType.Float, false, 0, FAOffset);

                /*
                 * Pokémon Sun/Moon seems to have fixed attributes for all unused attributes,
                 * with the vector set to zero (?). On the H3D shader this would normally
                 * make the Tangent scale one, and this signals the shader to use the Tangent
                 * to calculate the normal quaternion, and that would ruin the lighting
                 * 'cause the tangent is actually zero, so we force it to use normals by
                 * setting the Scale to zero here. Using the original Sun/Moon shaders
                 * should avoid this issue entirely.
                 */
                SetScale(Attrib.Name, Attrib.Name != PICAAttributeName.Tangent ? 1 : 0);

                FAOffset += 0x10 * VtxCount;
            }

            GL.BindVertexArray(0);
        }
예제 #11
0
파일: GFModel.cs 프로젝트: yorki00/SPICA
        public H3DModel ToH3DModel()
        {
            H3DModel Output = new H3DModel()
            {
                Name = Name
            };

            //Skeleton
            foreach (GFBone Bone in Skeleton)
            {
                Output.Skeleton.Add(new H3DBone()
                {
                    ParentIndex = (short)Skeleton.FindIndex(x => x.Name == Bone.Parent),

                    Name        = Bone.Name,
                    Scale       = Bone.Scale,
                    Rotation    = Bone.Rotation,
                    Translation = Bone.Translation
                });
            }

            foreach (H3DBone Bone in Output.Skeleton)
            {
                Bone.CalculateTransform(Output.Skeleton);

                Bone.Flags |= H3DBoneFlags.IsSegmentScaleCompensate;
            }

            if (Output.Skeleton.Count > 0)
            {
                Output.Flags = H3DModelFlags.HasSkeleton;
            }

            //Materials
            foreach (GFMaterial Material in Materials)
            {
                H3DMaterial Mat = new H3DMaterial();

                H3DMaterialParams Params = Mat.MaterialParams;

                Mat.Name = Material.MaterialName;

                Params.FragmentFlags = H3DFragmentFlags.IsLUTReflectionEnabled;

                Array.Copy(Material.TextureSources, Params.TextureSources, 4);

                for (int Unit = 0; Unit < Material.TextureCoords.Length; Unit++)
                {
                    string TextureName = Material.TextureCoords[Unit].Name;

                    Mat.EnabledTextures[Unit] = TextureName != null;

                    switch (Unit)
                    {
                    case 0: Mat.Texture0Name = TextureName; break;

                    case 1: Mat.Texture1Name = TextureName; break;

                    case 2: Mat.Texture2Name = TextureName; break;
                    }

                    //Texture Coords
                    GFTextureMappingType MappingType = Material.TextureCoords[Unit].MappingType;

                    Params.TextureCoords[Unit].MappingType = (H3DTextureMappingType)MappingType;

                    Params.TextureCoords[Unit].Scale       = Material.TextureCoords[Unit].Scale;
                    Params.TextureCoords[Unit].Rotation    = Material.TextureCoords[Unit].Rotation;
                    Params.TextureCoords[Unit].Translation = Material.TextureCoords[Unit].Translation;

                    //Texture Mapper
                    Mat.TextureMappers[Unit].WrapU = (PICATextureWrap)Material.TextureCoords[Unit].WrapU;
                    Mat.TextureMappers[Unit].WrapV = (PICATextureWrap)Material.TextureCoords[Unit].WrapV;

                    Mat.TextureMappers[Unit].MagFilter = (H3DTextureMagFilter)Material.TextureCoords[Unit].MagFilter;
                    Mat.TextureMappers[Unit].MinFilter = (H3DTextureMinFilter)Material.TextureCoords[Unit].MinFilter;

                    Mat.TextureMappers[Unit].MinLOD = (byte)Material.TextureCoords[Unit].MinLOD;

                    Mat.TextureMappers[Unit].BorderColor = Material.BorderColor[Unit];
                }

                Params.EmissionColor  = Material.EmissionColor;
                Params.AmbientColor   = Material.AmbientColor;
                Params.DiffuseColor   = Material.DiffuseColor;
                Params.Specular0Color = Material.Specular0Color;
                Params.Specular1Color = Material.Specular1Color;
                Params.Constant0Color = Material.Constant0Color;
                Params.Constant1Color = Material.Constant1Color;
                Params.Constant2Color = Material.Constant2Color;
                Params.Constant3Color = Material.Constant3Color;
                Params.Constant4Color = Material.Constant4Color;
                Params.Constant5Color = Material.Constant5Color;
                Params.BlendColor     = Material.BlendColor;

                //HACK: It's usually 0 on Sun/Moon, this causes issues on some
                //models being rendered transparent (Shader differences).
                Params.DiffuseColor.A = 0xff;

                Params.ColorScale = 1f;

                Params.LUTInputAbsolute  = Material.LUTInputAbsolute;
                Params.LUTInputSelection = Material.LUTInputSelection;
                Params.LUTInputScale     = Material.LUTInputScale;

                Params.ColorOperation   = Material.ColorOperation;
                Params.BlendFunction    = Material.BlendFunction;
                Params.LogicalOperation = Material.LogicalOperation;
                Params.AlphaTest        = Material.AlphaTest;
                Params.StencilTest      = Material.StencilTest;
                Params.StencilOperation = Material.StencilOperation;
                Params.DepthColorMask   = Material.DepthColorMask;
                Params.FaceCulling      = Material.FaceCulling;

                Params.ColorBufferRead  = Material.ColorBufferRead;
                Params.ColorBufferWrite = Material.ColorBufferWrite;

                Params.StencilBufferRead  = Material.StencilBufferRead;
                Params.StencilBufferWrite = Material.StencilBufferWrite;

                Params.DepthBufferRead  = Material.DepthBufferRead;
                Params.DepthBufferWrite = Material.DepthBufferWrite;

                if (Material.LUT0HashId != 0)
                {
                    Params.LUTReflecRTableName   = DefaultLUTName;
                    Params.LUTReflecRSamplerName = GetLUTName(Material.LUT0HashId);
                }

                if (Material.LUT1HashId != 0)
                {
                    Params.LUTReflecGTableName   = DefaultLUTName;
                    Params.LUTReflecGSamplerName = GetLUTName(Material.LUT1HashId);
                }

                if (Material.LUT2HashId != 0)
                {
                    Params.LUTReflecBTableName   = DefaultLUTName;
                    Params.LUTReflecBSamplerName = GetLUTName(Material.LUT2HashId);
                }

                if (Material.BumpTexture != -1)
                {
                    Params.BumpTexture = (byte)Material.BumpTexture;
                    Params.BumpMode    = H3DBumpMode.AsBump;
                }

                Params.Constant0Assignment = Material.Constant0Assignment;
                Params.Constant1Assignment = Material.Constant1Assignment;
                Params.Constant2Assignment = Material.Constant2Assignment;
                Params.Constant3Assignment = Material.Constant3Assignment;
                Params.Constant4Assignment = Material.Constant4Assignment;
                Params.Constant5Assignment = Material.Constant5Assignment;

                string VtxShaderName = Material.VtxShaderName;

                //Make shader names match X/Y/OR/AS shader names.
                if (VtxShaderName == "Poke" ||
                    VtxShaderName == "PokeNormal")
                {
                    VtxShaderName = "PokePack";
                }

                Params.ShaderReference = $"0@{VtxShaderName}";
                Params.ModelReference  = $"{Mat.Name}@{Name}";

                /*
                 * Add those for compatibility with the older BCH models.
                 * It's worth noting that ShaderParam0 is usually used as "UVScale" on model that uses
                 * geometry shader to make billboarded point sprites. On the new shader it have a
                 * multiplication of the Color by 3, while the older one doesn't have such multiplication,
                 * so for compatibility with the older shader, the easiest thing to do is just multiply the
                 * scale by 3 to give the same results on the old shader.
                 */
                Params.MetaData = new H3DMetaData();

                Params.MetaData.Add(new H3DMetaDataValue("EdgeType", Material.EdgeType));
                Params.MetaData.Add(new H3DMetaDataValue("IDEdgeEnable", Material.IDEdgeEnable));
                Params.MetaData.Add(new H3DMetaDataValue("EdgeID", Material.EdgeID));

                Params.MetaData.Add(new H3DMetaDataValue("ProjectionType", Material.ProjectionType));

                Params.MetaData.Add(new H3DMetaDataValue("RimPow", Material.RimPower));
                Params.MetaData.Add(new H3DMetaDataValue("RimScale", Material.RimScale));
                Params.MetaData.Add(new H3DMetaDataValue("PhongPow", Material.PhongPower));
                Params.MetaData.Add(new H3DMetaDataValue("PhongScale", Material.PhongScale));

                Params.MetaData.Add(new H3DMetaDataValue("IDEdgeOffsetEnable", Material.IDEdgeOffsetEnable));

                Params.MetaData.Add(new H3DMetaDataValue("EdgeMapAlphaMask", Material.EdgeMapAlphaMask));

                Params.MetaData.Add(new H3DMetaDataValue("BakeTexture0", Material.BakeTexture0));
                Params.MetaData.Add(new H3DMetaDataValue("BakeTexture1", Material.BakeTexture1));
                Params.MetaData.Add(new H3DMetaDataValue("BakeTexture2", Material.BakeTexture2));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant0", Material.BakeConstant0));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant1", Material.BakeConstant1));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant2", Material.BakeConstant2));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant3", Material.BakeConstant3));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant4", Material.BakeConstant4));
                Params.MetaData.Add(new H3DMetaDataValue("BakeConstant5", Material.BakeConstant5));

                Params.MetaData.Add(new H3DMetaDataValue("VertexShaderType", Material.VertexShaderType));

                Params.MetaData.Add(new H3DMetaDataValue("ShaderParam0", Material.ShaderParam0 * 3));
                Params.MetaData.Add(new H3DMetaDataValue("ShaderParam1", Material.ShaderParam1));
                Params.MetaData.Add(new H3DMetaDataValue("ShaderParam2", Material.ShaderParam2));
                Params.MetaData.Add(new H3DMetaDataValue("ShaderParam3", Material.ShaderParam3));

                Output.Materials.Add(Mat);
            }

            //Meshes
            Output.MeshNodesTree = new H3DPatriciaTree();

            foreach (GFMesh Mesh in Meshes)
            {
                //Note: GFModel have one Vertex Buffer for each SubMesh,
                //while on H3D all SubMeshes shares the same Vertex Buffer.
                //For this reason we need to store SubMeshes as Meshes on H3D.
                foreach (GFSubMesh SubMesh in Mesh.SubMeshes)
                {
                    int NodeIndex = Output.MeshNodesTree.Find(Mesh.Name);

                    if (NodeIndex == -1)
                    {
                        Output.MeshNodesTree.Add(Mesh.Name);
                        Output.MeshNodesVisibility.Add(true);

                        NodeIndex = Output.MeshNodesCount++;
                    }

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

                    ushort[] BoneIndices = new ushort[SubMesh.BoneIndicesCount];

                    for (int Index = 0; Index < BoneIndices.Length; Index++)
                    {
                        BoneIndices[Index] = SubMesh.BoneIndices[Index];
                    }

                    H3DSubMeshSkinning SMSk = Output.Skeleton.Count > 0
                        ? H3DSubMeshSkinning.Smooth
                        : H3DSubMeshSkinning.None;

                    SubMeshes.Add(new H3DSubMesh()
                    {
                        Skinning         = SMSk,
                        BoneIndicesCount = SubMesh.BoneIndicesCount,
                        BoneIndices      = BoneIndices,
                        Indices          = SubMesh.Indices
                    });

                    H3DMesh M = new H3DMesh(
                        SubMesh.RawBuffer,
                        SubMesh.VertexStride,
                        SubMesh.Attributes,
                        SubMesh.FixedAttributes,
                        SubMeshes);

                    M.Skinning = H3DMeshSkinning.Smooth;

                    int MatIndex = Materials.FindIndex(x => x.MaterialName == SubMesh.Name);

                    GFMaterial Mat = Materials[MatIndex];

                    M.MaterialIndex = (ushort)MatIndex;
                    M.NodeIndex     = (ushort)NodeIndex;
                    M.Layer         = Mat.RenderLayer;
                    M.Priority      = Mat.RenderPriority;

                    M.UpdateBoolUniforms(Output.Materials[MatIndex]);

                    Output.AddMesh(M);
                }
            }

            return(Output);
        }
예제 #12
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);
        }
예제 #13
0
        private static PICAVertex[] GetWorldSpaceVertices(H3DDict <H3DBone> skeleton, H3DMesh mesh)
        {
            var vertices = mesh.GetVertices();

            var transformedVertices = new bool[vertices.Length];

            //Smooth meshes are already in World Space, so we don't need to do anything.
            if (mesh.Skinning != H3DMeshSkinning.Smooth)
            {
                foreach (var sm in mesh.SubMeshes)
                {
                    foreach (var i in sm.Indices)
                    {
                        if (transformedVertices[i])
                        {
                            continue;
                        }

                        transformedVertices[i] = true;

                        var v = vertices[i];

                        if (skeleton != null && skeleton.Count > 0 && sm.Skinning != H3DSubMeshSkinning.Smooth)
                        {
                            int b = sm.BoneIndices[v.Indices[0]];

                            var transform = skeleton[b].GetWorldTransform(skeleton);

                            v.Position = System.Numerics.Vector4.Transform(new System.Numerics.Vector3(v.Position.X, v.Position.Y, v.Position.Z), transform);

                            v.Normal.W = 0;

                            v.Normal = System.Numerics.Vector4.Transform(v.Normal, transform);
                            v.Normal = System.Numerics.Vector4.Normalize(v.Normal);
                        }

                        vertices[i] = v;
                    }
                }
            }

            return(vertices);
        }
예제 #14
0
        public static PICAVertex[] GetVertices(H3DMesh Mesh)
        {
            if (Mesh.RawBuffer.Length == 0)
            {
                return(new PICAVertex[0]);
            }

            float[] Elems = new float[4];

            PICAVertex[] Output = new PICAVertex[Mesh.RawBuffer.Length / Mesh.VertexStride];

            using (MemoryStream MS = new MemoryStream(Mesh.RawBuffer))
            {
                BinaryReader Reader = new BinaryReader(MS);

                for (int Index = 0; Index < Output.Length; Index++)
                {
                    PICAVertex Out = new PICAVertex();

                    MS.Seek(Index * Mesh.VertexStride, SeekOrigin.Begin);

                    int bi = 0;
                    int wi = 0;

                    foreach (PICAAttribute Attrib in Mesh.Attributes)
                    {
                        AlignStream(MS, Attrib.Format);

                        for (int Elem = 0; Elem < Attrib.Elements; Elem++)
                        {
                            switch (Attrib.Format)
                            {
                            case PICAAttributeFormat.Byte:  Elems[Elem] = Reader.ReadSByte();  break;

                            case PICAAttributeFormat.Ubyte: Elems[Elem] = Reader.ReadByte();   break;

                            case PICAAttributeFormat.Short: Elems[Elem] = Reader.ReadInt16();  break;

                            case PICAAttributeFormat.Float: Elems[Elem] = Reader.ReadSingle(); break;
                            }
                        }

                        Vector4 v = new Vector4(Elems[0], Elems[1], Elems[2], Elems[3]);

                        v *= Attrib.Scale;

                        if (Attrib.Name == PICAAttributeName.Position)
                        {
                            v += Mesh.PositionOffset;
                        }

                        switch (Attrib.Name)
                        {
                        case PICAAttributeName.Position:  Out.Position = v; break;

                        case PICAAttributeName.Normal:    Out.Normal = v; break;

                        case PICAAttributeName.Tangent:   Out.Tangent = v; break;

                        case PICAAttributeName.Color:     Out.Color = v; break;

                        case PICAAttributeName.TexCoord0: Out.TexCoord0 = v; break;

                        case PICAAttributeName.TexCoord1: Out.TexCoord1 = v; break;

                        case PICAAttributeName.TexCoord2: Out.TexCoord2 = v; break;

                        case PICAAttributeName.BoneIndex:
                            Out.Indices[bi++] = (int)v.X; if (Attrib.Elements == 1)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.Y; if (Attrib.Elements == 2)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.Z; if (Attrib.Elements == 3)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.W;                           break;

                        case PICAAttributeName.BoneWeight:
                            Out.Weights[wi++] = v.X; if (Attrib.Elements == 1)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.Y; if (Attrib.Elements == 2)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.Z; if (Attrib.Elements == 3)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.W;                           break;
                        }
                    }

                    if (Mesh.FixedAttributes != null)
                    {
                        bool HasFixedIndices = Mesh.FixedAttributes.Any(x => x.Name == PICAAttributeName.BoneIndex);
                        bool HasFixedWeights = Mesh.FixedAttributes.Any(x => x.Name == PICAAttributeName.BoneWeight);

                        if (HasFixedIndices || HasFixedWeights)
                        {
                            foreach (PICAFixedAttribute Attr in Mesh.FixedAttributes)
                            {
                                switch (Attr.Name)
                                {
                                case PICAAttributeName.BoneIndex:
                                    Out.Indices[0] = (int)Attr.Value.X;
                                    Out.Indices[1] = (int)Attr.Value.Y;
                                    Out.Indices[2] = (int)Attr.Value.Z;
                                    break;

                                case PICAAttributeName.BoneWeight:
                                    Out.Weights[0] = Attr.Value.X;
                                    Out.Weights[1] = Attr.Value.Y;
                                    Out.Weights[2] = Attr.Value.Z;
                                    break;
                                }
                            }
                        }
                    }

                    Output[Index] = Out;
                }
            }

            return(Output);
        }
예제 #15
0
        public H3D ToH3D()
        {
            H3D Output = new H3D();

            H3DModel Model = new H3DModel();

            Model.MeshNodesTree = new H3DPatriciaTree();

            Model.Flags = BoneIndicesGroups.Length > 0 ? H3DModelFlags.HasSkeleton : 0;
            Model.Name  = "Model";

            foreach (MTMaterial Mat in Materials)
            {
                H3DMaterial Mtl = H3DMaterial.GetSimpleMaterial(
                    Model.Name,
                    Mat.Name,
                    Path.GetFileNameWithoutExtension(Mat.Texture0Name));

                Mtl.MaterialParams.ColorOperation.BlendMode  = Mat.AlphaBlend.BlendMode;
                Mtl.MaterialParams.BlendFunction             = Mat.AlphaBlend.BlendFunction;
                Mtl.MaterialParams.DepthColorMask.RedWrite   = Mat.AlphaBlend.RedWrite;
                Mtl.MaterialParams.DepthColorMask.GreenWrite = Mat.AlphaBlend.GreenWrite;
                Mtl.MaterialParams.DepthColorMask.BlueWrite  = Mat.AlphaBlend.BlueWrite;
                Mtl.MaterialParams.DepthColorMask.AlphaWrite = Mat.AlphaBlend.AlphaWrite;
                Mtl.MaterialParams.DepthColorMask.Enabled    = Mat.DepthStencil.DepthTest;
                Mtl.MaterialParams.DepthColorMask.DepthWrite = Mat.DepthStencil.DepthWrite;
                Mtl.MaterialParams.DepthColorMask.DepthFunc  = Mat.DepthStencil.DepthFunc;

                Model.Materials.Add(Mtl);
            }

            ushort Index = 0;

            foreach (MTMesh Mesh in Meshes)
            {
                if (Mesh.RenderType != -1)
                {
                    continue;
                }

                H3DMesh M = new H3DMesh(
                    Mesh.RawBuffer,
                    Mesh.VertexStride,
                    Mesh.Attributes,
                    null,
                    null)
                {
                    MaterialIndex = (ushort)Mesh.MaterialIndex,
                    NodeIndex     = Index,
                    Priority      = Mesh.RenderPriority
                };

                byte[] BoneIndices = BoneIndicesGroups[Mesh.BoneIndicesIndex];

                if ((Model.Flags & H3DModelFlags.HasSkeleton) != 0 && BoneIndices.Length > 0)
                {
                    M.Skinning = H3DMeshSkinning.Smooth;

                    PICAVertex[] Vertices = M.GetVertices();

                    for (int v = 0; v < Vertices.Length; v++)
                    {
                        Vector4 Position = Vector4.Zero;

                        float WeightSum = 0;

                        for (int i = 0; i < 4; i++)
                        {
                            if (Vertices[v].Weights[i] == 0)
                            {
                                break;
                            }

                            WeightSum += Vertices[v].Weights[i];

                            int bi = BoneIndicesGroups[Mesh.BoneIndicesIndex][Vertices[v].Indices[i]];

                            Vector4 Trans = Vector4.Zero;

                            for (int b = bi; b != -1; b = Skeleton[b].ParentIndex)
                            {
                                Trans += new Vector4(
                                    Skeleton[b].LocalTransform.M41,
                                    Skeleton[b].LocalTransform.M42,
                                    Skeleton[b].LocalTransform.M43, 0);
                            }

                            Matrix4x4 WT = Skeleton[bi].WorldTransform;

                            Vector3 P = new Vector3(
                                Vertices[v].Position.X,
                                Vertices[v].Position.Y,
                                Vertices[v].Position.Z);

                            Vector4 TP = Vector4.Transform(P, WT);

                            Position += (TP + Trans) * Vertices[v].Weights[i];
                        }

                        if (WeightSum < 1)
                        {
                            Position += Vertices[v].Position * (1 - WeightSum);
                        }

                        Vertices[v].Position = Position;
                    }

                    /*
                     * Removes unused bone from bone indices list, also splits sub meshes on exceeding bones if
                     * current Mesh uses more than 20 (BCH only supports up to 20).
                     */
                    Queue <ushort> IndicesQueue = new Queue <ushort>(Mesh.Indices);

                    while (IndicesQueue.Count > 0)
                    {
                        int Count = IndicesQueue.Count / 3;

                        List <ushort> Indices = new List <ushort>();
                        List <int>    Bones   = new List <int>();

                        while (Count-- > 0)
                        {
                            ushort i0 = IndicesQueue.Dequeue();
                            ushort i1 = IndicesQueue.Dequeue();
                            ushort i2 = IndicesQueue.Dequeue();

                            List <int> TempBones = new List <int>(12);

                            for (int j = 0; j < 4; j++)
                            {
                                int b0 = Vertices[i0].Indices[j];
                                int b1 = Vertices[i1].Indices[j];
                                int b2 = Vertices[i2].Indices[j];

                                if (!(Bones.Contains(b0) || TempBones.Contains(b0)))
                                {
                                    TempBones.Add(b0);
                                }
                                if (!(Bones.Contains(b1) || TempBones.Contains(b1)))
                                {
                                    TempBones.Add(b1);
                                }
                                if (!(Bones.Contains(b2) || TempBones.Contains(b2)))
                                {
                                    TempBones.Add(b2);
                                }
                            }

                            if (Bones.Count + TempBones.Count > 20)
                            {
                                IndicesQueue.Enqueue(i0);
                                IndicesQueue.Enqueue(i1);
                                IndicesQueue.Enqueue(i2);
                            }
                            else
                            {
                                Indices.Add(i0);
                                Indices.Add(i1);
                                Indices.Add(i2);

                                Bones.AddRange(TempBones);
                            }
                        }

                        H3DSubMesh SM = new H3DSubMesh();

                        SM.Skinning         = H3DSubMeshSkinning.Smooth;
                        SM.Indices          = Indices.ToArray();
                        SM.BoneIndicesCount = (ushort)Bones.Count;

                        for (int i = 0; i < Bones.Count; i++)
                        {
                            SM.BoneIndices[i] = BoneIndices[Bones[i]];
                        }

                        bool[] Visited = new bool[Vertices.Length];

                        foreach (ushort i in Indices)
                        {
                            if (!Visited[i])
                            {
                                Visited[i] = true;

                                Vertices[i].Indices[0] = Bones.IndexOf(Vertices[i].Indices[0]);
                                Vertices[i].Indices[1] = Bones.IndexOf(Vertices[i].Indices[1]);
                                Vertices[i].Indices[2] = Bones.IndexOf(Vertices[i].Indices[2]);
                                Vertices[i].Indices[3] = Bones.IndexOf(Vertices[i].Indices[3]);
                            }
                        }

                        M.SubMeshes.Add(SM);
                    }

                    M.RawBuffer = VerticesConverter.GetBuffer(Vertices, M.Attributes);
                }
                else
                {
                    M.SubMeshes.Add(new H3DSubMesh()
                    {
                        Indices = Mesh.Indices
                    });
                }

                Model.AddMesh(M);

                Model.MeshNodesTree.Add($"Mesh_{Index++}");

                Model.MeshNodesVisibility.Add(true);
            }

            int BoneIndex = 0;

            foreach (MTBone Bone in Skeleton)
            {
                Model.Skeleton.Add(new H3DBone()
                {
                    Name        = $"Bone_{BoneIndex++}",
                    ParentIndex = Bone.ParentIndex,
                    Translation = Bone.Position,
                    Scale       = Vector3.One
                });
            }

            foreach (H3DBone Bone in Model.Skeleton)
            {
                Bone.CalculateTransform(Model.Skeleton);
            }

            if (Model.Materials.Count == 0)
            {
                Model.Materials.Add(H3DMaterial.GetSimpleMaterial(Model.Name, "DummyMaterial", null));
            }

            Output.Models.Add(Model);

            Output.CopyMaterials();

            return(Output);
        }
예제 #16
0
        public H3D ToH3D(string TextureSearchPath = null)
        {
            H3D Output = new H3D();

            H3DModel Model = new H3DModel();

            Model.Name = "Model";

            ushort MaterialIndex = 0;

            if (Skeleton.Count > 0)
            {
                Model.Flags = H3DModelFlags.HasSkeleton;
            }

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

            foreach (SMDMesh 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>();
                    List <ushort> BoneIndices = new List <ushort>();

                    int TriCount = VerticesQueue.Count / 3;

                    while (TriCount-- > 0)
                    {
                        PICAVertex[] Triangle = new PICAVertex[3];

                        Triangle[0] = VerticesQueue.Dequeue();
                        Triangle[1] = VerticesQueue.Dequeue();
                        Triangle[2] = VerticesQueue.Dequeue();

                        List <ushort> TempIndices = new List <ushort>();

                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = Triangle[Tri];

                            for (int i = 0; i < 4; i++)
                            {
                                ushort Index = (ushort)Vertex.Indices[i];

                                if (!(BoneIndices.Contains(Index) || TempIndices.Contains(Index)))
                                {
                                    TempIndices.Add(Index);
                                }
                            }
                        }

                        if (BoneIndices.Count + TempIndices.Count > 20)
                        {
                            VerticesQueue.Enqueue(Triangle[0]);
                            VerticesQueue.Enqueue(Triangle[1]);
                            VerticesQueue.Enqueue(Triangle[2]);

                            continue;
                        }

                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = Triangle[Tri];

                            for (int Index = 0; Index < 4; Index++)
                            {
                                int BoneIndex = BoneIndices.IndexOf((ushort)Vertex.Indices[Index]);

                                if (BoneIndex == -1)
                                {
                                    BoneIndex = BoneIndices.Count;
                                    BoneIndices.Add((ushort)Vertex.Indices[Index]);
                                }

                                Vertex.Indices[Index] = BoneIndex;
                            }

                            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);
                            }
                        }
                    }

                    SubMeshes.Add(new H3DSubMesh()
                    {
                        Skinning         = H3DSubMeshSkinning.Smooth,
                        BoneIndicesCount = (ushort)BoneIndices.Count,
                        BoneIndices      = BoneIndices.ToArray(),
                        Indices          = Indices.ToArray()
                    });
                }

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

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

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

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

                Model.Materials.Add(Material);

                if (TextureSearchPath != null && !Output.Textures.Contains(TexName))
                {
                    string TextureFile = Path.Combine(TextureSearchPath, Mesh.MaterialName);

                    if (File.Exists(TextureFile))
                    {
                        Output.Textures.Add(new H3DTexture(TextureFile));
                    }
                }

                M.UpdateBoolUniforms(Material);

                Model.AddMesh(M);
            }

            //Build Skeleton
            foreach (SMDBone Bone in Skeleton)
            {
                SMDNode Node = Nodes[Bone.NodeIndex];

                Model.Skeleton.Add(new H3DBone()
                {
                    Name        = Node.Name,
                    ParentIndex = (short)Node.ParentIndex,
                    Translation = Bone.Translation,
                    Rotation    = Bone.Rotation,
                    Scale       = Vector3.One
                });
            }

            //Calculate Absolute Inverse Transforms for all bones
            foreach (H3DBone Bone in Model.Skeleton)
            {
                Bone.CalculateTransform(Model.Skeleton);
            }

            Output.Models.Add(Model);

            Output.CopyMaterials();

            return(Output);
        }
예제 #17
0
파일: Gfx.cs 프로젝트: yorki00/SPICA
        public H3D ToH3D()
        {
            H3D Output = new H3D();

            foreach (GfxModel Model in Models)
            {
                H3DModel Mdl = new H3DModel();

                Mdl.Name = Model.Name;

                Mdl.WorldTransform = Model.WorldTransform;

                foreach (GfxMaterial Material in Model.Materials)
                {
                    H3DMaterial Mat = new H3DMaterial()
                    {
                        Name = Material.Name
                    };

                    Mat.MaterialParams.ModelReference  = $"{Mat.Name}@{Model.Name}";
                    Mat.MaterialParams.ShaderReference = "0@DefaultShader";

                    Mat.MaterialParams.Flags = (H3DMaterialFlags)Material.Flags;

                    Mat.MaterialParams.TranslucencyKind = (H3DTranslucencyKind)Material.TranslucencyKind;
                    Mat.MaterialParams.TexCoordConfig   = (H3DTexCoordConfig)Material.TexCoordConfig;

                    Mat.MaterialParams.EmissionColor  = Material.Colors.Emission;
                    Mat.MaterialParams.AmbientColor   = Material.Colors.Ambient;
                    Mat.MaterialParams.DiffuseColor   = Material.Colors.Diffuse;
                    Mat.MaterialParams.Specular0Color = Material.Colors.Specular0;
                    Mat.MaterialParams.Specular1Color = Material.Colors.Specular1;
                    Mat.MaterialParams.Constant0Color = Material.Colors.Constant0;
                    Mat.MaterialParams.Constant1Color = Material.Colors.Constant1;
                    Mat.MaterialParams.Constant2Color = Material.Colors.Constant2;
                    Mat.MaterialParams.Constant3Color = Material.Colors.Constant3;
                    Mat.MaterialParams.Constant4Color = Material.Colors.Constant4;
                    Mat.MaterialParams.Constant5Color = Material.Colors.Constant5;
                    Mat.MaterialParams.ColorScale     = Material.Colors.Scale;

                    if (Material.Rasterization.IsPolygonOffsetEnabled)
                    {
                        Mat.MaterialParams.Flags |= H3DMaterialFlags.IsPolygonOffsetEnabled;
                    }

                    Mat.MaterialParams.FaceCulling       = Material.Rasterization.FaceCulling.ToPICAFaceCulling();
                    Mat.MaterialParams.PolygonOffsetUnit = Material.Rasterization.PolygonOffsetUnit;

                    Mat.MaterialParams.DepthColorMask = Material.FragmentOperation.Depth.ColorMask;

                    Mat.MaterialParams.DepthColorMask.RedWrite   = true;
                    Mat.MaterialParams.DepthColorMask.GreenWrite = true;
                    Mat.MaterialParams.DepthColorMask.BlueWrite  = true;
                    Mat.MaterialParams.DepthColorMask.AlphaWrite = true;
                    Mat.MaterialParams.DepthColorMask.DepthWrite = true;

                    Mat.MaterialParams.ColorBufferRead  = false;
                    Mat.MaterialParams.ColorBufferWrite = true;

                    Mat.MaterialParams.StencilBufferRead  = false;
                    Mat.MaterialParams.StencilBufferWrite = false;

                    Mat.MaterialParams.DepthBufferRead  = true;
                    Mat.MaterialParams.DepthBufferWrite = true;

                    Mat.MaterialParams.ColorOperation   = Material.FragmentOperation.Blend.ColorOperation;
                    Mat.MaterialParams.LogicalOperation = Material.FragmentOperation.Blend.LogicalOperation;
                    Mat.MaterialParams.BlendFunction    = Material.FragmentOperation.Blend.Function;
                    Mat.MaterialParams.BlendColor       = Material.FragmentOperation.Blend.Color;

                    Mat.MaterialParams.StencilOperation = Material.FragmentOperation.Stencil.Operation;
                    Mat.MaterialParams.StencilTest      = Material.FragmentOperation.Stencil.Test;

                    int TCIndex = 0;

                    foreach (GfxTextureCoord TexCoord in Material.TextureCoords)
                    {
                        H3DTextureCoord TC = new H3DTextureCoord();

                        TC.MappingType = (H3DTextureMappingType)TexCoord.MappingType;

                        TC.ReferenceCameraIndex = (sbyte)TexCoord.ReferenceCameraIndex;

                        TC.TransformType = (H3DTextureTransformType)TexCoord.TransformType;

                        TC.Scale       = TexCoord.Scale;
                        TC.Rotation    = TexCoord.Rotation;
                        TC.Translation = TexCoord.Translation;

                        switch (TexCoord.MappingType)
                        {
                        case GfxTextureMappingType.UvCoordinateMap:
                            Mat.MaterialParams.TextureSources[TCIndex] = TexCoord.SourceCoordIndex;
                            break;

                        case GfxTextureMappingType.CameraCubeEnvMap:
                            Mat.MaterialParams.TextureSources[TCIndex] = 3;
                            break;

                        case GfxTextureMappingType.CameraSphereEnvMap:
                            Mat.MaterialParams.TextureSources[TCIndex] = 4;
                            break;
                        }

                        Mat.MaterialParams.TextureCoords[TCIndex++] = TC;

                        if (TCIndex == Material.UsedTextureCoordsCount)
                        {
                            break;
                        }
                    }

                    int TMIndex = 0;

                    foreach (GfxTextureMapper TexMapper in Material.TextureMappers)
                    {
                        if (TexMapper == null)
                        {
                            break;
                        }

                        H3DTextureMapper TM = new H3DTextureMapper();

                        TM.WrapU = TexMapper.WrapU;
                        TM.WrapV = TexMapper.WrapV;

                        TM.MagFilter = (H3DTextureMagFilter)TexMapper.MinFilter;

                        switch ((uint)TexMapper.MagFilter | ((uint)TexMapper.MipFilter << 1))
                        {
                        case 0: TM.MinFilter = H3DTextureMinFilter.NearestMipmapNearest; break;

                        case 1: TM.MinFilter = H3DTextureMinFilter.LinearMipmapNearest;  break;

                        case 2: TM.MinFilter = H3DTextureMinFilter.NearestMipmapLinear;  break;

                        case 3: TM.MinFilter = H3DTextureMinFilter.LinearMipmapLinear;   break;
                        }

                        TM.LODBias = TexMapper.LODBias;
                        TM.MinLOD  = TexMapper.MinLOD;

                        TM.BorderColor = TexMapper.BorderColor;

                        Mat.TextureMappers[TMIndex++] = TM;
                    }

                    Mat.EnabledTextures[0] = Material.TextureMappers[0] != null;
                    Mat.EnabledTextures[1] = Material.TextureMappers[1] != null;
                    Mat.EnabledTextures[2] = Material.TextureMappers[2] != null;

                    Mat.Texture0Name = Material.TextureMappers[0]?.Texture.Path;
                    Mat.Texture1Name = Material.TextureMappers[1]?.Texture.Path;
                    Mat.Texture2Name = Material.TextureMappers[2]?.Texture.Path;

                    GfxFragmentFlags SrcFlags = Material.FragmentShader.Lighting.Flags;
                    H3DFragmentFlags DstFlags = 0;

                    if ((SrcFlags & GfxFragmentFlags.IsClampHighLightEnabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsClampHighLightEnabled;
                    }

                    if ((SrcFlags & GfxFragmentFlags.IsLUTDist0Enabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsLUTDist0Enabled;
                    }

                    if ((SrcFlags & GfxFragmentFlags.IsLUTDist1Enabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsLUTDist1Enabled;
                    }

                    if ((SrcFlags & GfxFragmentFlags.IsLUTGeoFactor0Enabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsLUTGeoFactor0Enabled;
                    }

                    if ((SrcFlags & GfxFragmentFlags.IsLUTGeoFactor1Enabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsLUTGeoFactor1Enabled;
                    }

                    if ((SrcFlags & GfxFragmentFlags.IsLUTReflectionEnabled) != 0)
                    {
                        DstFlags |= H3DFragmentFlags.IsLUTReflectionEnabled;
                    }

                    if (Material.FragmentShader.Lighting.IsBumpRenormalize)
                    {
                        DstFlags |= H3DFragmentFlags.IsBumpRenormalizeEnabled;
                    }

                    Mat.MaterialParams.FragmentFlags = DstFlags;

                    Mat.MaterialParams.FresnelSelector = (H3DFresnelSelector)Material.FragmentShader.Lighting.FresnelSelector;

                    Mat.MaterialParams.BumpTexture = (byte)Material.FragmentShader.Lighting.BumpTexture;

                    Mat.MaterialParams.BumpMode = (H3DBumpMode)Material.FragmentShader.Lighting.BumpMode;

                    Mat.MaterialParams.LUTInputSelection.ReflecR = Material.FragmentShader.LUTs.ReflecR?.Input ?? 0;
                    Mat.MaterialParams.LUTInputSelection.ReflecG = Material.FragmentShader.LUTs.ReflecG?.Input ?? 0;
                    Mat.MaterialParams.LUTInputSelection.ReflecB = Material.FragmentShader.LUTs.ReflecB?.Input ?? 0;
                    Mat.MaterialParams.LUTInputSelection.Dist0   = Material.FragmentShader.LUTs.Dist0?.Input ?? 0;
                    Mat.MaterialParams.LUTInputSelection.Dist1   = Material.FragmentShader.LUTs.Dist1?.Input ?? 0;
                    Mat.MaterialParams.LUTInputSelection.Fresnel = Material.FragmentShader.LUTs.Fresnel?.Input ?? 0;

                    Mat.MaterialParams.LUTInputScale.ReflecR = Material.FragmentShader.LUTs.ReflecR?.Scale ?? 0;
                    Mat.MaterialParams.LUTInputScale.ReflecG = Material.FragmentShader.LUTs.ReflecG?.Scale ?? 0;
                    Mat.MaterialParams.LUTInputScale.ReflecB = Material.FragmentShader.LUTs.ReflecB?.Scale ?? 0;
                    Mat.MaterialParams.LUTInputScale.Dist0   = Material.FragmentShader.LUTs.Dist0?.Scale ?? 0;
                    Mat.MaterialParams.LUTInputScale.Dist1   = Material.FragmentShader.LUTs.Dist1?.Scale ?? 0;
                    Mat.MaterialParams.LUTInputScale.Fresnel = Material.FragmentShader.LUTs.Fresnel?.Scale ?? 0;

                    Mat.MaterialParams.LUTReflecRTableName = Material.FragmentShader.LUTs.ReflecR?.Sampler.TableName;
                    Mat.MaterialParams.LUTReflecGTableName = Material.FragmentShader.LUTs.ReflecG?.Sampler.TableName;
                    Mat.MaterialParams.LUTReflecBTableName = Material.FragmentShader.LUTs.ReflecB?.Sampler.TableName;
                    Mat.MaterialParams.LUTDist0TableName   = Material.FragmentShader.LUTs.Dist0?.Sampler.TableName;
                    Mat.MaterialParams.LUTDist1TableName   = Material.FragmentShader.LUTs.Dist1?.Sampler.TableName;
                    Mat.MaterialParams.LUTFresnelTableName = Material.FragmentShader.LUTs.Fresnel?.Sampler.TableName;

                    Mat.MaterialParams.LUTReflecRSamplerName = Material.FragmentShader.LUTs.ReflecR?.Sampler.SamplerName;
                    Mat.MaterialParams.LUTReflecGSamplerName = Material.FragmentShader.LUTs.ReflecG?.Sampler.SamplerName;
                    Mat.MaterialParams.LUTReflecBSamplerName = Material.FragmentShader.LUTs.ReflecB?.Sampler.SamplerName;
                    Mat.MaterialParams.LUTDist0SamplerName   = Material.FragmentShader.LUTs.Dist0?.Sampler.SamplerName;
                    Mat.MaterialParams.LUTDist1SamplerName   = Material.FragmentShader.LUTs.Dist1?.Sampler.SamplerName;
                    Mat.MaterialParams.LUTFresnelSamplerName = Material.FragmentShader.LUTs.Fresnel?.Sampler.SamplerName;

                    Mat.MaterialParams.TexEnvStages[0] = Material.FragmentShader.TextureEnvironments[0].Stage;
                    Mat.MaterialParams.TexEnvStages[1] = Material.FragmentShader.TextureEnvironments[1].Stage;
                    Mat.MaterialParams.TexEnvStages[2] = Material.FragmentShader.TextureEnvironments[2].Stage;
                    Mat.MaterialParams.TexEnvStages[3] = Material.FragmentShader.TextureEnvironments[3].Stage;
                    Mat.MaterialParams.TexEnvStages[4] = Material.FragmentShader.TextureEnvironments[4].Stage;
                    Mat.MaterialParams.TexEnvStages[5] = Material.FragmentShader.TextureEnvironments[5].Stage;

                    Mat.MaterialParams.AlphaTest = Material.FragmentShader.AlphaTest.Test;

                    Mat.MaterialParams.TexEnvBufferColor = Material.FragmentShader.TexEnvBufferColor;

                    Mdl.Materials.Add(Mat);
                }

                foreach (GfxMesh Mesh in Model.Meshes)
                {
                    GfxShape Shape = Model.Shapes[Mesh.ShapeIndex];

                    H3DMesh M = new H3DMesh();

                    PICAVertex[] Vertices = null;

                    foreach (GfxVertexBuffer VertexBuffer in Shape.VertexBuffers)
                    {
                        /*
                         * CGfx supports 3 types of vertex buffer:
                         * - Non-Interleaved: Each attribute is stored on it's on stream, like this:
                         * P0 P1 P2 P3 P4 P5 ... N0 N1 N2 N3 N4 N5
                         * - Interleaved: All attributes are stored on the same stream, like this:
                         * P0 N0 P1 N1 P2 N2 P3 N3 P4 N4 P5 N5 ...
                         * - Fixed: The attribute have only a single fixed value, so instead of a stream,
                         * it have a single vector.
                         */
                        if (VertexBuffer is GfxAttribute)
                        {
                            //Non-Interleaved buffer
                            GfxAttribute Attr = (GfxAttribute)VertexBuffer;

                            M.Attributes.Add(Attr.ToPICAAttribute());

                            int Length = Attr.Elements;

                            switch (Attr.Format)
                            {
                            case GfxGLDataType.GL_SHORT: Length <<= 1; break;

                            case GfxGLDataType.GL_FLOAT: Length <<= 2; break;
                            }

                            M.VertexStride += Length;

                            Vector4[] Vectors = Attr.GetVectors();

                            if (Vertices == null)
                            {
                                Vertices = new PICAVertex[Vectors.Length];
                            }

                            for (int i = 0; i < Vectors.Length; i++)
                            {
                                switch (Attr.AttrName)
                                {
                                case PICAAttributeName.Position:  Vertices[i].Position = Vectors[i]; break;

                                case PICAAttributeName.Normal:    Vertices[i].Normal = Vectors[i]; break;

                                case PICAAttributeName.Tangent:   Vertices[i].Tangent = Vectors[i]; break;

                                case PICAAttributeName.TexCoord0: Vertices[i].TexCoord0 = Vectors[i]; break;

                                case PICAAttributeName.TexCoord1: Vertices[i].TexCoord1 = Vectors[i]; break;

                                case PICAAttributeName.TexCoord2: Vertices[i].TexCoord2 = Vectors[i]; break;

                                case PICAAttributeName.Color:     Vertices[i].Color = Vectors[i]; break;

                                case PICAAttributeName.BoneIndex:
                                    Vertices[i].Indices[0] = (int)Vectors[i].X;
                                    Vertices[i].Indices[1] = (int)Vectors[i].Y;
                                    Vertices[i].Indices[2] = (int)Vectors[i].Z;
                                    Vertices[i].Indices[3] = (int)Vectors[i].W;
                                    break;

                                case PICAAttributeName.BoneWeight:
                                    Vertices[i].Weights[0] = Vectors[i].X;
                                    Vertices[i].Weights[1] = Vectors[i].Y;
                                    Vertices[i].Weights[2] = Vectors[i].Z;
                                    Vertices[i].Weights[3] = Vectors[i].W;
                                    break;
                                }
                            }
                        }
                        else if (VertexBuffer is GfxVertexBufferFixed)
                        {
                            //Fixed vector
                            float[] Vector = ((GfxVertexBufferFixed)VertexBuffer).Vector;

                            M.FixedAttributes.Add(new PICAFixedAttribute()
                            {
                                Name = VertexBuffer.AttrName,

                                Value = new PICAVectorFloat24(
                                    Vector.Length > 0 ? Vector[0] : 0,
                                    Vector.Length > 1 ? Vector[1] : 0,
                                    Vector.Length > 2 ? Vector[2] : 0,
                                    Vector.Length > 3 ? Vector[3] : 0)
                            });
                        }
                        else
                        {
                            //Interleaved buffer
                            GfxVertexBufferInterleaved VtxBuff = (GfxVertexBufferInterleaved)VertexBuffer;

                            foreach (GfxAttribute Attr in ((GfxVertexBufferInterleaved)VertexBuffer).Attributes)
                            {
                                M.Attributes.Add(Attr.ToPICAAttribute());
                            }

                            M.RawBuffer    = VtxBuff.RawBuffer;
                            M.VertexStride = VtxBuff.VertexStride;
                        }
                    }

                    if (Vertices != null)
                    {
                        M.RawBuffer = VerticesConverter.GetBuffer(Vertices, M.Attributes);
                    }

                    Vector4 PositionOffset = new Vector4(Shape.PositionOffset, 0);

                    int Layer = (int)Model.Materials[Mesh.MaterialIndex].TranslucencyKind;

                    M.MaterialIndex  = (ushort)Mesh.MaterialIndex;
                    M.NodeIndex      = (ushort)Mesh.MeshNodeIndex;
                    M.PositionOffset = PositionOffset;
                    M.MeshCenter     = Shape.BoundingBox.Center;
                    M.Layer          = Layer;
                    M.Priority       = Mesh.RenderPriority;

                    H3DBoundingBox OBB = new H3DBoundingBox()
                    {
                        Center      = Shape.BoundingBox.Center,
                        Orientation = Shape.BoundingBox.Orientation,
                        Size        = Shape.BoundingBox.Size
                    };

                    M.MetaData = new H3DMetaData();

                    M.MetaData.Add(new H3DMetaDataValue(OBB));

                    int SmoothCount = 0;

                    foreach (GfxSubMesh SubMesh in Shape.SubMeshes)
                    {
                        foreach (GfxFace Face in SubMesh.Faces)
                        {
                            foreach (GfxFaceDescriptor Desc in Face.FaceDescriptors)
                            {
                                H3DSubMesh SM = new H3DSubMesh();

                                SM.BoneIndicesCount = (ushort)SubMesh.BoneIndices.Count;

                                for (int i = 0; i < SubMesh.BoneIndices.Count; i++)
                                {
                                    SM.BoneIndices[i] = (ushort)SubMesh.BoneIndices[i];
                                }

                                switch (SubMesh.Skinning)
                                {
                                case GfxSubMeshSkinning.None:   SM.Skinning = H3DSubMeshSkinning.None;   break;

                                case GfxSubMeshSkinning.Rigid:  SM.Skinning = H3DSubMeshSkinning.Rigid;  break;

                                case GfxSubMeshSkinning.Smooth: SM.Skinning = H3DSubMeshSkinning.Smooth; break;
                                }

                                SM.Indices = Desc.Indices;

                                SM.Indices = new ushort[Desc.Indices.Length];

                                Array.Copy(Desc.Indices, SM.Indices, SM.Indices.Length);

                                M.SubMeshes.Add(SM);
                            }
                        }

                        if (SubMesh.Skinning == GfxSubMeshSkinning.Smooth)
                        {
                            SmoothCount++;
                        }
                    }

                    if (SmoothCount == Shape.SubMeshes.Count)
                    {
                        M.Skinning = H3DMeshSkinning.Smooth;
                    }
                    else if (SmoothCount > 0)
                    {
                        M.Skinning = H3DMeshSkinning.Mixed;
                    }
                    else
                    {
                        M.Skinning = H3DMeshSkinning.Rigid;
                    }

                    GfxMaterial Mat = Model.Materials[Mesh.MaterialIndex];

                    M.UpdateBoolUniforms(Mdl.Materials[Mesh.MaterialIndex]);

                    Mdl.AddMesh(M);
                }

                //Workaround to fix blending problems until I can find a proper way.
                Mdl.MeshesLayer1.Reverse();

                Mdl.MeshNodesTree = new H3DPatriciaTree();

                foreach (GfxMeshNodeVisibility MeshNode in Model.MeshNodeVisibilities)
                {
                    Mdl.MeshNodesTree.Add(MeshNode.Name);
                    Mdl.MeshNodesVisibility.Add(MeshNode.IsVisible);
                }

                if (Model is GfxModelSkeletal)
                {
                    foreach (GfxBone Bone in ((GfxModelSkeletal)Model).Skeleton.Bones)
                    {
                        H3DBone B = new H3DBone()
                        {
                            Name             = Bone.Name,
                            ParentIndex      = (short)Bone.ParentIndex,
                            Translation      = Bone.Translation,
                            Rotation         = Bone.Rotation,
                            Scale            = Bone.Scale,
                            InverseTransform = Bone.InvWorldTransform
                        };

                        bool ScaleCompensate = (Bone.Flags & GfxBoneFlags.IsSegmentScaleCompensate) != 0;

                        if (ScaleCompensate)
                        {
                            B.Flags |= H3DBoneFlags.IsSegmentScaleCompensate;
                        }

                        Mdl.Skeleton.Add(B);
                    }

                    Mdl.Flags |= H3DModelFlags.HasSkeleton;

                    Mdl.BoneScaling = (H3DBoneScaling)((GfxModelSkeletal)Model).Skeleton.ScalingRule;
                }

                Output.Models.Add(Mdl);
            }

            foreach (GfxTexture Texture in Textures)
            {
                H3DTexture Tex = new H3DTexture()
                {
                    Name       = Texture.Name,
                    Width      = Texture.Width,
                    Height     = Texture.Height,
                    Format     = Texture.HwFormat,
                    MipmapSize = (byte)Texture.MipmapSize
                };

                if (Texture is GfxTextureCube)
                {
                    Tex.RawBufferXPos = ((GfxTextureCube)Texture).ImageXPos.RawBuffer;
                    Tex.RawBufferXNeg = ((GfxTextureCube)Texture).ImageXNeg.RawBuffer;
                    Tex.RawBufferYPos = ((GfxTextureCube)Texture).ImageYPos.RawBuffer;
                    Tex.RawBufferYNeg = ((GfxTextureCube)Texture).ImageYNeg.RawBuffer;
                    Tex.RawBufferZPos = ((GfxTextureCube)Texture).ImageZPos.RawBuffer;
                    Tex.RawBufferZNeg = ((GfxTextureCube)Texture).ImageZNeg.RawBuffer;
                }
                else
                {
                    Tex.RawBuffer = ((GfxTextureImage)Texture).Image.RawBuffer;
                }

                Output.Textures.Add(Tex);
            }

            foreach (GfxLUT LUT in LUTs)
            {
                H3DLUT L = new H3DLUT()
                {
                    Name = LUT.Name
                };

                foreach (GfxLUTSampler Sampler in LUT.Samplers)
                {
                    L.Samplers.Add(new H3DLUTSampler()
                    {
                        Flags = Sampler.IsAbsolute ? H3DLUTFlags.IsAbsolute : 0,
                        Name  = Sampler.Name,
                        Table = Sampler.Table
                    });
                }

                Output.LUTs.Add(L);
            }

            foreach (GfxCamera Camera in Cameras)
            {
                Output.Cameras.Add(Camera.ToH3DCamera());
            }

            foreach (GfxLight Light in Lights)
            {
                Output.Lights.Add(Light.ToH3DLight());
            }

            foreach (GfxAnimation SklAnim in SkeletalAnimations)
            {
                Output.SkeletalAnimations.Add(SklAnim.ToH3DAnimation());
            }

            foreach (GfxAnimation MatAnim in MaterialAnimations)
            {
                Output.MaterialAnimations.Add(new H3DMaterialAnim(MatAnim.ToH3DAnimation()));
            }

            foreach (GfxAnimation VisAnim in VisibilityAnimations)
            {
                Output.VisibilityAnimations.Add(VisAnim.ToH3DAnimation());
            }

            foreach (GfxAnimation CamAnim in CameraAnimations)
            {
                Output.CameraAnimations.Add(CamAnim.ToH3DAnimation());
            }

            Output.CopyMaterials();

            return(Output);
        }
예제 #18
0
        public H3DMeshWrapper(BCH bch, H3DModelWrapper parentModel, H3DMesh mesh) : base()
        {
            ParentBCH   = bch;
            ParentModel = parentModel;
            Mesh        = mesh;

            ImageKey         = "mesh";
            SelectedImageKey = "mesh";

            MaterialIndex = Mesh.MaterialIndex;

            foreach (var subMesh in mesh.SubMeshes)
            {
                STGenericPolygonGroup group = new STGenericPolygonGroup();
                for (int i = 0; i < subMesh.Indices.Length; i++)
                {
                    group.faces.Add(subMesh.Indices[i]);
                }

                group.PrimativeType = STPrimitiveType.Triangles;

                /*     switch (subMesh.PrimitiveMode)
                 *   {
                 *       case SPICA.PICA.Commands.PICAPrimitiveMode.Triangles:
                 *           group.PrimativeType = STPrimitiveType.Triangles;
                 *           break;
                 *       case SPICA.PICA.Commands.PICAPrimitiveMode.TriangleStrip:
                 *           group.PrimativeType = STPrimitiveType.TrangleStrips;
                 *           break;
                 *   }*/

                PolygonGroups.Add(group);
            }

            var vertices = mesh.GetVertices();

            List <ushort> boneIndices = new List <ushort>();

            foreach (var subMesh in mesh.SubMeshes)
            {
                if (subMesh.BoneIndicesCount > 0)
                {
                    boneIndices.AddRange(subMesh.BoneIndices.ToArray());
                }
            }

            for (int v = 0; v < vertices.Length; v++)
            {
                Vertex vertex = new Vertex();
                vertex.pos = ConvertVector3(vertices[v].Position);
                vertex.nrm = ConvertVector3(vertices[v].Normal);
                vertex.tan = ConvertVector4(vertices[v].Tangent);
                vertex.uv0 = ConvertVector2(vertices[v].TexCoord0);
                vertex.uv1 = ConvertVector2(vertices[v].TexCoord1);
                vertex.uv2 = ConvertVector2(vertices[v].TexCoord2);
                vertex.col = ConvertVector4(vertices[v].Color);

                //Flip UVs
                vertex.uv0 = new Vector2(vertex.uv0.X, 1 - vertex.uv0.Y);
                if (boneIndices.Count > 0)
                {
                    /*  if (vertices[v].Indices.b0 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b0]);
                     * if (vertices[v].Indices.b1 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b1]);
                     * if (vertices[v].Indices.b2 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b2]);
                     * if (vertices[v].Indices.b3 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b3]);*/

                    if (mesh.Skinning == H3DMeshSkinning.Rigid)
                    {
                        int index = boneIndices[vertices[v].Indices.b0];
                        vertex.pos = Vector3.TransformPosition(vertex.pos, parentModel.Skeleton.Renderable.bones[index].Transform);
                        // vertex.nrm = Vector3.TransformNormal(vertex.nrm, parentModel.Skeleton.Renderable.bones[index].Transform);
                    }

                    /*    vertex.boneWeights.Add(vertices[v].Weights.w0);
                     *  vertex.boneWeights.Add(vertices[v].Weights.w1);
                     *  vertex.boneWeights.Add(vertices[v].Weights.w2);
                     *  vertex.boneWeights.Add(vertices[v].Weights.w3);*/
                }

                this.vertices.Add(vertex);
            }
        }
예제 #19
0
        public H3D ToH3D(string TextureAndMtlSearchPath = null, bool noTextures = false)
        {
            H3D Output = new H3D();

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

            if (TextureAndMtlSearchPath != null)
            {
                TextReader Reader = null;
                if (textureOnly)
                {
                    Reader = new StreamReader(textureOnlyFile);
                }
                else
                {
                    string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile);

                    if (File.Exists(MaterialFile))
                    {
                        Reader = new StreamReader(MaterialFile);
                    }
                }
                if (Reader != null)
                {
                    string MaterialName = null;

                    OBJMaterial Material = default(OBJMaterial);

                    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.GetFileName(TextureFile);

                                if (File.Exists(TextureFile) && !noTextures)
                                {
                                    if (Output.Textures.Contains(TextureName))
                                    {
                                        Output.Textures.Remove(Output.Textures[Output.Textures.Find(TextureName)]);
                                    }
                                    Output.Textures.Add(new H3DTexture(TextureFile));
                                }

                                Material.DiffuseTexture = 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 && !textureOnly)
                    {
                        Materials.Add(MaterialName, Material);
                    }
                }
            }

            if (!textureOnly)
            {
                H3DModel Model = new H3DModel();

                string newName = Microsoft.VisualBasic.Interaction.InputBox("Enter model name: ", "Name", Model.Name);

                if (newName != "")
                {
                    Model.Name = newName;
                }

                ushort MaterialIndex = 0;

                Model.Flags       = 0;
                Model.BoneScaling = H3DBoneScaling.Standard;
                Model.MeshNodesVisibility.Clear();
                Model.Skeleton.Clear();
                Model.MeshNodesVisibility.Add(true);

                float Height = 0;

                Meshes.Sort((x, y) => string.Compare(x.Name, y.Name));

                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 (Mesh.Name.Contains("uncolor"))
                                {
                                    Vertex.Color = Vector4.One;
                                }

                                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[] { };
                        SM.Skinning    = H3DSubMeshSkinning.None;
                        SM.Indices     = Indices.ToArray();

                        SubMeshes.Add(SM);
                    }

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

                    H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes)
                    {
                        Skinning      = H3DMeshSkinning.Rigid,
                        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, Mesh.MaterialName, Materials[Mesh.MaterialName].DiffuseTexture);

                    Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture;

                    Material.MaterialParams.FaceCulling      = PICAFaceCulling.BackFace;
                    Material.MaterialParams.Flags            = H3DMaterialFlags.IsFragmentLightingEnabled | H3DMaterialFlags.IsVertexLightingEnabled | H3DMaterialFlags.IsFragmentLightingPolygonOffsetDirty;
                    Material.MaterialParams.FragmentFlags    = 0;
                    Material.MaterialParams.LightSetIndex    = 0;
                    Material.MaterialParams.FogIndex         = 0;
                    Material.MaterialParams.LogicalOperation = PICALogicalOp.Noop;

                    Material.MaterialParams.AmbientColor        = RGBA.White;
                    Material.MaterialParams.DiffuseColor        = RGBA.White;
                    Material.MaterialParams.EmissionColor       = RGBA.Black;
                    Material.MaterialParams.Specular0Color      = RGBA.Black;
                    Material.MaterialParams.Specular1Color      = RGBA.Black;
                    Material.MaterialParams.Constant0Color      = RGBA.White;
                    Material.MaterialParams.Constant1Color      = RGBA.White;
                    Material.MaterialParams.Constant2Color      = RGBA.White;
                    Material.MaterialParams.Constant3Color      = RGBA.White;
                    Material.MaterialParams.Constant4Color      = RGBA.White;
                    Material.MaterialParams.Constant5Color      = RGBA.White;
                    Material.MaterialParams.BlendColor          = RGBA.Black;
                    Material.MaterialParams.Constant2Assignment = 2;

                    Material.MaterialParams.ColorScale = 1;

                    Material.MaterialParams.FresnelSelector   = H3DFresnelSelector.No;
                    Material.MaterialParams.BumpMode          = H3DBumpMode.NotUsed;
                    Material.MaterialParams.BumpTexture       = 0;
                    Material.MaterialParams.PolygonOffsetUnit = 0;

                    Material.MaterialParams.TexEnvBufferColor = RGBA.White;

                    Material.MaterialParams.ColorOperation.FragOpMode = PICAFragOpMode.Default;
                    Material.MaterialParams.ColorOperation.BlendMode  = PICABlendMode.Blend;

                    Material.MaterialParams.ColorBufferRead  = true;
                    Material.MaterialParams.ColorBufferWrite = true;

                    Material.MaterialParams.StencilBufferRead  = true;
                    Material.MaterialParams.StencilBufferWrite = true;

                    Material.MaterialParams.DepthBufferRead                   = true;
                    Material.MaterialParams.DepthBufferWrite                  = false;
                    Material.MaterialParams.TexEnvStages[0].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Texture0 };
                    Material.MaterialParams.TexEnvStages[0].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0 };
                    Material.MaterialParams.TexEnvStages[0].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[0].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[0].Combiner.Color    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[0].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[0].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[0].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[0].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[0].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[0].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[1].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.FragmentPrimaryColor, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[1].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[1].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[1].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[1].Combiner.Color    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[1].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[1].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[1].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[1].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[1].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[1].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[2].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[2].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[2].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[2].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[2].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[2].Combiner.Alpha    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[2].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[2].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[2].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[2].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[2].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[3].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[3].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Constant, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[3].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[3].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[3].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[3].Combiner.Alpha    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[3].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[3].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[3].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[3].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[3].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[4].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[4].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[4].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[4].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[4].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[4].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[4].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[4].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[4].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[4].UpdateColorBuffer = true;
                    Material.MaterialParams.TexEnvStages[4].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[5].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[5].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[5].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[5].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[5].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[5].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[5].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[5].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[5].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[5].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[5].UpdateAlphaBuffer = false;

                    if (Mesh.Name.Contains("alpha"))
                    {
                        if (Mesh.Name.Contains("alphablend"))
                        {
                            M.Layer = 1;
                            Material.MaterialParams.ColorOperation.BlendMode    = PICABlendMode.Blend;
                            Material.MaterialParams.BlendFunction.ColorDstFunc  = PICABlendFunc.OneMinusSourceAlpha;
                            Material.MaterialParams.BlendFunction.ColorEquation = PICABlendEquation.FuncAdd;
                            Material.MaterialParams.BlendFunction.ColorSrcFunc  = PICABlendFunc.SourceAlpha;
                            Material.MaterialParams.BlendFunction.AlphaDstFunc  = PICABlendFunc.OneMinusSourceAlpha;
                            Material.MaterialParams.BlendFunction.AlphaEquation = PICABlendEquation.FuncAdd;
                            Material.MaterialParams.BlendFunction.AlphaSrcFunc  = PICABlendFunc.SourceAlpha;
                            if (Mesh.Name.Contains("rl"))
                            {
                                int digit = Mesh.Name[Mesh.Name.IndexOf("rl") + 2] - '0';
                                if (digit >= 0 && digit <= 3)
                                {
                                    //set renderlayer
                                    M.Priority = digit;
                                }
                            }
                        }
                        Material.MaterialParams.AlphaTest.Enabled   = true;
                        Material.MaterialParams.AlphaTest.Function  = PICATestFunc.Greater;
                        Material.MaterialParams.AlphaTest.Reference = 0;
                    }

                    if (Mesh.Name.Contains("unculled"))
                    {
                        Material.MaterialParams.FaceCulling = PICAFaceCulling.Never;
                    }

                    if (Material.Name.Contains("mado") || Material.Name.Contains("window"))
                    {
                        Material.MaterialParams.LightSetIndex = 1;
                    }

                    Material.TextureMappers[0].MagFilter = H3DTextureMagFilter.Linear;

                    if (Model.Materials.Find(Material.Name) != -1)
                    {
                        M.MaterialIndex = (ushort)Model.Materials.Find(Material.Name);

                        MaterialIndex--;

                        M.UpdateBoolUniforms(Model.Materials[M.MaterialIndex]);
                    }
                    else
                    {
                        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);
        }