2016-09-07 22 views
0

.objファイルを読み込み、アンドロイドエミュレータでレンダリングしています。サードパーティ製の.objビューアではモデルが正しく表示されていますが(open3mod)、Androidのエミュレータで起動すると奇妙に見えます。なぜ、エミュレータモデルのリダイアルが間違っているのか説明してください。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ファイルを試して、あなたの質問にAPIに渡しているobjファイルとfloatリストの両方を含めることができます。何が起こっているのか分かりにくいですが、 – solidpixel

+0

の問題は、浮動小数点リストも正しく表示されないことです。私はobj2javaスクリプトを作成し、それをメインクラスにインポートしました。結果は同じ –

+0

です。これはおそらく、ファイルを正しく読み込めないことを意味しますが、ファイルとスクリプトの両方を見ることなく、 。 – solidpixel

答えて

0

OBJファイルは、インデックス付きジオメトリフォーマットされている(つまり、顔要素ラインは「F」で始まるものだがエンコードされている - 彼らは、各三角形を構成する頂点配列内の頂点たあなたを伝えます)。

現在のコードはインデックス値をデコードしていますが、レンダリング時には現在のコードは完全に無視されます。 glDrawElementsを使用する必要があります。インデックスバッファを使用して、どの頂点がどの三角形に寄与しているかを選択します。

EDIT私はロード時に手動で頂点データを再パックすることを忘れていました。 APIはインデックス付きレンダリングをネイティブにサポートしています(共有バーテックスは一度しか処理されないため、はるかに効率的です)。

+0

私は 'glDrawElements'を試しました。同じ結果です。.objファイルにはインデックス情報が含まれていないため、単に0から三角形の数にインデックスを付ける必要があります。 –

+0

'ロード時に頂点データを手動で再パックします - クリアしてください。 –

+0

"... .objファイルにインデックス情報が含まれていないため"。はい、彼らがやります。 "f"で始まる行は何だと思いますか?あなたはすでにそれらをデコードしてインデックスとして使用しています... – solidpixel

関連する問題