2011-07-05 9 views
0

頂点とそのプロパティを持つバイナリファイルを解析しています。これらのファイルの範囲は50,000〜200,000の頂点です。下位のファイルについては、配列の割り当てとポイントの描画に問題はありませんが、ファイルが大きい場合は大きな問題です。私のようなfloatbufferを作成するとAndroid OpenGL OutOfMemory(バッファ割り当て)

FloatBuffer buf = ByteBuffer.allocateDirect(vertices.length * 4); 

私は時々のOutOfMemoryエラーが発生します。これは私が描く唯一のバッファではない、私はまた色をする。頂点を描画するか、バッファにバッファに割り当てるより良い方法がありますか?毎回描画しますか? new ProgressTask(ctx).execute();だけで解析し、配列を移入し

public PointCloud(String passedFileName, Context ctx) { 

    fileName = passedFileName; 
    header = new LAS_HeadParser(fileName); 
    numVertices = (int)header.numberOfPoints; 

    lasVertices = new float[numVertices*3]; 
    lasColors = new float[numVertices*4]; 
    intensity = new float[numVertices]; 
    vbb = ByteBuffer.allocateDirect(lasVertices.length * 4); 
    cbb = ByteBuffer.allocateDirect(lasColors.length * 4); 

    new ProgressTask(ctx).execute(); 
} 
public void setupBuffers(){ 
    // a float is 4 bytes, therefore we multiply the number if 
    // vertices with 4. 

    vbb.order(ByteOrder.nativeOrder()); 
    vertexBuffer = vbb.asFloatBuffer(); 
    vertexBuffer.put(lasVertices); 
    vertexBuffer.position(0); 

    cbb.order(ByteOrder.nativeOrder()); 
    colorBuffer = cbb.asFloatBuffer(); 
    colorBuffer.put(lasColors); 
    colorBuffer.position(0); 
} 

public void draw(GL10 gl) { 
    //Log.d("Enter Draw", "*****************"); 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glEnableClientState(GL10.GL_COLOR_ARRAY); 
    gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer); 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
    gl.glPointSize(0.6f); 
    gl.glDrawArrays(GL10.GL_POINTS, 0, numVertices); 
    gl.glDisableClientState(GL10.GL_COLOR_ARRAY); 
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
} 

コール:ここで私が使用していますいくつかの基本的な描画コードです。私は継続的にファイルを解析する余裕がない、それは時間がかかります。どのようなオプションがありますか?

+0

どのコード行がOutOfMemoryエラーを投げていますか? – DoomGoober

+0

@DoomGoober - vbb = ByteBuffer.allocateDirect(lasVertices.length * 4); – RedLeader

答えて

1

1)私はあなたが何をレンダリングしているのかはわかりませんが、50,000個のGL_POINTをレンダリングするのはむしろ奇妙なようです。 GL_TRIANGLE_STRIPまたはGL_TRIANGLE_FANを使用してポリゴンをレンダリングする場合は、データの最適化の程度に応じて、おそらく半分または3分の1の頂点数を削減できます。

2)頂点とカラーバッファへの参照が2つあることがあります。ドキュメントによると、allocateDiretは中間メモリにマップするか、バイト全体をコピーするだけかもしれません。ガベージコレクタは、lasVerticesとlasColorsを、それらをメンバ変数にするのではなく、PointCloudコンストラクタのローカル変数にすることでクリーンアップさせます。 (または、メンバーでなければならない場合は、ByteBuffersに入れた後にnullに設定します)。このように、ByteBufferがデータをコピーしている場合、2つのコピーはありません。

+0

返信いただきありがとうございます。私はポイントの数についてのあなたの考えを理解していますが、それは必要です。また、これはシェイプでレンダリングされるはずではありません(もしそうであれば、別のインデックス配列もありません)。 Androidの使用可能アプリのメモリをどうにか増やすことはできますか?再度、感謝します! – RedLeader

+0

あなたのコードには、レンダリングに実際に必要な3つの一時バッファと2つのバッファがあります。まず、可能であれば、強度と呼ばれる余分な未使用バッファを殺す。次に、可能な場合は、コードを次のように再配置します。一時的な割り当て、一時的なByteBufferへのコピー。一時的に「リリース」します。次の一時的な割り当て、一時的なByteBufferへのコピー。一時的に「リリース」します。 ByteBuffersをレンダリングします。たいていの場合、メモリにはN + 1個のバッファしか存在しません.Nはレンダリングコールに必要なバッファの数です。現時点では、メモリにN + 2個のバッファがあります(強度が使用されていないと仮定します)。 – DoomGoober

+0

リリース時とは、「バッファへの参照を削除してガベージコレクタでクリーンアップできる」という意味です。私はJavaのガベージコレクターに精通しているわけではありませんが、十分なメモリがない状態で割り当てを実行すると仮定します。 lasVertices = nullのようなものは、そのバイト配列への他の参照がないと仮定して、このトリックを行う必要があります。 – DoomGoober