Beispiel #1
0
        public GX_Vertex this[int i]
        {
            get
            {
                switch (i)
                {
                case 0: return(_x);

                case 1: return(_y);

                case 2: return(_z);
                }
                return(new GX_Vertex());
            }
            set
            {
                switch (i)
                {
                case 0: _x = value; break;

                case 1: _y = value; break;

                case 2: _z = value; break;
                }
            }
        }
Beispiel #2
0
 public bool Contains(GX_Vertex f)
 {
     if (_x == f)
     {
         return(true);
     }
     if (_y == f)
     {
         return(true);
     }
     if (_z == f)
     {
         return(true);
     }
     return(false);
 }
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="PrimitiveGroup"></param>
        /// <param name="Attributes"></param>
        /// <returns></returns>
        private static GX_Vertex[] GetDecodedVertices(GX_PrimitiveGroup PrimitiveGroup, GX_Attribute[] Attributes)
        {
            // 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.Length; i++)
                {
                    var attribute = Attributes[i];

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

                    if (attribute.AttributeType != GXAttribType.GX_DIRECT)
                    {
                        var values = attribute.GetDecodedDataAt(index);

                        // convert to float
                        f = new float[values.Length];
                        for (int j = 0; j < f.Length; j++)
                        {
                            f[j] = (float)values[j];
                        }
                    }

                    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 (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)
                        {
                            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_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());
        }
Beispiel #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);
            }
        }
Beispiel #5
0
 public PointTriangle(GX_Vertex x, GX_Vertex y, GX_Vertex z)
 {
     _x = x;
     _y = y;
     _z = z;
 }
Beispiel #6
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);
        }
Beispiel #7
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());
        }