-1

I'm trying to load Wavefront OBJ files for a game I'm trying to make. I have it down... sort of. Some of the faces are either missing when rendered, or they have incorrect vertex positions. The way I'm loading them probably isn't very optimized, too. I'm using LWJGL and it's OpenGL binding (I think it's a binding) to render my model.

Here's what the model is supposed to look like: http://i1291.photobucket.com/albums/b560/DandDMC/blender2014-07-0415-28-40-23_zps0fbfcebb.png

Here's what it looks like ingame: http://i1291.photobucket.com/albums/b560/DandDMC/javaw2014-07-0415-52-54-99_zpsdf14fb6c.png

Here's the loading method:

public static Model loadModel(String fileLocation)
{
    File file = new File(fileLocation);

    if(!file.exists())
    {
        try
        {
            throw new FileNotFoundException("The file named: " + fileLocation + " doesn't exist!");
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }

        return null;
    }

    ArrayList<Vertex> vertices = new ArrayList<Vertex> ();
    ArrayList<Vertex> texVertices = new ArrayList<Vertex> ();
    ArrayList<Face> faces = new ArrayList<Face> ();

    try
    {
        BufferedReader r = new BufferedReader(new FileReader(file));
        String s = "";

        int refIndex = 1;

        int vertIndex = 1;
        int texVertIndex = 1;

        while((s = r.readLine()) != null)
        {               
            String[] split = s.split(" ");

            if(split[0].equals("v"))
            {
                vertices.add(new Vertex(Double.parseDouble(split[1]), Double.parseDouble(split[2]), Double.parseDouble(split[3]), vertIndex));
                vertIndex ++;
            }
            else if(split[0].equals("vt"))
            {
                texVertices.add(new Vertex(Double.parseDouble(split[1]), Double.parseDouble(split[2]), 0.0, texVertIndex));
                texVertIndex ++;
            }
            else if(split[0].equals("f"))
            {
                ArrayList<Integer> vert = new ArrayList<Integer> ();
                ArrayList<Integer> texVert = new ArrayList<Integer> ();

                for(int i = 1; i < split.length; i ++)
                {
                    String[] fSplit = split[i].split("/");

                    vert.add(Integer.parseInt(fSplit[0]));
                    texVert.add(Integer.parseInt(fSplit[1]));
                }

                faces.add(new Face(vert, texVert));
            }
            else if(split[0].equals("#") || split[0].equals("o") || split[0].equals("mtllib") || split[0].equals("usemtl") || split[0].equals("s"))
            {
                // Don't have a use for as of now
            }
            else
            {
                throw new Exception("The syntax at line: " + refIndex + " is incorrect.");
            }

            refIndex ++;
        }

        r.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    return new Model(vertices, texVertices, faces);
}

Here's the Face class (it's pretty simple):

package com.glh.model;

import java.util.*;

public class Face
{
public ArrayList<Integer> verticeIndexes;
public ArrayList<Integer> texVerticeIndexes;

public Face(ArrayList<Integer> verticeIndexes, ArrayList<Integer> texVerticeIndexes)
{
    this.verticeIndexes = verticeIndexes;
    this.texVerticeIndexes = texVerticeIndexes;
}

public ArrayList<Vertex> getVertexPositions(Model parentModel)
{
    ArrayList<Vertex> l = new ArrayList<Vertex> ();

    for(int i : verticeIndexes)
    {
        l.add(parentModel.vertices.get(i - 1));
    }

    return l;
}

public ArrayList<Vertex> getTextureVertexPositions(Model parentModel)
{
    ArrayList<Vertex> l = new ArrayList<Vertex> ();

    for(int i : texVerticeIndexes)
    {
        l.add(parentModel.texVertices.get(i - 1));
    }

    return l;
}

}

The Vertex class even simpler:

package com.glh.model;

public class Vertex
{
public double x;
public double y;
public double z;
public int index;

public Vertex(double x, double y, double z, int index)
{
    this.x = x;
    this.y = y;
    this.z = z;
    this.index = index;
}

public Vertex()
{
    this(0.0, 0.0, 0.0, 0);
}
}

And the method to render it:

public void renderModel_tri(Model m)
{
    // The model is much smaller in Blender
    glScalef(0.3F, 0.3F, 0.3F);

    glBegin(GL_QUADS);

    for(Face f : m.faces)
    {
        ArrayList<Vertex> vertices = f.getVertexPositions(m);
        ArrayList<Vertex> texVertices = f.getTextureVertexPositions(m);

        for(int i = 0; i < vertices.size(); i ++)
        {
            Vertex vert = vertices.get(i);
            Vertex texVert = texVertices.get(i);

            glTexCoord2d(texVert.x, texVert.y);
            glVertex3d(vert.x, vert.y, vert.z);
        }
    }

    glEnd();
}

The Model class just holds a list of all the vertices and faces.

package com.glh.model;

import java.util.*;

public class Model
{
public ArrayList<Vertex> vertices;
public ArrayList<Vertex> texVertices;
public ArrayList<Face> faces;

public Model(ArrayList<Vertex> vertices, ArrayList<Vertex> texVertices, ArrayList<Face> faces)
{
    this.vertices = vertices;
    this.texVertices = texVertices;
    this.faces = faces;
}
}
drs
  • 5,679
  • 4
  • 42
  • 67
David
  • 41
  • 6
  • why did you delete your most recent question? I have a pertinent answer if you are interested. – chqrlie Mar 23 '16 at 02:09
  • Woops, the most recent comment confirmed my suspicions so I figured I'd get rid of it, although I don't see a undelete button anywhere, so you could probably PM it to me, heh, stackoverflow noob mistake xD – David Mar 23 '16 at 02:14
  • I have voted for undelete, but I doubt there will be 14 other members to support it. I don't know how to PM you either. – chqrlie Mar 23 '16 at 02:24
  • The short answer is **no**, you cannot *recover* from undefined behavior. Once undefined behavior is invoked, something goes wrong. Undefined behavior does not necessarily mean a crash or even any user or programmer observable behavior. It just means the program does not behave in a way defined by the standard. – chqrlie Mar 23 '16 at 02:24
  • In some cases of undefined behavior, such as dereferencing a null pointer, in some environments, a signal is raised and you might be able to register a handler to be called for this signal. Your handler would be called then and you might be able to transmit a message to the user with some relevant information about the crash location. Read the manual for `signal` and try and register a handler for `SIGILL`, `SIGBUS` and `SIGSEGV`. Providing the location may be quite difficult and very system specific, but you might still provide useful information and even restart the program. – chqrlie Mar 23 '16 at 02:24
  • Very interesting, I'm glad you went out of your way to answer my question. The first time I read about signaling, I didn't really understand it and it didn't seem relevant to my current C++ hello world project, but I'll have to look into that, it seems pretty useful. A quick question however, would it still be possible to access a variable in memory that was unaffected by the undefined behavior? Or would C++ be running around with its hair on fire at that point? Again, thanks a lot for going the extra mile to answer my question. – David Mar 23 '16 at 02:40
  • The rest of the program is still accessible from the signal handler, but if you trigger another signal from the handler, it might be a problem. – chqrlie Mar 23 '16 at 02:59

1 Answers1

0

I found it... My model is composed of triangles, and I was drawing QUADS in the game. I changed the: glBegin(GL_QUADS); to glBegin(GL_TRIANGLES);

David
  • 41
  • 6
  • You can use `GL_TRIANGLE_FAN`. Then it will work no matter how many vertices your faces have. Was this the only issue? I saw this when I looked at your question yesterday. But based on the picture, I didn't think that this alone explained the output you were getting. – Reto Koradi Jul 06 '14 at 18:47
  • The model before I swapped the QUADS with TRIANGLES made me think there was more issues too. But it's the only issue that I found, and the models render perfectly now. And I tried the 'GL_TRIANGLES_FAN', it works, but I only tried it with models made of triangles. (Not that it makes much of a difference, because it's easy enough just to press Ctrl + T in Blender, and render them as GL_TRIANGLES. – David Jul 09 '14 at 00:46