2011-07-05 121 views
0

我正在解析一個包含頂點及其屬性的二進制文件。這些文件的範圍從50,000-2,000,000個頂點。對於較低的文件,我沒有問題直接分配數組並繪製點,但對於較大的文件,這是一個很大的問題。Android OpenGL OutOfMemory(分配緩衝區)

當我創建一個floatbuffer這樣:

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

我有時會內存溢出錯誤。這不是我繪製的唯一緩衝區,我也是彩色的。有沒有更好的方式繪製頂點或動態分配到緩衝區,並且每次繪製?下面是我使用一些基本的繪圖代碼:

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); 
} 

呼叫new ProgressTask(ctx).execute();只是解析並填充陣列。我無法繼續解析文件,這需要很長時間。我有什麼選擇?

+0

哪行代碼拋出了OutOfMemory錯誤? – DoomGoober

+0

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

回答

1

1)我不知道你在渲染什麼,但渲染50,000 GL_POINT似乎很奇怪。如果您要渲染多邊形(使用GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN),則可以將頂點的數量減半或減至三分之一,具體取決於優化數據的程度。

2)您可能持有兩個對頂點和顏色緩衝區的引用。根據文檔allocateDiret可能映射到中間內存 - 或者它可能只是複製整個字節[]。讓垃圾收集器通過在PointCloud構造函數中使它們成爲局部變量來清理lasVertices和lasColors,而不是使它們成爲成員變量。 (或者如果它們必須是成員,則在將它們放入ByteBuffers後將它們設置爲null)。這樣,如果ByteBuffer正在複製數據,則不會有兩個副本。

+0

謝謝你的回覆。我理解你對#點的想法,然而這是必要的。此外,這不應該與形狀呈現(如果它是,我不會有另一個索引數組?)。我能否以某種方式增加Android的可用應用內存?再次感謝! – RedLeader

+0

您的代碼有3個臨時緩衝區和2個緩衝區實際需要進行渲染。首先,如果可以,請殺掉稱爲強度的額外未使用的緩衝區。接下來,如果可能的話,像這樣重新安排你的代碼:分配臨時的,臨時複製到ByteBuffer。 「釋放」臨時。分配下一個臨時的,臨時複製到ByteBuffer。 「釋放」臨時。渲染字節緩衝區。最多隻能在內存中擁有N + 1個緩衝區,其中N是渲染調用所需的緩衝區數量。目前,你在內存中有N + 2個緩衝區(假設沒有使用強度)。 – DoomGoober

+0

順便說一下,當我說釋放時,我的意思是「移除對緩衝區的引用,以便垃圾收集器清理它們。我對Java的垃圾回收器並不是很熟悉,但我認爲它在分配時運行時沒有足夠的內存。像lasVertices = null這樣的東西應該做的伎倆,假設你沒有其他引用該字節數組。 – DoomGoober