예제 #1
0
        private void CleanUpScene(H3DModel model)
        {
            var armature  = model.Skeleton.Count == 0 ? "None" : $"bpy.data.armatures.new('{model.Skeleton[0].Name}')";
            var modelName = model.Skeleton.Count == 0 ? model.Name : model.Skeleton[0].Name;

            pythonScript = new StringBuilder($"import bpy\nimport bmesh\nimport math\nimport mathutils\ndef vec_roll_to_mat3(vec, roll):\n\ttarget = mathutils.Vector((0, 0.1, 0))\n\tnor = vec.normalized()\n\taxis = target.cross(nor)\n\tif axis.dot(axis) > 0.0000000001:\n\t\taxis.normalize()\n\t\ttheta = target.angle(nor)\n\t\tbMatrix = mathutils.Matrix.Rotation(theta, 3, axis)\n\telse:\n\t\tupdown = 1 if target.dot(nor) > 0 else -1\n\t\tbMatrix = mathutils.Matrix.Scale(updown, 3)\n\t\t# C code:\n\t\t#bMatrix[0][0]=updown; bMatrix[1][0]=0.0; bMatrix[2][0]=0.0;\n\t\t#bMatrix[0][1]=0.0; bMatrix[1][1]=updown; bMatrix[2][1]=0.0;\n\t\t#bMatrix[0][2]=0.0; bMatrix[1][2]=0.0; bMatrix[2][2]=1.0;\n\t\tbMatrix[2][2] = 1.0\n\trMatrix = mathutils.Matrix.Rotation(roll, 3, nor)\n\tmat = rMatrix @ bMatrix\n\treturn mat\ndef mat3_to_vec_roll(mat):\n\tvec = mat.col[1]\n\tvecmat = vec_roll_to_mat3(mat.col[1], 0)\n\tvecmatinv = vecmat.inverted()\n\trollmat = vecmatinv @ mat\n\troll = math.atan2(rollmat[0][2], rollmat[2][2])\n\treturn vec, roll\nfor o in bpy.data.objects: bpy.data.objects.remove(o, do_unlink=True)\nroot = bpy.data.objects.new('{modelName}', {armature})\nbpy.context.scene.collection.objects.link(root)\nbpy.context.scene.render.fps = 29\nbpy.context.scene.render.fps_base = {29f / 29.97f}\n");
        }
예제 #2
0
        private void BuildMaterials(H3DModel model)
        {
            for (var mi = 0; mi < model.Materials.Count; ++mi)
            {
                var mat = model.Materials[mi];
                pythonScript.AppendLine($"mat{mi} = bpy.data.materials.new('{mat.Name}')");

                for (var ti = 0; ti < 3; ++ti)
                {
                    if (!mat.EnabledTextures[ti])
                    {
                        continue;
                    }

                    string tex = null;
                    switch (ti)
                    {
                    case 0: tex = mat.Texture0Name; break;

                    case 1: tex = mat.Texture1Name; break;

                    case 2: tex = mat.Texture2Name; break;
                    }

                    if (tex == null)
                    {
                        continue;
                    }

                    //pythonScript.AppendLine($"tex{mi}_{ti} = bpy.data.textures.new('{tex}', type='IMAGE')");
                    //pythonScript.AppendLine($"slt{mi}_{ti} = mat{mi}.texture_slots.add()");
                    //pythonScript.AppendLine($"slt{mi}_{ti}.texture = tex{mi}_{ti}");
                }
            }
        }
예제 #3
0
파일: MBn.cs 프로젝트: yorki00/SPICA
        public H3D ToH3D()
        {
            H3D Output = BaseScene;

            H3DModel Model = Output.Models[0];

            int IndicesIndex = 0, i = 0;

            foreach (H3DMesh Mesh in Model.Meshes.OrderBy(x => (int)x.MetaData["ShapeId"].Values[0]))
            {
                Mesh.PositionOffset = Vector4.Zero;

                Mesh.Attributes.Clear();
                Mesh.Attributes.AddRange(VerticesDesc[i].Attributes);

                Mesh.RawBuffer    = VerticesDesc[i].RawBuffer;
                Mesh.VertexStride = VerticesDesc[i].VertexStride;

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

                    SM.Indices     = IndicesDesc[IndicesIndex].Indices;
                    SM.BoneIndices = IndicesDesc[IndicesIndex].BoneIndices;

                    IndicesIndex++;
                }

                i++;
            }

            return(Output);
        }
예제 #4
0
        private void BuildArmature(H3DModel model)
        {
            pythonScript.AppendLine("bpy.context.view_layer.objects.active = root");
            pythonScript.AppendLine("bpy.ops.object.editmode_toggle()");

            var parentString = new StringBuilder();

            for (var bi = 1; bi < model.Skeleton.Count; ++bi)
            {
                var bone = model.Skeleton[bi];

                var t = bone.GetWorldTransform(model.Skeleton) * MTX_ANGLE * MTX_SCALE;

                Matrix4x4.Decompose(t, out var _, out var rot, out var pos);
                var m = Matrix4x4.CreateFromQuaternion(rot);

                if (bone.ParentIndex > 0)
                {
                    parentString.AppendLine($"b{bi}.parent = b{bone.ParentIndex}");
                }

                pythonScript.AppendLine($"mat = mathutils.Matrix([[{m.M11},{m.M12},{m.M13}],[{m.M21},{m.M22},{m.M23}],[{m.M31},{m.M32},{m.M33}]])");
                pythonScript.AppendLine($"tail, roll = mat3_to_vec_roll(mat)");

                pythonScript.AppendLine($"b{bi} = root.data.edit_bones.new('{bone.Name}')");
                pythonScript.AppendLine($"b{bi}.head = [{pos.X}, {pos.Y}, {pos.Z}]");
                pythonScript.AppendLine($"b{bi}.tail = tail + b{bi}.head");
                pythonScript.AppendLine($"b{bi}.roll = roll");
            }

            pythonScript.Append(parentString);
            pythonScript.AppendLine("bpy.ops.object.editmode_toggle()");
            pythonScript.AppendLine("bpy.ops.object.select_all(action='DESELECT')");
        }
예제 #5
0
        public void Load(H3DModel model, BCH bch)
        {
            Renderable = new STSkeleton();
            bch.DrawableContainer.Drawables.Add(Renderable);

            BcresParent = bch;
            ModelParent = model;

            Text    = "Skeleton";
            Checked = true;

            foreach (var bone in model.Skeleton)
            {
                Renderable.bones.Add(new H3DBoneWrapper(Renderable, bone, bch));
            }

            Nodes.Clear();
            foreach (var bone in Renderable.bones)
            {
                if (bone.Parent == null)
                {
                    Nodes.Add(bone);
                }
            }

            Renderable.update();
            Renderable.reset();
        }
예제 #6
0
파일: CSGL.cs 프로젝트: Nicolecnu/SunA
 public void AddModel(string modelname)
 {
     model = H3DModel.FromFile(modelname);
     if (!model.LoadTextrue())                                                           // Jump To Texture Loading Routine ( NEW )
     {
         MessageBox.Show("纹理读取失败!");                                                     // If Texture Didn't Load Return FALSE
     }
 }
