Beispiel #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            IOScene scene = new IOScene();

            scene.Animations.Add(MayaAnim.ImportAnimation(filePath, new ImportSettings()));
            return(scene);
        }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        private static void ExportMTL(IOScene scene, string filePath)
        {
            using (FileStream stream = File.OpenWrite(filePath))
                using (StreamWriter w = new StreamWriter(stream))
                {
                    foreach (var mat in scene.Materials)
                    {
                        w.WriteLine($"newmtl {mat.Name}");

                        w.WriteLine(" illum 2");
                        w.WriteLine($" Ka {mat.AmbientColor.X} {mat.AmbientColor.Y} {mat.AmbientColor.Z}");
                        w.WriteLine($" Kd {mat.DiffuseColor.X} {mat.DiffuseColor.Y} {mat.DiffuseColor.Z}");
                        w.WriteLine($" Ks {mat.SpecularColor.X} {mat.SpecularColor.Y} {mat.SpecularColor.Z}");
                        w.WriteLine($" Ns {mat.Shininess}");
                        w.WriteLine($" d {mat.Alpha}");
                        w.WriteLine($" Tr {1 - mat.Alpha}");

                        if (mat.AmbientMap != null)
                        {
                            w.WriteLine($" map_Ka {mat.AmbientMap.FilePath}");
                        }
                        if (mat.DiffuseMap != null)
                        {
                            w.WriteLine($" map_Kd {mat.DiffuseMap.FilePath}");
                        }
                        if (mat.SpecularMap != null)
                        {
                            w.WriteLine($" map_Ks {mat.SpecularMap.FilePath}");
                        }
                    }
                }
        }
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            FbxHelper helper = new FbxHelper(FbxIO.ReadBinary(filePath));


            //TODO: FBX Version 2006-2010 unupported. (Anything < 7100 works. But textures aren't grabbed)
            //FBX Version 2011-2020 <-- Tested & Supported!
            //FBX Version 2011-2020 currently supported
            if (helper.Version < 7100)
            {
                throw new NotSupportedException($"FBX Version {helper.Version} not supported");
            }

            IOScene scene = new IOScene();

            IOModel model = new IOModel();

            model.Skeleton = helper.GetSkeleton();
            scene.Models.Add(model);

            model.Meshes.AddRange(helper.ExtractMesh());

            scene.Materials.AddRange(helper.GetMaterials());

            return(scene);
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        public void ExportScene(IOScene scene, string filePath, ExportSettings settings)
        {
            // create collada document
            _collada  = new IONET.Collada.Collada();
            _settings = settings;

            _collada.Version = "1.4.1";


            // export materials
            foreach (var mat in scene.Materials)
            {
                ProcessMaterial(mat);
            }


            // initialize scene
            var visscene = new Visual_Scene
            {
                Name = scene.Name
            };

            visscene.ID = scene.Name;


            // export models nodes
            List <Node> nodes = new List <Node>();

            foreach (var mod in scene.Models)
            {
                nodes.AddRange(ProcessModel(mod));
            }
            visscene.Node = nodes.ToArray();


            // instance the scene
            var scene_instance = new Instance_Visual_Scene();

            scene_instance.URL = "#" + visscene.Name;

            _collada.Library_Visual_Scene = new Library_Visual_Scenes();
            _collada.Library_Visual_Scene.Visual_Scene = new Visual_Scene[] { visscene };

            _collada.Scene = new Scene();
            _collada.Scene.Visual_Scene = scene_instance;


            // initialize asset
            InitAsset();


            // save to file
            _collada.SaveToFile(filePath);

            // cleanup
            _usedIDs.Clear();
            _collada = null;
        }
Beispiel #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public void ExportScene(IOScene scene, string filePath, ExportSettings settings)
        {
            if (scene.Models.Count == 0)
            {
                throw new Exception($"Failed to export animation! Model must have a skeleton to export!");
            }

            MayaAnim.ExportAnimation(filePath, settings,
                                     scene.Animations[0],
                                     scene.Models[0].Skeleton);
        }
