2016-09-07 218 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