Obj文件无法正确呈现

时间:2015-03-13 22:01:51

标签: java opengl lwjgl loader mesh

我创建了一个对象加载器,当我比较文件中的数据和控制台输出时,它似乎工作但是当我渲染它时,它似乎完全断开了。我使用opengl(v 3.3)和lwjgl来渲染网格。我怎样才能让它正确渲染?此外,似乎有一些面正在渲染,但大多数面只是没有渲染...我认为这意味着错误在for循环的某处,但我还没有找到问题。这是一些图片:

Incorrectly rendered mesh

Correctly rendered mesh

这是一些代码: 这是加载和处理数据的Obj类。这里要注意的重要一点是make faces方法。重新排序顶点但仅适用于输入的大约三分之一。然后它停止,这意味着它必须有某种逻辑错误。似乎除了那种方法之外别无其他。

package main;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Obj {
public Point[] verticesArray = null;
public float[] facesInOrder = new float[50];
ArrayList<Point> vertices = new ArrayList<Point>();
ArrayList<Integer> faces = new ArrayList<Integer>();

public Point[] points(String s) {

    // Declares an arraylist to store an undefined number of values
    String stuff = new String();
    BufferedReader br = null;

    try {
        br = new BufferedReader(new FileReader(s));

    } catch (FileNotFoundException e) {
        // Auto-generated catch block
        e.printStackTrace();
    }
    try {
        stuff = br.readLine();// Reads a line
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    String[] stuffArray;
    while (stuff != null) {
        stuffArray = stuff.split("\\s+");// splits the line into an array

        if (stuffArray[0].equals("v")) {// Searches for vertices
            Point p = new Point();

            p.set(0, Float.parseFloat(stuffArray[1]));// places vertices
                                                        // into points
            p.set(1, Float.parseFloat(stuffArray[2]));
            p.set(2, Float.parseFloat(stuffArray[3]));

            vertices.add(p);
            System.out.println(p.x + " " + p.y + " " + p.z);
        } else if (stuffArray[0].equals("f")) {// Finds a face

            faces.add(Integer.parseInt(stuffArray[1]) - 1);
            faces.add(Integer.parseInt(stuffArray[2]) - 1);// puts face into
                                                            // an arraylist
            faces.add(Integer.parseInt(stuffArray[3]) - 1);
        }
        try {
            stuff = br.readLine();// reads a new line
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    Point[] arrResult = new Point[vertices.size()];
    for (int i = 0; i < vertices.size(); i++) {
        arrResult[i] = vertices.get(i);// converts arralist to array
    }
    facesInOrder = new float[faces.size()];
    try {
        br.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return arrResult;
}

public void makeFaces() {
    for (int i = 0, b = 0; i < faces.size(); i += 3, b++) {
        facesInOrder[i] = verticesArray[faces.get(b)].x;
        facesInOrder[i + 1] = verticesArray[faces.get(b)].y;
        // orders the faces in a new array 

        facesInOrder[i + 2] = verticesArray[faces.get(b)].z;

        System.out.println(facesInOrder[i]+" "+ facesInOrder[i+1]+" "+ facesInOrder[i+2]+" "+ facesInOrder[i+3]);
    }

}

public Obj(String s) {
    verticesArray = points(s);
    makeFaces();

}
}

这是在上面某些地方使用的点类,它用于存储点数据/顶点数据:

package main;

public class Point {
public float x;
public float y;
public float z;
public float w;

public Point(float x, float y,float z,float w){
this.x=x;
this.y=y;
this.z=z;
this.w=w;
}
public Point(){

}
public void set(int i,float value){
switch(i){
case 0:
    x=value;
    break;
case 1:
    y=value;
    break;
case 2:
    z=value;
    break;

}
}
}

我决定编辑渲染循环因为它无关紧要。重新创建此示例的最小代码是导入上面的两个类并调用

Obj obj=new Obj("/path/to/.obj");

请注意,打印出的线条数量远少于应有的线条数量(约少三倍)。

1 个答案:

答案 0 :(得分:1)

我没有参与java编程,但是在你的程序中快速查看我已经注意到你忽略了所有索引点并且只是将顶点绘制为面部列表。至少这是这个命令所说的:

glDrawArrays(GL_TRIANGLES, 0, vertexBuffer.capacity()/4);

你不能这样做。 Wavefront是一个对象文件规范,它使用索引列表来描述网格,并且必须使用它来重新创建网格。

我建议你先阅读article,然后再讨论index buffer

PS。你的程序可以,当然也有另一个错误。