Beispiel #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="iomodel"></param>
        public override void FromIOModel(IOScene iomodel)
        {
            var model = iomodel.Models[0];

            InvertSingleBinds(model);

            // dobjs to import to
            var dobjs = GetMeshObjects();

            // clear pobjs
            foreach (SBHsdMesh m in GetMeshObjects())
            {
                m.DOBJ.Pobj = null;
            }

            var attributeGroup       = MakeRiggedAttributes();
            var singleAttributeGroup = MakeSingleAttributes();

            // get a compressor ready
            // the compressor will handle making the compressed attribute buffers
            POBJ_Generator compressor = new POBJ_Generator();

            // import the iomeshes into their respective dobjs
            foreach (var iomesh in model.Meshes)
            {
                int dobjId = -1;
                int.TryParse(iomesh.Name.Replace("DOBJ_", ""), out dobjId);

                SBConsole.WriteLine(iomesh.Name + " imported:" + (dobjId != -1));

                if (dobjId != -1)
                {
                    var dobj = (SBHsdMesh)dobjs[dobjId];
                    dobj.ImportPOBJs(iomesh, (SBSkeleton)Skeleton, compressor, dobj.ParentBone == "JOBJ_0" ? attributeGroup : singleAttributeGroup);
                }
            }

            // finalizes and remakes the buffer
            compressor.SaveChanges();

            // refresh everything
            RefreshRendering();
        }
Beispiel #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            // generate a new scene
            IOScene scene = new IOScene();


            // load collada file
            _collada = Collada.LoadFromFile(filePath);

            // failed to load collada file
            if (_collada == null)
            {
                return(scene);
            }

            // load material library's to scene
            if (_collada.Library_Materials != null)
            {
                foreach (var mat in _collada.Library_Materials.Material)
                {
                    scene.Materials.Add(LoadMaterial(mat));
                }
            }


            // look through all visual scene
            foreach (var colscene in _collada.Library_Visual_Scene.Visual_Scene)
            {
                // treat each scene as a "model"
                IOModel model = new IOModel()
                {
                    Name = colscene.Name
                };

                // scan skeletons
                List <string> skelIDs = new List <string>();
                foreach (var v in colscene.Node)
                {
                    if (GetSkeletonReferences(v, out List <string> joints))
                    {
                        foreach (var j in joints)
                        {
                            if (!skelIDs.Contains(j))
                            {
                                skelIDs.Add(j);
                            }
                        }
                    }
                }

                // load nodes
                foreach (var v in colscene.Node)
                {
                    LoadNodes(v, null, model, skelIDs);
                }

                // add model
                scene.Models.Add(model);
            }


            // cleanup
            _collada = null;


            // done
            return(scene);
        }
