2011-07-05 5 views
0

저는 정점과 그 속성을 가진 이진 파일을 구문 분석합니다. 이 파일의 범위는 50,000-2,000,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을 사용하여) 폴리곤을 렌더링하는 경우 데이터를 얼마나 잘 최적화했는지에 따라 정점 수를 반 또는 세 번째로 줄일 수 있습니다.

2) 버텍스 및 색상 버퍼에 대한 두 개의 참조가있을 수 있습니다. 문서에 따르면 allocateDiret는 중간 메모리에 매핑 할 수도 있고 아니면 그냥 전체 바이트 []를 복사 할 수도 있습니다. 가비지 컬렉터가 멤버 변수가 아닌 PointCloud 생성자에서 로컬 변수를 만들어 lasVertices 및 lasColors를 정리하도록합니다. (또는 멤버가되어야하는 경우 ByteBuffers에 넣은 후 null로 설정하십시오.) 그런 식으로 ByteBuffer가 데이터를 복사하는 경우 두 개의 복사본이 없습니다.

+0

답장을 보내 주셔서 감사합니다. 포인트 수에 대한 귀하의 생각을 이해하지만 필요한 부분입니다. 또한, 이것은 셰이프로 렌더링되지 않아야합니다 (그렇다면 인덱스의 배열이 아직 없습니까?). 어떻게하면 Android의 사용 가능한 앱 메모리를 늘릴 수 있습니까? 다시 한 번 감사드립니다! – RedLeader

+0

코드에는 렌더링을 위해 실제로 필요한 3 개의 임시 버퍼와 2 개의 버퍼가 있습니다. 우선, 가능한 경우 강도라고하는 여분의 사용되지 않는 버퍼를 제거하십시오. 가능한 경우 다음과 같이 코드를 재정렬하십시오. 임시 할당, 임시 임시 복사, ByteBuffer. 임시 "릴리스". 다음 임시를 할당하고 임시로 ByteBuffer에 복사합니다. 임시 "릴리스". ByteBuffers 렌더링. 기껏해야 메모리에 N + 1 개의 버퍼 만 있어야합니다. N은 렌더링 호출에 필요한 버퍼의 수입니다. 현재 메모리에 N + 2 버퍼가 있습니다 (강도가 사용되지 않는다고 가정합니다). – DoomGoober

+0

BTW, 출시 할 때 "가비지 수집기가 버퍼를 정리할 수 있도록 버퍼에 대한 참조를 제거하십시오"라는 의미입니다. Java의 가비지 수집기에 익숙하지는 않지만 메모리가 충분하지 않은 상태로 할당을 실행한다고 가정합니다. lasVertices = null과 같은 것은 그 바이트 배열에 대한 다른 참조가 없다는 가정하에 트릭을 수행해야합니다. – DoomGoober