Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android OpenGL: IllegalArgumentException use native order direct buffer

android developers! I'm in trouble. My android app has to draw a few lines using OpenGL. I started off with this as example and rewrote it. It throws up the IllegalArgumentException: must use a native order direct Buffer when calling GLES20.glVertexAttribPointer. I don't understand why, since I set it to the nativeorder, like in the example I used. Here's my complete OpenGLRenderer class: (I use the second constructor with the float[] parameter when creating an instance of this class)

public class OpenGLRenderer implements GLSurfaceView.Renderer {

        final int COORDS_PER_VERTEX = 3;
        final int NR_OF_LINES; 
        final int NR_OF_VERTECES;
        final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
        final int NR_OF_VERTECES_PER_LINE = 2;
        final int BYTES_PER_VERTEX = 4;


    private FloatBuffer bufferVertecesLines;
    private float[] arrayVertecesLines;
    //private FloatBuffer ColorBuffer;      
    // Set color with red, green, blue and alpha (opacity) values
    float color[] = { 0.3f, 0.7f, 0.2f, 1.0f };

    private int GlProgram;
    private int PositionHandle;
    private int ColorHandle;


    //SHADERS----------------------------------------------------------------------------------------------------------------------------
    private final String VertexShaderCode =
            // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform mat4 uMVPMatrix;" +

        "attribute vec4 vPosition;" +
        "void main() {" +
        // the matrix must be included as a modifier of gl_Position
        "  gl_Position = uMVPMatrix * vPosition;" +
        "}";

    private final String FragmentShaderCode =
            "precision mediump float;" +
        "uniform vec4 vColor;" +
        "void main() {" +
        "  gl_FragColor = vColor;" +
        "}";


    //CONSTRUCTOR----------------------------------------------------------------------------------------------------------------------------
    public OpenGLRenderer(FloatBuffer thisLineVertexBuffer, int numberoflines)
    {

        bufferVertecesLines = thisLineVertexBuffer; 
        NR_OF_VERTECES = numberoflines * 2;
        NR_OF_LINES = numberoflines;
        Log.v("Leen","mijn eigen logje - OpenGLRenderer - Constructor");
    }

    public OpenGLRenderer(float[] thisLineVertexArray)
    {
        arrayVertecesLines = thisLineVertexArray;
        NR_OF_VERTECES = thisLineVertexArray.length / COORDS_PER_VERTEX;
        NR_OF_LINES = thisLineVertexArray.length / COORDS_PER_VERTEX / NR_OF_VERTECES_PER_LINE; 
    }

    private void convertArrayToBuffer()
    {
        int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
        // in voorbeeld:
        // NrOfBytes =          2   *           2           *           3           *       4       =   48                   

        ByteBuffer bb = ByteBuffer.allocate(NrOfBytes);
        bb.order(ByteOrder.nativeOrder());
        bufferVertecesLines = bb.asFloatBuffer();
        bufferVertecesLines.put(arrayVertecesLines);

    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    @Override
    public void onSurfaceChanged(GL10 unused, int width, int height) 
    {
        // Adjust the viewport based on geometry changes,
        // such as screen rotation
        GLES20.glViewport(0, 0, width, height);
    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    @Override
    public void onDrawFrame(GL10 arg0) 
    {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);

        GlProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
        GLES20.glAttachShader(GlProgram, vertexShader);   // add the vertex shader to program
        GLES20.glAttachShader(GlProgram, fragmentShader); // add the fragment shader to program
        GLES20.glLinkProgram(GlProgram);                  // creates OpenGL ES program executables

        this.drawAllLines();
    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    @Override
    public void onSurfaceCreated(GL10 unused, EGLConfig config) 
    {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }


    //---------------------------------------------------------------------------------------------------------------------------------------   
    public static int loadShader(int type, String shaderCode){

        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(type);

        // add the source code to the shader and compile it
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;

    }

    //---------------------------------------------------------------------------------------------------------------------------------------
    public void drawAllLines()
    {
        // Add program to OpenGL ES environment
        GLES20.glUseProgram(GlProgram);

        // get handle to vertex shader's vPosition member
        PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(PositionHandle);

        // Prepare the Line coordinate data
        // vertexstride = offset. 3 coordinaten per vertex * 4 bytes per vertex = 12

        this.convertArrayToBuffer();

        GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
                                             GLES20.GL_FLOAT, false,
                                             VertexStride, bufferVertecesLines);

        // get handle to fragment shader's vColor member
        ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");

        // Set color for drawing the triangle
        GLES20.glUniform4fv(ColorHandle, 1, color, 0);

        // Draw the triangle
        GLES20.glDrawArrays(GLES20.GL_LINES, 0, NR_OF_VERTECES);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(PositionHandle);

    }

}
like image 686
blubbiedevis Avatar asked Oct 25 '13 15:10

blubbiedevis


3 Answers

OK, found it. I didn't use the ByteBuffer.allocate() method, but the ByteBuffer.allocateDirect() - method. This piece is throwing no exceptions:

private void convertArrayToBuffer()
{
    int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
    // in voorbeeld:
    // NrOfBytes =          2   *           2           *           3           *       4       =   48                   

    ByteBuffer bb = ByteBuffer.allocateDirect(NrOfBytes);       //!!!!!!!!!!
    bb.order(ByteOrder.nativeOrder());
    bufferVertecesLines = bb.asFloatBuffer();
    bufferVertecesLines.put(arrayVertecesLines);
    bb.position(0);                 
    bufferVertecesLines.position(0);
}
like image 162
blubbiedevis Avatar answered Sep 29 '22 11:09

blubbiedevis


private void convertArrayToBuffer()
{
    int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
    // in voorbeeld:
    // NrOfBytes =          2   *           2           *           3           *       4       =   48                   

    ByteBuffer bb = ByteBuffer.allocate(NrOfBytes);
    bb.order(ByteOrder.nativeOrder());
    bufferVertecesLines = bb.asFloatBuffer();
    bufferVertecesLines.put(arrayVertecesLines);
    bb.position(0);                 //!!!!!!!!!!!!!
    bufferVertecesLines.position(0);//!!!!!!!!!!!!!
}
like image 38
vadimvolk Avatar answered Sep 29 '22 12:09

vadimvolk


I have encountered the same problem, and I find the answer at enter link description here. use allocateDirect instead of allocate, the bb needs to be direct so it isn't move around the memeory.

like image 34
peng tom Avatar answered Sep 29 '22 12:09

peng tom