2011-12-10 39 views
0

我正在和一些朋友一起玩遊戲,爲了讓生活更輕鬆我決定全部使用.obj文件製作3D模型,並導出到程序中3DSMax,Maya和Blender3D。LWJGL .OBJ文件讀取器有時會影響或不渲染文件

因此,我寫了一個.obj文件閱讀器,並在簡單的場景中嘗試過,一些.obj文件呈現良好(如簡單的多維數據集),一些渲染得非常奇怪,然後一些渲染完全沒有。我希望有人能指出我做錯了什麼,下面的代碼包含一個類,其中2個嵌入類,其中一個包含另一個嵌入類。它可能會引起混淆,因此如果需要,您可以複製並粘貼到文件中以便於閱讀。

腳本在文件中逐行讀取,如果它以「v」(頂點)開頭,則按空格分割該行,並採用索引1 2和3(xy和z),並將整數值存儲在稱爲頂點的類,並將其添加到頂點對象的數組中。頂點對象就像一個矢量一樣,只有它包含兩個矢量,一個用於位置,另一個用於法線。

如果行以「vn」(Vertex Normal)開頭,則它將行分割爲「」,並採用索引1 2和3,然後將其添加到Vertex對象,該對象的作用與迄今爲止的向量相同,然後頂點被添加到專門用於法線的不同頂點陣列。

現在,這裏是最有趣的部分,當符合 「F」(FACE)行可能看起來像開始:

f 1//3 5//3 6//1 2//4 

每個#1 //#2,#1的索引正確的頂點,#2是正確的法線的索引。因此,我將線段的每一部分按「」拆分,並用「//」拆分,從頂點數組和頂點從法線數組中取頂點,將頂點法線設置爲法線的xy和z,製作了一個Face對象,並將其添加到一個面的列表中,該面只包含3個或4個Vertex對象。

希望這個解釋可能會使文件看起來不那麼雜亂。

好,這裏是代碼:

package org.ic3d.utils; 

import java.io.*; 
import org.ic3d.utils.ObjReader.Face.FaceStateException; 
import org.lwjgl.opengl.GL11; 

public class ObjReader 
{ 
    public ObjReader(String file) 
    { 
     try 
     { 
      BufferedReader reader = new BufferedReader(new FileReader(new File(file))); 
      parse(reader); 
     } 
     catch(Exception e) 
     { 
      System.out.println(file+" Failed To Load! Can't continue."); 
      System.exit(0); 
     } 
    } 

