Skip to main content
removed blacklisted tag
Link
Pikalek
  • 13.4k
  • 5
  • 49
  • 54
added 3861 characters in body
Source Link
Joel
  • 1.5k
  • 1
  • 12
  • 29

EDIT 2: And here is my OBJ loader... There's quite a chance this is the problem.

public class ObjLoader
{
    public MeshData LoadStream(Stream stream)
    {
        StreamReader reader = new StreamReader(stream);
        List<Vector3> points = new List<Vector3>();
        List<Vector3> normals = new List<Vector3>();
        List<Vector2> texCoords = new List<Vector2>();
        List<Tri> tris = new List<Tri>();
        string line;
        char[] splitChars = { ' ' };
        while ((line = reader.ReadLine()) != null)
        {
            line = line.Trim(splitChars);
            line = line.Replace("  ", " ");

            string[] parameters = line.Split(splitChars);

            switch (parameters[0])
            {
                case "p":
                    // Point
                    break;

                case "v":
                    // Vertex
                    float x = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float y = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    float z = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                    points.Add(new Vector3(x, y, z));
                    break;

                case "vt":
                    // TexCoord
                    float u = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float v = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    texCoords.Add(new Vector2(u, v));
                    break;

                case "vn":
                    // Normal
                    float nx = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float ny = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    float nz = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                    normals.Add(new Vector3(nx, ny, nz));
                    break;

                case "f":
                    // Face
                    tris.AddRange(parseFace(parameters));
                    break;
            }
        }

        Vector3[] p = points.ToArray();
        Vector2[] tc = texCoords.ToArray();
        Vector3[] n = normals.ToArray();
        Tri[] f = tris.ToArray();

        // If there are no specified texcoords or normals, we add a dummy one.
        // That way the Points will have something to refer to.
        if (tc.Length == 0)
        {
            tc = new Vector2[1];
            tc[0] = new Vector2(0, 0);
        }
        if (n.Length == 0)
        {
            n = new Vector3[1];
            n[0] = new Vector3(1, 0, 0);
        }

        return new MeshData(p, n, tc, f);
    }

    public MeshData LoadFile(string file)
    {
        // Silly me, using() closes the file automatically.
        using (FileStream s = File.Open(file, FileMode.Open))
        {
            return LoadStream(s);
        }
    }

    private static Tri[] parseFace(string[] indices)
    {
        Point[] p = new Point[indices.Length - 1];
        for (int i = 0; i < p.Length; i++)
        {
            p[i] = parsePoint(indices[i + 1]);
        }
        return Triangulate(p);
        //return new Face(p);
    }

    // Takes an array of points and returns an array of triangles.
    // The points form an arbitrary polygon.
    private static Tri[] Triangulate(Point[] ps)
    {
        List<Tri> ts = new List<Tri>();
        if (ps.Length < 3)
        {
            throw new Exception("Invalid shape!  Must have >2 points");
        }

        Point lastButOne = ps[1];
        Point lastButTwo = ps[0];
        for (int i = 2; i < ps.Length; i++)
        {
            Tri t = new Tri(lastButTwo, lastButOne, ps[i]);
            lastButOne = ps[i];
            lastButTwo = ps[i - 1];
            ts.Add(t);
        }
        return ts.ToArray();
    }

    private static Point parsePoint(string s)
    {
        s += "//";
        char[] splitChars = { '/' };
        string[] parameters = s.Split(splitChars);
        int vert, tex, norm;
        vert = tex = norm = 0;
        vert = int.Parse(parameters[0]) - 1;
        // Texcoords and normals are optional in .obj files
        if (parameters[1] != "")
        {
            tex = int.Parse(parameters[1]) - 1;
        }
        if (parameters[2] != "")
        {
            norm = int.Parse(parameters[2]) - 1;
        }
        return new Point(vert, norm, tex);
    }
}

EDIT 2: And here is my OBJ loader... There's quite a chance this is the problem.