예제 #7
0
파일: SMD.cs 프로젝트: HelloOO7/SPICA
        public SMD(H3D Scene, int MdlIndex, int AnimIndex = -1)
        {
            int Index = 0;

            if (Scene == null || Scene.Models.Count == 0)
            {
                return;
            }

            if (MdlIndex != -1 && AnimIndex == -1)
            {
                H3DModel Mdl = Scene.Models[MdlIndex];

                foreach (H3DBone Bone in Mdl.Skeleton)
                {
                    SMDNode Node = new SMDNode()
                    {
                        Index       = Index,
                        Name        = Bone.Name,
                        ParentIndex = Bone.ParentIndex
                    };

                    SMDBone B = new SMDBone()
                    {
                        NodeIndex   = Index++,
                        Translation = Bone.Translation,
                        Rotation    = Bone.Rotation
                    };

                    Nodes.Add(Node);
                    Skeleton.Add(B);
                }

                foreach (H3DMesh Mesh in Mdl.Meshes)
                {
                    if (Mesh.Type == H3DMeshType.Silhouette)
                    {
                        continue;
                    }

                    PICAVertex[] Vertices = Mesh.GetVertices();

                    string MaterialName = Mdl.Materials[Mesh.MaterialIndex].Texture0Name;
                    if (MaterialName.Equals("projection_dummy") && Mdl.Materials[Mesh.MaterialIndex].Texture1Name != null)
                    {
                        MaterialName = Mdl.Materials[Mesh.MaterialIndex].Texture1Name;
                    }

                    Meshes.Add(new SMDMesh()
                    {
                        MaterialName = MaterialName + ".png",
                        Vertices     = MeshTransform.GetVerticesList(Mdl.Skeleton, Mesh)
                    });
                }
            }
        }
예제 #8
0
        public static void CreateModelBBox(H3DModel Model)
        {
            Vector4 Min = Vector4.Zero;
            Vector4 Max = Vector4.Zero;

            bool isFirst = true;

            foreach (H3DMesh Mesh in Model.Meshes)
            {
                PICAVertex[] Vertices = Mesh.GetVertices();

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

                Vector4 MeshMin;
                Vector4 MeshMax;

                MeshMin = MeshMax = Vertices[0].Position;

                foreach (PICAVertex Vertex in Vertices)
                {
                    Vector4 P = Vertex.Position;

                    MeshMin = Vector4.Min(MeshMin, P);
                    MeshMax = Vector4.Max(MeshMax, P);
                }
                if (isFirst)
                {
                    Min     = MeshMin;
                    Max     = MeshMax;
                    isFirst = false;
                }
                else
                {
                    Min = Vector4.Min(Min, MeshMin);
                    Max = Vector4.Max(Max, MeshMax);
                }

                CreateMetaDataAndAddValue(Mesh, new H3DMetaDataValue(BBOX_MIN_MAX, new float[] { MeshMin.X, MeshMin.Y, MeshMin.Z, MeshMax.X, MeshMax.Y, MeshMax.Z }));
            }

            if (Model.MetaData == null)
            {
                Model.MetaData = new H3DMetaData();
            }
            int Find = Model.MetaData.Find(BBOX_MIN_MAX);

            if (Find != -1)
            {
                Model.MetaData.Remove(Model.MetaData[Find]);
            }
            Model.MetaData.Add(new H3DMetaDataValue(BBOX_MIN_MAX, new float[] { Min.X, Min.Y, Min.Z, Max.X, Max.Y, Max.Z }));
        }
예제 #9
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));
            }
        }
예제 #10
0
        public void LoadModel(H3DModel model, BCH bch)
        {
            BchParent = bch;

            ImageKey         = "model";
            SelectedImageKey = "model";

            Model = model;
            Text  = model.Name;

            var MaterialFolder = new TreeNode("Materials");
            var MeshFolder     = new TreeNode("Meshes");

            Skeleton      = new H3DSkeletonWrapper();
            Skeleton.Text = "Skeleton";
            Checked       = true;

            Nodes.Add(MeshFolder);
            Nodes.Add(MaterialFolder);
            Nodes.Add(Skeleton);

            if (model.Skeleton != null)
            {
                Skeleton.Load(model, bch);
            }

            int Index = 0;

            foreach (var material in model.Materials)
            {
                var matWrapper = new H3DMaterialWrapper(bch, this, material);
                matWrapper.Text = material.Name;
                MaterialFolder.Nodes.Add(matWrapper);
                Materials.Add(matWrapper);
            }

            Index = 0;
            foreach (var mesh in model.Meshes)
            {
                var meshWrapper = new H3DMeshWrapper(bch, this, mesh);

                MeshFolder.Nodes.Add(meshWrapper);
                bch.Renderer.Meshes.Add(meshWrapper);

                if (meshWrapper.Text == string.Empty)
                {
                    meshWrapper.Text = $"mesh_{model.Materials[mesh.MaterialIndex].Name}";
                }
                Meshes.Add(meshWrapper);
            }
        }
예제 #11
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++;
            }
        }
예제 #12
0
        private BoneContent ImportBones(H3DModel model)
        {
            var rootNode = new BoneContent();

            var childBones = new Queue <Tuple <H3DBone, BoneContent> >();

            childBones.Enqueue(Tuple.Create(model.Skeleton[0], rootNode));

            while (childBones.Count > 0)
            {
                var boneNode = childBones.Dequeue();

                var bone = boneNode.Item1;

                boneNode.Item2.Identity  = _identity;
                boneNode.Item2.Name      = bone.Name;
                boneNode.Item2.Transform = bone.Transform.ToXNA();

                foreach (var b in model.Skeleton)
                {
                    if (b.ParentIndex == -1)
                    {
                        continue;
                    }

                    var parentBone = model.Skeleton[b.ParentIndex];

                    if (parentBone == bone)
                    {
                        var nnode = new BoneContent();

                        childBones.Enqueue(Tuple.Create(b, nnode));

                        boneNode.Item2.Children.Add(nnode);
                    }
                }
            }

            return(rootNode);
        }
예제 #13
0
파일: Model.cs 프로젝트: HelloOO7/SPICA
        public Model(Renderer Renderer, H3DModel BaseModel)
        {
            this.Renderer  = Renderer;
            this.BaseModel = BaseModel;

            Meshes0 = new List <Mesh>();
            Meshes1 = new List <Mesh>();
            Meshes2 = new List <Mesh>();
            Meshes3 = new List <Mesh>();
            Shaders = new List <Shader>();

            ShaderHashes = new Dictionary <int, int>();

            InverseTransforms = new Matrix4[BaseModel.Skeleton.Count];

            for (int Bone = 0; Bone < BaseModel.Skeleton.Count; Bone++)
            {
                InverseTransforms[Bone] = BaseModel.Skeleton[Bone].InverseTransform.ToMatrix4();
            }

            UpdateShaders();

            AddMeshes(Meshes0, BaseModel.MeshesLayer0);
            AddMeshes(Meshes1, BaseModel.MeshesLayer1);
            AddMeshes(Meshes2, BaseModel.MeshesLayer2);
            AddMeshes(Meshes3, BaseModel.MeshesLayer3);

            SkeletalAnim   = new SkeletalAnimation(BaseModel.Skeleton);
            MaterialAnim   = new MaterialAnimation(BaseModel.Materials);
            VisibilityAnim = new VisibilityAnimation(
                BaseModel.MeshNodesTree,
                BaseModel.MeshNodesVisibility);

            Transform = Matrix4.Identity;

            UpdateAnimationTransforms();
        }
예제 #14
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);
        }