Beispiel #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        public void ExportScene(IOScene scene, string filePath, ExportSettings settings)
        {
            if (scene.Models.Count == 0)
            {
                return;
            }

            using (FileStream stream = new FileStream(filePath, FileMode.Create))
                using (StreamWriter w = new StreamWriter(stream))
                {
                    var model = scene.Models[0];

                    w.WriteLine("version 1");


                    var bones = model.Skeleton.BreathFirstOrder();

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

                    w.WriteLine("nodes");
                    var index = 0;
                    foreach (var b in bones)
                    {
                        nodeToID.Add(b.Name, index);
                        w.WriteLine($"{index++} \"{b.Name}\" {model.Skeleton.IndexOf(b.Parent)}");
                    }
                    foreach (var b in model.Meshes)
                    {
                        nodeToID.Add(b.Name, index);
                        w.WriteLine($"{index++} \"{b.Name}\" {-1}");
                    }
                    w.WriteLine("end");


                    w.WriteLine("skeleton");

                    w.WriteLine("time 0");
                    index = 0;
                    foreach (var b in bones)
                    {
                        // since we can't store scale we have to improvise and extract the world scale
                        Matrix4x4.Decompose(b.WorldTransform, out Vector3 uniformScale, out Quaternion rot, out Vector3 pos);
                        w.WriteLine($"{index++} {b.TranslationX * uniformScale.X} {b.TranslationY * uniformScale.Y} {b.TranslationZ * uniformScale.Z} {b.RotationEuler.X} {b.RotationEuler.Y} {b.RotationEuler.Z}");
                    }

                    foreach (var b in model.Meshes)
                    {
                        w.WriteLine($"{index++} 0 0 0 0 0 0");
                    }

                    w.WriteLine("end");


                    if (model.Meshes.Count > 0)
                    {
                        w.WriteLine("triangles");

                        foreach (var m in model.Meshes)
                        {
                            // smd only supports triangles
                            m.MakeTriangles();

                            // look though all poly groups
                            for (int p = 0; p < m.Polygons.Count; p++)
                            {
                                var poly = m.Polygons[p];
                                for (int i = 0; i < poly.Indicies.Count; i += 3)
                                {
                                    if (string.IsNullOrEmpty(poly.MaterialName))
                                    {
                                        w.WriteLine($"{m.Name}_poly_{p}");
                                    }
                                    else
                                    {
                                        w.WriteLine($"{poly.MaterialName}");
                                    }

                                    {
                                        var v1  = m.Vertices[poly.Indicies[i]];
                                        var env = v1.Envelope;
                                        w.WriteLine($"{nodeToID[m.Name]} {v1.Position.X} {v1.Position.Y} {v1.Position.Z} {v1.Normal.X} {v1.Normal.Y} {v1.Normal.Z} {(v1.UVs.Count > 0 ? v1.UVs[0].X : 0)} {(v1.UVs.Count > 0 ? v1.UVs[0].Y : 0)} {env.Weights.Count + " " + string.Join(" ", env.Weights.Select(e => nodeToID[e.BoneName] + " " + e.Weight))}");
                                    }
                                    {
                                        var v1  = m.Vertices[poly.Indicies[i + 1]];
                                        var env = v1.Envelope;
                                        w.WriteLine($"{nodeToID[m.Name]} {v1.Position.X} {v1.Position.Y} {v1.Position.Z} {v1.Normal.X} {v1.Normal.Y} {v1.Normal.Z} {(v1.UVs.Count > 0 ? v1.UVs[0].X : 0)} {(v1.UVs.Count > 0 ? v1.UVs[0].Y : 0)} {env.Weights.Count + " " + string.Join(" ", env.Weights.Select(e => nodeToID[e.BoneName] + " " + e.Weight))}");
                                    }
                                    {
                                        var v1  = m.Vertices[poly.Indicies[i + 2]];
                                        var env = v1.Envelope;
                                        w.WriteLine($"{nodeToID[m.Name]} {v1.Position.X} {v1.Position.Y} {v1.Position.Z} {v1.Normal.X} {v1.Normal.Y} {v1.Normal.Z} {(v1.UVs.Count > 0 ? v1.UVs[0].X : 0)} {(v1.UVs.Count > 0 ? v1.UVs[0].Y : 0)} {env.Weights.Count + " " + string.Join(" ", env.Weights.Select(e => nodeToID[e.BoneName] + " " + e.Weight))}");
                                    }
                                }
                            }
                        }

                        w.WriteLine("end");
                    }
                }
        }
