Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private void ProcessMesh(IOScene scene, IOMesh mesh, HSD_JOBJ rootnode)
        {
            HSD_JOBJ parent = rootnode;

            HashSet <HSD_JOBJ> nodes = new HashSet <HSD_JOBJ>();

            foreach (var j in rootnode.BreathFirstList)
            {
                nodes.Add(j);
            }


            if (mesh.ParentBone != null && _cache.NameToJOBJ.ContainsKey(mesh.ParentBone.Name))
            {
                parent = _cache.NameToJOBJ[mesh.ParentBone.Name];
            }


            HSD_DOBJ root = null;
            HSD_DOBJ prev = null;

            //var skeleton = rootnode.BreathFirstList;
            Console.WriteLine("Processing " + mesh.Name);

            bool singleBinded = mesh.Name.Contains("SINGLE");

            foreach (var poly in mesh.Polygons)
            {
                // Skip Empty Polygon
                if (poly.Indicies.Count == 0)
                {
                    continue;
                }


                // convert to triangles
                poly.ToTriangles(mesh);

                if (poly.PrimitiveType != IOPrimitive.TRIANGLE)
                {
                    continue;
                }


                // Generate DOBJ
                HSD_DOBJ dobj = new HSD_DOBJ();

                if (Settings.ImportMeshNames)
                {
                    dobj.ClassName = mesh.Name;
                }

                if (root == null)
                {
                    root = dobj;
                }
                else
                {
                    prev.Next = dobj;
                }
                prev = dobj;


                // generate material
                var material = scene.Materials.Find(e => e.Name == poly.MaterialName);

                dobj.Mobj = GenerateMaterial(material);


                Console.WriteLine(mesh.Name + " " + material?.Name);


                // reflective mobjs do not use uvs
                var hasReflection = false;

                // bump maps need tangents and bitangents
                var hasBump = false;

                // Assess needed attributes based on the material MOBJ
                if (mesh.Name.Contains("REFLECTIVE"))
                {
                    hasReflection = true;
                }
#if DEBUG
                if (Settings.MetalModel)
                {
                    hasReflection = true;
                }
#endif

                if (mesh.Name.Contains("BUMP"))
                {
                    hasBump = true;
                }

                if (dobj.Mobj.Textures != null)
                {
                    foreach (var t in dobj.Mobj.Textures.List)
                    {
                        if (t.Flags.HasFlag(TOBJ_FLAGS.COORD_REFLECTION))
                        {
                            hasReflection = true;
                        }
                        if (t.Flags.HasFlag(TOBJ_FLAGS.BUMP))
                        {
                            hasBump = true;
                        }
                    }
                }

                // assess attributes
                List <GXAttribName> Attributes = new List <GXAttribName>();

                if (mesh.HasEnvelopes() && Settings.ImportRigging && !singleBinded)
                {
                    Attributes.Add(GXAttribName.GX_VA_PNMTXIDX);

                    if (hasReflection)
                    {
                        Attributes.Add(GXAttribName.GX_VA_TEX0MTXIDX);

                        if (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 1)
                        {
                            Attributes.Add(GXAttribName.GX_VA_TEX1MTXIDX);
                        }

#if DEBUG
                        if (Settings.MetalModel && !Attributes.Contains(GXAttribName.GX_VA_TEX1MTXIDX))
                        {
                            Attributes.Add(GXAttribName.GX_VA_TEX1MTXIDX);
                        }
#endif
                    }
                }


                Attributes.Add(GXAttribName.GX_VA_POS);


                if (hasBump)
                {
                    Attributes.Add(GXAttribName.GX_VA_NBT);
                }
                else
                if (mesh.HasNormals && Settings.ImportNormals)
                {
                    Attributes.Add(GXAttribName.GX_VA_NRM);
                }


                if (mesh.HasColorSet(0) && Settings.ImportVertexColor)
                {
                    Attributes.Add(GXAttribName.GX_VA_CLR0);
                }

                if (mesh.HasColorSet(1) && Settings.ImportVertexColor)
                {
                    Attributes.Add(GXAttribName.GX_VA_CLR1);
                }


                if (mesh.HasUVSet(0) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX0);
                }

                if ((mesh.HasUVSet(1) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 1)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX1);
                }

                if ((mesh.HasUVSet(2) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 2)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX2);
                }

                if ((mesh.HasUVSet(3) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 3)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX3);
                }

                if ((mesh.HasUVSet(4) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 4)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX4);
                }

                if ((mesh.HasUVSet(5) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 5)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX5);
                }

                if ((mesh.HasUVSet(6) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 6)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX6);
                }

                if ((mesh.HasUVSet(7) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 7)) && !hasReflection)
                {
                    Attributes.Add(GXAttribName.GX_VA_TEX7);
                }


                var vertices   = new List <GX_Vertex>();
                var jobjList   = new List <HSD_JOBJ[]>();
                var weightList = new List <float[]>();

                foreach (var face in poly.Indicies)
                {
                    var v = mesh.Vertices[face];

                    GX_Vertex vertex = new GX_Vertex();

                    var tkvert  = new Vector3(v.Position.X, v.Position.Y, v.Position.Z);
                    var tknrm   = new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z);
                    var tktan   = new Vector3(v.Tangent.X, v.Tangent.Y, v.Tangent.Z);
                    var tkbitan = new Vector3(v.Binormal.X, v.Binormal.Y, v.Binormal.Z);

                    var parentTransform = _cache.jobjToWorldTransform[parent].Inverted();

                    if (_cache.jobjToWorldTransform[parent] != Matrix4.Identity)
                    {
                        tkvert  = Vector3.TransformPosition(tkvert, parentTransform);
                        tknrm   = Vector3.TransformNormal(tknrm, parentTransform).Normalized();
                        tktan   = Vector3.TransformNormal(tktan, parentTransform).Normalized();
                        tkbitan = Vector3.TransformNormal(tkbitan, parentTransform).Normalized();
                    }


                    if (mesh.HasEnvelopes() && Settings.ImportRigging)
                    {
                        // create weighting lists
                        List <float>    weight = new List <float>();
                        List <HSD_JOBJ> bones  = new List <HSD_JOBJ>();

                        if (v.Envelope.Weights.Count == 0)
                        {
                            weight.Add(1);
                            bones.Add(rootnode);
                        }

                        if (v.Envelope.Weights.Count > 4)
                        {
                            throw new Exception($"Too many weights! {v.Envelope.Weights.Count} in {mesh.Name}");
                        }

                        foreach (var bw in v.Envelope.Weights)
                        {
                            // check if skeleton actually contains bone
                            if (_cache.NameToJOBJ.ContainsKey(bw.BoneName) && nodes.Contains(_cache.NameToJOBJ[bw.BoneName]))
                            {
                                // add envelope
                                bones.Add(_cache.NameToJOBJ[bw.BoneName]);
                                weight.Add(bw.Weight);

                                // indicate enveloped jobjs
                                if (!_cache.EnvelopedJOBJs.Contains(_cache.NameToJOBJ[bw.BoneName]))
                                {
                                    _cache.EnvelopedJOBJs.Add(_cache.NameToJOBJ[bw.BoneName]);
                                }
                            }
                            else
                            {
                                throw new Exception($"Bone not found \"{bw.BoneName}\" Weight: {bw.Weight} in {mesh.Name}");
                            }
                        }

                        jobjList.Add(bones.ToArray());
                        weightList.Add(weight.ToArray());

                        // invert single binds
                        if (v.Envelope.Weights.Count == 1)
                        {
                            var inv = _cache.jobjToWorldTransform[_cache.NameToJOBJ[v.Envelope.Weights[0].BoneName]].Inverted();
                            tkvert  = Vector3.TransformPosition(tkvert, inv);
                            tknrm   = Vector3.TransformNormal(tknrm, inv).Normalized();
                            tktan   = Vector3.TransformNormal(tknrm, inv).Normalized();
                            tkbitan = Vector3.TransformNormal(tknrm, inv).Normalized();
                        }
                    }

                    vertex.POS   = GXTranslator.fromVector3(tkvert);
                    vertex.NRM   = GXTranslator.fromVector3(tknrm.Normalized());
                    vertex.TAN   = GXTranslator.fromVector3(tktan);
                    vertex.BITAN = GXTranslator.fromVector3(tkbitan);

                    if (Settings.InvertNormals)
                    {
                        vertex.NRM.X   *= -1;
                        vertex.NRM.Y   *= -1;
                        vertex.NRM.Z   *= -1;
                        vertex.TAN.X   *= -1;
                        vertex.TAN.Y   *= -1;
                        vertex.TAN.Z   *= -1;
                        vertex.BITAN.X *= -1;
                        vertex.BITAN.Y *= -1;
                        vertex.BITAN.Z *= -1;
                    }

                    if (mesh.HasUVSet(0))
                    {
                        vertex.TEX0 = new GXVector2(v.UVs[0].X, v.UVs[0].Y);
                    }

                    if (mesh.HasUVSet(1))
                    {
                        vertex.TEX1 = new GXVector2(v.UVs[1].X, v.UVs[1].Y);
                    }

                    if (mesh.HasUVSet(2))
                    {
                        vertex.TEX2 = new GXVector2(v.UVs[2].X, v.UVs[2].Y);
                    }

                    if (mesh.HasUVSet(3))
                    {
                        vertex.TEX3 = new GXVector2(v.UVs[3].X, v.UVs[3].Y);
                    }

                    if (mesh.HasUVSet(4))
                    {
                        vertex.TEX4 = new GXVector2(v.UVs[4].X, v.UVs[4].Y);
                    }

                    if (mesh.HasUVSet(5))
                    {
                        vertex.TEX5 = new GXVector2(v.UVs[5].X, v.UVs[5].Y);
                    }

                    if (mesh.HasUVSet(6))
                    {
                        vertex.TEX6 = new GXVector2(v.UVs[6].X, v.UVs[6].Y);
                    }

                    if (mesh.HasUVSet(7))
                    {
                        vertex.TEX7 = new GXVector2(v.UVs[7].X, v.UVs[7].Y);
                    }

                    if (mesh.HasColorSet(0))
                    {
                        vertex.CLR0 = new GXColor4(
                            v.Colors[0].X * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            v.Colors[0].Y * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            v.Colors[0].Z * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            Settings.ImportVertexAlpha ? v.Colors[0].W : 1);
                    }

                    if (mesh.HasColorSet(1))
                    {
                        vertex.CLR1 = new GXColor4(
                            v.Colors[1].X * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            v.Colors[1].Y * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            v.Colors[1].Z * (Settings.MultiplyVertexColorBy2 ? 2 : 1),
                            Settings.ImportVertexAlpha ? v.Colors[1].W : 1);
                    }

                    vertices.Add(vertex);
                }


                // generate pobjs
                HSD_POBJ pobj = null;

                if (mesh.HasEnvelopes() && Settings.ImportRigging && !singleBinded)
                {
                    pobj = _cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), jobjList, weightList);
                }
                else
                {
                    pobj = _cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), null);
                }

                if (singleBinded && jobjList.Count > 0 && jobjList[0].Length > 0)
                {
                    parent = jobjList[0][0];
                }

                if (pobj != null)
                {
                    if (dobj.Pobj == null)
                    {
                        dobj.Pobj = pobj;
                    }
                    else
                    {
                        dobj.Pobj.Add(pobj);
                    }
                }
            }

            if (parent.Dobj == null)
            {
                parent.Dobj = root;
            }
            else
            {
                parent.Dobj.Add(root);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private string GenerateGeometry(IOMesh mesh)
        {
            // convert mesh to triangles to simplify
            mesh.MakeTriangles();

            // create a unique geometry id
            var geomID = GetUniqueID(mesh.Name + "-geometry");

            // create geometry element
            Geometry geom = new Geometry()
            {
                ID   = geomID,
                Name = mesh.Name
            };

            geom.Mesh = new Mesh();

            // generate sources
            SourceGenerator srcgen = new SourceGenerator();

            srcgen.AddSourceData(
                geomID, Input_Semantic.POSITION,
                mesh.Vertices.SelectMany(e => new float[] { e.Position.X, e.Position.Y, e.Position.Z }).ToArray());

            srcgen.AddSourceData(
                geomID, Input_Semantic.NORMAL,
                mesh.Vertices.SelectMany(e => new float[] { e.Normal.X, e.Normal.Y, e.Normal.Z }).ToArray());

            for (int i = 0; i < 7; i++)
            {
                if (mesh.HasUVSet(i))
                {
                    srcgen.AddSourceData(
                        geomID, Input_Semantic.TEXCOORD,
                        mesh.Vertices.SelectMany(e => new float[] { e.UVs[i].X, e.UVs[i].Y }).ToArray(),
                        i);
                }
            }

            for (int i = 0; i < 7; i++)
            {
                if (mesh.HasColorSet(i))
                {
                    srcgen.AddSourceData(
                        geomID, Input_Semantic.COLOR,
                        mesh.Vertices.SelectMany(e => new float[] { e.Colors[i].X, e.Colors[i].Y, e.Colors[i].Z, e.Colors[i].W }).ToArray(),
                        i);
                }
            }

            // fill in vertex info
            geom.Mesh.Vertices = new Vertices()
            {
                ID    = GetUniqueID(mesh.Name + "-vertices"),
                Input = new Input_Unshared[] {
                    new Input_Unshared()
                    {
                        Semantic = IONET.Collada.Enums.Input_Semantic.POSITION,
                        source   = "#" + srcgen.GetID(Input_Semantic.POSITION)
                    }
                }
            };

            // fill in triangles

            var polyIndex = 0;

            geom.Mesh.Triangles = new Triangles[mesh.Polygons.Count];
            foreach (var poly in mesh.Polygons)
            {
                if (poly.PrimitiveType != IOPrimitive.TRIANGLE)
                {
                    System.Diagnostics.Debug.WriteLine("Warning: " + poly.PrimitiveType + " not currently supported");
                    continue;
                }

                Triangles tri = new Triangles()
                {
                    Count    = poly.Indicies.Count / 3,
                    Material = poly.MaterialName
                };

                List <Input_Shared> inputs = new List <Input_Shared>();
                inputs.Add(new Input_Shared()
                {
                    Semantic = Input_Semantic.VERTEX,
                    Offset   = inputs.Count,
                    source   = "#" + geom.Mesh.Vertices.ID
                });

                inputs.Add(new Input_Shared()
                {
                    Semantic = Input_Semantic.NORMAL,
                    Offset   = inputs.Count,
                    source   = "#" + srcgen.GetID(Input_Semantic.NORMAL)
                });

                for (int i = 0; i < 7; i++)
                {
                    if (mesh.HasUVSet(i))
                    {
                        inputs.Add(new Input_Shared()
                        {
                            Semantic = Input_Semantic.TEXCOORD,
                            source   = "#" + srcgen.GetID(Input_Semantic.TEXCOORD, i),
                            Offset   = inputs.Count,
                            Set      = i
                        });
                    }
                }

                for (int i = 0; i < 7; i++)
                {
                    if (mesh.HasColorSet(i))
                    {
                        inputs.Add(new Input_Shared()
                        {
                            Semantic = Input_Semantic.COLOR,
                            source   = "#" + srcgen.GetID(Input_Semantic.COLOR, i),
                            Offset   = inputs.Count,
                            Set      = i
                        });
                    }
                }

                tri.Input = inputs.ToArray();

                tri.P = new IONET.Collada.Types.Int_Array_String()
                {
                    Value_As_String = string.Join(" ", srcgen.Remap(poly.Indicies))
                };

                geom.Mesh.Triangles[polyIndex++] = tri;
            }


            // generate sources
            geom.Mesh.Source = srcgen.GetSources();


            // add geometry element to document
            if (_collada.Library_Geometries == null)
            {
                _collada.Library_Geometries = new Library_Geometries();
            }

            if (_collada.Library_Geometries.Geometry == null)
            {
                _collada.Library_Geometries.Geometry = new Geometry[0];
            }

            Array.Resize(ref _collada.Library_Geometries.Geometry, _collada.Library_Geometries.Geometry.Length + 1);

            _collada.Library_Geometries.Geometry[_collada.Library_Geometries.Geometry.Length - 1] = geom;

            // return geometry id
            return(geomID);
        }