예제 #15
0
        public H3D ToH3D()
        {
            H3D Output = new H3D();

            H3DLUT L = new H3DLUT();

            L.Name = GFModel.DefaultLUTName;

            for (int MdlIndex = 0; MdlIndex < Models.Count; MdlIndex++)
            {
                GFModel  Model = Models[MdlIndex];
                H3DModel Mdl   = Model.ToH3DModel();

                for (int MatIndex = 0; MatIndex < Model.Materials.Count; MatIndex++)
                {
                    H3DMaterialParams Params = Mdl.Materials[MatIndex].MaterialParams;

                    string FragShaderName = Model.Materials[MatIndex].FragShaderName;
                    string VtxShaderName  = Model.Materials[MatIndex].VtxShaderName;

                    GFShader FragShader = Shaders.FirstOrDefault(x => x.Name == FragShaderName);
                    GFShader VtxShader  = Shaders.FirstOrDefault(x => x.Name == VtxShaderName);

                    if (FragShader != null)
                    {
                        Params.TexEnvBufferColor = FragShader.TexEnvBufferColor;

                        Array.Copy(FragShader.TexEnvStages, Params.TexEnvStages, 6);
                    }

                    if (VtxShader != null)
                    {
                        foreach (KeyValuePair <uint, Vector4> KV in VtxShader.VtxShaderUniforms)
                        {
                            Params.VtxShaderUniforms.Add(KV.Key, KV.Value);
                        }

                        foreach (KeyValuePair <uint, Vector4> KV in VtxShader.GeoShaderUniforms)
                        {
                            Params.GeoShaderUniforms.Add(KV.Key, KV.Value);
                        }
                    }
                }

                foreach (GFLUT LUT in Model.LUTs)
                {
                    L.Samplers.Add(new H3DLUTSampler()
                    {
                        Name  = LUT.Name,
                        Table = LUT.Table
                    });
                }

                Output.Models.Add(Mdl);
            }

            Output.LUTs.Add(L);

            Output.CopyMaterials();

            foreach (GFTexture Texture in Textures)
            {
                Output.Textures.Add(Texture.ToH3DTexture());
            }

            return(Output);
        }
예제 #16
0
        private void BuildModel(H3DModel model)
        {
            pythonScript.AppendLine($"m = bpy.data.meshes.new('{model.Name}')");
            pythonScript.AppendLine($"o = bpy.data.objects.new('{model.Name}', m)");
            pythonScript.AppendLine($"o.parent = root");
            pythonScript.AppendLine($"bpy.context.scene.collection.objects.link(o)");
            pythonScript.AppendLine($"bm = bmesh.new()");
            pythonScript.AppendLine($"uvl = bm.loops.layers.uv.new()");

            var vertices  = new List <BLENDVertex>();
            var tris      = new List <int[]>();
            var loops     = new List <BLENDLoop>();
            var groups    = new List <BLENDVertGroup>();
            var materials = new List <int>();

            foreach (var mesh in model.Meshes)
            {
                if (mesh.Type == H3DMeshType.Silhouette)
                {
                    continue;
                }

                if (!materials.Contains(mesh.MaterialIndex))
                {
                    materials.Add(mesh.MaterialIndex);
                }

                var newVertices = mesh.GetVertices();
                var ids         = new Dictionary <int, int>();
                for (var vi = 0; vi < newVertices.Length; ++vi)
                {
                    var vert  = newVertices[vi];
                    var index = vertices.FindIndex(x => x.Matches(vert));

                    if (index == -1)                     // New vertex
                    {
                        index = vertices.Count;
                        vertices.Add(new BLENDVertex(vert));
                    }

                    ids.Add(vi, index);
                }

                var newTris = new List <int[]>();
                foreach (var subMesh in mesh.SubMeshes)
                {
                    for (var ti = 0; ti < subMesh.Indices.Length; ti += 3)
                    {
                        var tri = new int[] { subMesh.Indices[ti], subMesh.Indices[ti + 1], subMesh.Indices[ti + 2] };

                        if (newTris.Any(x => x.SequenceEqual(tri)))
                        {
                            continue;
                        }

                        newTris.Add(tri);
                        var formattedTri = tri.Select(x => ids[x]).ToArray();

                        for (var i = 0; i < tri.Length; ++i)
                        {
                            var vert = newVertices[tri[i]];
                            loops.Add(new BLENDLoop
                            {
                                vert = formattedTri[i],
                                face = tris.Count,
                                uv   = new Vector2(vert.TexCoord0.X, vert.TexCoord0.Y)
                            });
                        }

                        tris.Add(formattedTri);
                    }

                    // Has armature and controller
                    if (subMesh.BoneIndicesCount > 0 && (model.Skeleton?.Count ?? 0) > 0)
                    {
                        if (subMesh.Skinning == H3DSubMeshSkinning.Smooth)
                        {
                            for (int vi = 0; vi < newVertices.Length; ++vi)
                            {
                                var vertex = newVertices[vi];

                                for (int i = 0; i < 4; i++)
                                {
                                    var index  = vertex.Indices[i];
                                    var weight = vertex.Weights[i];

                                    if (weight == 0)
                                    {
                                        break;
                                    }

                                    if (index < subMesh.BoneIndices.Length && index >= 0)
                                    {
                                        index = subMesh.BoneIndices[index];
                                    }
                                    else
                                    {
                                        index = 0;
                                    }

                                    var gName  = model.Skeleton[index].Name;
                                    var gIndex = groups.FindIndex(x => x.name == gName);

                                    if (gIndex == -1)
                                    {
                                        gIndex = groups.Count;
                                        groups.Add(new BLENDVertGroup(gName));
                                    }

                                    var realVertex = vertices[ids[vi]];

                                    if (!realVertex.vertGroup.ContainsKey(gIndex))
                                    {
                                        realVertex.vertGroup.Add(gIndex, weight);
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int vi = 0; vi < newVertices.Length; ++vi)
                            {
                                var vertex = newVertices[vi];
                                var index  = vertex.Indices[0];

                                if (index < subMesh.BoneIndices.Length && index >= 0)
                                {
                                    index = subMesh.BoneIndices[index];
                                }
                                else
                                {
                                    index = 0;
                                }

                                var gName = model.Skeleton[index].Name;

                                if (!groups.Any(x => x.name == gName))
                                {
                                    groups.Add(new BLENDVertGroup(gName));
                                }

                                var gIndex     = groups.FindIndex(x => x.name == gName);
                                var realVertex = vertices[ids[vi]];

                                if (!realVertex.vertGroup.ContainsKey(gIndex))
                                {
                                    realVertex.vertGroup.Add(gIndex, 1f);
                                }
                            }
                        }
                    }
                }
            }

            pythonScript.AppendLine($"vs = []");

            // Y and Z are swapped in blender's space
            foreach (var v in vertices)
            {
                var pos    = new Vector3(v.vert.Position.X, -v.vert.Position.Z, v.vert.Position.Y) * SCALE;
                var normal = new Vector3(v.vert.Normal.X, -v.vert.Normal.Z, v.vert.Normal.Y);

                pythonScript.AppendLine($"v = bm.verts.new([{pos.X},{pos.Y},{pos.Z}])");
                pythonScript.AppendLine($"v.normal = [{normal.X},{normal.Y},{normal.Z}]");
                pythonScript.AppendLine($"vs.append(v)");
            }

            pythonScript.AppendLine("bm.verts.index_update()");

            for (var ti = 0; ti < tris.Count; ++ti)
            {
                var tri = tris[ti];

                pythonScript.AppendLine($"f = bm.faces.new([vs[{tri[0]}],vs[{tri[1]}],vs[{tri[2]}]])");
                pythonScript.AppendLine("f.smooth = True");
                pythonScript.AppendLine("lv = {}");

                foreach (var loop in loops.Where(x => x.face == ti))
                {
                    pythonScript.AppendLine($"lv['{loop.vert}'] = [{loop.uv.X},{loop.uv.Y}]");
                }

                pythonScript.AppendLine($"for loop in f.loops: loop[uvl].uv = lv[str(loop.vert.index)]");
            }

            foreach (var mat in materials)
            {
                pythonScript.AppendLine($"o.data.materials.append(mat{mat})");
            }

            pythonScript.AppendLine($"bm.to_mesh(m)");
            pythonScript.AppendLine($"bm.free()");
            pythonScript.AppendLine($"bpy.context.view_layer.objects.active = o");
            pythonScript.AppendLine($"bpy.ops.object.editmode_toggle()");
            pythonScript.AppendLine($"bpy.ops.object.editmode_toggle()");
            pythonScript.AppendLine($"bpy.ops.object.select_all(action='DESELECT')");

            for (var gi = 0; gi < groups.Count; ++gi)
            {
                pythonScript.AppendLine($"vg = o.vertex_groups.new(name='{groups[gi].name}')");

                foreach (var vert in vertices.Where(x => x.vertGroup.ContainsKey(gi)))
                {
                    var weight = vert.vertGroup[gi];
                    var index  = vertices.IndexOf(vert);

                    pythonScript.AppendLine($"vg.add([{index}], {weight}, 'ADD')");
                }
            }

            if ((model.Skeleton?.Count ?? 0) > 0)
            {
                pythonScript.AppendLine($"mod = o.modifiers.new(name='Skeleton', type='ARMATURE')");
                pythonScript.AppendLine($"mod.object = root");
                pythonScript.AppendLine($"mod.use_deform_preserve_volume = True");
            }
        }
예제 #17
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);
        }