Beispiel #9
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 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            IOScene scene = new IOScene();

            IOModel model = new IOModel();

            scene.Models.Add(model);

            using (FileStream stream = new FileStream(filePath, FileMode.Open))
                using (StreamReader r = new StreamReader(stream))
                {
                    Dictionary <string, IOMesh> nameToMesh  = new Dictionary <string, IOMesh>();
                    HashSet <IOBone>            meshBones   = new HashSet <IOBone>();
                    Dictionary <int, IOBone>    idxToBone   = new Dictionary <int, IOBone>();
                    Dictionary <int, int>       idxToParent = new Dictionary <int, int>();

                    string mode = "";
                    int    time = 0;

                    while (!r.EndOfStream)
                    {
                        // read and clean line args
                        var line = r.ReadLine().Trim();
                        var args = Regex.Replace(line, @"\s+", " ").Split(' ');

                        // check for grouping
                        switch (args[0])
                        {
                        case "nodes":
                        case "skeleton":
                        case "triangles":
                        case "end":
                            mode = args[0];
                            break;
                        }

                        switch (mode)
                        {
                        case "nodes":
                            if (args.Length >= 3)
                            {
                                args = line.Split('"');

                                var index       = int.Parse(args[0].Trim());
                                var name        = args[1];
                                var parentIndex = int.Parse(args[2].Trim());

                                IOBone bone = new IOBone()
                                {
                                    Name = name
                                };

                                idxToBone.Add(index, bone);
                                idxToParent.Add(index, parentIndex);
                            }
                            break;

                        case "skeleton":
                            if (args.Length == 2 && args[0] == "time")
                            {
                                int.TryParse(args[1], out time);
                            }
                            if (args.Length == 7)
                            {
                                var index = int.Parse(args[0]);

                                if (time == 0)
                                {
                                    idxToBone[index].Translation   = new System.Numerics.Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]));
                                    idxToBone[index].RotationEuler = new System.Numerics.Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6]));
                                }
                            }
                            break;

                        case "triangles":
                        {
                            if (args.Length > 0 && args.Length < 9 && args[0] != "triangles")
                            {
                                var material = string.Join(" ", args);

                                var v1 = ParseVertex(r.ReadLine(), idxToBone, out IOBone parent);
                                var v2 = ParseVertex(r.ReadLine(), idxToBone, out parent);
                                var v3 = ParseVertex(r.ReadLine(), idxToBone, out parent);

                                var meshName = parent.Name + material;

                                if (!meshBones.Contains(parent))
                                {
                                    meshBones.Add(parent);
                                }

                                meshName = Regex.Replace(meshName.Trim(), @"\s+", "_").Replace("#", "");

                                if (!nameToMesh.ContainsKey(meshName))
                                {
                                    // create and load material
                                    IOMaterial mat = new IOMaterial()
                                    {
                                        Name = material
                                    };
                                    scene.Materials.Add(mat);

                                    // create io mesh
                                    var iomesh = new IOMesh()
                                    {
                                        Name = meshName
                                    };

                                    // create triangle polygon
                                    iomesh.Polygons.Add(new IOPolygon()
                                        {
                                            MaterialName  = material,
                                            PrimitiveType = IOPrimitive.TRIANGLE
                                        });

                                    nameToMesh.Add(meshName, iomesh);
                                }

                                var mesh = nameToMesh[meshName];
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count);
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count + 1);
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count + 2);
                                mesh.Vertices.Add(v1);
                                mesh.Vertices.Add(v2);
                                mesh.Vertices.Add(v3);
                            }
                        }
                        break;
                        }
                    }

                    // create skeleton hierarchy
                    foreach (var bone in idxToBone)
                    {
                        var parent = idxToParent[bone.Key];

                        if (parent == -1)
                        {
                            if (meshBones.Count > 1 && meshBones.Contains(bone.Value))
                            {
                                continue;
                            }
                            else
                            {
                                model.Skeleton.RootBones.Add(bone.Value);
                            }
                        }
                        else
                        {
                            idxToBone[parent].AddChild(bone.Value);
                        }
                    }

                    // dump mesh
                    model.Meshes.AddRange(nameToMesh.Values);
                }

            return(scene);
        }
