Below of my main class I am trying to render a obj from a blender .obj file after reformatting it to (supposedly) work for my rendering it gives the error. How can I fix this?
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at flow_control.MainLoop.render(MainLoop.java:85)
at flow_control.MainLoop.main(MainLoop.java:45)
Main class:
package flow_control;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
import static org.lwjgl.opengl.GL11.*;
public class MainLoop {
MainLoop(){
camera = new Camera(this);
loadTextures();
}
private static final int WIDTH = 1280
private static final int HEIGHT = 700;
boolean[] keys = new boolean[256];
Camera camera;
Texture TexFloor;
Texture TexWhite;
Model m = null;
public static void main(String[] args) {
System.out.println("S");
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
MainLoop game = new MainLoop();
game.load();
game.loadTextures();
while(!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
game.update();
game.render();
Display.update();
Display.sync(60);
}
Display.destroy();
System.exit(0);
}
private void loadTextures(){
try{
TexFloor = TextureLoader.getTexture("JPG", ResourceLoader.getResourceAsStream("res/floor.jpg"));
}catch(FileNotFoundException e) {
System.err.println("Could not find textures");
e.printStackTrace();
}catch(IOException e){
System.err.println("IO problem");
e.printStackTrace();
}
}
public void render() {
clearScreen();
camera.translatePostion();
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0, 0, 0);
glTexCoord2f(128/8, 0);
glVertex3f(500, 0, 0);
glTexCoord2f(128/8, 128/8);
glVertex3f(500, 0, 500);
glTexCoord2f(0, 128/8);
glVertex3f(0, 0, 500);
glEnd();
glBegin(GL_TRIANGLES);
for (Faces face : m.faces) {
//error occurs on the line below
Vector3f n1 = m.normals.get((int) face.normals.x - 1);
glNormal3f(n1.x, n1.y, n1.z);
Vector3f v1 = m.vertices.get((int) face.Vertex.x - 1);
glNormal3f(v1.x, v1.y, v1.z);
Vector3f n2 = m.normals.get((int) face.normals.y - 1);
glNormal3f(n2.x, n2.y, n2.z);
Vector3f v2 = m.vertices.get((int) face.Vertex.y - 1);
glNormal3f(v2.x, v2.y, v2.z);
Vector3f n3 = m.normals.get((int) face.normals.z - 1);
glNormal3f(n3.x, n3.y, n3.z);
Vector3f v3 = m.vertices.get((int) face.Vertex.z - 1);
glNormal3f(v3.x, v3.y, v3.z);
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
TexFloor.bind();
}
public void load() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective((float) 100, WIDTH/HEIGHT, 0.001f, 1000);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
try{
m = OBJLoader.loadModel(new File("res/tree.obj"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void clearScreen() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
public void update() {
mapKeys();
camera.update();
}
private void mapKeys(){
for(int i=0;i<keys.length; i++) {
keys[i] = Keyboard.isKeyDown(i);
}
}
}
Class OBJLoader:
package flow_control;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.lwjgl.util.vector.Vector3f;
public class OBJLoader {
public static Model loadModel(File f) throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader(new FileReader(f));
Model m = new Model();
String line;
while((line = reader.readLine()) != null){
//parse object
if (line.startsWith("v ")){
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
m.vertices.add(new Vector3f(x,y,z));
} else if (line.startsWith("vn ")) {
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
m.normals.add(new Vector3f(x,y,z));
} else if (line.startsWith("f ")) {
Vector3f vertexIndices = new Vector3f(Float.valueOf(line.split(" ")[1].split("/")[0]),Float.valueOf(line.split(" ")[2].split("/")[0]),Float.valueOf(line.split(" ")[3].split("/")[0]));
Vector3f normalIndices = new Vector3f(Float.valueOf(line.split(" ")[1].split("/")[2]),Float.valueOf(line.split(" ")[2].split("/")[2]),Float.valueOf(line.split(" ")[3].split("/")[2]));
m.faces.add(new Faces(vertexIndices, normalIndices));
}
}
reader.close();
return m;
}
}
Class Model:
package flow_control;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Vector3f;
public class Model {
public List<Vector3f> vertices = new ArrayList<Vector3f>();
public List<Vector3f> normals = new ArrayList<Vector3f>();
public List<Faces> faces = new ArrayList<Faces>();
public Model(){
}
}
Class Faces:
package flow_control;
import org.lwjgl.util.vector.Vector3f;
public class Faces {
public Vector3f Vertex = new Vector3f();
public Vector3f normals = new Vector3f();
public Faces(Vector3f vertex, Vector3f normal) {
this.Vertex = vertex;
this.normals = normals;
}
}
Sorry if some of this is excessive I know the errors coming from line 85 but I can't seem to figure out how to fix it.
OBJ file example (slimmed down):
# Blender v2.74 (sub 0) OBJ File: ''
# www.blender.org
mtllib tree.mtl
o Mesh_default
v -0.163260 2.023340 -0.247879
v 0.163260 2.023340 -0.247878
v 0.163260 2.023340 0.247879
f 35//34 39//40 36//35
f 36//35 40//39 37//36
f 38//37 34//41 41//38
vn -0.259900 0.445500 -0.856700
vn 0.087800 0.445500 -0.891000
vn -0.422000 0.445500 -0.789600
You made a couple of typo's in your program.
First off, in your OBJLoader class
else if (line.startsWith("vm "))
Its looking for lines in the OBJ file that start with "vm " but your obj files uses "vn ". Simply change this and the array won't be empty anymore.
vn -0.259900 0.445500 -0.856700
vn 0.087800 0.445500 -0.891000
vn -0.422000 0.445500 -0.789600
Secondly, in the Faces class
public Faces(Vector3f vertex, Vector3f normal)
{
this.Vertex = vertex;
this.normals = normals;
}
You are setting the "normals" variable equal to itself rather then the Vector3f in the constructor, change it to this.
this.normals = normal;