예제 #18
0
        private AnimationContent ImportSkeletalAnimation(H3DModel model, H3DAnimation animation)
        {
            var framesCount = (int)animation.FramesCount + 1;

            var animationNode = new AnimationContent
            {
                Name     = animation.Name,
                Identity = _identity,
                Duration = TimeSpan.FromSeconds((float)1 / (float)30 * (float)framesCount)
            };


            foreach (var elem in animation.Elements)
            {
                if (elem.PrimitiveType != H3DPrimitiveType.Transform && elem.PrimitiveType != H3DPrimitiveType.QuatTransform)
                {
                    continue;
                }

                var sklBone = model.Skeleton.FirstOrDefault(x => x.Name == elem.Name);
                var parent  = sklBone != null && sklBone.ParentIndex != -1 ? model.Skeleton[sklBone.ParentIndex] : null;

                var channel = new AnimationChannel();
                for (var frame = 0; frame < framesCount; frame++)
                {
                    var translation = Matrix.Identity;
                    if (elem.Content is H3DAnimTransform transform0)
                    {
                        if (!transform0.TranslationExists)
                        {
                            continue;
                        }

                        translation = Matrix.CreateTranslation(new Vector3(
                                                                   transform0.TranslationX.Exists ? transform0.TranslationX.GetFrameValue(frame) : sklBone.Translation.X,
                                                                   transform0.TranslationY.Exists ? transform0.TranslationY.GetFrameValue(frame) : sklBone.Translation.Y,
                                                                   transform0.TranslationZ.Exists ? transform0.TranslationZ.GetFrameValue(frame) : sklBone.Translation.Z));
                    }
                    else if (elem.Content is H3DAnimQuatTransform quatTransform)
                    {
                        if (!quatTransform.HasTranslation)
                        {
                            continue;
                        }

                        translation = Matrix.CreateTranslation(quatTransform.GetTranslationValue(frame).ToXNA());
                    }

                    var rotation = Matrix.Identity;
                    if (elem.Content is H3DAnimTransform transform1)
                    {
                        if (!(transform1.RotationX.Exists || transform1.RotationY.Exists ||
                              transform1.RotationZ.Exists))
                        {
                            continue;
                        }

                        rotation = Matrix.CreateRotationX(transform1.RotationX.GetFrameValue(frame)) *
                                   Matrix.CreateRotationY(transform1.RotationY.GetFrameValue(frame)) *
                                   Matrix.CreateRotationZ(transform1.RotationZ.GetFrameValue(frame));
                    }
                    else if (elem.Content is H3DAnimQuatTransform quatTransform)
                    {
                        if (!quatTransform.HasRotation)
                        {
                            continue;
                        }

                        rotation = Matrix.CreateFromQuaternion(quatTransform.GetRotationValue(frame).ToXNA());
                    }

                    var scale    = Matrix.Identity;
                    var invScale = System.Numerics.Vector3.One;
                    var pElem    = animation.Elements.FirstOrDefault(x => x.Name == parent?.Name);
                    if (elem.Content is H3DAnimTransform transform2)
                    {
                        if (!transform2.ScaleExists)
                        {
                            continue;
                        }

                        //Compensate parent bone scale (basically, don't inherit scales)
                        if (parent != null && (sklBone.Flags & H3DBoneFlags.IsSegmentScaleCompensate) != 0)
                        {
                            if (pElem != null)
                            {
                                var pTrans = (H3DAnimTransform)pElem.Content;

                                invScale /= new System.Numerics.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;
                            }
                        }

                        scale = Matrix.CreateScale((invScale * new System.Numerics.Vector3(
                                                        transform2.ScaleX.Exists ? transform2.ScaleX.GetFrameValue(frame) : sklBone.Scale.X,
                                                        transform2.ScaleY.Exists ? transform2.ScaleY.GetFrameValue(frame) : sklBone.Scale.Y,
                                                        transform2.ScaleZ.Exists ? transform2.ScaleZ.GetFrameValue(frame) : sklBone.Scale.Z)).ToXNA());
                    }
                    else if (elem.Content is H3DAnimQuatTransform quatTransform)
                    {
                        if (!quatTransform.HasScale)
                        {
                            continue;
                        }

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

                        scale = Matrix.CreateScale((invScale * quatTransform.GetScaleValue(frame)).ToXNA());
                    }

                    channel.Add(new AnimationKeyframe(TimeSpan.FromSeconds((float)frame / 30f), scale * rotation * translation));
                }

                animationNode.Channels[elem.Name] = channel;
            }

            return(animationNode);
        }