Beispiel #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        public void ExportScene(IOScene scene, string filePath, ExportSettings settings)
        {
            var matLib = filePath.Replace(".obj", ".mtl");

            // sanatize material names
            scene.CleanMaterialNames();
            ExportMTL(scene, matLib);

            using (FileStream stream = new FileStream(filePath, FileMode.Create))
                using (StreamWriter w = new StreamWriter(stream))
                {
                    w.WriteLine($"mtllib {Path.GetFileName(matLib)}");

                    Dictionary <string, int> v_strToIndex  = new Dictionary <string, int>();
                    Dictionary <string, int> vt_strToIndex = new Dictionary <string, int>();
                    Dictionary <string, int> vn_strToIndex = new Dictionary <string, int>();

                    foreach (var mod in scene.Models)
                    {
                        foreach (var mesh in mod.Meshes)
                        {
                            // make mesh triangles
                            mesh.MakeTriangles();

                            //
                            Dictionary <int, int> vmap  = new Dictionary <int, int>();
                            Dictionary <int, int> vtmap = new Dictionary <int, int>();
                            Dictionary <int, int> vnmap = new Dictionary <int, int>();

                            // add vertices
                            for (int i = 0; i < mesh.Vertices.Count; i++)
                            {
                                var v = mesh.Vertices[i];

                                // positions
                                var vv = $"v {v.Position.X} {v.Position.Y} {v.Position.Z}";
                                if (!v_strToIndex.ContainsKey(vv))
                                {
                                    v_strToIndex.Add(vv, v_strToIndex.Count);
                                    w.WriteLine(vv);
                                }
                                vmap.Add(i, v_strToIndex[vv] + 1);

                                // uvs
                                if (v.UVs.Count > 0)
                                {
                                    var vtv = $"vt {v.UVs[0].X} {v.UVs[0].Y}";

                                    if (!vt_strToIndex.ContainsKey(vtv))
                                    {
                                        vt_strToIndex.Add(vtv, vt_strToIndex.Count);
                                        w.WriteLine(vtv);
                                    }
                                    vtmap.Add(i, vt_strToIndex[vtv] + 1);
                                }

                                // normals
                                var vnv = $"vn {v.Normal.X} {v.Normal.Y} {v.Normal.Z}";
                                if (!vn_strToIndex.ContainsKey(vnv))
                                {
                                    vn_strToIndex.Add(vnv, vn_strToIndex.Count);
                                    w.WriteLine(vnv);
                                }
                                vnmap.Add(i, vn_strToIndex[vnv] + 1);
                            }

                            // add polygons
                            w.WriteLine($"o {mesh.Name}");
                            foreach (var poly in mesh.Polygons)
                            {
                                w.WriteLine($"g polygon_{mesh.Polygons.IndexOf(poly)}");

                                w.WriteLine($"usemtl {poly.MaterialName}");

                                for (int i = 0; i < poly.Indicies.Count; i += 3)
                                {
                                    w.WriteLine(
                                        $"f {vmap[poly.Indicies[i]]}/{(vtmap.ContainsKey(poly.Indicies[i]) ? vtmap[poly.Indicies[i]].ToString() : "")}/{vnmap[poly.Indicies[i]]} " +
                                        $"{vmap[poly.Indicies[i + 1]]}/{(vtmap.ContainsKey(poly.Indicies[i + 1]) ? vtmap[poly.Indicies[i + 1]].ToString() : "")}/{vnmap[poly.Indicies[i + 1]]} " +
                                        $"{vmap[poly.Indicies[i + 2]]}/{(vtmap.ContainsKey(poly.Indicies[i + 2]) ? vtmap[poly.Indicies[i + 2]].ToString() : "")}/{vnmap[poly.Indicies[i + 2]]}");
                                }
                            }
                        }
                    }
                }
        }
Beispiel #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        public static void ExportScene(IOScene scene, string filePath, ExportSettings settings = null)
        {
            var ext = Path.GetExtension(filePath).ToLower();

            if (settings == null)
            {
                settings = new ExportSettings();
            }

            foreach (var l in SceneExporters)
            {
                foreach (var e in l.GetExtensions())
                {
                    if (e.Equals(ext))
                    {
                        // apply post processing
                        foreach (var model in scene.Models)
                        {
                            // smooth normals
                            if (settings.SmoothNormals)
                            {
                                model.SmoothNormals();
                            }

                            // post process mesh
                            foreach (var m in model.Meshes)
                            {
                                // optimize vertices
                                if (settings.Optimize)
                                {
                                    m.Optimize();
                                }

                                // vertex modifications
                                if (settings.FlipUVs)
                                {
                                    foreach (var v in m.Vertices)
                                    {
                                        // flip uvs
                                        if (settings.FlipUVs)
                                        {
                                            for (int i = 0; i < v.UVs.Count; i++)
                                            {
                                                v.UVs[i] = new System.Numerics.Vector2(v.UVs[i].X, 1 - v.UVs[i].Y);
                                            }
                                        }
                                    }
                                }

                                // flip winding order
                                if (settings.FlipWindingOrder)
                                {
                                    foreach (var p in m.Polygons)
                                    {
                                        p.ToTriangles(m);

                                        if (p.PrimitiveType == Core.Model.IOPrimitive.TRIANGLE)
                                        {
                                            for (int i = 0; i < p.Indicies.Count; i += 3)
                                            {
                                                var temp = p.Indicies[i + 1];
                                                p.Indicies[i + 1] = p.Indicies[i + 2];
                                                p.Indicies[i + 2] = temp;
                                            }
                                        }
                                    }
                                }

                                // reset envelopes
                                foreach (var v in m.Vertices)
                                {
                                    v.ResetEnvelope(model.Skeleton);
                                }
                            }
                        }

                        l.ExportScene(scene, filePath, settings);
                        break;
                    }
                }
            }
        }
