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;
}
}