예제 #19
0
        private void BuildAnimations(H3DAnimation anim, H3DModel model)
        {
            // Note: Because bones and armatures in Blender are an immense calvary, the animations are exported as a separate XML file, that we can re-import in the final engine (Unity for instance) as a readable format.

            animationXml = new XmlDocument();

            var xmlRoot = animationXml.CreateElement("animation");

            var rootName = animationXml.CreateAttribute("name");

            rootName.Value = anim.Name;

            var rootLength = animationXml.CreateAttribute("framesCount");

            rootLength.Value = (anim.FramesCount + 1).ToString();

            xmlRoot.Attributes.Append(rootName);
            xmlRoot.Attributes.Append(rootLength);
            animationXml.AppendChild(xmlRoot);

            for (int frame = 0; frame <= anim.FramesCount; ++frame)
            {
                var xmlFrame = animationXml.CreateElement("frame");

                var frameNumber = animationXml.CreateAttribute("number");
                frameNumber.Value = frame.ToString();

                xmlFrame.Attributes.Append(frameNumber);
                xmlRoot.AppendChild(xmlFrame);
            }

            pythonScript.AppendLine($"act1 = bpy.data.actions.new('{anim.Name}')");
            pythonScript.AppendLine($"root.animation_data_create()");
            pythonScript.AppendLine($"root.animation_data.action = act1");

            foreach (var element in anim.Elements)
            {
                var fc = new BLENDFCurve(element.Content);

                if (fc.IsNull || fc.NothingExists())
                {
                    continue;
                }

                var bone = model.Skeleton.FirstOrDefault(x => x.Name == element.Name);
                Matrix4x4.Decompose(bone.Transform, out var _, out var lr, out var ll);
                Matrix4x4.Decompose(bone.GetWorldTransform(model.Skeleton), out var _, out var wr, out var wl);

                H3DBone parentbone = null;

                if (bone.ParentIndex != -1)
                {
                    parentbone = model.Skeleton[bone.ParentIndex];
                }

                var bData = $"pose.bones[\"{element.Name}\"]";

                pythonScript.AppendLine($"flx = act1.fcurves.new(data_path='{bData}.location', index=0)");
                pythonScript.AppendLine($"fly = act1.fcurves.new(data_path='{bData}.location', index=1)");
                pythonScript.AppendLine($"flz = act1.fcurves.new(data_path='{bData}.location', index=2)");

                if (fc.IsQuaternion)
                {
                    pythonScript.AppendLine($"root.pose.bones['{element.Name}'].rotation_mode = 'QUATERNION'");
                    pythonScript.AppendLine($"frw = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=0)");
                    pythonScript.AppendLine($"frx = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=1)");
                    pythonScript.AppendLine($"fry = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=2)");
                    pythonScript.AppendLine($"frz = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=3)");
                }
                else
                {
                    pythonScript.AppendLine($"root.pose.bones['{element.Name}'].rotation_mode = 'XYZ'");
                    pythonScript.AppendLine($"frx = act1.fcurves.new(data_path='{bData}.rotation_euler', index=0)");
                    pythonScript.AppendLine($"fry = act1.fcurves.new(data_path='{bData}.rotation_euler', index=1)");
                    pythonScript.AppendLine($"frz = act1.fcurves.new(data_path='{bData}.rotation_euler', index=2)");
                }

                pythonScript.AppendLine($"fsx = act1.fcurves.new(data_path='{bData}.scale', index=0)");
                pythonScript.AppendLine($"fsy = act1.fcurves.new(data_path='{bData}.scale', index=1)");
                pythonScript.AppendLine($"fsz = act1.fcurves.new(data_path='{bData}.scale', index=2)");

                for (int frame = 0; frame <= anim.FramesCount; ++frame)
                {
                    var xmlElement = animationXml.CreateElement("element");

                    var elemName = animationXml.CreateAttribute("name");
                    elemName.Value = element.Name;

                    var elemPath = animationXml.CreateAttribute("path");
                    elemPath.Value = GetBonePath(bone, model.Skeleton);

                    xmlElement.Attributes.Append(elemName);
                    xmlElement.Attributes.Append(elemPath);

                    var l = ll * SCALE - fc.GetLocationAtFrame(frame) * SCALE;

                    pythonScript.AppendLine($"flx.keyframe_points.insert({frame + 1}, {l.Z})");
                    pythonScript.AppendLine($"fly.keyframe_points.insert({frame + 1}, {-l.Y})");
                    pythonScript.AppendLine($"flz.keyframe_points.insert({frame + 1}, {-l.X})");

                    var locAttr = animationXml.CreateAttribute("location");
                    locAttr.Value = $"{l.X},{l.Y},{l.Z}";
                    xmlElement.Attributes.Append(locAttr);

                    var r = fc.GetRotationAtFrame(frame);

                    if (r is Vector3 rv)
                    {
                        //pythonScript.AppendLine($"frx.keyframe_points.insert({frame + 1}, {rv.Z})");
                        //pythonScript.AppendLine($"fry.keyframe_points.insert({frame + 1}, {-rv.Y})");
                        //pythonScript.AppendLine($"frz.keyframe_points.insert({frame + 1}, {-rv.X})");

                        var rotAttr = animationXml.CreateAttribute("rotation");
                        rotAttr.Value = $"{rv.X},{rv.Y},{rv.Z}";
                        xmlElement.Attributes.Append(rotAttr);
                    }
                    else if (r is Quaternion rq)
                    {
                        //rq = Quaternion.Multiply(lr, Quaternion.Inverse(rq));
                        //pythonScript.AppendLine($"frw.keyframe_points.insert({frame + 1}, {rq.W})");
                        //pythonScript.AppendLine($"frx.keyframe_points.insert({frame + 1}, {rq.X})");
                        //pythonScript.AppendLine($"fry.keyframe_points.insert({frame + 1}, {rq.Y})");
                        //pythonScript.AppendLine($"frz.keyframe_points.insert({frame + 1}, {rq.Z})");

                        var rotAttr = animationXml.CreateAttribute("rotation");
                        rotAttr.Value = $"{rq.X},{rq.Y},{rq.Z},{rq.W}";
                        xmlElement.Attributes.Append(rotAttr);
                    }

                    var s = fc.GetScaleAtFrame(frame);
                    pythonScript.AppendLine($"fsx.keyframe_points.insert({frame + 1}, {s.X})");
                    pythonScript.AppendLine($"fsy.keyframe_points.insert({frame + 1}, {s.Y})");
                    pythonScript.AppendLine($"fsz.keyframe_points.insert({frame + 1}, {s.Z})");

                    var scaleAttr = animationXml.CreateAttribute("scale");
                    scaleAttr.Value = $"{s.X},{s.Y},{s.Z}";
                    xmlElement.Attributes.Append(scaleAttr);

                    xmlRoot.SelectSingleNode($"frame[@number={frame}]").AppendChild(xmlElement);
                }
            }
        }
