Exemplo n.º 1
0
        public void CompactFaceGroups()
        {
            var groups = new List <ObjFaceGroup>(this.FaceGroups.Count);

            foreach (var faceGroup in this.FaceGroups)
            {
                ObjFaceGroup index = null;

                foreach (var group in groups)
                {
                    if (group.MaterialName == faceGroup.MaterialName)
                    {
                        index = group;
                        break;
                    }
                }

                if (index == null)
                {
                    groups.Add(faceGroup);
                }
                else
                {
                    foreach (var face in faceGroup.Faces)
                    {
                        index.Faces.Add(face);
                    }
                }
            }

            groups.TrimExcess();
            this.FaceGroups = groups;
        }
Exemplo n.º 2
0
        public void SplitFaceGroups()
        {
            this.CompactFaceGroups();

            Func <ObjIndex, int[]> indices = index =>
                                             index.D < 0 ?
                                             new[] { index.A, index.B, index.C } :
            new[] { index.A, index.B, index.C, index.D };

            var faceGroups = new List <ObjFaceGroup>();

            foreach (var faceGroup in this.FaceGroups)
            {
                var groups = new List <ObjFaceGroup>();

                foreach (var face in faceGroup.Faces)
                {
                    var faceIndices = indices(face.VerticesIndex);

                    var group = groups
                                .Where(g => g.Faces.SelectMany(t => indices(t.VerticesIndex)).Any(t => faceIndices.Contains(t)))
                                .FirstOrDefault();

                    if (group != null)
                    {
                        group.Faces.Add(face);
                    }
                    else
                    {
                        group = new ObjFaceGroup();
                        group.MaterialName = faceGroup.MaterialName;
                        group.Faces.Add(face);
                        groups.Add(group);
                    }
                }

                faceGroups.AddRange(groups);
            }

            this.FaceGroups = faceGroups;
        }
Exemplo n.º 3
0
        public static ObjFile FromFile(string fileName)
        {
            ObjFile obj = new ObjFile();

            obj.FileName = fileName;

            using (StreamReader file = new StreamReader(fileName))
            {
                string line;

                string materialName = null;

                ObjMesh mesh = new ObjMesh("unnamed");
                obj.Meshes.Add(mesh);

                ObjFaceGroup faceGroup = new ObjFaceGroup();
                mesh.FaceGroups.Add(faceGroup);

                while ((line = file.ReadLine()) != null)
                {
                    if (string.IsNullOrWhiteSpace(line))
                    {
                        continue;
                    }

                    line = line.Trim();

                    if (line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    string[] values = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                    switch (values[0].ToUpperInvariant())
                    {
                    case "MTLLIB":
                        if (values.Length != 2)
                        {
                            throw new InvalidDataException("missing mtllib name");
                        }

                        if (obj.Materials.Count > 0)
                        {
                            throw new InvalidDataException("multiple mtllib");
                        }

                        obj.Materials = ObjMaterialDictionary.FromFile(Path.Combine(Path.GetDirectoryName(fileName), values[1]));
                        break;

                    case "V":
                        if (values.Length < 4)
                        {
                            throw new InvalidDataException("v must be x y z");
                        }

                        obj.Vertices.Add(new ObjVector3(
                                             float.Parse(values[1], CultureInfo.InvariantCulture),
                                             float.Parse(values[2], CultureInfo.InvariantCulture),
                                             float.Parse(values[3], CultureInfo.InvariantCulture)));
                        break;

                    case "VT":
                        if (values.Length < 3)
                        {
                            throw new InvalidDataException("vt must be u v");
                        }

                        obj.VertexTexCoords.Add(new ObjVector2(
                                                    float.Parse(values[1], CultureInfo.InvariantCulture),
                                                    float.Parse(values[2], CultureInfo.InvariantCulture)));
                        break;

                    case "VN":
                        if (values.Length < 4)
                        {
                            throw new InvalidDataException("vn must be x y z");
                        }

                        obj.VertexNormals.Add(new ObjVector3(
                                                  float.Parse(values[1], CultureInfo.InvariantCulture),
                                                  float.Parse(values[2], CultureInfo.InvariantCulture),
                                                  float.Parse(values[3], CultureInfo.InvariantCulture)));
                        break;

                    case "O":
                    case "G":
                        if (values.Length < 2)
                        {
                            throw new InvalidDataException("missing object name");
                        }

                        if (faceGroup.Faces.Count == 0)
                        {
                            mesh.Name = values[1];
                        }
                        else
                        {
                            mesh = new ObjMesh(values[1]);
                            obj.Meshes.Add(mesh);

                            faceGroup = new ObjFaceGroup();
                            faceGroup.MaterialName = materialName;
                            mesh.FaceGroups.Add(faceGroup);
                        }
                        break;

                    case "USEMTL":
                        if (values.Length != 2)
                        {
                            throw new InvalidDataException("missing material name");
                        }

                        materialName = values[1];

                        if (faceGroup.Faces.Count == 0)
                        {
                            faceGroup.MaterialName = materialName;
                        }
                        else
                        {
                            faceGroup = new ObjFaceGroup();
                            faceGroup.MaterialName = materialName;
                            mesh.FaceGroups.Add(faceGroup);
                        }
                        break;

                    case "F":
                        if (values.Length == 4)
                        {
                            var v1 = ParseFaceVertex(values[1]);
                            var v2 = ParseFaceVertex(values[2]);
                            var v3 = ParseFaceVertex(values[3]);

                            var face = new ObjFace();
                            face.VerticesIndex        = new ObjIndex(v1.Item1, v2.Item1, v3.Item1);
                            face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2);
                            face.VertexNormalsIndex   = new ObjIndex(v1.Item3, v2.Item3, v3.Item3);

                            faceGroup.Faces.Add(face);
                        }
                        else if (values.Length == 5)
                        {
                            var v1 = ParseFaceVertex(values[1]);
                            var v2 = ParseFaceVertex(values[2]);
                            var v3 = ParseFaceVertex(values[3]);
                            var v4 = ParseFaceVertex(values[4]);

                            var face = new ObjFace();
                            face.VerticesIndex        = new ObjIndex(v1.Item1, v2.Item1, v3.Item1, v4.Item1);
                            face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2, v4.Item2);
                            face.VertexNormalsIndex   = new ObjIndex(v1.Item3, v2.Item3, v3.Item3, v4.Item3);

                            faceGroup.Faces.Add(face);
                        }
                        else
                        {
                            throw new InvalidDataException("invalid face");
                        }
                        break;
                    }
                }
            }

            return(obj);
        }
