android - Vuforia 6.0.117 0x501 error when rendering texture


Keywords:android 


Question: 

I'm trying to get Vuforia 6.0.117 working in my Android app. I'm using this specific version since its the last version supporting FrameMarkers. The detection of FrameMarkers is working fine, but when i'm trying to render a texture over the FrameMarker on my phone I get an error stating:

After operation FrameMarkers render frame got glError 0x501

My renderFrame method:

// Clear color and depth buffer
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    // Get the state from Vuforia and mark the beginning of a rendering
    // section
    State state = Renderer.getInstance().begin();

    // Explicitly render the Video Background
    Renderer.getInstance().drawVideoBackground();

    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendEquation(GLES20.GL_FUNC_ADD);

// GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    // We must detect if background reflection is active and adjust the
    // culling direction.
    // If the reflection is active, this means the post matrix has been
    // reflected as well,
    // therefore standard counter clockwise face culling will result in
    // "inside out" models.
    GLES20.glEnable(GLES20.GL_CULL_FACE);
    GLES20.glCullFace(GLES20.GL_BACK);
    if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON) {
        GLES20.glFrontFace(GLES20.GL_CW);  // Front camera
    } else {
        GLES20.glFrontFace(GLES20.GL_CCW);   // Back camera
    }

    // Did we find any trackables this frame?
    if (mActivity.isHelpVisible() || state.getNumTrackableResults() == 0) {
        // no marker scanned
        mActivity.hideInfoButton();
    } else {
        // Get the trackable:
        TrackableResult trackableResult = state.getTrackableResult(0);
        float[] modelViewMatrix = Tool.convertPose2GLMatrix(trackableResult.getPose()).getData();

        // Check the type of the trackable:
        MarkerResult markerResult = (MarkerResult) trackableResult;
        Marker marker = (Marker) markerResult.getTrackable();

        if (markerId != marker.getMarkerId()) {
            markerId = marker.getMarkerId();
            tag = DataManager.getInstance().getTagByMarkerId(markerId);
            if (tag != null) {
                texture = Texture.loadTexture(tag.getTexture());
                setupTexture(texture);
                tag.addToDB();
            }
        }

        if (tag != null) {
            String poiReference = tag.getPoiReference();
            if (!poiReference.isEmpty()) {
                mActivity.showInfoButton(poiReference);
            }

            // Select which model to draw:
            Buffer vertices = planeObject.getVertices();
            Buffer normals = planeObject.getNormals();
            Buffer indices = planeObject.getIndices();
            Buffer texCoords = planeObject.getTexCoords();
            int numIndices = planeObject.getNumObjectIndex();

            float[] modelViewProjection = new float[16];

            float scale = (float) tag.getScale();
            Matrix.scaleM(modelViewMatrix, 0, scale, scale, scale);

            Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession.getProjectionMatrix().getData(), 0, modelViewMatrix, 0);

            GLES20.glUseProgram(shaderProgramID);

            GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 0, vertices);
            GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 0, normals);
            GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, texCoords);

            GLES20.glEnableVertexAttribArray(vertexHandle);
            GLES20.glEnableVertexAttribArray(normalHandle);
            GLES20.glEnableVertexAttribArray(textureCoordHandle);

            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.mTextureID[0]);
            GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, modelViewProjection, 0);
            GLES20.glUniform1i(texSampler2DHandle, 0);
            GLES20.glDrawElements(GLES20.GL_TRIANGLES, numIndices, GLES20.GL_UNSIGNED_SHORT, indices);

            GLES20.glDisableVertexAttribArray(vertexHandle);
            GLES20.glDisableVertexAttribArray(normalHandle);
            GLES20.glDisableVertexAttribArray(textureCoordHandle);

            SampleUtils.checkGLError("FrameMarkers render frame");
        }
    }

    GLES20.glDisable(GLES20.GL_DEPTH_TEST);

    Renderer.getInstance().end();

}

I'm loading a texture of the size 640x482 and is loading as follows:

public class Texture {

public int mWidth;          // The width of the texture.
public int mHeight;         // The height of the texture.
public int mChannels;       // The number of channels.
public ByteBuffer mData;    // The pixel data.
public int[] mTextureID = new int[1];
public boolean mSuccess = false;

public static Texture loadTexture(String fileName) {

    try {
        InputStream inputStream = new FileInputStream(fileName);
        BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);

        Bitmap bitMap = BitmapFactory.decodeStream(bufferedStream);

        bufferedStream.close();
        inputStream.close();

        int[] data = new int[bitMap.getWidth() * bitMap.getHeight()];
        bitMap.getPixels(data, 0, bitMap.getWidth(), 0, 0, bitMap.getWidth(), bitMap.getHeight());

        return loadTextureFromIntBuffer(data, bitMap.getWidth(), bitMap.getHeight());
    } catch (IOException e) {
        Log.e(Constants.DEBUG, "Failed to load texture '" + fileName + "' from APK");
        Log.i(Constants.DEBUG, e.getMessage());
        return null;
    }
}

public static Texture loadTextureFromIntBuffer(int[] data, int width, int height) {
    // Convert:
    int numPixels = width * height;
    byte[] dataBytes = new byte[numPixels * 4];

    for (int p = 0; p < numPixels; ++p) {
        int colour = data[p];
        dataBytes[p * 4] = (byte) (colour >>> 16); // R
        dataBytes[p * 4 + 1] = (byte) (colour >>> 8); // G
        dataBytes[p * 4 + 2] = (byte) colour; // B
        dataBytes[p * 4 + 3] = (byte) (colour >>> 24); // A
    }

    Texture texture = new Texture();
    texture.mWidth = width;
    texture.mHeight = height;
    texture.mChannels = 4;

    texture.mData = ByteBuffer.allocateDirect(dataBytes.length).order(ByteOrder.nativeOrder());
    int rowSize = texture.mWidth * texture.mChannels;
    for (int r = 0; r < texture.mHeight; r++) {
        texture.mData.put(dataBytes, rowSize * (texture.mHeight - 1 - r), rowSize);
    }

    texture.mData.rewind();

    texture.mSuccess = true;

    return texture;
}

}

Anybody got an idea why i'm getting this error and how to fix it?


1 Answer: 

I cannot go over your entire code right now, and even if I could I'm not sure it would help. You first need to narrow down the problem, so I will first give you the method to do that, and I hope it will serve you in other cases as well.

You managed to find out that there was an error - but you are checking it only at the end of the rendering function. What you need to do is to place the checkGLError call in several places inside the rendering code (print a different text message), until you can pin-point the exact line after which the error first appears. Then, if you cannot understand the problem, comment here what is the problematic line and I will try to help.

UPDATE:

After looking at the shader code, following your report that normalHandle is -1, I got to the following conclusions:

The error, which indicates the variable vertexNormal cannot be found in the shader, may be due to the fact that this variable is probably optimized out during shader compilation, since it is not really required.

Explanation: in the vertex shader (CUBE_MESH_VERTEX_SHADER), vertexNormal is assigned to a varying called normal (variable that is passed to the fragment shader). In the fragment shader, this varying is declared but not used. Therefore, you can actually delete the variables vertexNormal and normal from the shader, and you can delete all usages of 'normalHandle' in your code.

This should eliminate the error.