【问题标题】:Loading .obj file strange results加载 .obj 文件奇怪的结果
【发布时间】:2015-03-16 13:25:22
【问题描述】:

我正在编写一个 Java LWJGL 3D 游戏引擎。我决定重写我的网格类和 .obj 加载器。手动输入数据时,mesh 类工作正常,但从 .obj 文件加载时会产生一些奇怪的结果:(它应该是一条龙,但看起来像 2D ......)

public static Mesh loadMesh(String fileName) throws IOException
{
    String splitArray[] = fileName.split("\\.");
    String ext = splitArray[splitArray.length-1];

    if(!ext.equals("obj"))
        System.err.println("Error: Engine can only load .obj files, try converting the file: " + fileName);

    ArrayList<Vector3f> vertices = new ArrayList<Vector3f>();
    ArrayList<Integer> vindices = new ArrayList<Integer>();
    ArrayList<Integer> tindices = new ArrayList<Integer>();
    ArrayList<Integer> nindices = new ArrayList<Integer>();
    ArrayList<Vector3f> normals  = new ArrayList<Vector3f>();
    ArrayList<Vector2f> texCoords = new ArrayList<Vector2f>();



    BufferedReader reader = new BufferedReader(new FileReader("./res/models/"+fileName));
    String line = "";

    while((line=reader.readLine())!=null)
    {
        String[] p = line.split(" ");
        if(line.startsWith("v"))
        {
            vertices.add(new Vector3f(Float.valueOf(p[1]),
                                      Float.valueOf(p[2]),
                                      Float.valueOf(p[3])));
        }
        if(line.startsWith("vn"))
        {
            normals.add(new Vector3f(Float.valueOf(p[1]),
                                      Float.valueOf(p[2]),
                                      Float.valueOf(p[3])));
        }
        if(line.startsWith("vt"))
        {
            texCoords.add(new Vector2f(Float.valueOf(p[1]),
                                      Float.valueOf(p[2])));
        }
        if(line.startsWith("f"))
        {
            String[] arg1 = p[1].split("/");
            String[] arg2 = p[2].split("/");
            String[] arg3 = p[3].split("/");
            vindices.add(Integer.parseInt(arg1[0]));
            if(arg1.length>1)
            tindices.add(Integer.parseInt(arg1[1]));
            if(arg1.length>2)
            nindices.add(Integer.parseInt(arg1[3]));

            vindices.add(Integer.parseInt(arg2[0]));
            if(arg1.length>1)
            tindices.add(Integer.parseInt(arg2[1]));
            if(arg2.length>2)
            nindices.add(Integer.parseInt(arg2[3]));

            vindices.add(Integer.parseInt(arg3[0]));
            if(arg1.length>1)
            tindices.add(Integer.parseInt(arg3[1]));
            if(arg3.length>2)
            nindices.add(Integer.parseInt(arg3[3]));
        }   
    }

    float[] vdata = new float[vertices.size() * 3];
    float[] tdata = new float[texCoords.size() * 2];
    float[] ndata = new float[normals.size() * 3];
    for(int i = 0; i < vdata.length; i++)
    {
        vdata[i] = vertices.get(Integer.valueOf(vindices.get(i))).getX();
        vdata[i++] = vertices.get(Integer.valueOf(vindices.get(i))).getY();
        vdata[i++] = vertices.get(Integer.valueOf(vindices.get(i))).getZ();
    }
    for(int i = 0; i < ndata.length; i++)
    {
        ndata[i] = normals.get(Integer.valueOf(nindices.get(i))).getX();
        ndata[i++] = normals.get(Integer.valueOf(nindices.get(i))).getY();
        ndata[i++] = normals.get(Integer.valueOf(nindices.get(i))).getZ();
    }
    for(int i = 0; i < tdata.length; i++)
    {
        tdata[i] = texCoords.get(Integer.valueOf(tindices.get(i))).getX();
        tdata[i++] = texCoords.get(Integer.valueOf(tindices.get(i))).getY();
    }
    return new Mesh(vdata, tdata, ndata);
}

这就是我的 .obj 文件加载器。看不出有什么问题...

【问题讨论】:

  • 每个面只能容纳三个顶点。您的对象是否导出为“仅限三”,即没有四边形?
  • 只有它的三角形,在我改变它之前它工作得很好......

标签: java lwjgl loader .obj


【解决方案1】:

仔细检查后发现有一些不错的错误:

vindices.add(Integer.parseInt(arg1[0]));
if(arg1.length>1)
tindices.add(Integer.parseInt(arg1[1]));
if(arg1.length>2)
nindices.add(Integer.parseInt(arg1[3])); // this should be 2 for the normals

和

for(int i = 0; i < vdata.length; i++)
{
    vdata[i] = vertices.get(Integer.valueOf(vindices.get(i))).getX();  //i=0
    vdata[i++] = vertices.get(Integer.valueOf(vindices.get(i))).getY(); //i=0 and counted up afterwards
    vdata[i++] = vertices.get(Integer.valueOf(vindices.get(i))).getZ();//i=1 and counted up afterwards
}

这就是使网格成为二维的原因。
我建议使用++i 或

for(int i = 0; i < vdata.length; i+=3)
{
    vdata[i] = vertices.get(Integer.valueOf(vindices.get(i))).getX();
    vdata[i+1] = vertices.get(Integer.valueOf(vindices.get(i))).getY(); 
    vdata[i+2] = vertices.get(Integer.valueOf(vindices.get(i))).getZ();
}

【讨论】:

  • 你完全正确。现在它是 3D,但看起来仍然不太正确。我一定是把索引搞砸了……
猜你喜欢
  • 1970-01-01
  • 2013-12-16
  • 2015-09-24
  • 1970-01-01
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多