Exemplo n.º 4
0
        public static void OptToObj(OptFile opt, string objPath, bool scale)
        {
            if (opt == null)
            {
                throw new ArgumentNullException("opt");
            }

            string objDirectory = Path.GetDirectoryName(objPath);
            string objName = Path.GetFileNameWithoutExtension(objPath);

            var objMaterials = new ObjMaterialDictionary();

            foreach (var texture in opt.Textures.Values)
            {
                var material = new ObjMaterial
                {
                    Name = texture.Name,
                    DiffuseMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}.png", texture.Name)
                };

                texture.Save(Path.Combine(objDirectory, material.DiffuseMapFileName));

                if (texture.HasAlpha)
                {
                    material.AlphaMapFileName = string.Format(CultureInfo.InvariantCulture, "{0}_alpha.png", texture.Name);

                    texture.SaveAlphaMap(Path.Combine(objDirectory, material.AlphaMapFileName));
                }

                objMaterials.Add(texture.Name, material);
            }

            objMaterials.Save(Path.ChangeExtension(objPath, "mtl"));

            var distances = opt.Meshes
                .SelectMany(t => t.Lods)
                .Select(t => t.Distance)
                .Distinct()
                .OrderByDescending(t => t)
                .ToArray();

            for (int distance = 0; distance < distances.Length; distance++)
            {
                var obj = new ObjFile();

                int objectsIndex = 0;
                int verticesIndex = 0;
                int verticesTexIndex = 0;
                int verticesNormalIndex = 0;

                foreach (var mesh in opt.Meshes)
                {
                    var lod = mesh.Lods.FirstOrDefault(t => t.Distance <= distances[distance]);

                    if (lod == null)
                    {
                        continue;
                    }

                    var objMesh = new ObjMesh(string.Format(CultureInfo.InvariantCulture, "{0}.{1:D3}", mesh.Descriptor.MeshType, objectsIndex));
                    obj.Meshes.Add(objMesh);
                    objectsIndex++;

                    if (scale)
                    {
                        foreach (var v in mesh.Vertices)
                        {
                            obj.Vertices.Add(new ObjVector3(v.X * OptFile.ScaleFactor, v.Z * OptFile.ScaleFactor, v.Y * OptFile.ScaleFactor));
                        }
                    }
                    else
                    {
                        foreach (var v in mesh.Vertices)
                        {
                            obj.Vertices.Add(new ObjVector3(v.X, v.Z, v.Y));
                        }
                    }

                    foreach (var v in mesh.TextureCoordinates)
                    {
                        obj.VertexTexCoords.Add(new ObjVector2(v.U, -v.V));
                    }

                    foreach (var v in mesh.VertexNormals)
                    {
                        obj.VertexNormals.Add(new ObjVector3(v.X, v.Z, v.Y));
                    }

                    foreach (var faceGroup in lod.FaceGroups)
                    {
                        var objFaceGroup = new ObjFaceGroup();

                        if (faceGroup.Textures.Count > 0)
                        {
                            objFaceGroup.MaterialName = faceGroup.Textures[0];
                        }

                        objMesh.FaceGroups.Add(objFaceGroup);

                        foreach (var face in faceGroup.Faces)
                        {
                            if (face.VerticesIndex.D < 0)
                            {
                                objFaceGroup.Faces.Add(new ObjFace()
                                {
                                    VerticesIndex = new ObjIndex(
                                        verticesIndex + face.VerticesIndex.A,
                                        verticesIndex + face.VerticesIndex.B,
                                        verticesIndex + face.VerticesIndex.C
                                        ),

                                    VertexTexCoordsIndex = new ObjIndex(
                                        verticesTexIndex + face.TextureCoordinatesIndex.A,
                                        verticesTexIndex + face.TextureCoordinatesIndex.B,
                                        verticesTexIndex + face.TextureCoordinatesIndex.C),

                                    VertexNormalsIndex = new ObjIndex(
                                        verticesNormalIndex + face.VertexNormalsIndex.A,
                                        verticesNormalIndex + face.VertexNormalsIndex.B,
                                        verticesNormalIndex + face.VertexNormalsIndex.C)
                                });
                            }
                            else
                            {
                                objFaceGroup.Faces.Add(new ObjFace()
                                {
                                    VerticesIndex = new ObjIndex(
                                        verticesIndex + face.VerticesIndex.A,
                                        verticesIndex + face.VerticesIndex.B,
                                        verticesIndex + face.VerticesIndex.C,
                                        verticesIndex + face.VerticesIndex.D
                                        ),

                                    VertexTexCoordsIndex = new ObjIndex(
                                        verticesTexIndex + face.TextureCoordinatesIndex.A,
                                        verticesTexIndex + face.TextureCoordinatesIndex.B,
                                        verticesTexIndex + face.TextureCoordinatesIndex.C,
                                        verticesTexIndex + face.TextureCoordinatesIndex.D),

                                    VertexNormalsIndex = new ObjIndex(
                                        verticesNormalIndex + face.VertexNormalsIndex.A,
                                        verticesNormalIndex + face.VertexNormalsIndex.B,
                                        verticesNormalIndex + face.VertexNormalsIndex.C,
                                        verticesNormalIndex + face.VertexNormalsIndex.D)
                                });
                            }
                        }
                    }

                    verticesIndex += mesh.Vertices.Count;
                    verticesTexIndex += mesh.TextureCoordinates.Count;
                    verticesNormalIndex += mesh.VertexNormals.Count;
                }

                obj.Save(Path.Combine(objDirectory, string.Format(CultureInfo.InvariantCulture, "{0}_{1}.obj", objName, distance)), objName);
            }
        }