Beispiel #13
0
        public override IOScene GetIOModel()
        {
            IOScene scene = new IOScene();

            IOModel iomodel = new IOModel();

            scene.Models.Add(iomodel);

            iomodel.Skeleton = ((SBSkeleton)Skeleton).ToIOSkeleton();

            // bone indices
            List <SBHsdBone> bones = new List <SBHsdBone>();

            foreach (SBHsdBone bone in Skeleton.Bones)
            {
                bones.Add(bone);
            }


            // gather textures
            Dictionary <HSDStruct, string> tobjToName = new Dictionary <HSDStruct, string>();

            List <SBSurface> textures = new List <SBSurface>();

            foreach (var tex in tobjToSurface)
            {
                tex.Value.Name = $"TOBJ_{textures.Count}";
                tobjToName.Add(tex.Key, tex.Value.Name);
                textures.Add(tex.Value);
            }


            // process mesh
            foreach (SBHsdMesh me in GetMeshObjects())
            {
                var dobj = me.DOBJ;

                var parent = Skeleton.Bones[0];
                foreach (var b in Skeleton.Bones)
                {
                    if (b is SBHsdBone bone)
                    {
                        if (bone.GetJOBJ().Dobj != null)
                        {
                            if (bone.GetJOBJ().Dobj.List.Contains(dobj))
                            {
                                parent = b;
                                break;
                            }
                        }
                    }
                }

                var iomesh = new IOMesh();
                iomesh.Name = me.Name;
                iomodel.Meshes.Add(iomesh);
                IOPolygon poly = new IOPolygon();
                iomesh.Polygons.Add(poly);

                if (dobj.Pobj != null)
                {
                    foreach (var pobj in dobj.Pobj.List)
                    {
                        var dl       = pobj.ToDisplayList();
                        var vertices = GX_VertexAccessor.GetDecodedVertices(dl, pobj);

                        HSD_Envelope[] bindGroups = null;;
                        if (pobj.EnvelopeWeights != null)
                        {
                            bindGroups = pobj.EnvelopeWeights;
                        }

                        var offset = 0;
                        foreach (var v in dl.Primitives)
                        {
                            List <GX_Vertex> strip = new List <GX_Vertex>();
                            for (int i = 0; i < v.Count; i++)
                            {
                                strip.Add(vertices[offset + i]);
                            }
                            offset += v.Count;
                            iomesh.Vertices.AddRange(ConvertGXDLtoTriangleList(v.PrimitiveType, SBHsdMesh.GXVertexToHsdVertex(strip, bones, bindGroups), (SBHsdBone)parent));
                        }
                    }
                }


                // flip faces
                for (int i = 0; i < iomesh.Vertices.Count; i += 3)
                {
                    if (i + 2 < iomesh.Vertices.Count)
                    {
                        poly.Indicies.Add(i + 2);
                        poly.Indicies.Add(i + 1);
                        poly.Indicies.Add(i);
                    }
                    else
                    {
                        break;
                    }
                }

                poly.MaterialName = iomesh.Name + "_material";


                // create material
                IOMaterial mat = new IOMaterial();

                mat.Name = iomesh.Name + "_material";
                if (dobj.Mobj.Material != null)
                {
                    mat.DiffuseColor = new System.Numerics.Vector4(
                        dobj.Mobj.Material.DiffuseColor.R / 255f,
                        dobj.Mobj.Material.DiffuseColor.G / 255f,
                        dobj.Mobj.Material.DiffuseColor.B / 255f,
                        dobj.Mobj.Material.DiffuseColor.A / 255f);
                    mat.SpecularColor = new System.Numerics.Vector4(
                        dobj.Mobj.Material.SpecularColor.R / 255f,
                        dobj.Mobj.Material.SpecularColor.G / 255f,
                        dobj.Mobj.Material.SpecularColor.B / 255f,
                        dobj.Mobj.Material.SpecularColor.A / 255f);
                    mat.AmbientColor = new System.Numerics.Vector4(
                        dobj.Mobj.Material.AmbientColor.R / 255f,
                        dobj.Mobj.Material.AmbientColor.G / 255f,
                        dobj.Mobj.Material.AmbientColor.B / 255f,
                        dobj.Mobj.Material.AmbientColor.A / 255f);
                    mat.Alpha     = dobj.Mobj.Material.Alpha;
                    mat.Shininess = dobj.Mobj.Material.Shininess;
                }

                if (dobj.Mobj.Textures != null)
                {
                    mat.DiffuseMap = new IOTexture()
                    {
                        Name     = tobjToName[dobj.Mobj.Textures._s],
                        FilePath = tobjToName[dobj.Mobj.Textures._s]
                    }
                }
                ;
                scene.Materials.Add(mat);
            }

            return(scene);
        }