예제 #20
0
        //public MaterialScript() { }

        public MaterialScript(H3D Scene, int MdlIndex, int AnimIndex = -1)  //TODO: Needs more object-oriented-ness?
        {
            if (MdlIndex != -1)
            {
                H3DModel Mdl = Scene.Models[MdlIndex];

                if (Mdl.Materials.Count < 1)
                {
                    return;                          //if model has no materials, abort
                }
                //
                int             stageN;
                PICATexEnvStage stage;

                //Initialize script Stringbuilder
                script = new StringBuilder("vtxColor = VertexColor()\n");
                script.Append("scriptPath = getThisScriptFilename()\nscriptPath = getFilenamePath scriptPath\n\n");
                //TODO: add script path get, append it to texture files

                foreach (H3DMaterial Mtl in Mdl.Materials)
                {
                    #region >=============(Basic Material Setup)=============<
                    //Assign basic properties
                    script.Append(
                        $"{Mtl.Name}_mat = standardMaterial()\n"
                        + $"{Mtl.Name}_mat.name = \"{Mtl.Name}_mat\"\n"
                        + $"{Mtl.Name}_mat.shaderByName = \"phong\"\n"
                        + $"{Mtl.Name}_mat.showInViewport = true\n"
                        + $"{Mtl.Name}_mat.ambient = {GetMaxColorString(Mtl.MaterialParams.AmbientColor)}\n"
                        + $"{Mtl.Name}_mat.diffuse = {GetMaxColorString(Mtl.MaterialParams.DiffuseColor)}\n"      //TODO: should these colors include the alpha value?
                        + $"{Mtl.Name}_mat.specular = {GetMaxColorString(Mtl.MaterialParams.Specular0Color)}\n"
                        + $"{Mtl.Name}_mat.specularLevel = {Mtl.MaterialParams.Specular0Color.A/2.55d}\n"
                        //TODO: set 2-sidedness
                        + '\n');

                    //create bitmap maps for textures
                    if (Mtl.Texture0Name != null && Mtl.Texture0Name.Length > 0)
                    {
                        script.Append(GetTextureString(Mtl, 0));
                    }
                    if (Mtl.Texture1Name != null && Mtl.Texture1Name.Length > 0)
                    {
                        script.Append(GetTextureString(Mtl, 1));
                    }
                    if (Mtl.Texture2Name != null && Mtl.Texture2Name.Length > 0)
                    {
                        script.Append(GetTextureString(Mtl, 2));
                    }
                    script.Append('\n');

                    //find the greatest used map channel (may be unreliable, assumes all map channels on the mesh are used by at least one texture)
                    maxMapChannel = 0;
                    for (int i = 0; i < Mtl.MaterialParams.TextureCoords.Length; i++)
                    {//TODO: is scale != <0,0> the best way to tell if the texture coord is used?
                        if (Mtl.MaterialParams.TextureSources[i] + 1 > maxMapChannel && Mtl.MaterialParams.TextureCoords[i].MappingType == H3DTextureMappingType.UvCoordinateMap && Mtl.MaterialParams.TextureCoords[i].Scale != Vector2.Zero)
                        {
                            maxMapChannel = (int)Mtl.MaterialParams.TextureSources[i] + 1;
                        }
                    }

                    #endregion


                    #region >=============(Diffuse Map Creation)=============<
                    //create diffuse composite map
                    script.Append("comp = compositeMap()\n");

                    //Setup diffuse map stages
                    stageN = 1;
                    for (int j = 0; j < Mtl.MaterialParams.TexEnvStages.Length; j++)
                    {
                        stage = Mtl.MaterialParams.TexEnvStages[j];
                        if (stage.IsColorPassThrough)
                        {
                            continue;                                                           //if passthrough stage, skip
                        }
                        if (stage.UpdateColorBuffer)                                            //if this stage updates the color Buffer
                        {
                            script.Append("buffer = copy(comp)\n");                             //  store copy of composite map as "buffer"
                            if (stage.Source.Color[0] != PICATextureCombinerSource.Previous)    //  if current stage is not using previous   //TODO: Check for "Previous" in 1 or 2?
                            {
                                script.Append("comp = compositeMap()\n");                       //    start a new composite map
                                stageN = 1;
                            }
                        }

                        //assign the stage's const color
                        stageColor = GetConstColor(Mtl, j);

                        //create layers based on combiner type //TODO: put more comments here
                        for (int i = 0; i < combinerTxtCount[(int)(stage.Combiner.Color)]; i++)
                        {
                            //if operand is "Previous" don't add a layer for it
                            if (stage.Source.Color[i] == PICATextureCombinerSource.Previous)
                            {
                                continue;                                                               //TODO: Throw exception if 1 or 2 is "Previous"?
                            }
                            if (i == 2 && stage.Combiner.Color == PICATextureCombinerMode.Interpolate)  //if combiner mode is "Interpolate", assign the last source as a mask to the previous layer
                            {
                                script.Append($"comp.mask[{stageN-1}] = {GetSourceStringColor(stage, i)}\n");
                            }
                            else  //otherwise add a layer for the source and set the layer's blend mode based on the stage's combiner mode
                            {
                                script.Append($"comp.mapList[{stageN}] = {GetSourceStringColor(stage, i)}\n");
                                script.Append($"comp.blendMode[{stageN}] = {combinerOps[(int)(stage.Combiner.Color), i]}\n");
                                stageN++;
                            }
                        }
                    }

                    //assign composite map to main material
                    script.Append($"{Mtl.Name}_mat.diffuseMap = comp\n");
                    #endregion


                    #region >=============(Alpha Map Creation)=============<
                    //only create/assign alpha if it's used
                    if (!Mtl.MaterialParams.AlphaTest.Enabled && Mtl.MaterialParams.BlendFunction.ColorDstFunc == PICABlendFunc.Zero && Mtl.MaterialParams.BlendFunction.AlphaDstFunc == PICABlendFunc.Zero)
                    {
                        //Alpha source of "DestinationColor" is a special exception
                        if (Mtl.MaterialParams.BlendFunction.AlphaSrcFunc == PICABlendFunc.DestinationColor)//if alpha src = DestinationColor, use vtx alpha
                        {
                            script.Append("vtxAlpha = VertexColor()\n"
                                          + $"vtxAlpha.map = {maxMapChannel + 1}\n"
                                          + "vtxAlpha.subid = 1\n");
                            script.Append($"{Mtl.Name}_mat.opacityMap = vtxAlpha\n");
                        }
                        script.Append("\n\n");
                        continue;   //skip to next material
                    }

                    //reenable texture alpha if alpha test is enabled
                    if (Mtl.MaterialParams.AlphaTest.Enabled)  //TODO: this could be better somehow
                    {
                        if (Mtl.Texture0Name != null && Mtl.Texture0Name.Length > 0)
                        {
                            script.AppendLine($"txt{0}.alphasource = 0");
                        }
                        if (Mtl.Texture1Name != null && Mtl.Texture1Name.Length > 0)
                        {
                            script.AppendLine($"txt{1}.alphasource = 0");
                        }
                        if (Mtl.Texture2Name != null && Mtl.Texture2Name.Length > 0)
                        {
                            script.AppendLine($"txt{2}.alphasource = 0");
                        }
                        script.Append('\n');
                    }


                    //create alpha composite map
                    script.Append("comp = compositeMap()\n");

                    //Setup alpha map stages
                    stageN = 1;
                    for (int j = 0; j < Mtl.MaterialParams.TexEnvStages.Length; j++)
                    {
                        stage = Mtl.MaterialParams.TexEnvStages[j];
                        if (stage.IsAlphaPassThrough)
                        {
                            continue;                                                           //if passthrough stage, skip
                        }
                        if (stage.UpdateAlphaBuffer)                                            //if this stage updates the alpha Buffer
                        {
                            script.Append("buffer = copy(comp)\n");                             //  store copy of composite map as "buffer"
                            if (stage.Source.Alpha[0] != PICATextureCombinerSource.Previous)    //  if current stage is not using previous   //TODO: Check for "Previous" in 1 or 2
                            {
                                script.Append("comp = compositeMap()\n");                       //    start a new composite map
                                stageN = 1;
                            }
                        }

                        //assign the stage's const color
                        stageColor = GetConstColor(Mtl, j);

                        //create layers based on combiner type
                        for (int i = 0; i < combinerTxtCount[(int)(stage.Combiner.Alpha)]; i++)
                        {
                            //if operand is "Previous" don't add a layer for it
                            if (stage.Source.Alpha[i] == PICATextureCombinerSource.Previous)
                            {
                                continue;                                                               //TODO: Throw exception if 1 or 2 is "Previous"?
                            }
                            if (i == 2 && stage.Combiner.Alpha == PICATextureCombinerMode.Interpolate)  //if combiner mode is "Interpolate", assign the last source as a mask to the previous layer
                            {
                                script.Append($"comp.mask[{stageN - 1}] = {GetSourceStringAlpha(stage, i)}\n");
                            }
                            else  //otherwise add a layer for the source and set the layer's blend mode based on the stage's combiner mode
                            {
                                script.Append($"comp.mapList[{stageN}] = {GetSourceStringAlpha(stage, i)}\n");
                                script.Append($"comp.blendMode[{stageN}] = {combinerOps[(int)(stage.Combiner.Alpha), i]}\n");
                                stageN++;
                            }
                        }
                    }

                    //assign composite map to main material
                    script.Append($"{Mtl.Name}_mat.opacityMap = comp\n");
                    #endregion

                    script.Append("\n\n");
                }

                //create material assignment loop
                script.Append("for OBJ in Geometry do\n(\n  if OBJ.material != undefined then\n  (\n");
                foreach (H3DMaterial Mtl in Mdl.Materials)
                {
                    script.Append($"    if OBJ.material.name == \"{Mtl.Name}_mat\" then OBJ.material = {Mtl.Name}_mat\n");
                }
                script.Append("  )\n)\n");
            } //MdlIndex != -1
        }
예제 #21
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);
        }
예제 #22
0
 public H3DModelWrapper(H3DModel model, BCH bch) : base()
 {
     BchParent = bch;
     LoadModel(model, bch);
 }
예제 #23
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);
        }
