2016-09-07 185 views
0

我正在加載.obj文件並在android模擬器中呈現它。儘管第三方.obj查看器正確地顯示模型(open3mod),但是當我在android模擬器上啓動它時,它看起來很奇怪。你能解釋爲什麼在enulator模型中不正確地返回?OpenGL ES 1.0 - 不正確的渲染

import android.content.Context; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLU; 
import java.util.Hashtable; 
import java.util.ArrayList; 
import java.io.InputStreamReader; 
import java.io.BufferedReader; 
import java.nio.FloatBuffer; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

public class MyGLSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer 
{ 
    private Context context; 
    private Hashtable<String, ArrayList<Float>> obj; 

    public MyGLSurfaceView(Context context) 
    { 
     super(context); 
     setRenderer(this); 
     this.context = context; 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    { 
     obj = new Hashtable<String, ArrayList<Float>>(); 

     try 
     { 
      BufferedReader reader = new BufferedReader(
       new InputStreamReader(context.getAssets().open("calculator.obj"))); 

      ArrayList<Float> vertex = new ArrayList<Float>(); 

      String name = null; 
      String line = null; 
      while ((line = reader.readLine()) != null) 
      { 
       if (line.startsWith("v ")) 
       { 
        String[] parts = line.substring(2).trim().split("\\s+"); 

        vertex.add(Float.valueOf(Float.valueOf(parts[0]).floatValue()/2f)); // scale to smaller twice 
        vertex.add(Float.valueOf(Float.valueOf(parts[1]).floatValue()/2f)); // scale to smaller twice 
        vertex.add(Float.valueOf(Float.valueOf(parts[2]).floatValue()/2f)); // scale to smaller twice 
       } 

       if (line.startsWith("f ")) 
       { 
        String[] parts = line.substring(2).trim().split("\\s+"); 

        obj.get(name).add(vertex.get(Integer.valueOf(parts[0]).intValue() - 1)); 
        obj.get(name).add(vertex.get(Integer.valueOf(parts[1]).intValue() - 1)); 
        obj.get(name).add(vertex.get(Integer.valueOf(parts[2]).intValue() - 1)); 
       } 

       if (line.startsWith("g ")) 
       { 
        name = line.substring(2).trim(); 

        obj.put(name, new ArrayList<Float>()); 
       } 
      } 

      reader.close(); 
     } 
     catch (Exception e) 
     { 
      System.exit(0); 
     } 
    } 

    public void onSurfaceChanged(GL10 gl, int width, int height) 
    { 
     gl.glViewport(0, 0, width, height); 
    } 

    public void onDrawFrame(GL10 gl) 
    { 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     gl.glClearDepthf(1.0f); 

     int i; 

     ByteBuffer fByteBuffer = ByteBuffer.allocateDirect(obj.get("calculator").size() * 4); 
     fByteBuffer.order(ByteOrder.nativeOrder()); 
     FloatBuffer faces = fByteBuffer.asFloatBuffer(); 
     for (i = 0; i < obj.get("calculator").size(); i++) 
      faces.put(obj.get("calculator").get(i).floatValue());    
     faces.position(0); 

     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, faces); 

     gl.glDrawArrays(GL10.GL_TRIANGLES, 0, faces.capacity()/3); 
    } 
} 

+0

可以嘗試一個更簡單的OBJ文件,並且包括obj文件和您傳遞給您的問題中的API的浮動列表。這很難看到事情進展, – solidpixel

+0

問題是浮動列表也呈現不正確。我寫了obj2java腳本並將它導入到主類中 - 結果是一樣的 –

+0

當然,這可能意味着你沒有正確讀取文件,但是沒有看到這個文件,以及你的腳本用它做了什麼,很難說。 – solidpixel

回答

0

的OBJ文件索引幾何格式(這就是臉元素行以「F」的編碼 - 他們告訴你的頂點數組中頂點構成每一個三角形)。

您當前的代碼正在解碼索引值,但在渲染時完全忽略它們。您需要使用glDrawElements,使用索引緩衝區來選擇哪些頂點貢獻哪些三角形。

編輯我錯過了手動重新加載頂點數據的事實。您不需要這樣做 - API本身支持索引渲染(因爲共享vert只處理一次,效率更高)。

+0

我已經嘗試過'glDrawElements' - 同樣的結果,因爲.obj文件不包含索引信息,我不得不簡單地從0到三角形索引計數頂點。 –

+0

'您手動重新包裝加載的頂點數據 - 請清除。 –

+0

「...因爲.obj文件不包含索引信息」。是的,他們有。你認爲以「f」開頭的行是什麼?你已經解碼他們,並使用它們作爲索引... – solidpixel