0

I'm writing a Java LWJGL 3D game-engine. I decided to rewrite my mesh class and the .obj loader. The mesh class works fine when putting in data manually, but wehn loading from an .obj-file it gives some strange results: (it's supposed to be a dragon but lokks like a 2D ... something)

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

thats my .obj-file loader. Can't see what is wrong...

l'arbre
  • 719
  • 2
  • 10
  • 29

1 Answers1

0

Upon closer inspection there are some nice bugs:

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

and

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
}

This is what makes the mesh two-dimensional.
I would suggest using eigther ++i or

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();
}
Dawnkeeper
  • 2,844
  • 1
  • 25
  • 41
  • You are totally right. Now it's 3D, but still doesn't look quite right. I must have messed up something with the indices... – l'arbre Jan 23 '15 at 22:09