    /** 
    * Parse all lines in the BufferedReader to convert the .obj file 
    * 
    * @param br - A BufferedReader object pointing to the desired .obj file 
    * @throws IOException If the obj file can not be read for any reason. 
    * @throws FaceStateException If the obj file is malformed and vertice are added to a face of different shape (tri - quad) 
    */ 
    public void parse(BufferedReader br) throws IOException, FaceStateException 
    { 
     String s=""; 

     Vertex[] v1 = new Vertex[15000]; 
     Vertex[] n1 = new Vertex[15000]; 

     while((s = br.readLine())!=null) 
     { 
      if(s.startsWith("v")) 
      { 
       String[] pv = s.split(" "); 

       Vertex vert_0x = new Vertex(Float.parseFloat(pv[1]), Float.parseFloat(pv[2]), Float.parseFloat(pv[3])); 

       v1 = appendVert(v1, vert_0x); 
      } 
      if(s.startsWith("vn")) 
      { 
       String[] pv = s.split(" "); 

       Vertex vert_0x = new Vertex(Float.parseFloat(pv[1]), Float.parseFloat(pv[2]), Float.parseFloat(pv[3])); 

       n1 = appendVert(n1, vert_0x); 
      } 
      if(s.startsWith("f")) 
      { 
       String[] pv = s.split(" "); 

       Vertex[] temp = new Vertex[pv.length-1]; 

       for(int i=1;i<pv.length;i++) 
       { 
        String[] vn = pv[i].split("//"); 

        Vertex v = v1[Integer.parseInt(vn[0])]; 

        Vertex n = n1[Integer.parseInt(vn[1])]; 

        v.setNormals(n.getX(), n.getY(), n.getZ()); 

        temp = appendVert(temp, v); 
       } 
       try 
       { 
        Face f = new Face(temp.length==3?Face.GL_FACE_TRI:Face.GL_FACE_QUAD, temp); 
        faces = appendFace(faces, f); 
       } 
       catch(FaceStateException e) 
       { 
        throw e; 
       } 
      } 
     } 
    } 
    private Vertex[] appendVert(Vertex[] l, Vertex v) 
    { 
     for(int i=0;i<l.length;i++) 
     { 
      if(l[i]==null) 
      { 
       l[i] = v; 
       return l; 
      } 
     } 
     System.out.println("Vertex[] can only hold "+l.length+" Vertices at one time"); 
     return l; 
    } 
    private Face[] appendFace(Face[] l, Face f) 
    { 
     for(int i=0;i<l.length;i++) 
     { 
      if(l[i]==null) 
      { 
       l[i] = f; 
       return l; 
      } 
     } 
     System.out.println("Face[] can only hold "+faces.length+" Faces at one time"); 
     return l; 
    } 
    public void renderTri(Face f, float x, float y, float z) 
    { 
     Vertex[] v = f.getVerts(); 

     GL11.glBegin(GL11.GL_TRIANGLES); 

     Vertex cv = v[0]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     cv = v[1]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     cv = v[2]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     GL11.glEnd(); 
    } 
    public void renderQuad(Face f, float x, float y, float z) 
    { 
     Vertex[] v = f.getVerts(); 

     GL11.glBegin(GL11.GL_QUADS); 

     Vertex cv = v[0]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     cv = v[2]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     cv = v[2]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     cv = v[3]; 
     GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ()); 
     GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ()); 

     GL11.glEnd(); 
    } 
    public void render(float x, float y, float z) 
    { 
     GL11.glPushMatrix(); 
     for(Face f : faces) 
     { 
      if(f==null) 
      { 
       GL11.glPopMatrix(); 
       return; 
      } 
      else 
      { 
       switch(f.getType()) 
       { 
        case(3): 
        { 
         renderTri(f, x, y, z); 
        } 
        case(4): 
        { 
         renderQuad(f, x, y, z); 
        } 
       } 
      } 
     } 
     GL11.glPopMatrix(); 
    } 
    public int listid=0; 
    public Face[] faces = new Face[15000]; 
    public class Face 
    { 
     /** 
     * Create a new Face object, Faces Hold 3 or 4 Vertex Objects, Polygons not accepted. 
     * @param shape 
     * @param verts 
     * @throws FaceStateException - If the number of vertice in the Vertex[] is not equal to the face type set. 
     */ 
     public Face(int shape, Vertex[] vertlist) throws FaceStateException{ 

      int vert_n = GL_FACE_NONE-shape; 

      if(vertlist.length>vert_n) 
      { 
       throw new FaceStateException(vert_n+" Vertice faces can not hold "+verts.length+" vertices"); 
      } 
      if(vertlist.length<vert_n) 
      { 
       throw new FaceStateException(vert_n+" Vertice faces must hold "+vert_n+" vertice, not "+verts.length+" vertices"); 
      } 
      if(vert_n!=3 && vert_n!=4) 
      { 
       throw new FaceStateException("Faces can only be 3 or 4 vertice. Shapes besides QUAD and TRI are not allowed."); 
      } 
      type=vert_n; 

      verts=vertlist; 
     } 
     public Vertex[] getVerts() 
     { 
      return verts; 
     } 
     public int getType() 
     { 
      return type; 
     } 
     public String getType(int i) 
     { 
      if(i==1) 
      { 
       return(type==3?"TRI":"QUAD"); 
      } 
      else 
      { 
       return(type==3?"TRIANGLE":"QUAD"); 
      } 
     } 
     private Vertex[] verts; 
     public static final int GL_FACE_QUAD = 3; 
     public static final int GL_FACE_TRI = 4; 
     public static final int GL_FACE_NONE = 7; 
     private int type=7; 
     public class FaceStateException extends Exception 
     { 
      public FaceStateException(String s) 
      { 
       super(s); 
      } 
      private static final long serialVersionUID = 1L; 
     } 
    } 
    public class Vertex 
    { 
     public Vertex(float x, float y, float z) 
     { 
      _x=x; 
      _y=y; 
      _z=z; 
     } 
     public void setNormals(float x, float y, float z) 
     { 
      _nx=x; 
      _ny=y; 
      _nz=z; 
     } 
     public float getX() 
     { 
      return _x; 
     } 
     public float getY() 
     { 
      return _y; 
     } 
     public float getZ() 
     { 
      return _z; 
     } 
     public float getNormalX() 
     { 
      return _nx; 
     } 
     public float getNormalY() 
     { 
      return _ny; 
     } 
     public float getNormalZ() 
     { 
      return _nz; 
     } 
     public float[] getNormalXYZ() 
     { 
      return new float[]{_nx, _ny, _nz}; 
     } 
     public void setXYZ(float x, float y, float z) 
     { 
      _x=x; 
      _y=y; 
      _z=z; 
     } 
     public float[] getXYZ() 
     { 
      return new float[]{_x, _y, _z}; 
     } 
     private float _x; 
     private float _y; 
     private float _z; 
     private float _nx; 
     private float _ny; 
     private float _nz; 
    } 
} 
+0

我不知道你有沒有遇到過,但在使用代碼時,我不得不遞減索引查找當建立的面孔,以使其發揮作用。 –

回答

1

我認爲這是相當簡單的修復,真的不需要GL11.glEnd(),你可以啓動另一個渲染使用開始類型,甚至沒有第一結束它。嘗試切割GL11.glEnd()到整個渲染腳本的末尾,看看是否有幫助任何:

public void render() 
{ 
    Object1.render(5, 0, 5); 
    Object1.render(-5, 0,-5); 
    Object2.render(5, 0,-5); 
    Object2.render(-5, 0, 5); 
    GL11.glEnd(); 
} 
+0

謝謝你,幫了我不少,我希望我能在方法中結束它,但我不知道我可以從四邊形開始渲染三角形,反之亦然。謝謝。 –