예제 #1
0
        public ObjModel(String filename)
        {
            String contents = File.ReadAllText(filename);

            v  = new List <Vector3>();
            vn = new List <Vector3>();
            vt = new List <Vector3>();
            f  = new List <Indexes>();
            c  = new List <VColor>();
            List <VColor> colors = new List <VColor>();

            buffer = new List <byte>();

            contents = Regex.Replace(contents, @" +", " "); // replace multiple spaces with one

            // PARSE
            string[] lines = contents.Split('\n').ToList().Select(m => m.Trim()).ToArray();

            VColor color = new VColor();

            foreach (string line in lines)
            {
                if (String.IsNullOrEmpty(line))
                {
                    continue;
                }

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

                if (line.StartsWith("usemtl"))
                {
                    color = new VColor();

                    if (line == "usemtl default")
                    {
                        continue;
                    }

                    if (line.StartsWith("usemtl Color.") && line.Contains(","))
                    {
                        string[] colorParts     = line.Split('.');
                        string[] colorFractions = colorParts[1].Split(',');
                        color.r = byte.Parse(colorFractions[0]);
                        color.g = byte.Parse(colorFractions[1]);
                        color.b = byte.Parse(colorFractions[2]);
                        color.a = byte.Parse(colorFractions[3]);
                    }
                    else
                    {
                        color = new VColor {
                            r = 0, g = 0, b = 0, a = 255
                        }
                    };

                    colors.Add(color);
                    continue;
                }

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

                switch (parts[0])
                {
                case "v":
                case "vn":
                case "vt":
                    Vector3 aux = new Vector3()
                    {
                        x = float.Parse(parts[1]),
                        y = float.Parse(parts[2]),
                        z = parts.Length > 3 ? float.Parse(parts[3]) : 0
                    };

                    switch (parts[0])
                    {
                    case "v": v.Add(aux); break;

                    case "vn": vn.Add(aux); break;

                    case "vt":
                        vt.Add(aux);
                        break;
                    }

                    break;

                case "f":

                    Indexes index = new Indexes();

                    for (int h = 1; h <= 3; h++)
                    {
                        string[] subparts = parts[h].Split('/').ToArray();

                        Vector3UShort auxf = new Vector3UShort()
                        {
                            x = ushort.Parse(subparts[0]),
                            y = subparts.Length < 2 || subparts[1].Length == 0 ? (ushort)0 : ushort.Parse(subparts[1]),
                            z = subparts.Length < 3 || subparts[2].Length == 0 ? (ushort)0 : ushort.Parse(subparts[2])
                        };

                        index.positions[h - 1] = auxf;
                    }

                    f.Add(index);

                    c.Add(color);

                    break;
                }
            }

            // reorder
            List <Vector3> vertices = new List <Vector3>();
            List <Vector3> uvs      = new List <Vector3>();
            List <Vector3> normals  = new List <Vector3>();

            float texturePosModifier = (1.0f / colors.Count);

            int     materialIndex = 0;
            int     keyIndex      = 0;
            Vector3 vaux;

            foreach (Indexes index in f)
            {
                foreach (Vector3UShort part in index.positions)
                {
                    vertices.Add(v[part.x - 1]);

                    if (vt.Count > 0)
                    {
                        vaux = new Vector3()
                        {
                            x = vt[part.y - 1].x, y = 1 - vt[part.y - 1].y, z = vt[part.y - 1].z
                        };

                        if (colors.Count > 1)
                        {
                            materialIndex = colors.IndexOf(c[keyIndex]);

                            //vaux.x = vaux.x * texturePosModifier / 100.0f + materialIndex * texturePosModifier + (vaux.x == 1.0f ? 0.0f : .01f);
                            vaux.y = .5f;
                            vaux.z = 0;
                            vaux.x = texturePosModifier * materialIndex + texturePosModifier / 2;
                        }

                        uvs.Add(vaux);
                    }

                    if (vn.Count > 0)
                    {
                        normals.Add(vn[part.z - 1]);
                    }
                }

                keyIndex++;
            }

            // WRITE TO BUFFER
            buffer.AddRange(BitConverter.GetBytes((ushort)vertices.Count));
            foreach (Vector3 vector in vertices)
            {
                AddVector(vector);
            }

            if (vertices.Count > 0)
            {
                Vector3 min, max, size;

                min = new Vector3()
                {
                    x = vertices.Min(m => m.x),
                    y = vertices.Min(m => m.y),
                    z = vertices.Min(m => m.z)
                };

                max = new Vector3()
                {
                    x = vertices.Max(m => m.x),
                    y = vertices.Max(m => m.y),
                    z = vertices.Max(m => m.z)
                };

                size = new Vector3()
                {
                    x = Math.Abs(max.x - min.x),
                    y = Math.Abs(max.y - min.y),
                    z = Math.Abs(max.z - min.z)
                };

                AddVector(size);
            }

            buffer.AddRange(BitConverter.GetBytes((ushort)uvs.Count));
            foreach (Vector3 vector in uvs)
            {
                AddVector(vector);
            }

            buffer.AddRange(BitConverter.GetBytes((ushort)normals.Count));
            foreach (Vector3 vector in normals)
            {
                AddVector(vector);
            }

            buffer.AddRange(BitConverter.GetBytes((ushort)colors.Count));
            foreach (VColor c in colors)
            {
                AddVector(c);
            }
        }