Ejemplo n.º 1
0
        // ---- METHODS (PUBLIC) -------------------------------------------------------------------------------------

        /// <summary>
        /// Creates a generic model which can be exported into a .obj file format.
        /// </summary>
        /// <returns></returns>
        public ObjModel CreateGenericModel()
        {
            ObjModel objModel = new ObjModel();

            Dictionary <string, ObjMesh> meshes = new Dictionary <string, ObjMesh>();

            bool spltByMaterial = true;

            foreach (KCLModel model in Models)
            {
                //Distinct check. Some cases prisims have a unique ID
                //Only split when they don't each have their own.
                var distinctPrisms = model.Prisms
                                     .GroupBy(p => p.CollisionFlags)
                                     .Select(g => g.First())
                                     .ToList().Count;

                if (distinctPrisms == model.Prisms.Length)
                {
                    spltByMaterial = false;
                }
            }

            var mesh = new ObjMesh($"Mesh");

            if (!spltByMaterial)
            {
                objModel.Meshes.Add(mesh);
            }

            foreach (KCLModel model in Models)
            {
                foreach (var face in model.Prisms)
                {
                    var triangle = model.GetTriangle(face);
                    var normal   = triangle.Normal;
                    if (triangle.HasNan())
                    {
                        continue;
                    }

                    ObjFace objFace = new ObjFace();
                    objFace.Material = $"COL_{face.CollisionFlags.ToString("X")}";
                    objFace.Vertices = new ObjVertex[3];
                    for (int i = 0; i < 3; i++)
                    {
                        objFace.Vertices[i] = new ObjVertex()
                        {
                            Position = triangle.Vertices[i],
                            Normal   = normal,
                        };
                    }

                    if (spltByMaterial)
                    {
                        if (!meshes.ContainsKey(objFace.Material))
                        {
                            meshes.Add(objFace.Material, new ObjMesh(objFace.Material));
                            objModel.Meshes.Add(meshes[objFace.Material]);
                        }
                        meshes[objFace.Material].Faces.Add(objFace);
                    }
                    else
                    {
                        mesh.Faces.Add(objFace);
                    }
                }
            }
            return(objModel);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Loads the object file data from the given <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
        /// <param name="leaveOpen"><c>true</c> to leave <paramref name="stream"/> open after loading the instance.
        /// </param>
        public void Load(Stream stream)
        {
            DebugLogger.WriteLine($"Loading obj file....");

            Meshes    = new List <ObjMesh>();
            Materials = new List <ObjMaterial>();

            ObjMesh currentMesh = new ObjMesh("Mesh");

            HashSet <string> faceHashes = new HashSet <string>();

            Dictionary <ObjFace, int> faceDupes = new Dictionary <ObjFace, int>();

            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                List <Vector3> Positions = new List <Vector3>();
                List <Vector2> TexCoords = new List <Vector2>();
                List <Vector3> Normals   = new List <Vector3>();

                var    enusculture     = new CultureInfo("en-US");
                string currentMaterial = null;
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();
                    line = line.Replace(",", ".");

                    // Ignore empty lines and comments.
                    if (String.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
                    {
                        continue;
                    }

                    string[] args = line.Split(_argSeparators, StringSplitOptions.RemoveEmptyEntries);
                    if (args.Length == 1)
                    {
                        continue;
                    }

                    switch (args[0])
                    {
                    case "o":
                    case "g":
                        currentMesh = new ObjMesh(args.Length > 1 ? args[1] : $"Mesh{Meshes.Count}");
                        Meshes.Add(currentMesh);
                        continue;

                    case "v":
                        Positions.Add(new Vector3(
                                          Single.Parse(args[1], enusculture),
                                          Single.Parse(args[2], enusculture),
                                          Single.Parse(args[3], enusculture)));
                        continue;

                    case "vt":
                        TexCoords.Add(new Vector2(
                                          Single.Parse(args[1], enusculture),
                                          Single.Parse(args[2], enusculture)));
                        continue;

                    case "vn":
                        Normals.Add(new Vector3(
                                        Single.Parse(args[1], enusculture),
                                        Single.Parse(args[2], enusculture),
                                        Single.Parse(args[3], enusculture)));
                        continue;

                    case "f":
                        if (args.Length != 4)
                        {
                            throw new Exception("Obj must be trianglulated!");
                        }

                        int[] indices = new int[3 * 2];     //3 faces, position and normal indices

                        // Only support triangles for now.
                        ObjFace face = new ObjFace()
                        {
                            Vertices = new ObjVertex[3]
                        };
                        face.Material = currentMaterial;
                        for (int i = 0; i < face.Vertices.Length; i++)
                        {
                            string[] vertexArgs    = args[i + 1].Split(_vertexSeparators, StringSplitOptions.None);
                            int      positionIndex = Int32.Parse(vertexArgs[0]) - 1;

                            face.Vertices[i].Position = Positions[positionIndex];

                            if (float.IsNaN(face.Vertices[i].Position.X) ||
                                float.IsNaN(face.Vertices[i].Position.Y) ||
                                float.IsNaN(face.Vertices[i].Position.Z))
                            {
                                face.Vertices = null;
                                break;
                            }

                            if (vertexArgs.Length > 1 && vertexArgs[1] != String.Empty)
                            {
                                face.Vertices[i].TexCoord = TexCoords[Int32.Parse(vertexArgs[1]) - 1];
                            }
                            if (vertexArgs.Length > 2 && vertexArgs[2] != String.Empty)
                            {
                                face.Vertices[i].Normal = Normals[Int32.Parse(vertexArgs[2]) - 1];
                            }
                        }

                        string faceStr = face.ToString();
                        if (faceHashes.Contains(faceStr))
                        {
                            continue;
                        }

                        faceHashes.Add(faceStr);

                        if (face.Vertices != null)
                        {
                            currentMesh.Faces.Add(face);
                        }
                        continue;

                    case "usemtl":
                    {
                        if (args.Length < 2)
                        {
                            continue;
                        }
                        currentMaterial = args[1];
                        continue;
                    }
                    }
                }
            }

            Console.WriteLine($"FACE COUNT {currentMesh.Faces.Count}");

            faceDupes.Clear();

            if (Meshes.Count == 0) //No object or groups present, use one single mesh
            {
                Meshes.Add(currentMesh);
            }
        }