Beispiel #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            // create scene and model
            IOScene scene = new IOScene();

            // load materials
            var mtlFile = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".mtl");

            if (File.Exists(mtlFile))
            {
                LoadMaterialLibrary(scene, mtlFile);
            }

            // parse obj file
            using (FileStream stream = new FileStream(filePath, FileMode.Open))
                using (StreamReader r = new StreamReader(stream))
                {
                    List <Vector3> v  = new List <Vector3>();
                    List <Vector2> vt = new List <Vector2>();
                    List <Vector3> vn = new List <Vector3>();

                    List <Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > > > objects = new List <Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > > >();

                    var objName = "Mesh";
                    var matNam  = "";
                    Dictionary <IOPrimitive, List <int[]> > polygons = new Dictionary <IOPrimitive, List <int[]> >();

                    while (!r.EndOfStream)
                    {
                        var args = Regex.Replace(r.ReadLine().Trim(), @"\s+", " ").Split(' ');

                        if (args.Length > 0)
                        {
                            switch (args[0])
                            {
                            case "v":
                                v.Add(new Vector3(
                                          args.Length > 1 ? float.Parse(args[1]) : 0,
                                          args.Length > 2 ? float.Parse(args[2]) : 0,
                                          args.Length > 3 ? float.Parse(args[3]) : 0));
                                break;

                            case "vt":
                                vt.Add(new Vector2(
                                           args.Length > 1 ? float.Parse(args[1]) : 0,
                                           args.Length > 2 ? float.Parse(args[2]) : 0));
                                break;

                            case "vn":
                                vn.Add(new Vector3(
                                           args.Length > 1 ? float.Parse(args[1]) : 0,
                                           args.Length > 2 ? float.Parse(args[2]) : 0,
                                           args.Length > 3 ? float.Parse(args[3]) : 0));
                                break;

                            case "f":
                                var faces = ParseFaces(args);

                                if (args.Length == 2)
                                {
                                    // point
                                    if (!polygons.ContainsKey(IOPrimitive.POINT))
                                    {
                                        polygons.Add(IOPrimitive.POINT, new List <int[]>());
                                    }
                                    polygons[IOPrimitive.POINT].AddRange(faces);
                                }
                                if (args.Length == 3)
                                {
                                    // line
                                    if (!polygons.ContainsKey(IOPrimitive.LINE))
                                    {
                                        polygons.Add(IOPrimitive.LINE, new List <int[]>());
                                    }
                                    polygons[IOPrimitive.LINE].AddRange(faces);
                                }
                                if (args.Length == 4)
                                {
                                    // triangle
                                    if (!polygons.ContainsKey(IOPrimitive.TRIANGLE))
                                    {
                                        polygons.Add(IOPrimitive.TRIANGLE, new List <int[]>());
                                    }
                                    polygons[IOPrimitive.TRIANGLE].AddRange(faces);
                                }
                                if (args.Length == 5)
                                {
                                    // quad
                                    if (!polygons.ContainsKey(IOPrimitive.QUAD))
                                    {
                                        polygons.Add(IOPrimitive.QUAD, new List <int[]>());
                                    }
                                    polygons[IOPrimitive.QUAD].AddRange(faces);
                                }
                                if (args.Length == 6)
                                {
                                    // strip
                                    if (!polygons.ContainsKey(IOPrimitive.TRISTRIP))
                                    {
                                        polygons.Add(IOPrimitive.TRISTRIP, new List <int[]>());
                                    }
                                    polygons[IOPrimitive.TRISTRIP].AddRange(faces);
                                }
                                break;

                            case "o":
                                if (polygons.Count > 0)
                                {
                                    objects.Add(new Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > >(objName, matNam, polygons));
                                }
                                objName  = args[1];
                                matNam   = "";
                                polygons = new Dictionary <IOPrimitive, List <int[]> >();
                                break;

                            case "usemtl":
                                matNam = args[1];
                                break;
                            }
                        }
                    }

                    objects.Add(new Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > >(objName, matNam, polygons));

                    // generate model
                    IOModel model = new IOModel();
                    scene.Models.Add(model);

                    // dummy bone
                    model.Skeleton.RootBones.Add(new Core.Skeleton.IOBone()
                    {
                        Name = "Root"
                    });

                    // convert and add polygons
                    foreach (var obj in objects)
                    {
                        IOMesh mesh = new IOMesh()
                        {
                            Name = obj.Item1
                        };

                        foreach (var p in obj.Item3)
                        {
                            IOPolygon poly = new IOPolygon()
                            {
                                PrimitiveType = p.Key,
                                MaterialName  = obj.Item2,
                            };

                            for (int i = 0; i < p.Value.Count; i++)
                            {
                                var face = p.Value[i];

                                IOVertex vert = new IOVertex()
                                {
                                    Position = face[0] != -1 ? v[face[0]] : Vector3.Zero,
                                    Normal   = face[2] != -1 ? vn[face[2]] : Vector3.Zero,
                                };
                                if (face[1] != -1)
                                {
                                    vert.UVs.Add(vt[face[1]]);
                                }

                                poly.Indicies.Add(mesh.Vertices.Count);
                                mesh.Vertices.Add(vert);
                            }

                            mesh.Polygons.Add(poly);
                        }

                        // add mesh to model
                        model.Meshes.Add(mesh);
                    }
                    ;
                }

            return(scene);
        }
