Ejemplo n.º 1
0
        public GX_DisplayList(HSD_POBJ pobj)
        {
            var attrs = pobj.Attributes;

            if (attrs[attrs.Length - 1].AttributeName != GXAttribName.GX_VA_NULL)
            {
                throw new System.FormatException("Attribute buffer does not end with null vertex attribute");
            }

            Attributes.AddRange(attrs);

            Open(pobj.DisplayListBuffer);

            Vertices.AddRange(GX_VertexAccessor.GetDecodedVertices(this, pobj));

            if (pobj.EnvelopeWeights != null)
            {
                Envelopes.AddRange(pobj.EnvelopeWeights);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads the vertex buffer into a more accessable format : <see cref="GXVertex"/>
        /// </summary>
        /// <param name="DisplayList">Display list belonging to given PBOJ</param>
        /// <param name="Polygon"><see cref="HSD_POBJ"/> the the display list belong to</param>
        /// <returns>Array of <see cref="GXVertex"/></returns>
        public static GX_Shape[] GetShapeSet(GX_DisplayList DisplayList, HSD_POBJ Polygon, int shapeset)
        {
            // Create Vertex List
            List <GX_Shape> Vertices = new List <GX_Shape>();

            // Read through the Display Lists
            foreach (GX_PrimitiveGroup pg in DisplayList.Primitives)
            {
                var v = GetDecodedVertices(pg, DisplayList.Attributes, Polygon, shapeset);

                foreach (var gv in v)
                {
                    Vertices.Add(new GX_Shape()
                    {
                        POS = gv.POS, NRM = gv.NRM
                    });
                }
            }

            return(Vertices.ToArray());
        }
Ejemplo n.º 3
0
        public GX_DisplayList(HSD_POBJ pobj, GX_Attribute[] attrs = null)
        {
            // read attributes
            if (attrs == null)
            {
                attrs = pobj.ToGXAttributes();
            }

            if (attrs[attrs.Length - 1].AttributeName != GXAttribName.GX_VA_NULL)
            {
                System.Diagnostics.Debug.WriteLine("Attribute buffer does not end with null vertex attribute");
            }

            Attributes.AddRange(attrs);

            // read display list buffer
            Open(pobj.DisplayListBuffer);

            // load vertices
            Vertices.AddRange(GX_VertexAccessor.GetDecodedVertices(this, pobj));

            // load shape sets if they exist
            if (pobj.ShapeSet != null)
            {
                for (int i = 0; i < pobj.ShapeSet.VertexIndices.Count; i++)
                {
                    ShapeSets.Add(GX_VertexAccessor.GetShapeSet(this, pobj, i));
                }
            }

            // get envelopse
            if (pobj.EnvelopeWeights != null)
            {
                Envelopes.AddRange(pobj.EnvelopeWeights);
            }
        }
Ejemplo n.º 4
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.º 5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="triList"></param>
        /// <param name="attrGroup"></param>
        /// <param name="weights"></param>
        public HSD_POBJ CreatePOBJsFromTriangleList(List <GX_Vertex> triList, GXAttribName[] attributes, List <HSD_Envelope> weights)
        {
            TriangleConverter.TriangleConverter converter = new TriangleConverter.TriangleConverter(UseTriangleStrips, 32, 3, true);
            int pointCount, faceCount;

            HSD_JOBJ singleBind = null;

            bool HasPositionNormalMatrix = attributes.Contains(GXAttribName.GX_VA_PNMTXIDX);

            // Optimize single bind

            /*if (weights != null && weights.Count == 1 && weights[0].EnvelopeCount == 1)
             * {
             *  singleBind = weights[0].GetJOBJAt(0);
             *  var al = attributes.ToList();
             *  al.Remove(GXAttribName.GX_VA_PNMTXIDX);
             *  attributes = al.ToArray();
             * }*/

            var groups = converter.GroupPrimitives(triList.ToArray(), out pointCount, out faceCount);

            HSD_POBJ rootPOBJ = null;
            HSD_POBJ prevPOBJ = null;

            foreach (var g in groups)
            {
                var jobjweights = new List <HSD_Envelope>();
                var pmidToNewID = new Dictionary <ushort, ushort>();

                if (HasPositionNormalMatrix == true && weights.Count > 0)
                {
                    foreach (var n in g._nodes)
                    {
                        pmidToNewID.Add(n, (ushort)(jobjweights.Count * 3));
                        jobjweights.Add(weights[n / 3]);
                    }
                }

                GX_DisplayList newdl = new GX_DisplayList();

                foreach (var t in g._triangles)
                {
                    var newVert = new List <GX_Vertex>();
                    for (int p = 0; p < t.Points.Count; p++)
                    {
                        var point = t.Points[p];
                        if (HasPositionNormalMatrix)
                        {
                            point.PNMTXIDX   = pmidToNewID[point.PNMTXIDX];
                            point.TEX0MTXIDX = (ushort)(point.PNMTXIDX + 30);
                            point.TEX1MTXIDX = point.TEX0MTXIDX;
                        }
                        t.Points[p] = point;
                        newVert.Add(point);
                    }

                    newdl.Primitives.Add(Compress(GXPrimitiveType.Triangles, newVert.ToArray(), attributes));
                }
                foreach (var t in g._tristrips)
                {
                    var newVert = new List <GX_Vertex>();
                    for (int p = 0; p < t.Points.Count; p++)
                    {
                        var point = t.Points[p];
                        if (HasPositionNormalMatrix)
                        {
                            point.PNMTXIDX   = pmidToNewID[point.PNMTXIDX];
                            point.TEX0MTXIDX = (ushort)(point.PNMTXIDX + 30);
                            point.TEX1MTXIDX = point.TEX0MTXIDX;
                        }
                        t.Points[p] = point;
                        newVert.Add(point);
                    }
                    newdl.Primitives.Add(Compress(GXPrimitiveType.TriangleStrip, newVert.ToArray(), attributes));
                }

                if (singleBind == null)
                {
                    newdl.Envelopes = jobjweights;
                }

                var newpobj = new HSD_POBJ();
                CreatedPOBJs.Add(newpobj);

                if (singleBind != null)
                {
                    newpobj.SingleBoundJOBJ = singleBind;
                }

                pobjToDisplayList.Add(newpobj, newdl);
                pobjToAttributes.Add(newpobj, attributes);

                if (prevPOBJ == null)
                {
                    rootPOBJ = newpobj;
                }
                else
                {
                    prevPOBJ.Next = newpobj;
                }
                prevPOBJ = newpobj;
            }

            //Console.WriteLine(rootPOBJ.List.Count + " POBJs generated");


            return(rootPOBJ);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Gets decoded vertices for <see cref="HSD_POBJ"/>
 /// </summary>
 /// <param name="Polygon"></param>
 /// <returns></returns>
 public static GXVertex[] GetDecodedVertices(HSD_POBJ Polygon)
 {
     return(GetDecodedVertices(GetDisplayList(Polygon), Polygon));
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Returns display list for <see cref="HSD_POBJ"/>
 /// </summary>
 /// <param name="Polygon"></param>
 /// <returns></returns>
 public static GXDisplayList GetDisplayList(HSD_POBJ Polygon)
 {
     return(new GXDisplayList(Polygon.DisplayListBuffer, Polygon.VertexAttributes));
 }
Ejemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private static HSD_DOBJ GetMeshes(ProcessingCache cache, ModelImportSettings settings, Scene scene, Node node)
        {
            HSD_DOBJ root = null;
            HSD_DOBJ prev = null;

            Console.WriteLine("Processing " + node.Name);

            foreach (int index in node.MeshIndices)
            {
                Mesh mesh     = scene.Meshes[index];
                var  material = scene.Materials[mesh.MaterialIndex];

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

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

                // hack to make dobjs merged by texture
                if (settings.ImportTexture &&
                    settings.ForceMergeObjects == ForceGroupModes.Texture &&
                    material.HasTextureDiffuse &&
                    cache.TextureToDOBJ.ContainsKey(material.TextureDiffuse.FilePath))
                {
                    dobj = cache.TextureToDOBJ[material.TextureDiffuse.FilePath];
                }
                else
                {
                    if (root == null)
                    {
                        root = dobj;
                    }
                    else
                    {
                        prev.Next = dobj;
                    }
                    prev = dobj;

                    dobj.Mobj = GenerateMaterial(cache, settings, material);
                    if (settings.ForceMergeObjects == ForceGroupModes.Texture &&
                        material.HasTextureDiffuse &&
                        settings.ImportTexture)
                    {
                        cache.TextureToDOBJ.Add(material.TextureDiffuse.FilePath, dobj);
                    }
                }

                if (root != null && settings.ForceMergeObjects == ForceGroupModes.MeshGroup)
                {
                    dobj = root;
                }

                // Assessment
                if (!mesh.HasFaces)
                {
                    continue;
                }

                // Assess needed attributes based on the material MOBJ

                // reflective mobjs do not use uvs
                var hasReflection = false;
                // bump maps need tangents and bitangents
                var hasBump = false;

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

                List <GXAttribName> Attributes = new List <GXAttribName>();

                // todo: rigging
                List <HSD_JOBJ>[] jobjs   = new List <HSD_JOBJ> [mesh.Vertices.Count];
                List <float>[]    weights = new List <float> [mesh.Vertices.Count];
                if (mesh.HasBones)
                {
                    Attributes.Add(GXAttribName.GX_VA_PNMTXIDX);

                    foreach (var v in mesh.Bones)
                    {
                        var jobj = cache.NameToJOBJ[v.Name];

                        if (!cache.EnvelopedJOBJs.Contains(jobj))
                        {
                            cache.EnvelopedJOBJs.Add(jobj);
                        }

                        if (v.HasVertexWeights)
                        {
                            foreach (var vw in v.VertexWeights)
                            {
                                if (jobjs[vw.VertexID] == null)
                                {
                                    jobjs[vw.VertexID] = new List <HSD_JOBJ>();
                                }
                                if (weights[vw.VertexID] == null)
                                {
                                    weights[vw.VertexID] = new List <float>();
                                }
                                if (vw.Weight > 0)
                                {
                                    jobjs[vw.VertexID].Add(jobj);
                                    weights[vw.VertexID].Add(vw.Weight);
                                }
                            }
                        }
                    }
                }

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

                if (mesh.HasVertices)
                {
                    Attributes.Add(GXAttribName.GX_VA_POS);
                }

                if (mesh.HasVertexColors(0) && settings.ShadingType == ShadingType.VertexColor)
                {
                    Attributes.Add(GXAttribName.GX_VA_CLR0);
                }

                //if (mesh.HasVertexColors(1) && settings.ImportVertexColors)
                //    Attributes.Add(GXAttribName.GX_VA_CLR1);

                if (!hasBump && mesh.HasNormals && settings.ShadingType == ShadingType.Material)
                {
                    Attributes.Add(GXAttribName.GX_VA_NRM);
                }

                if (hasBump)
                {
                    Attributes.Add(GXAttribName.GX_VA_NBT);
                }

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

                //if (mesh.HasTextureCoords(1))
                //    Attributes.Add(GXAttribName.GX_VA_TEX1);

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

                foreach (var face in mesh.Faces)
                {
                    PrimitiveType faceMode;
                    switch (face.IndexCount)
                    {
                    case 1:
                        faceMode = PrimitiveType.Point;
                        break;

                    case 2:
                        faceMode = PrimitiveType.Line;
                        break;

                    case 3:
                        faceMode = PrimitiveType.Triangle;
                        break;

                    default:
                        faceMode = PrimitiveType.Polygon;
                        break;
                    }

                    if (faceMode != PrimitiveType.Triangle)
                    {
                        continue;
                        //throw new NotSupportedException($"Non triangle primitive types not supported at this time {faceMode}");
                    }

                    for (int i = 0; i < face.IndexCount; i++)
                    {
                        int indicie = face.Indices[i];

                        GX_Vertex vertex = new GX_Vertex();

                        if (mesh.HasBones)
                        {
                            jobjList.Add(jobjs[indicie].ToArray());
                            wList.Add(weights[indicie].ToArray());

                            // Single Binds Get Inverted
                            var tkvert = new Vector3(mesh.Vertices[indicie].X, mesh.Vertices[indicie].Y, mesh.Vertices[indicie].Z) * settings.Scale;
                            var tknrm  = new Vector3(mesh.Normals[indicie].X, mesh.Normals[indicie].Y, mesh.Normals[indicie].Z);

                            Vector3 tktan   = Vector3.Zero;
                            Vector3 tkbitan = Vector3.Zero;

                            if (mesh.HasTangentBasis)
                            {
                                tktan   = new Vector3(mesh.Tangents[indicie].X, mesh.Tangents[indicie].Y, mesh.Tangents[indicie].Z);
                                tkbitan = new Vector3(mesh.BiTangents[indicie].X, mesh.BiTangents[indicie].Y, mesh.BiTangents[indicie].Z);
                            }

                            if (jobjs[indicie].Count == 1 || weights[indicie][0] == 1)
                            {
                                tkvert = Vector3.TransformPosition(tkvert, cache.jobjToInverseTransform[jobjs[indicie][0]]);
                                tknrm  = Vector3.TransformNormal(tknrm, cache.jobjToInverseTransform[jobjs[indicie][0]]);

                                if (mesh.HasTangentBasis)
                                {
                                    tktan   = Vector3.TransformNormal(tktan, cache.jobjToInverseTransform[jobjs[indicie][0]]);
                                    tkbitan = Vector3.TransformNormal(tkbitan, cache.jobjToInverseTransform[jobjs[indicie][0]]);
                                }
                            }

                            vertex.POS   = GXTranslator.fromVector3(tkvert);
                            vertex.NRM   = GXTranslator.fromVector3(tknrm);
                            vertex.TAN   = GXTranslator.fromVector3(tktan);
                            vertex.BITAN = GXTranslator.fromVector3(tkbitan);
                        }
                        else
                        {
                            if (mesh.HasVertices)
                            {
                                vertex.POS = new GXVector3(mesh.Vertices[indicie].X * settings.Scale, mesh.Vertices[indicie].Y * settings.Scale, mesh.Vertices[indicie].Z * settings.Scale);
                            }

                            if (mesh.HasNormals)
                            {
                                vertex.NRM = new GXVector3(mesh.Normals[indicie].X, mesh.Normals[indicie].Y, mesh.Normals[indicie].Z);
                            }

                            if (mesh.HasTangentBasis)
                            {
                                vertex.TAN   = new GXVector3(mesh.Tangents[indicie].X, mesh.Tangents[indicie].Y, mesh.Tangents[indicie].Z);
                                vertex.BITAN = new GXVector3(mesh.BiTangents[indicie].X, mesh.BiTangents[indicie].Y, mesh.BiTangents[indicie].Z);
                            }
                        }

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

                        if (mesh.HasTextureCoords(0))
                        {
                            vertex.TEX0 = new GXVector2(
                                mesh.TextureCoordinateChannels[0][indicie].X,
                                mesh.TextureCoordinateChannels[0][indicie].Y);
                        }

                        if (mesh.HasTextureCoords(1))
                        {
                            vertex.TEX1 = new GXVector2(
                                mesh.TextureCoordinateChannels[1][indicie].X,
                                mesh.TextureCoordinateChannels[1][indicie].Y);
                        }

                        if (mesh.HasVertexColors(0))
                        {
                            vertex.CLR0 = new GXColor4(
                                mesh.VertexColorChannels[0][indicie].R,
                                mesh.VertexColorChannels[0][indicie].G,
                                mesh.VertexColorChannels[0][indicie].B,
                                settings.ImportVertexAlpha ? mesh.VertexColorChannels[0][indicie].A : 1);
                        }

                        if (mesh.HasVertexColors(1))
                        {
                            vertex.CLR0 = new GXColor4(
                                mesh.VertexColorChannels[1][indicie].R,
                                mesh.VertexColorChannels[1][indicie].G,
                                mesh.VertexColorChannels[1][indicie].B,
                                settings.ImportVertexAlpha ? mesh.VertexColorChannels[1][indicie].A : 1);
                        }

                        vertices.Add(vertex);
                    }
                }

                HSD_POBJ pobj = null;
                if (mesh.HasBones)
                {
                    pobj = cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), jobjList, wList);
                }
                else
                {
                    pobj = cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), null);
                }
                if (pobj != null)
                {
                    if (dobj.Pobj == null)
                    {
                        dobj.Pobj = pobj;
                    }
                    else
                    {
                        dobj.Pobj.Add(pobj);
                    }
                }
            }

            return(root);
        }