예제 #24
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
        }
예제 #25
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);
        }
예제 #26
0
파일: FileIO.cs 프로젝트: HelloOO7/SPICA
        public static void Save(H3D Scene, SceneState State)
        {
            if (Scene == null)
            {
                MessageBox.Show(
                    "Please load a file first!",
                    "No data",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);

                return;
            }

            using (SaveFileDialog SaveDlg = new SaveFileDialog())
            {
                SaveDlg.Filter =
                    "COLLADA 1.4.1|*.dae" +
                    "|Valve StudioMdl|*.smd" +
                    "|Binary Ctr H3D v33|*.bch" +
                    "|Binary Ctr H3D v7|*.bch" +
                    /* "|Game Freak Binary Model Pack|*.gfbmdlp" +*/
                    "|Binary CTR Resource|*.bcres"// +
                    /*"|Game Freak Binary Model|*.gfbmdl"*/
                ;

                SaveDlg.FileName = "Model";
                if (Scene.Models.Count > 0)
                {
                    SaveDlg.FileName = Scene.Models[0].Name;
                }

                if (SaveDlg.ShowDialog() == DialogResult.OK)
                {
                    int MdlIndex  = State.ModelIndex;
                    int AnimIndex = State.SklAnimIndex;

                    switch (SaveDlg.FilterIndex)
                    {
                    case 1: new DAE(Scene, MdlIndex, AnimIndex).Save(SaveDlg.FileName); break;

                    case 2: new SMD(Scene, MdlIndex, AnimIndex).Save(SaveDlg.FileName); break;

                    case 3:
                        Scene.BackwardCompatibility = 0x21;
                        Scene.ForwardCompatibility  = 0x21;
                        H3D.Save(SaveDlg.FileName, Scene);
                        break;

                    case 4:
                        Scene.BackwardCompatibility = 0x7;
                        Scene.ForwardCompatibility  = 0x7;
                        H3D.Save(SaveDlg.FileName, Scene);
                        break;

                    case 5:
                        Gfx GFX = new Gfx(Scene);
                        Gfx.Save(SaveDlg.FileName, GFX);
                        break;

                    case 6:
                        MessageBox.Show(
                            "GFBMDLP writing comes with no warranty whatsoever. In fact, character and Pokémon models will most certainly not work at all.\n\n(Before you ask, this dialog can not be disabled. Intentionally.)",
                            "Disclaimer",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Exclamation);
                        using (BinaryWriter Writer = new BinaryWriter(new FileStream(SaveDlg.FileName, FileMode.Create, FileAccess.Write)))
                        {
                            GFModelPack ModelPack = new GFModelPack(Scene);
                            ModelPack.Write(Writer);
                            Writer.Close();
                        }
                        break;

                    case 7:
                        if (State.ModelIndex != -1)
                        {
                            H3DModel Model = Scene.Models[State.ModelIndex];

                            using (BinaryWriter Writer = new BinaryWriter(new FileStream(SaveDlg.FileName, FileMode.Create, FileAccess.Write)))
                            {
                                GFModel Mdl = new GFModel(Model, Scene.LUTs);
                                Mdl.Write(Writer);
                            }
                        }
                        else
                        {
                            MessageBox.Show(
                                "Please select a model to export.",
                                "No model selected",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                        }
                        break;
                    }
                }
            }
        }
예제 #27
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);
        }
예제 #28
0
        private MaterialAnimationContent ImportMaterialAnimation(H3DModel model, H3DDict <H3DMaterialParams> materials, H3DMaterialAnim animation)
        {
            var framesCount = (int)animation.FramesCount + 1;

            var animationNode = new MaterialAnimationContent
            {
                Name     = animation.Name,
                Identity = _identity,
                Duration = TimeSpan.FromSeconds((float)1 / (float)30 * (float)framesCount)
            };

            foreach (var elem in animation.Elements)
            {
                var material       = model.Materials.Single(mat => elem.Name == mat.Name);
                var materialParams = material.MaterialParams;

                var channel = new MaterialAnimationChannel();
                for (var frame = 0; frame < framesCount; frame++)
                {
                    var keyFrame = new MaterialAnimationKeyframe(TimeSpan.FromSeconds((float)frame / 30f))
                    {
                        Material   = material.Name,
                        Transforms = new Matrix[3]
                    };
                    var tc = new [] { materialParams.TextureCoords[0], materialParams.TextureCoords[1], materialParams.TextureCoords[2] };

                    if (elem.PrimitiveType == H3DPrimitiveType.RGBA)
                    {
                        void SetColor(H3DAnimRGBA c, string name)
                        {
                            var color = new Color();

                            if (c.R.Exists)
                            {
                                color.R = (byte)c.R.GetFrameValue(frame);
                            }
                            if (c.G.Exists)
                            {
                                color.G = (byte)c.G.GetFrameValue(frame);
                            }
                            if (c.B.Exists)
                            {
                                color.B = (byte)c.B.GetFrameValue(frame);
                            }
                            if (c.A.Exists)
                            {
                                color.A = (byte)c.A.GetFrameValue(frame);
                            }
                            keyFrame.OpaqueData.Add(name, color);
                        }

                        var rgba = (H3DAnimRGBA)elem.Content;
                        switch (elem.TargetType)
                        {
                        case H3DTargetType.MaterialEmission:  SetColor(rgba, "EmissionColor"); break;

                        case H3DTargetType.MaterialAmbient:   SetColor(rgba, "AmbientColor"); break;

                        case H3DTargetType.MaterialDiffuse:   SetColor(rgba, "DiffuseColor"); break;

                        case H3DTargetType.MaterialSpecular0: SetColor(rgba, "Specular0Color"); break;

                        case H3DTargetType.MaterialSpecular1: SetColor(rgba, "Specular1Color"); break;

                        case H3DTargetType.MaterialConstant0: SetColor(rgba, "Constant0Color"); break;

                        case H3DTargetType.MaterialConstant1: SetColor(rgba, "Constant1Color"); break;

                        case H3DTargetType.MaterialConstant2: SetColor(rgba, "Constant2Color"); break;

                        case H3DTargetType.MaterialConstant3: SetColor(rgba, "Constant3Color"); break;

                        case H3DTargetType.MaterialConstant4: SetColor(rgba, "Constant4Color"); break;

                        case H3DTargetType.MaterialConstant5: SetColor(rgba, "Constant5Color"); break;
                        }
                    }
                    else if (elem.PrimitiveType == H3DPrimitiveType.Vector2D)
                    {
                        void SetVector2(H3DAnimVector2D v, ref System.Numerics.Vector2 t)
                        {
                            if (v.X.Exists)
                            {
                                t.X = v.X.GetFrameValue(frame);
                            }
                            if (v.Y.Exists)
                            {
                                t.Y = v.Y.GetFrameValue(frame);
                            }
                        }

                        var vector = (H3DAnimVector2D)elem.Content;
                        switch (elem.TargetType)
                        {
                        case H3DTargetType.MaterialTexCoord0Scale: SetVector2(vector, ref tc[0].Scale); break;

                        case H3DTargetType.MaterialTexCoord1Scale: SetVector2(vector, ref tc[1].Scale); break;

                        case H3DTargetType.MaterialTexCoord2Scale: SetVector2(vector, ref tc[2].Scale); break;

                        case H3DTargetType.MaterialTexCoord0Trans: SetVector2(vector, ref tc[0].Translation); break;

                        case H3DTargetType.MaterialTexCoord1Trans: SetVector2(vector, ref tc[1].Translation); break;

                        case H3DTargetType.MaterialTexCoord2Trans: SetVector2(vector, ref tc[2].Translation); break;
                        }
                    }
                    else if (elem.PrimitiveType == H3DPrimitiveType.Float)
                    {
                        var @float = ((H3DAnimFloat)elem.Content).Value;
                        if ([email protected])
                        {
                            continue;
                        }

                        var value = @float.GetFrameValue(frame);
                        switch (elem.TargetType)
                        {
                        case H3DTargetType.MaterialTexCoord0Rot: tc[0].Rotation = value; break;

                        case H3DTargetType.MaterialTexCoord1Rot: tc[1].Rotation = value; break;

                        case H3DTargetType.MaterialTexCoord2Rot: tc[2].Rotation = value; break;
                        }
                    }
                    else if (elem.PrimitiveType == H3DPrimitiveType.Texture)
                    {
                        var @int = ((H3DAnimFloat)elem.Content).Value;
                        if ([email protected])
                        {
                            continue;
                        }

                        var value = (int)@int.GetFrameValue(frame);
                        var name  = materials[value].Name;
                        switch (elem.TargetType)
                        {
                        case H3DTargetType.MaterialMapper0Texture: keyFrame.OpaqueData.Add("Texture0", name); break;

                        case H3DTargetType.MaterialMapper1Texture: keyFrame.OpaqueData.Add("Texture1", name); break;

                        case H3DTargetType.MaterialMapper2Texture: keyFrame.OpaqueData.Add("Texture2", name); break;
                        }
                    }

                    keyFrame.Transforms[0] = tc[0].GetTransform().ToXNA();
                    keyFrame.Transforms[1] = tc[1].GetTransform().ToXNA();
                    keyFrame.Transforms[2] = tc[2].GetTransform().ToXNA();

                    channel.Add(keyFrame);
                }

                animationNode.Channels[elem.Name] = channel;
            }

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

            Output.SourceData.Add(this);

            H3DLUT L = new H3DLUT();

            L.Name = GFModel.DefaultLUTName;

            for (int MdlIndex = 0; MdlIndex < Models.Count; MdlIndex++)
            {
                GFModel  Model = Models[MdlIndex];
                H3DModel Mdl   = Model.ToH3DModel();

                for (int MatIndex = 0; MatIndex < Model.Materials.Count; MatIndex++)
                {
                    H3DMaterialParams Params = Mdl.Materials[MatIndex].MaterialParams;

                    string FragShaderName = Model.Materials[MatIndex].FragShaderName;
                    string VtxShaderName  = Model.Materials[MatIndex].VtxShaderName;

                    GFShader FragShader = MaterialShaders.FirstOrDefault(x => x.Name == FragShaderName);
                    GFShader VtxShader  = MaterialShaders.FirstOrDefault(x => x.Name == VtxShaderName);

                    if (FragShader != null)
                    {
                        Params.TexEnvBufferColor = FragShader.TexEnvBufferColor;

                        Array.Copy(FragShader.TexEnvStages, Params.TexEnvStages, 6);
                    }

                    Params.MetaData.Add(new H3DMetaDataValue("OriginMaterialHash", (int)GetTexEnvConfigHash(Params)));

                    if (VtxShader != null)
                    {
                        foreach (KeyValuePair <uint, Vector4> KV in VtxShader.VtxShaderUniforms)
                        {
                            Params.VtxShaderUniforms.Add(KV.Key, KV.Value);
                        }

                        foreach (KeyValuePair <uint, Vector4> KV in VtxShader.GeoShaderUniforms)
                        {
                            Params.GeoShaderUniforms.Add(KV.Key, KV.Value);
                        }
                    }
                }

                int Index = 1;

                while (Output.Models.Contains(Mdl.Name))
                {
                    Mdl.Name = $"{Mdl.Name}_{Index}";
                }

                Model.AddToH3DLUT(L);

                Output.Models.Add(Mdl);
            }

            Output.LUTs.Add(L);

            Output.CopyMaterials();

            foreach (GFTexture Texture in Textures)
            {
                Output.Textures.Add(Texture.ToH3DTexture());
            }

            /*Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(Output, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonSerializerSettings()
             *  {
             *      ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
             *  }));*/

            return(Output);
        }