public class ObjLoader
{
    public MeshData LoadStream(Stream stream)
    {
        StreamReader reader = new StreamReader(stream);
        List<Vector3> points = new List<Vector3>();
        List<Vector3> normals = new List<Vector3>();
        List<Vector2> texCoords = new List<Vector2>();
        List<Tri> tris = new List<Tri>();
        string line;
        char[] splitChars = { ' ' };
        while ((line = reader.ReadLine()) != null)
        {
            line = line.Trim(splitChars);
            line = line.Replace("  ", " ");

            string[] parameters = line.Split(splitChars);

            switch (parameters[0])
            {
                case "p":
                    // Point
                    break;

                case "v":
                    // Vertex
                    float x = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float y = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    float z = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                    points.Add(new Vector3(x, y, z));
                    break;

                case "vt":
                    // TexCoord
                    float u = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float v = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    texCoords.Add(new Vector2(u, v));
                    break;

                case "vn":
                    // Normal
                    float nx = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                    float ny = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                    float nz = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                    normals.Add(new Vector3(nx, ny, nz));
                    break;

                case "f":
                    // Face
                    tris.AddRange(parseFace(parameters));
                    break;
            }
        }

        Vector3[] p = points.ToArray();
        Vector2[] tc = texCoords.ToArray();
        Vector3[] n = normals.ToArray();
        Tri[] f = tris.ToArray();

        // If there are no specified texcoords or normals, we add a dummy one.
        // That way the Points will have something to refer to.
        if (tc.Length == 0)
        {
            tc = new Vector2[1];
            tc[0] = new Vector2(0, 0);
        }
        if (n.Length == 0)
        {
            n = new Vector3[1];
            n[0] = new Vector3(1, 0, 0);
        }

        return new MeshData(p, n, tc, f);
    }

    public MeshData LoadFile(string file)
    {
        // Silly me, using() closes the file automatically.
        using (FileStream s = File.Open(file, FileMode.Open))
        {
            return LoadStream(s);
        }
    }

    private static Tri[] parseFace(string[] indices)
    {
        Point[] p = new Point[indices.Length - 1];
        for (int i = 0; i < p.Length; i++)
        {
            p[i] = parsePoint(indices[i + 1]);
        }
        return Triangulate(p);
        //return new Face(p);
    }

    // Takes an array of points and returns an array of triangles.
    // The points form an arbitrary polygon.
    private static Tri[] Triangulate(Point[] ps)
    {
        List<Tri> ts = new List<Tri>();
        if (ps.Length < 3)
        {
            throw new Exception("Invalid shape!  Must have >2 points");
        }

        Point lastButOne = ps[1];
        Point lastButTwo = ps[0];
        for (int i = 2; i < ps.Length; i++)
        {
            Tri t = new Tri(lastButTwo, lastButOne, ps[i]);
            lastButOne = ps[i];
            lastButTwo = ps[i - 1];
            ts.Add(t);
        }
        return ts.ToArray();
    }

    private static Point parsePoint(string s)
    {
        s += "//";
        char[] splitChars = { '/' };
        string[] parameters = s.Split(splitChars);
        int vert, tex, norm;
        vert = tex = norm = 0;
        vert = int.Parse(parameters[0]) - 1;
        // Texcoords and normals are optional in .obj files
        if (parameters[1] != "")
        {
            tex = int.Parse(parameters[1]) - 1;
        }
        if (parameters[2] != "")
        {
            norm = int.Parse(parameters[2]) - 1;
        }
        return new Point(vert, norm, tex);
    }
}
added 2321 characters in body
Source Link
Joel
  • 1.5k
  • 1
  • 12
  • 29

EDIT: Here's the buffer code if it helps...

