Пример #1
0
        public static OBJData ParseOBJ(OBJParserStatus s, string path = null)
        {
            using (StreamReader reader = path != null ? StreamProvider(s, "obj", path) : s.Reader ?? StreamProvider(s, "obj", s.Path))
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine().Trim();
                    if (line.Length == 0)
                    {
                        continue;
                    }
                    if (line[0] == '#' && (line.Length < 2 || line[1] != '!'))
                    {
                        continue;
                    }

                    if (2 < line.Length && line[0] == '#' && line[1] == '!')
                    {
                        line = line.Substring(2).Trim();
                        if (line.Length == 0)
                        {
                            continue;
                        }
                        ParseLineExt(s, line);
                    }
                    else
                    {
                        ParseLineStandard(s, line);
                    }
                }

            return(s.Data);
        }
Пример #2
0
        public static void ParseLineExt(OBJParserStatus s, string line)
        {
            string[] data = line.Split(' ');

            switch (data[0])
            {
            case "objx":
            case "import":
                ParseOBJX(s, line.Substring(5));
                return;
            }

            // Fallback for f.e. objx-only mtllibs
            ParseLineStandard(s, line);
        }
Пример #3
0
        public static void ParseLineStandard(OBJParserStatus s, string line)
        {
            OBJObject o;

            string[] data = line.Split(' ');

            switch (data[0])
            {
            case "mtllib":
                // Currently ignore material libraries.
                return;

            case "o":
                o = new OBJObject(line.Substring(2), s.Current);
                s.Data.Objects.Add(o);
                s.Current         = o.Groups[0];
                s.CurrentMaterial = "";
                return;

            case "g":
                if (s.Data.Objects.Count == 0)
                {
                    o = new OBJObject("", s.Current);
                    s.Data.Objects.Add(o);
                    s.Current      = o.Groups[0];
                    s.Current.Name = line.Substring(2);
                }
                else
                {
                    s.Current = new OBJGroup(line.Substring(2), s.Current);
                    if (s.Current.PrevObj.Groups.Count == 2 &&
                        s.Current.PrevObj.Groups[0].Name == "")
                    {
                        s.Current.PrevObj.Groups.RemoveAt(0);
                    }
                }
                s.CurrentMaterial = "";
                return;

            case "v":
                s.Current.Vertices.Add(_ParseV3(data, 1));
                return;

            case "vt":
                s.Current.UVs.Add(_ParseV2(data, 1));
                return;

            case "vn":
                s.Current.Normals.Add(_ParseV3(data, 1));
                return;

            case "usemtl":
                // Currently ignore material usages.
                s.Current.Materials.Add(line.Substring(7));
                return;

            case "s":
                if (data[1] == "off")
                {
                    // Currently ignore smoothing group disabling.
                }
                else
                {
                    // Currently ignore smoothing group 1 - 32.
                }
                return;

            case "f":
                OBJGroup current = s.Current;
                if (4 <= data.Length && data.Length < 6)
                {
                    int[] indices = new int[data.Length - 1];
                    for (int i = 0; i < indices.Length; i++)
                    {
                        string elem = data[i + 1];

                        int iV  = 0;
                        int iN  = 0;
                        int iUV = 0;

                        if (elem.Contains("//"))
                        {
                            string[] parts = elem.Split('/');
                            iV = int.Parse(parts[0]);
                            iN = int.Parse(parts[2]);
                        }
                        else if (_Count(elem, '/', 2))
                        {
                            string[] parts = elem.Split('/');
                            iV  = int.Parse(parts[0]);
                            iUV = int.Parse(parts[1]);
                            iN  = int.Parse(parts[2]);
                        }
                        else if (!elem.Contains("/"))
                        {
                            iV = int.Parse(elem);
                        }
                        else
                        {
                            string[] parts = elem.Split('/');
                            iV  = int.Parse(parts[0]);
                            iUV = int.Parse(parts[1]);
                        }


                        string cacheKey = $"{iV}; {iN}; {iUV}";
                        int    cacheValue;
                        if (current.IndexCache.TryGetValue(cacheKey, out cacheValue))
                        {
                            indices[i] = cacheValue;
                        }
                        else
                        {
                            cacheValue = current.IndexCache.Count;
                            indices[i] = cacheValue;
                            current.IndexCache[cacheKey] = cacheValue;

                            if ((1 <= iV && iV <= current.Vertices.Count) ||
                                (iV < 0 && 1 <= (iV = iV + current.Vertices.Count + 1) && iV <= current.Vertices.Count))
                            {
                                current.UVertices.Add(current.Vertices[iV - 1]);
                            }
                            else
                            {
                                current.UVertices.Add(Vector3.zero);
                            }

                            if ((1 <= iN && iN <= current.Normals.Count) ||
                                (iN < 0 && 1 <= (iN = iN + current.Normals.Count + 1) && iN <= current.Normals.Count))
                            {
                                current.ContainsNormals = true;
                                current.UNormals.Add(current.Normals[iN - 1]);
                            }
                            else
                            {
                                current.UNormals.Add(Vector3.zero);
                            }

                            if ((1 <= iUV && iUV <= current.UVs.Count) ||
                                (iUV < 0 && 1 <= (iUV = iUV + current.UVs.Count + 1) && iUV <= current.UVs.Count))
                            {
                                current.UUVs.Add(current.UVs[iUV - 1]);
                            }
                            else
                            {
                                current.UUVs.Add(Vector2.zero);
                            }
                        }
                    }

                    OBJFace face = new OBJFace();
                    face.IndexMap   = OBJFace.DefaultIndexMap;
                    face.RawIndices = indices;
                    face.Material   = s.CurrentMaterial;
                    s.Current.AddFace(face);
                    if (indices.Length > 3)
                    {
                        face            = new OBJFace();
                        face.IndexMap   = OBJFace.SecondaryIndexMap;
                        face.RawIndices = indices;
                        face.Material   = s.CurrentMaterial;
                        s.Current.AddFace(face);
                    }
                }
                return;
            }
        }