예제 #30
0
        //public MaterialScript() { }

        public MaterialDump(H3D Scene, int MdlIndex, int AnimIndex = -1)  //TODO: Needs more object-oriented-ness
        {
            if (MdlIndex != -1)
            {
                H3DModel Mdl = Scene.Models[MdlIndex];

                //Initialize text Stringbuilder
                text = new StringBuilder($"Material data for {Mdl.Name}\n\n");

                //if model has no materials, abort
                if (Mdl.Materials.Count < 1)
                {
                    text.AppendLine("None");
                    return;
                }

                //Write details for each material
                foreach (H3DMaterial Mtl in Mdl.Materials)
                {
                    text.AppendLine(Mtl.Name);

                    //Write color properties
                    text.AppendLine($"  Ambient Color: {Mtl.MaterialParams.AmbientColor}");
                    text.AppendLine($"  Diffuse Color: {Mtl.MaterialParams.DiffuseColor}");
                    text.AppendLine($"  Specular 0 Color: {Mtl.MaterialParams.Specular0Color}");
                    text.AppendLine($"  Specular 1 Color: {Mtl.MaterialParams.Specular1Color}");
                    text.AppendLine($"  Emission Color: {Mtl.MaterialParams.EmissionColor}");
                    text.Append('\n');

                    //TODO: write constants listed directly in Material? (they don't always match those in the stages)

                    //Write Texture properties
                    if (Mtl.Texture0Name != null && Mtl.Texture0Name.Length > 0)
                    {
                        WriteTextureString(Mtl, 0);
                    }
                    if (Mtl.Texture1Name != null && Mtl.Texture1Name.Length > 0)
                    {
                        WriteTextureString(Mtl, 1);
                    }
                    if (Mtl.Texture2Name != null && Mtl.Texture2Name.Length > 0)
                    {
                        WriteTextureString(Mtl, 2);
                    }
                    //text.Append('\n');

                    //write Alpha test properties
                    text.AppendLine("  Alpha Test");
                    text.AppendLine($"    Enabled: {Mtl.MaterialParams.AlphaTest.Enabled}");
                    text.AppendLine($"    Function: {Mtl.MaterialParams.AlphaTest.Function}");
                    text.AppendLine($"    Reference Value: {Mtl.MaterialParams.AlphaTest.Reference}\n");

                    //Write blend function properties
                    text.AppendLine("  Blending");
                    text.AppendLine($"    Blend Color: {Mtl.MaterialParams.BlendColor}");
                    text.AppendLine($"    Blend Color Dst Function: {Mtl.MaterialParams.BlendFunction.ColorDstFunc}");
                    text.AppendLine($"    Blend Color Src Function: {Mtl.MaterialParams.BlendFunction.ColorSrcFunc}");
                    text.AppendLine($"    Blend Color Equation: {Mtl.MaterialParams.BlendFunction.ColorEquation}");
                    text.AppendLine($"    Blend Alpha Dst Function: {Mtl.MaterialParams.BlendFunction.AlphaDstFunc}");
                    text.AppendLine($"    Blend Alpha Src Function: {Mtl.MaterialParams.BlendFunction.AlphaSrcFunc}");
                    text.AppendLine($"    Blend Alpha Equation: {Mtl.MaterialParams.BlendFunction.AlphaEquation}\n");

                    //Write Texture stages (layers)
                    text.AppendLine($"  TexEnv Stages:");
                    foreach (PICATexEnvStage stage in Mtl.MaterialParams.TexEnvStages)
                    {
                        WriteStageString(stage);
                        text.Append('\n');
                    }


                    text.Append("\n\n");
                }
            } //MdlIndex != -1
        }