Beispiel #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="filePath"></param>
        private void LoadMaterialLibrary(IOScene scene, string filePath)
        {
            using (FileStream stream = new FileStream(filePath, FileMode.Open))
                using (StreamReader r = new StreamReader(stream))
                {
                    IOMaterial currentMaterial = new IOMaterial();

                    while (!r.EndOfStream)
                    {
                        var args = Regex.Replace(r.ReadLine().Trim(), @"\s+", " ").Split(' ');

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

                        switch (args[0])
                        {
                        case "newmtl":
                            currentMaterial = new IOMaterial()
                            {
                                Name = args[1]
                            };
                            scene.Materials.Add(currentMaterial);
                            break;

                        case "Ka":
                            currentMaterial.AmbientColor = new Vector4(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]), 1);
                            break;

                        case "Kd":
                            currentMaterial.DiffuseColor = new Vector4(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]), 1);
                            break;

                        case "Ks":
                            currentMaterial.SpecularColor = new Vector4(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]), 1);
                            break;

                        case "Ns":
                            currentMaterial.Shininess = float.Parse(args[1]);
                            break;

                        case "d":
                            currentMaterial.Alpha = float.Parse(args[1]);
                            break;

                        case "Tr":
                            currentMaterial.Alpha = 1 - float.Parse(args[1]);
                            break;

                        case "map_Ka":
                            currentMaterial.AmbientMap = new IOTexture()
                            {
                                Name     = currentMaterial.Name + "_texture",
                                FilePath = string.Join(" ", args, 1, args.Length - 1)
                            };
                            break;

                        case "map_Kd":
                            currentMaterial.DiffuseMap = new IOTexture()
                            {
                                Name     = currentMaterial.Name + "_texture",
                                FilePath = string.Join(" ", args, 1, args.Length - 1)
                            };
                            break;

                        case "map_Ks":
                            currentMaterial.SpecularMap = new IOTexture()
                            {
                                Name     = currentMaterial.Name + "_texture",
                                FilePath = string.Join(" ", args, 1, args.Length - 1)
                            };
                            break;
                        }
                    }
                }
        }
Beispiel #16
0
 /// <summary>
 /// Imports an IO model into the scene
 /// </summary>
 /// <param name="iomodel"></param>
 public virtual void FromIOModel(IOScene iomodel)
 {
 }