Ejemplo n.º 1
0
        private static (List <Vertex> vertices, List <VertexNormal> normals, List <TextureUv> uvs, List <Group> groups) ExtractOBJData(string[] lines)
        {
            var enumerable = from line in lines
                             let split = line.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(l => l.Trim()).ToArray()
                                         where split.Any() && !split.First().StartsWith("#")
                                         select split;

            var vertices     = new List <Vertex>();
            var normals      = new List <VertexNormal>();
            var uvs          = new List <TextureUv>();
            var currentGroup = new Group("unnamed");
            var groups       = new List <Group>();

            var elementComparer = new ElementComparer(vertices, uvs, normals);


            foreach (var line in enumerable)
            {
                switch (line[0])
                {
                case "v":
                    Debug.Assert(line.Length == 4);
                    var vertex = new Vertex
                    {
                        X = float.Parse(line[1]),
                        Y = float.Parse(line[2]),
                        Z = float.Parse(line[3])
                    };

                    vertices.Add(vertex);
                    break;

                case "vn":
                    Debug.Assert(line.Length == 4);
                    normals.Add(new VertexNormal
                    {
                        X = float.Parse(line[1]),
                        Y = float.Parse(line[2]),
                        Z = float.Parse(line[3])
                    });
                    break;

                case "vt":
                    uvs.Add(new TextureUv
                    {
                        U = float.Parse(line[1]),
                        V = float.Parse(line[2])
                            //Ignore w
                    });
                    break;

                case "g":
                case "o":                         //For the sake of bedrock, treat groups and objects as the same thing.
                    currentGroup = new Group(line[1]);
                    groups.Add(currentGroup);

                    break;

                case "f":
                    Debug.Assert(line.Length >= 4 && line.Length <= 5);
                    var polygon = new Polygon();
                    for (var i = 1; i < line.Length; ++i)
                    {
                        var elements       = line[i].Split("/");
                        var vertexIndex    = int.Parse(elements[0]);
                        var textureUvIndex = int.Parse(elements[1]);
                        if (elements.Length > 2)
                        {
                            var normalIndex = int.Parse(elements[2]);
                            polygon.AddElement(new Element(vertexIndex, textureUvIndex, normalIndex));
                        }
                        else
                        {
                            polygon.AddElement(new Element(vertexIndex, textureUvIndex));
                        }
                    }

                    if (currentGroup.TryGetPreviousPolygon(out var lastPolygon) && lastPolygon.Vertices.Count == 3)
                    {
                        var uniqueElements  = lastPolygon.Vertices.Except(polygon.Vertices, elementComparer).ToArray();
                        var missingElements = polygon.Vertices.Except(lastPolygon.Vertices, elementComparer).ToArray();
                        if (uniqueElements.Length == 1 && missingElements.Length == 1)
                        {
                            lastPolygon.RepairToQuad(missingElements.Single());
                        }
                        else
                        {
                            currentGroup.AddPolygon(polygon);
                        }
                    }
                    else
                    {
                        currentGroup.AddPolygon(polygon);
                    }

                    break;
                }
            }