Exemplo n.º 5
0
        public static ObjFile FromFile(string fileName)
        {
            ObjFile obj = new ObjFile();

            obj.FileName = fileName;

            using (StreamReader file = new StreamReader(fileName))
            {
                string line;

                string materialName = null;

                ObjMesh mesh = new ObjMesh("unnamed");
                obj.Meshes.Add(mesh);

                ObjFaceGroup faceGroup = new ObjFaceGroup();
                mesh.FaceGroups.Add(faceGroup);

                while ((line = file.ReadLine()) != null)
                {
                    if (string.IsNullOrWhiteSpace(line))
                    {
                        continue;
                    }

                    line = line.Trim();

                    if (line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    string[] values = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                    switch (values[0].ToUpperInvariant())
                    {
                        case "MTLLIB":
                            if (values.Length != 2)
                            {
                                throw new InvalidDataException("missing mtllib name");
                            }

                            if (obj.Materials.Count > 0)
                            {
                                throw new InvalidDataException("multiple mtllib");
                            }

                            obj.Materials = ObjMaterialDictionary.FromFile(Path.Combine(Path.GetDirectoryName(fileName), values[1]));
                            break;

                        case "V":
                            if (values.Length < 4)
                            {
                                throw new InvalidDataException("v must be x y z");
                            }

                            obj.Vertices.Add(new ObjVector3(
                                float.Parse(values[1], CultureInfo.InvariantCulture),
                                float.Parse(values[2], CultureInfo.InvariantCulture),
                                float.Parse(values[3], CultureInfo.InvariantCulture)));
                            break;

                        case "VT":
                            if (values.Length < 3)
                            {
                                throw new InvalidDataException("vt must be u v");
                            }

                            obj.VertexTexCoords.Add(new ObjVector2(
                                float.Parse(values[1], CultureInfo.InvariantCulture),
                                float.Parse(values[2], CultureInfo.InvariantCulture)));
                            break;

                        case "VN":
                            if (values.Length < 4)
                            {
                                throw new InvalidDataException("vn must be x y z");
                            }

                            obj.VertexNormals.Add(new ObjVector3(
                                float.Parse(values[1], CultureInfo.InvariantCulture),
                                float.Parse(values[2], CultureInfo.InvariantCulture),
                                float.Parse(values[3], CultureInfo.InvariantCulture)));
                            break;

                        case "O":
                        case "G":
                            if (values.Length < 2)
                            {
                                throw new InvalidDataException("missing object name");
                            }

                            if (faceGroup.Faces.Count == 0)
                            {
                                mesh.Name = values[1];
                            }
                            else
                            {
                                mesh = new ObjMesh(values[1]);
                                obj.Meshes.Add(mesh);

                                faceGroup = new ObjFaceGroup();
                                faceGroup.MaterialName = materialName;
                                mesh.FaceGroups.Add(faceGroup);
                            }
                            break;

                        case "USEMTL":
                            if (values.Length != 2)
                            {
                                throw new InvalidDataException("missing material name");
                            }

                            materialName = values[1];

                            if (faceGroup.Faces.Count == 0)
                            {
                                faceGroup.MaterialName = materialName;
                            }
                            else
                            {
                                faceGroup = new ObjFaceGroup();
                                faceGroup.MaterialName = materialName;
                                mesh.FaceGroups.Add(faceGroup);
                            }
                            break;

                        case "F":
                            if (values.Length == 4)
                            {
                                var v1 = ParseFaceVertex(values[1]);
                                var v2 = ParseFaceVertex(values[2]);
                                var v3 = ParseFaceVertex(values[3]);

                                var face = new ObjFace();
                                face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1);
                                face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2);
                                face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3);

                                faceGroup.Faces.Add(face);
                            }
                            else if (values.Length == 5)
                            {
                                var v1 = ParseFaceVertex(values[1]);
                                var v2 = ParseFaceVertex(values[2]);
                                var v3 = ParseFaceVertex(values[3]);
                                var v4 = ParseFaceVertex(values[4]);

                                var face = new ObjFace();
                                face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1, v4.Item1);
                                face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2, v4.Item2);
                                face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3, v4.Item3);

                                faceGroup.Faces.Add(face);
                            }
                            else
                            {
                                throw new InvalidDataException("invalid face");
                            }
                            break;
                    }
                }
            }

            return obj;
        }
Exemplo n.º 6
0
        public void SplitFaceGroups()
        {
            this.CompactFaceGroups();

            Func<ObjIndex, int[]> indices = index =>
                index.D < 0 ?
                new[] { index.A, index.B, index.C } :
                new[] { index.A, index.B, index.C, index.D };

            var faceGroups = new List<ObjFaceGroup>();

            foreach (var faceGroup in this.FaceGroups)
            {
                var groups = new List<ObjFaceGroup>();

                foreach (var face in faceGroup.Faces)
                {
                    var faceIndices = indices(face.VerticesIndex);

                    var group = groups
                        .Where(g => g.Faces.SelectMany(t => indices(t.VerticesIndex)).Any(t => faceIndices.Contains(t)))
                        .FirstOrDefault();

                    if (group != null)
                    {
                        group.Faces.Add(face);
                    }
                    else
                    {
                        group = new ObjFaceGroup();
                        group.MaterialName = faceGroup.MaterialName;
                        group.Faces.Add(face);
                        groups.Add(group);
                    }
                }

                faceGroups.AddRange(groups);
            }

            this.FaceGroups = faceGroups;
        }