2017-03-22 95 views
1

因此,我正在用LWJGL製作一個「遊戲」,並開始加載3D模型(使用Wavefront .obj文件)。我已經成功地加載了模型,但沒有紋理,我想嘗試.mtl文件來指定材質。我「有點」做到了,但它似乎並沒有完全奏效。這裏是我的代碼,和樹模型的照片我試圖呈現: Tree Model在LWJGL中加載MTL文件

現在,這裏是我的代碼:

private static OBJMesh mesh; 

public static Mesh load3DModel(String objFileName) 
{ 
    mesh = new OBJMesh(); 

    BufferedReader reader = null; 

    try 
    { 
     reader = new BufferedReader(new FileReader(new File(objFileName))); 
    } 
    catch (FileNotFoundException e) 
    { 
     System.err.println("Could not locate OBJ File at " + objFileName); 
     e.printStackTrace(); 
    } 

    String mtlFileName = null; 
    String line = null; 
    String currentFaceMat = null; 
    try 
    { 
     while ((line = reader.readLine()) != null) 
     { 
      String[] lineParts = line.split(" "); 
      switch (line.substring(0, 2)) 
      { 
      case "v ": 
       Vertex v = new Vertex(lineParts[1], lineParts[2], lineParts[3]); 
       mesh.addVertex(v); 
       break; 
      case "vn": 
       Normal n = new Normal(lineParts[1], lineParts[2], lineParts[3]); 
       mesh.addNormal(n); 
       break; 
      case "mt": 
       mtlFileName = FileHelper.getDirectory(objFileName) + lineParts[1]; 
       break; 
      case "us": 
       currentFaceMat = lineParts[1]; 
       break; 
      case "f ": 
       Face face = createFace(currentFaceMat, lineParts); 
       mesh.addFace(face); 
       break; 
      } 
     } 

     reader = new BufferedReader(new FileReader(mtlFileName)); 

     Material mat = null; 
     while ((line = reader.readLine()) != null) 
     { 
      String[] lineParts = line.split(" "); 

      if (line.length() > 1) 
      { 
       switch (line.substring(0, 2)) 
       { 
       case "ne": 
        mat = new Material(lineParts[1]); 
        mesh.addMaterial(lineParts[1], mat); 
        break; 
       case "Ka": 
        mat.setKa(createVector(lineParts)); 
        break; 
       case "Kd": 
        mat.setKd(createVector(lineParts)); 
        break; 
       case "Ks": 
        mat.setKs(createVector(lineParts)); 
        break; 
       case "Ns": 
        mat.setNs(Float.parseFloat(lineParts[1])); 
        break; 
       case "d ": 
        mat.setD(Float.parseFloat(lineParts[1])); 
        break; 
       case "il": 
        mat.setIllum(Integer.parseInt(lineParts[1])); 
        break; 
       } 
      } 
     } 

     reader.close(); 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 

    mesh.normalArray = new float[mesh.vertices.size() * 3]; 

    for (Face face : mesh.faces) 
    { 
     decodeNormals(face.indices1); 
     decodeNormals(face.indices2); 
     decodeNormals(face.indices3); 
    } 

    mesh.vertexArray = new float[mesh.vertices.size() * 3]; 
    mesh.indexArray = new int[mesh.indices.size() * 3]; 
    mesh.colorArray = new float[mesh.faces.size() * 3]; 

    int vertexPointer = 0; 
    for (Vertex vertex : mesh.vertices) 
    { 
     mesh.vertexArray[vertexPointer++] = vertex.x; 
     mesh.vertexArray[vertexPointer++] = vertex.y; 
     mesh.vertexArray[vertexPointer++] = vertex.z; 
    } 

    for (int i = 0; i < mesh.indices.size(); i++) 
    { 
     mesh.indexArray[i] = mesh.indices.get(i); 
    } 

    int colorPointer = 0; 
    for (Face face : mesh.faces) 
    { 
     mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.x; 
     mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.y; 
     mesh.colorArray[colorPointer++] = mesh.materials.get(face.material).Kd.z; 
    } 

    return MeshLoader.genVertexModel(mesh.vertexArray, mesh.indexArray, mesh.colorArray); 
} 

private static Face createFace(String materialName, String[] lineData) 
{ 
    String[] indices1 = General.replaceEmptySlashes(lineData[1]).split("/"); 
    String[] indices2 = General.replaceEmptySlashes(lineData[2]).split("/"); 
    String[] indices3 = General.replaceEmptySlashes(lineData[3]).split("/"); 

    return new Face(materialName, indices1, indices2, indices3); 
} 

private static Vector3f createVector(String[] lineData) 
{ 
    float x = Float.parseFloat(lineData[1]); 
    float y = Float.parseFloat(lineData[2]); 
    float z = Float.parseFloat(lineData[3]); 

    return new Vector3f(x, y, z); 
} 

private static void decodeNormals(Vector3f vertex) 
{ 
    int vertexPointer = (int) vertex.x - 1; 
    mesh.indices.add(vertexPointer); 
    Normal normal = mesh.normals.get((int) vertex.z - 1); 
    mesh.normalArray[vertexPointer * 3] = normal.x; 
    mesh.normalArray[vertexPointer * 3 + 1] = normal.y; 
    mesh.normalArray[vertexPointer * 3 + 2] = normal.z; 
} 

的OBJMesh類:

public List<Vertex> vertices = new ArrayList<Vertex>(); 
public List<Normal> normals = new ArrayList<Normal>(); 
public List<Integer> indices = new ArrayList<Integer>(); 
public List<Face> faces = new ArrayList<Face>(); 
public Map<String, Material> materials = new HashMap<String, Material>(); 

public float[] vertexArray; 
public float[] normalArray; 
public float[] colorArray; 
public int[] indexArray; 

public void addVertex(Vertex vertex) 
{ 
    vertices.add(vertex); 
} 

public void addNormal(Normal normal) 
{ 
    normals.add(normal); 
} 

public void addMaterial(String name, Material material) 
{ 
    materials.put(name, material); 
} 

public void addFace(Face face) 
{ 
    faces.add(face); 
} 

Face類:

public Vector3f indices1; 
public Vector3f indices2; 
public Vector3f indices3; 
public String material; 

public Face(String material, String[] v1, String[] v2, String[] v3) 
{ 
    this.material = material; 
    this.indices1 = new Vector3f(Float.parseFloat(v1[0]), Float.parseFloat(v1[1]), Float.parseFloat(v1[2])); 
    this.indices2 = new Vector3f(Float.parseFloat(v2[0]), Float.parseFloat(v2[1]), Float.parseFloat(v2[2])); 
    this.indices3 = new Vector3f(Float.parseFloat(v3[0]), Float.parseFloat(v3[1]), Float.parseFloat(v3[2])); 
} 

材質類只包含RGB值。

如果你能找到一些東西,讓我知道;我一直在尋找數週(不是開玩笑!)。謝謝

+0

那麼問題是什麼? – Vallentin

+0

@Vallentin問題是材料不起作用。看看我放在鏈接中的圖片! – Kai

+0

從我的理解你的代碼,它看起來像你在'colorArray'中存儲每個面的顏色。然而,OpenGL期望它們是每個頂點。 – skalarproduktraum

回答

0

OpenGL預計所有的頂點屬性都是每個頂點。您在填寫您的colorArray時的方式表明您只能按此面試。改變這一點,它應該給出正確的結果。