Ejemplo n.º 9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="pobj"></param>
        private Mesh ProcessPOBJ(HSD_POBJ pobj, HSD_JOBJ parent, HSD_JOBJ singleBind)
        {
            Mesh m = new Mesh();

            m.Name          = "pobj";
            m.PrimitiveType = PrimitiveType.Triangle;

            m.MaterialIndex = 0;

            var dl        = pobj.ToDisplayList();
            var envelopes = pobj.EnvelopeWeights;

            var parentTransform = Matrix4.Identity;

            if (parent != null)
            {
                parentTransform = WorldTransforms[jobjToIndex[parent]];
            }

            var singleBindTransform = Matrix4.Identity;

            if (singleBind != null)
            {
                singleBindTransform = WorldTransforms[jobjToIndex[singleBind]];
            }

            Dictionary <HSD_JOBJ, Bone> jobjToBone = new Dictionary <HSD_JOBJ, Bone>();

            if (envelopes != null)
            {
                foreach (var jobj in Jobjs)
                {
                    var bone = new Bone();
                    bone.Name         = JobjNodes[jobjToIndex[jobj]].Name;
                    bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[jobj]].Inverted());
                    m.Bones.Add(bone);
                    jobjToBone.Add(jobj, bone);
                }
            }

            /*foreach (var en in envelopes)
             * {
             *  foreach (var jobj in en.JOBJs)
             *  {
             *      if (!jobjToBone.ContainsKey(jobj))
             *      {
             *          var bone = new Bone();
             *          bone.Name = JobjNodes[jobjToIndex[jobj]].Name;
             *          bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[jobj]].Inverted());
             *          m.Bones.Add(bone);
             *          jobjToBone.Add(jobj, bone);
             *      }
             *  }
             * }*/


            if (singleBind != null && !jobjToBone.ContainsKey(singleBind))
            {
                var bone = new Bone();
                bone.Name         = JobjNodes[jobjToIndex[singleBind]].Name;
                bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[singleBind]].Inverted());
                m.Bones.Add(bone);
                jobjToBone.Add(singleBind, bone);
            }

            int offset = 0;
            var vIndex = -1;

            foreach (var prim in dl.Primitives)
            {
                var verts = dl.Vertices.GetRange(offset, prim.Count);
                offset += prim.Count;

                switch (prim.PrimitiveType)
                {
                case GXPrimitiveType.Quads:
                    verts = TriangleConverter.QuadToList(verts);
                    break;

                case GXPrimitiveType.TriangleStrip:
                    verts = TriangleConverter.StripToList(verts);
                    break;

                case GXPrimitiveType.Triangles:
                    break;

                default:
                    Console.WriteLine(prim.PrimitiveType);
                    break;
                }

                for (int i = m.VertexCount; i < m.VertexCount + verts.Count; i += 3)
                {
                    var f = new Face();
                    f.Indices.Add(i);
                    f.Indices.Add(i + 1);
                    f.Indices.Add(i + 2);
                    m.Faces.Add(f);
                }

                foreach (var v in verts)
                {
                    vIndex++;
                    if (singleBind != null)
                    {
                        var vertexWeight = new VertexWeight();
                        vertexWeight.VertexID = vIndex;
                        vertexWeight.Weight   = 1;
                        jobjToBone[singleBind].VertexWeights.Add(vertexWeight);
                    }
                    Matrix4 weight = Matrix4.Identity;
                    foreach (var a in pobj.Attributes)
                    {
                        switch (a.AttributeName)
                        {
                        case GXAttribName.GX_VA_PNMTXIDX:

                            var en = envelopes[v.PNMTXIDX / 3];
                            for (int w = 0; w < en.EnvelopeCount; w++)
                            {
                                var vertexWeight = new VertexWeight();
                                vertexWeight.VertexID = vIndex;
                                vertexWeight.Weight   = en.Weights[w];
                                jobjToBone[en.JOBJs[w]].VertexWeights.Add(vertexWeight);
                            }

                            if (en.EnvelopeCount == 1 && jobjToIndex[parent] == 0)
                            {
                                weight = WorldTransforms[jobjToIndex[en.JOBJs[0]]];
                            }

                            break;

                        case GXAttribName.GX_VA_POS:
                            var vert = Vector3.TransformPosition(GXTranslator.toVector3(v.POS), parentTransform);
                            vert = Vector3.TransformPosition(vert, weight);
                            vert = Vector3.TransformPosition(vert, singleBindTransform);
                            m.Vertices.Add(new Vector3D(vert.X, vert.Y, vert.Z));
                            break;

                        case GXAttribName.GX_VA_NRM:
                            var nrm = Vector3.TransformNormal(GXTranslator.toVector3(v.NRM), parentTransform);
                            nrm = Vector3.TransformNormal(nrm, weight);
                            nrm = Vector3.TransformNormal(nrm, singleBindTransform);
                            m.Normals.Add(new Vector3D(nrm.X, nrm.Y, nrm.Z));
                            break;

                        case GXAttribName.GX_VA_CLR0:
                            m.VertexColorChannels[0].Add(new Color4D(v.CLR0.R, v.CLR0.G, v.CLR0.B, v.CLR0.A));
                            break;

                        case GXAttribName.GX_VA_CLR1:
                            m.VertexColorChannels[1].Add(new Color4D(v.CLR1.R, v.CLR1.G, v.CLR1.B, v.CLR1.A));
                            break;

                        case GXAttribName.GX_VA_TEX0:
                            m.TextureCoordinateChannels[0].Add(new Vector3D(v.TEX0.X, v.TEX0.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX1:
                            m.TextureCoordinateChannels[1].Add(new Vector3D(v.TEX1.X, v.TEX1.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX2:
                            m.TextureCoordinateChannels[2].Add(new Vector3D(v.TEX2.X, v.TEX2.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX3:
                            m.TextureCoordinateChannels[3].Add(new Vector3D(v.TEX3.X, v.TEX3.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX4:
                            m.TextureCoordinateChannels[4].Add(new Vector3D(v.TEX4.X, v.TEX4.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX5:
                            m.TextureCoordinateChannels[5].Add(new Vector3D(v.TEX5.X, v.TEX5.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX6:
                            m.TextureCoordinateChannels[6].Add(new Vector3D(v.TEX6.X, v.TEX6.Y, 1));
                            break;

                        case GXAttribName.GX_VA_TEX7:
                            m.TextureCoordinateChannels[7].Add(new Vector3D(v.TEX7.X, v.TEX7.Y, 1));
                            break;
                        }
                    }
                }
            }

            return(m);
        }
Ejemplo n.º 10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="PrimitiveGroup"></param>
        /// <param name="Attributes"></param>
        /// <returns></returns>
        private static GX_Vertex[] GetDecodedVertices(GX_PrimitiveGroup PrimitiveGroup, List <GX_Attribute> Attributes, HSD_POBJ Polygon, int shapeset)
        {
            // Create Vertex List
            List <GX_Vertex> Vertices = new List <GX_Vertex>();

            // Decode
            foreach (GX_IndexGroup ig in PrimitiveGroup.Indices)
            {
                GX_Vertex Vertex = new GX_Vertex();
                for (int i = 0; i < Attributes.Count; i++)
                {
                    var attribute = Attributes[i];

                    int     index = ig.Indices[i];
                    float[] f     = new float[4];

                    // check if index is in range of buffer
                    if (attribute.AttributeType != GXAttribType.GX_DIRECT &&
                        attribute.Buffer != null &&
                        index >= attribute.Count)
                    {
                        System.Diagnostics.Debug.WriteLine($"Warning: Attribute index out of range {index} >= {attribute.Count}");
                        continue;
                    }

                    // check if data is direct
                    if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                    {
                        f = attribute.GetDecodedDataAt(index);
                    }

                    switch (attribute.AttributeName)
                    {
                    case GXAttribName.GX_VA_NULL:
                        break;

                    case GXAttribName.GX_VA_PNMTXIDX:
                        if (attribute.AttributeType == GXAttribType.GX_DIRECT)
                        {
                            Vertex.PNMTXIDX = (ushort)index;
                        }
                        break;

                    case GXAttribName.GX_VA_TEX0MTXIDX:
                        if (attribute.AttributeType == GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX0MTXIDX = (ushort)index;
                        }
                        break;

                    case GXAttribName.GX_VA_TEX1MTXIDX:
                        if (attribute.AttributeType == GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX1MTXIDX = (ushort)index;
                        }
                        break;

                    case GXAttribName.GX_VA_POS:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            if (Polygon.ShapeSet != null)
                            {
                                var ss = Polygon.ShapeSet.VertexIndices[shapeset];
                                f = attribute.GetDecodedDataAt(ss[index]);
                            }

                            if (f.Length > 0)
                            {
                                Vertex.POS.X = f[0];
                            }
                            if (f.Length > 1)
                            {
                                Vertex.POS.Y = f[1];
                            }
                            if (f.Length > 2)
                            {
                                Vertex.POS.Z = f[2];
                            }
                        }
                        break;

                    case GXAttribName.GX_VA_NRM:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            if (Polygon.ShapeSet != null)
                            {
                                var ss = Polygon.ShapeSet.NormalIndicies[shapeset];
                                f = attribute.GetDecodedDataAt(ss[index]);
                            }

                            Vertex.NRM.X = f[0];
                            Vertex.NRM.Y = f[1];
                            Vertex.NRM.Z = f[2];
                        }
                        break;

                    case GXAttribName.GX_VA_NBT:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.NRM.X   = f[0];
                            Vertex.NRM.Y   = f[1];
                            Vertex.NRM.Z   = f[2];
                            Vertex.BITAN.X = f[3];
                            Vertex.BITAN.Y = f[4];
                            Vertex.BITAN.Z = f[5];
                            Vertex.TAN.X   = f[6];
                            Vertex.TAN.Y   = f[7];
                            Vertex.TAN.Z   = f[8];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX0:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX0.X = f[0];
                            Vertex.TEX0.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX1:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX1.X = f[0];
                            Vertex.TEX1.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX2:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX2.X = f[0];
                            Vertex.TEX2.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX3:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX3.X = f[0];
                            Vertex.TEX3.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX4:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX4.X = f[0];
                            Vertex.TEX4.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX5:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX5.X = f[0];
                            Vertex.TEX5.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX6:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX6.X = f[0];
                            Vertex.TEX6.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_TEX7:
                        if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                        {
                            Vertex.TEX7.X = f[0];
                            Vertex.TEX7.Y = f[1];
                        }
                        break;

                    case GXAttribName.GX_VA_CLR0:
                        if (attribute.AttributeType == GXAttribType.GX_DIRECT)
                        {
                            Vertex.CLR0.R = ig.Clr0[0] / 255f;
                            Vertex.CLR0.G = ig.Clr0[1] / 255f;
                            Vertex.CLR0.B = ig.Clr0[2] / 255f;
                            Vertex.CLR0.A = ig.Clr0[3] / 255f;
                        }
                        else
                        {
                            Vertex.CLR0.R = f[0];
                            Vertex.CLR0.G = f[1];
                            Vertex.CLR0.B = f[2];
                            Vertex.CLR0.A = f[3];
                        }
                        break;

                    case GXAttribName.GX_VA_CLR1:
                        if (attribute.AttributeType == GXAttribType.GX_DIRECT)
                        {
                            Vertex.CLR1.R = ig.Clr1[0] / 255f;
                            Vertex.CLR1.G = ig.Clr1[1] / 255f;
                            Vertex.CLR1.B = ig.Clr1[2] / 255f;
                            Vertex.CLR1.A = ig.Clr1[3] / 255f;
                        }
                        else
                        {
                            Vertex.CLR1.R = f[0];
                            Vertex.CLR1.G = f[1];
                            Vertex.CLR1.B = f[2];
                            Vertex.CLR1.A = f[3];
                        }
                        break;

                    default:
                        Console.WriteLine("To be implemented: " + attribute.AttributeName);
                        break;
                    }
                }
                Vertices.Add(Vertex);
            }

            return(Vertices.ToArray());
        }
Ejemplo n.º 11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="triList"></param>
        /// <param name="attrGroup"></param>
        /// <param name="weights"></param>
        public HSD_POBJ CreatePOBJ(List <GXVertex> triList, HSD_AttributeGroup attrGroup, List <HSD_JOBJWeight> weights)
        {
            TriangleConverter.TriangleConverter converter = new TriangleConverter.TriangleConverter(true, 100, 3, true);
            int pointCount, faceCount;

            var groups = converter.GroupPrimitives(triList.ToArray(), out pointCount, out faceCount);

            HSD_POBJ rootPOBJ = null;
            HSD_POBJ prevPOBJ = null;

            foreach (var g in groups)
            {
                var jobjweights = new List <HSD_JOBJWeight>();
                var pmidToNewID = new Dictionary <ushort, ushort>();

                foreach (var n in g._nodes)
                {
                    pmidToNewID.Add(n, (ushort)(jobjweights.Count * 3));
                    jobjweights.Add(weights[n / 3]);
                }

                GXDisplayList newdl = new GXDisplayList();

                foreach (var t in g._triangles)
                {
                    var newVert = new List <GXVertex>();
                    for (int p = 0; p < t.Points.Count; p++)
                    {
                        var point = t.Points[p];
                        point.PMXID = pmidToNewID[point.PMXID];
                        t.Points[p] = point;
                        newVert.Add(point);
                        //Console.WriteLine(t.points[p].PMID + " " + point.PMXID + " " + pmidToNewID[point.PMXID] + " " + jobjweights.Count);
                    }

                    newdl.Primitives.Add(Compress(GXPrimitiveType.Triangles, newVert.ToArray(), attrGroup));
                }
                foreach (var t in g._tristrips)
                {
                    var newVert = new List <GXVertex>();
                    for (int p = 0; p < t.Points.Count; p++)
                    {
                        //Console.WriteLine(t.Points[p].PMXID + " " + g._nodes.Count);
                        var point = t.Points[p];
                        point.PMXID = pmidToNewID[point.PMXID];
                        t.Points[p] = point;
                        newVert.Add(point);
                    }
                    newdl.Primitives.Add(Compress(GXPrimitiveType.TriangleStrip, newVert.ToArray(), attrGroup));
                }

                HSD_PointerArray <HSD_JOBJWeight> bindWeights = new HSD_PointerArray <HSD_JOBJWeight>();
                bindWeights.Elements = jobjweights.ToArray();

                var newpobj = new HSD_POBJ();

                newpobj.Flags             = POBJ_FLAG.ENVELOPE;
                newpobj.BindGroups        = bindWeights;
                newpobj.VertexAttributes  = attrGroup;
                newpobj.DisplayListBuffer = newdl.ToBuffer(attrGroup);

                if (prevPOBJ == null)
                {
                    rootPOBJ = newpobj;
                }
                else
                {
                    prevPOBJ.Next = newpobj;
                }
                prevPOBJ = newpobj;
            }

            return(rootPOBJ);
        }