public void LoadBuffers(MeshData m, out uint indexBuffer, out uint dataBuffer, out int vertOffset, out int normOffset, out int texcoordOffset)
    {
        float[] verts, norms, texcoords;
        uint[] indices;
        m.OpenGLArrays(out verts, out norms, out texcoords, out indices);
        GL.GenBuffers(1, out dataBuffer);
        GL.GenBuffers(1, out indexBuffer);

        int buffersize = (verts.Length + norms.Length + texcoords.Length);
        float[] bufferdata = new float[buffersize];
        vertOffset = 0;
        normOffset = verts.Length;
        texcoordOffset = (verts.Length + norms.Length);

        verts.CopyTo(bufferdata, vertOffset);
        norms.CopyTo(bufferdata, normOffset);
        texcoords.CopyTo(bufferdata, texcoordOffset);

        bool v = false;
        for (int i = texcoordOffset; i < bufferdata.Length; i++)
        {
            if (v)
            {
                bufferdata[i] = 1 - bufferdata[i];
                v = false;
            }
            else
            {
                v = true;
            }
        }

        GL.BindBuffer(BufferTarget.ArrayBuffer, dataBuffer);
        GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr)(buffersize * sizeof(float)), bufferdata,
                      BufferUsageHint.StaticDraw);

        GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
        GL.BufferData<uint>(BufferTarget.ElementArrayBuffer,
                      (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw);
    }

    public bool DrawBuffer(MeshData m, uint tex, uint indexBuffer, uint dataBuffer, int vertOffset, int normOffset, int texcoordOffset)
    {
        tex = tempTexture;
        GL.CullFace(CullFaceMode.Back);
        GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
        GL.ClientActiveTexture(TextureUnit.Texture0);
        GL.BindTexture(TextureTarget.Texture2D, tex);
        GL.BindBuffer(BufferTarget.ArrayBuffer, dataBuffer);
        GL.NormalPointer(NormalPointerType.Float, 0, (IntPtr)(normOffset * sizeof(float)));
        GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, (IntPtr)(texcoordOffset * sizeof(float)));
        GL.VertexPointer(3, VertexPointerType.Float, 0, (IntPtr)(vertOffset * sizeof(float)));
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
        GL.DrawElements(BeginMode.Triangles, m.Tris.Length * 3, DrawElementsType.UnsignedInt, IntPtr.Zero);
        GL.PopClientAttrib();

        return true;
    }

EDIT: Here's the buffer code if it helps...

public void LoadBuffers(MeshData m, out uint indexBuffer, out uint dataBuffer, out int vertOffset, out int normOffset, out int texcoordOffset)
    {
        float[] verts, norms, texcoords;
        uint[] indices;
        m.OpenGLArrays(out verts, out norms, out texcoords, out indices);
        GL.GenBuffers(1, out dataBuffer);
        GL.GenBuffers(1, out indexBuffer);

        int buffersize = (verts.Length + norms.Length + texcoords.Length);
        float[] bufferdata = new float[buffersize];
        vertOffset = 0;
        normOffset = verts.Length;
        texcoordOffset = (verts.Length + norms.Length);

        verts.CopyTo(bufferdata, vertOffset);
        norms.CopyTo(bufferdata, normOffset);
        texcoords.CopyTo(bufferdata, texcoordOffset);

        bool v = false;
        for (int i = texcoordOffset; i < bufferdata.Length; i++)
        {
            if (v)
            {
                bufferdata[i] = 1 - bufferdata[i];
                v = false;
            }
            else
            {
                v = true;
            }
        }

        GL.BindBuffer(BufferTarget.ArrayBuffer, dataBuffer);
        GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr)(buffersize * sizeof(float)), bufferdata,
                      BufferUsageHint.StaticDraw);

        GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
        GL.BufferData<uint>(BufferTarget.ElementArrayBuffer,
                      (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw);
    }

    public bool DrawBuffer(MeshData m, uint tex, uint indexBuffer, uint dataBuffer, int vertOffset, int normOffset, int texcoordOffset)
    {
        tex = tempTexture;
        GL.CullFace(CullFaceMode.Back);
        GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
        GL.ClientActiveTexture(TextureUnit.Texture0);
        GL.BindTexture(TextureTarget.Texture2D, tex);
        GL.BindBuffer(BufferTarget.ArrayBuffer, dataBuffer);
        GL.NormalPointer(NormalPointerType.Float, 0, (IntPtr)(normOffset * sizeof(float)));
        GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, (IntPtr)(texcoordOffset * sizeof(float)));
        GL.VertexPointer(3, VertexPointerType.Float, 0, (IntPtr)(vertOffset * sizeof(float)));
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
        GL.DrawElements(BeginMode.Triangles, m.Tris.Length * 3, DrawElementsType.UnsignedInt, IntPtr.Zero);
        GL.PopClientAttrib();

        return true;
    }
Source Link
Joel
  • 1.5k
  • 1
  • 12
  • 29
Loading