Java LWJGL 正确渲染 .obj

Java LWJGL rendering .obj correctly

在我的主要 class 下方,我试图从 blender .obj 文件中渲染一个 obj,然后将其重新格式化为(据推测)为我的渲染工作它给出了错误。我该如何解决这个问题?

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)

主要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 型号:

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 面孔:

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

抱歉,如果其中一些内容过多,我知道第 85 行出现错误,但我似乎无法弄清楚如何修复它。

OBJ 文件示例(精简):

# 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

你的程序中有几个错别字。

首先, 在您的 OBJLoader class

else if (line.startsWith("vm ")) 

它正在 OBJ 文件中查找以 "vm " 开头但您的 obj 文件使用 "vn " 的行。只需更改它,数组将不再为空。

vn -0.259900 0.445500 -0.856700
vn 0.087800 0.445500 -0.891000
vn -0.422000 0.445500 -0.789600

其次,在人脸class

public Faces(Vector3f vertex, Vector3f normal) 
{
    this.Vertex = vertex;
    this.normals = normals;
}

您正在将 "normals" 变量设置为等于自身而不是构造函数中的 Vector3f,请将其更改为此。

    this.normals = normal;