Android - How do I add textures to my model?

July 31, 2012 - 11:51am #1
Adding textures at startup

Adding new textures at startup is easy. Using any of the sample applications, follow these steps:

  1. Add the texture images to the assets folder.
  2. In the main activity class (e.g. ImageTargets.java) find the loadTextures() method. Add additional calls to mTextures.add for each of your image files. Note that the order in which the textures are added determines their order in the native texture array.
  3. In the native renderFrame() method (e.g. in ImageTargets.cpp) find the point at which the texture object is obtained (textures[textureIndex]). Change the texture index to select the desired texture. The indices start at 0, where index 0 is the first texture added in the loadTextures() Java method.
Adding textures at runtime

Sometimes, it might be preferable to create textures at runtime, for example when the texture image is downloaded from a server. First, we need a method to load a texture from a bitmap rather than from the APK. The loadTextureFromApk() method in Texture.java can be easily modified for this purpose:

 

public static Texture loadTextureFromBitmap(Bitmap bitMap)
{

    int[] data = new int[bitMap.getWidth() * bitMap.getHeight()];
    bitMap.getPixels(data, 0, bitMap.getWidth(), 0, 0, bitMap.getWidth(), bitMap.getHeight());
    // Convert:
    byte[] dataBytes = new byte[bitMap.getWidth() * bitMap.getHeight() * 4];

    for (int p = 0; p < bitMap.getWidth() * bitMap.getHeight(); ++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 = bitMap.getWidth();
    texture.mHeight = bitMap.getHeight();
    texture.mChannels = 4;
    texture.mData = dataBytes;

    return texture;
}

Next, we need a native method for creating the OpenGL texture. Here is a version that can be added to ImageTargets.cpp:

Texture* myTexture = NULL;

JNIEXPORT void JNICALL
Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_createGLTextureNative(
                                                    JNIEnv* env, jobject obj, jobject textureObject)
{
    if (textureObject != NULL)
    {
        myTexture = Texture::create(env, textureObject);

        glGenTextures(1, &(myTexture->;mTextureID));
        glBindTexture(GL_TEXTURE_2D, myTexture->;mTextureID);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexture->;mWidth,
                     myTexture->;mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     (GLvoid*) myTexture->;mData);
    }
}

 

Add the corresponding method signature to ImageTargetsRenderer.java:

public native void createGLTextureNative(Texture texture);

public void createGLTexture(Texture texture)
{
    createGLTextureNative(texture);
}

 

When you are done with the native texture, be sure to call glDeleteTextures to delete the GL texture. Also delete the Texture object. You may also need to free the Android Bitmap using Bitmap.recycle().

Topic locked