MrMysterious2502
MrMysterious2502

Reputation: 105

Android OpenGLES2.0 - Solid Black Textures When Rendered

I've been making an Android OpenGLES2.0 2D game engine for the past week or so, and after a few bumps in the road, I've largely been successful. I've got the ModelMatrix, ProjectionMatrix, ViewMatrix, LightMatrix, shaders, 2D planes, and textures implemented. However, although my data is seemingly passing through this jungle of pipeline just fine, my textures do not appear, and are instead a solid black.

Most, if not all of my code was derived from this source, and it is ultimately the same, except that I created my own shader class, bounding box class, room class, and game object class to simplify the process of instantiating objects in-game. Renderer takes Room, Room takes GameObject(s) (SpaceShip extends game object), and GameObject takes BoundingBox, then Renderer renders the room's objects in a for loop. To do this, I moved the exact code from the example around so that certain handles are elements of some of the classes I created, instead of being elements of the renderer. This hasn't caused any problems with matrix multiplication or my data reaching the end of the pipeline, so I doubt moving the handles is the problem, but I felt it was important to know.

Things I've tried:

  1. Changing the bitmap
    • Changed it to a bitmap with no alpha channel, both were 32x32 (2^5) and were .png.
  2. Changing the order of operations
    • I moved glBindTexture in my implementation, so I moved it back, then back again.
  3. Changing the texture parameters
    • I tried several combinations, none with mip-mapping
  4. Changing the way I load the image
    • Went from BitmapFactory.decodeResource to BitmapFactory.decodeStream
  5. Moved the texture to all drawable folders
    • Also tried it in the raw folder
  6. Tried it on another device
    • My friend's DROID (Froyo 2.2), My rooted NextBook (Gingerbread 2.3). Both support OpenGLES2.0.

Thigs I haven't tried (That I'm aware of):

  1. Changing the texture coordinates
    • They came directly from the example. I just took one face of the cube.
  2. Changing my shader
    • It also came directly from the example (aside from it being it's own class now).
  3. Restructuring my program to be just two (3, 4... x) classes
    • Dude...

I've been testing on the emulator (Eclipse Indigo, AVD, Intel Atom x86, ICS 4.2.2, API level 17) for some time now, and right about the time I got all the matrixes working, the emulator failed to render anything. It used to render just fine (when the projection was all screwy), now it just shows up black with a titlebar. This has made debugging incredibly difficult. I'm not sure if this is something related to what I've done (probably is) or if it is related to the emulator sucking at OpenGL.

Sorry to be so long winded and include so much code, but I don't know how to use a show/hide button.

Any ideas?

Edit: I was using the wrong shader from the example. The naming was very misleading. I wasn't passing in the color info. I still don't have texture, but the emulator works again. :)

OpenGLES20_2DRenderer

package mycompany.OpenGLES20_2DEngine;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

public class OpenGLES20_2DRenderer implements GLSurfaceView.Renderer {

/** Used for debug logs. */
private static final String TAG = "Renderer";

//Matrix Declarations*************************
/**
 * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
 * of being located at the center of the universe) to world space.
 */
private float[] mModelMatrix = new float[16];
/**
 * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
 * it positions things relative to our eye.
 */
private float[] mViewMatrix = new float[16];
/** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
private float[] mProjectionMatrix = new float[16];
/** Allocate storage for the final combined matrix. This will be passed into the shader program. */
private float[] mMVPMatrix = new float[16];
/**
 * Stores a copy of the model matrix specifically for the light position.
 */
private float[] mLightModelMatrix = new float[16];

//********************************************

//Global Variable Declarations****************
//Shader
Shader shader;
//PointShader
PointShader pointShader;
//Application Context
Context context;
//A room to add objects to
Room room;
//********************************************

public OpenGLES20_2DRenderer(Context ctx) {
    context = ctx;
}

public void onSurfaceCreated(GL10 unused, EGLConfig config) {

    //Initialize GLES20***************************
    // Set the background frame color
    GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    // Use culling to remove back faces.
    GLES20.glEnable(GLES20.GL_CULL_FACE);
    // Enable depth testing
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    // Position the eye in front of the origin.
    final float eyeX = 0.0f;
    final float eyeY = 0.0f;
    final float eyeZ = -0.5f;
    // We are looking toward the distance
    final float lookX = 0.0f;
    final float lookY = 0.0f;
    final float lookZ = -5.0f;
    // Set our up vector. This is where our head would be pointing were we holding the camera.
    final float upX = 0.0f;
    final float upY = 1.0f;
    final float upZ = 0.0f;
    // Set the view matrix. This matrix can be said to represent the camera position.
    // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
    // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
    Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);    
    //********************************************

    //Initialize Shaders**************************
    shader = new Shader();
    pointShader = new PointShader();
    //********************************************

    //Load The Level******************************
    //Create a new room
    room = new Room(800,600, 0);
    //Load game objects
    SpaceShip user = new SpaceShip();
    //Load sprites
    for(int i=0;i<room.numberOfGameObjects;i++) {
        room.gameObjects[i].spriteGLIndex = room.gameObjects[i].loadSprite(context, room.gameObjects[i].spriteResId);   
    }
    //Add them to the room
    room.addGameObject(user);
    //********************************************

}

public void onDrawFrame(GL10 unused) {

    //Caclulate MVPMatrix*************************
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    // Set our per-vertex lighting program.
    GLES20.glUseProgram(shader.mProgram);
    // Set program handles for object drawing.
    shader.mMVPMatrixHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_MVPMatrix");
    shader.mMVMatrixHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_MVMatrix");
    shader.mLightPosHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_LightPos");
    shader.mTextureUniformHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_Texture");
    shader.mPositionHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Position");
    shader.mColorHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Color");
    shader.mNormalHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Normal");
    shader.mTextureCoordinateHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_TexCoordinate");

    // Calculate position of the light. Rotate and then push into the distance.
    Matrix.setIdentityM(mLightModelMatrix, 0);
    Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -5.0f);
    Matrix.rotateM(mLightModelMatrix, 0, 0, 0.0f, 1.0f, 0.0f);
    Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 2.0f);
    Matrix.multiplyMV(shader.mLightPosInWorldSpace, 0, mLightModelMatrix, 0, shader.mLightPosInModelSpace, 0);
    Matrix.multiplyMV(shader.mLightPosInEyeSpace, 0, mViewMatrix, 0, shader.mLightPosInWorldSpace, 0); 
    //********************************************

    //Draw****************************************
    //Draw the background
    //room.drawBackground(mMVPMatrix);
    // Draw game objects
    for(int i=0;i<room.numberOfGameObjects;i++) {

        // Set the active texture unit to texture unit 0.
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        // Bind the texture to this unit.
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, room.gameObjects[i].spriteGLIndex);
        // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
        GLES20.glUniform1i(shader.mTextureUniformHandle, 0);

        //Set up the model matrix
        Matrix.setIdentityM(mModelMatrix, 0);
        Matrix.translateM(mModelMatrix, 0, 4.0f, 0.0f, -7.0f);
        Matrix.rotateM(mModelMatrix, 0, room.gameObjects[i].rotation, 1.0f, 0.0f, 0.0f); 

        //Draw the object
        room.gameObjects[i].draw(mModelMatrix, mViewMatrix, mProjectionMatrix, mMVPMatrix, shader);
    }
    //********************************************

    // Draw a point to indicate the light.********
    drawLight();
    //********************************************

}

public void onSurfaceChanged(GL10 unused, int width, int height) {

    //Initialize Projection Matrix****************
    // Set the OpenGL viewport to the same size as the surface.
    GLES20.glViewport(0, 0, width, height);
    // Create a new perspective projection matrix. The height will stay the same
    // while the width will vary as per aspect ratio.
    final float ratio = (float) width / height;
    final float left = -ratio;
    final float right = ratio;
    final float bottom = -1.0f;
    final float top = 1.0f;
    final float near = 1.0f;
    final float far = 10.0f;
    Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
    //********************************************

}

// Draws a point representing the position of the light.
private void drawLight()
{
    GLES20.glUseProgram(pointShader.mProgram);
    final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(pointShader.mProgram, "u_MVPMatrix");
    final int pointPositionHandle = GLES20.glGetAttribLocation(pointShader.mProgram, "a_Position");
    // Pass in the position.
    GLES20.glVertexAttrib3f(pointPositionHandle, shader.mLightPosInModelSpace[0], shader.mLightPosInModelSpace[1], shader.mLightPosInModelSpace[2]);
    // Since we are not using a buffer object, disable vertex arrays for this attribute.
    GLES20.glDisableVertexAttribArray(pointPositionHandle);
    // Pass in the transformation matrix.
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    // Draw the point.
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
}

Shader

package mycompany.OpenGLES20_2DEngine;

import android.opengl.GLES20;
import android.util.Log;

public class Shader {

/** Used for debug logs. */
private static final String TAG = "Shader";

//Shaders*************************************
public int vertexShader;
public int fragmentShader;
//********************************************

//Handles*************************************
/** This will be used to pass in model position information. */
public int mPositionHandle;
/** This will be used to pass in model color information. */
public int mColorHandle;
/** This will be used to pass in model normal information. */
public int mNormalHandle;
/** This will be used to pass in model texture coordinate information. */
public int mTextureCoordinateHandle;
/** This will be used to pass in the transformation matrix. */
public int mMVPMatrixHandle;
/** This will be used to pass in the modelview matrix. */
public int mMVMatrixHandle;
/** This will be used to pass in the light position. */
public int mLightPosHandle;
/** This will be used to pass in the texture. */
public int mTextureUniformHandle;
/** Used to hold a light centered on the origin in model space. We need a 4th coordinate so we can get translations to work when
 * we multiply this by our transformation matrices. */
public final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
/** Used to hold the current position of the light in world space (after transformation via model matrix). */
public final float[] mLightPosInWorldSpace = new float[4];
/** Used to hold the transformed position of the light in eye space (after transformation via modelview matrix) */
public final float[] mLightPosInEyeSpace = new float[4];
//********************************************

//GL Code For Shaders*************************
public final String vertexShaderCode =
    // A constant representing the combined model/view/projection matrix.
    "uniform mat4 u_MVPMatrix;" + "\n" + 
    // A constant representing the combined model/view matrix.
    "uniform mat4 u_MVMatrix;" + "\n" + 
    // Per-vertex position information we will pass in.
    "attribute vec4 a_Position;" + "\n" + 
    // Per-vertex normal information we will pass in.
    "attribute vec3 a_Normal;" + "\n" + 
    // Per-vertex texture coordinate information we will pass in.
    "attribute vec2 a_TexCoordinate;" + "\n" + 
    // This will be passed into the fragment shader.
    "varying vec3 v_Position;" + "\n" + 
    // This will be passed into the fragment shader.
    "varying vec3 v_Normal;" + "\n" + 
    // This will be passed into the fragment shader.
    "varying vec2 v_TexCoordinate;" + "\n" + 

    // The entry point for our vertex shader.
    "void main()" + "\n" +
        "{" + "\n" +
        // Transform the vertex into eye space.
        "v_Position = vec3(u_MVMatrix * a_Position);" + "\n" +
        // Pass through the texture coordinate.
        "v_TexCoordinate = a_TexCoordinate;" + "\n" +
        // Transform the normal's orientation into eye space.
        "v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));" + "\n" +
        // gl_Position is a special variable used to store the final position.
        // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
        "gl_Position = u_MVPMatrix * a_Position;" + "\n" +
    "}";
public final String fragmentShaderCode =
    "precision mediump float;" + "\n" +  // Set the default precision to medium. We don't need as high of a
    // precision in the fragment shader.
    "uniform vec3 u_LightPos;" + "\n" +  // The position of the light in eye space.
    "uniform sampler2D u_Texture;" + "\n" +  // The input texture.
    "varying vec3 v_Position;" + "\n" +  // Interpolated position for this fragment.
    "varying vec3 v_Normal;" + "\n" +  // Interpolated normal for this fragment.
    "varying vec2 v_TexCoordinate;" + "\n" +  // Interpolated texture coordinate per fragment.

    // The entry point for our fragment shader.
    "void main()" + "\n" + 
    "{" + "\n" + 
        // Will be used for attenuation.
        "float distance = length(u_LightPos - v_Position);" + "\n" + 
        // Get a lighting direction vector from the light to the vertex.
        "vec3 lightVector = normalize(u_LightPos - v_Position);" + "\n" + 
        // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
        // pointing in the same direction then it will get max illumination.
        "float diffuse = max(dot(v_Normal, lightVector), 0.0);" + "\n" + 
        // Add attenuation.
        "diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance)));" + "\n" + 
        // Add ambient lighting
        "diffuse = diffuse + 0.7;" + "\n" + 
        // Multiply the color by the diffuse illumination level and texture value to get final output color.
        "gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));" + "\n" + 
    "}";
//********************************************

//GL Program Handle***************************
public int mProgram;
//********************************************

public Shader() {

    //Load Shaders********************************
    vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
    //********************************************

    //Create GL Program***************************
    mProgram = createAndLinkProgram(vertexShader, fragmentShader, new String[] {"a_Position",  "a_Color", "a_Normal", "a_TexCoordinate"});
    //********************************************

}

/**
 * Helper function to compile a shader.
 *
 * @param shaderType The shader type.
 * @param shaderSource The shader source code.
 * @return An OpenGL handle to the shader.
 */
public static int compileShader(final int shaderType, final String shaderSource)
{
    int shaderHandle = GLES20.glCreateShader(shaderType);

    if (shaderHandle != 0)
    {
        // Pass in the shader source.
        GLES20.glShaderSource(shaderHandle, shaderSource);

        // Compile the shader.
        GLES20.glCompileShader(shaderHandle);

        // Get the compilation status.
        final int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

        // If the compilation failed, delete the shader.
        if (compileStatus[0] == 0)
        {
            Log.e(TAG, "Error compiling shader " /*+ GLES20.glGetShaderInfoLog(shaderHandle)*/);
            GLES20.glDeleteShader(shaderHandle);
            shaderHandle = 0;
        }
    }

    if (shaderHandle == 0)
    {   
        throw new RuntimeException("Error creating shader.");
    }

    return shaderHandle;
}

/**
 * Helper function to compile and link a program.
 *
 * @param vertexShaderHandle An OpenGL handle to an already-compiled vertex shader.
 * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
 * @param attributes Attributes that need to be bound to the program.
 * @return An OpenGL handle to the program.
 */
public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes)
{
    int programHandle = GLES20.glCreateProgram();

    if (programHandle != 0)
    {
        // Bind the vertex shader to the program.
        GLES20.glAttachShader(programHandle, vertexShaderHandle);   

        // Bind the fragment shader to the program.
        GLES20.glAttachShader(programHandle, fragmentShaderHandle);

        // Bind attributes
        if (attributes != null)
        {
            final int size = attributes.length;
            for (int i = 0; i < size; i++)
            {
                GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
            }   
        }

        // Link the two shaders together into a program.
        GLES20.glLinkProgram(programHandle);

        // Get the link status.
        final int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);

        // If the link failed, delete the program.
        if (linkStatus[0] == 0)
        {   
            Log.e(TAG, "Error compiling program " /*+ GLES20.glGetProgramInfoLog(programHandle)*/);
            GLES20.glDeleteProgram(programHandle);
            programHandle = 0;
        }
    }

    if (programHandle == 0)
    {
        throw new RuntimeException("Error creating program.");
    }

    return programHandle;
}

}

GameObject

package mycompany.OpenGLES20_2DEngine;

import java.io.IOException;
import java.io.InputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.Log;

public class GameObject {

/** Used for debug logs. */
private static final String TAG = "GameObject";

//Declare Variables****************************
//Position
public int x;
public int y;
public int z;
//Size
public int width;
public int height;
//Movement
double thrustX;
double thrustY;
//Rotation
public int rotation;
public int rotationSpeed;
//Unique Identifier
public int UID;
//Sprite Resource ID
int spriteResId;
//GL Texture Reference
int spriteGLIndex;
//Bounding Box
BoundingBox boundingBox;
//********************************************

GameObject() {

}

public int loadSprite(final Context context, final int resourceId) {
    final int[] textureHandle = new int[1];

    GLES20.glGenTextures(1, textureHandle, 0);

    if (textureHandle[0] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling

        // Read in the resource
        InputStream is = context.getResources()
                .openRawResource(resourceId);
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch(IOException e) {
            Log.e(TAG, "Could not load the texture");
        }

        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

        // Set filtering
        //TODO: Offending Line - Makes textures black because of parameters
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        // Load the bitmap into the bound texture.
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

        // Recycle the bitmap, since its data has been loaded into OpenGL.
        bitmap.recycle();
    }

    if (textureHandle[0] == 0)
    {
        throw new RuntimeException("Error loading texture.");
    }

    return textureHandle[0];
}

public void setUID(int uid) {
    UID = uid;
}

public int getUID() {
    return UID;
}

public void draw(float[] mModelMatrix, float[] mViewMatrix, float[] mProjectionMatrix, float[] mMVPMatrix, Shader shader) {

    {   
        // Pass in the position information
        boundingBox.mPositions.position(0); 
        GLES20.glVertexAttribPointer(shader.mPositionHandle, boundingBox.mPositionDataSize, GLES20.GL_FLOAT, false,
                0, boundingBox.mPositions);

        GLES20.glEnableVertexAttribArray(shader.mPositionHandle);

        // Pass in the color information
        boundingBox.mColors.position(0);
        GLES20.glVertexAttribPointer(shader.mColorHandle, boundingBox.mColorDataSize, GLES20.GL_FLOAT, false,
                0, boundingBox.mColors);

        GLES20.glEnableVertexAttribArray(shader.mColorHandle);

        // Pass in the normal information
        boundingBox.mNormals.position(0);
        GLES20.glVertexAttribPointer(shader.mNormalHandle, boundingBox.mNormalDataSize, GLES20.GL_FLOAT, false,
                0, boundingBox.mNormals);

        GLES20.glEnableVertexAttribArray(shader.mNormalHandle);

        // Pass in the texture coordinate information
        boundingBox.mTextureCoordinates.position(0);
        GLES20.glVertexAttribPointer(shader.mTextureCoordinateHandle, boundingBox.mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
                0, boundingBox.mTextureCoordinates);

        GLES20.glEnableVertexAttribArray(shader.mTextureCoordinateHandle);

        // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
        // (which currently contains model * view).
        Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

        // Pass in the modelview matrix.
        GLES20.glUniformMatrix4fv(shader.mMVMatrixHandle, 1, false, mMVPMatrix, 0);

        // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
        // (which now contains model * view * projection).
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

        // Pass in the combined matrix.
        GLES20.glUniformMatrix4fv(shader.mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

        // Pass in the light position in eye space.
        GLES20.glUniform3f(shader.mLightPosHandle, shader.mLightPosInEyeSpace[0], shader.mLightPosInEyeSpace[1], shader.mLightPosInEyeSpace[2]);

        // Draw the object
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
    }
}
}

BoundingBox

package mycompany.OpenGLES20_2DEngine;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
//TODO: make this dynamic, both the constructor and the coordinates.
class BoundingBox {

//Variable Declarations***********************
/** How many bytes per float. */
private final int mBytesPerFloat = 4;
/** Store our model data in a float buffer. */
public final FloatBuffer mPositions;
public final FloatBuffer mColors;
public final FloatBuffer mNormals;
public final FloatBuffer mTextureCoordinates;
//Number of coordinates per vertex in this array
final int COORDS_PER_VERTEX = 3;
//Coordinates
float[] positionData;
//Texture Coordinates
float[] textureCoordinateData;
//Vertex Color
float[] colorData;
float[] normalData;
//Vertex Stride
final int vertexStride = COORDS_PER_VERTEX * 4;
/** Size of the position data in elements. */
public final int mPositionDataSize = 3; 
/** Size of the color data in elements. */
public final int mColorDataSize = 4;    
/** Size of the normal data in elements. */
public final int mNormalDataSize = 3;
/** Size of the texture coordinate data in elements. */
public final int mTextureCoordinateDataSize = 2;
//********************************************

public BoundingBox(float[] coords) {
    //TODO: Normalize values
    //Set Coordinates and Texture Coordinates*****
    if(coords==null) {
        float[] newPositionData = {
                // Front face
                -1.0f, 1.0f, 1.0f,  
                -1.0f, -1.0f, 1.0f,
                1.0f, 1.0f, 1.0f,
                -1.0f, -1.0f, 1.0f,
                1.0f, -1.0f, 1.0f,
                1.0f, 1.0f, 1.0f
        };
        positionData = newPositionData;

        float[] newColorData = {
                // Front face (red)
                1.0f, 0.0f, 0.0f, 1.0f, 
                1.0f, 0.0f, 0.0f, 1.0f,
                1.0f, 0.0f, 0.0f, 1.0f,
                1.0f, 0.0f, 0.0f, 1.0f, 
                1.0f, 0.0f, 0.0f, 1.0f,
                1.0f, 0.0f, 0.0f, 1.0f
        };

        colorData = newColorData;

        float[] newTextureCoordinateData =
            {   
                // Front face
                0.0f, 0.0f,
                0.0f, 1.0f,
                1.0f, 0.0f,
                0.0f, 1.0f,
                1.0f, 1.0f,
                1.0f, 0.0f, 
            };
        textureCoordinateData = newTextureCoordinateData;

        float[] newNormalData = {
                // Front face
                0.0f, 0.0f, 1.0f,   
                0.0f, 0.0f, 1.0f,
                0.0f, 0.0f, 1.0f,
                0.0f, 0.0f, 1.0f,   
                0.0f, 0.0f, 1.0f,
                0.0f, 0.0f, 1.0f
        };

        normalData = newNormalData;
    }
    else {
        positionData = coords;
        //TODO:Reverse coords HERE
        textureCoordinateData = coords;
    }
    //********************************************

    //Initialize Buffers**************************
    mPositions = ByteBuffer.allocateDirect(positionData.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();    
    mPositions.put(positionData).position(0);   

    mColors = ByteBuffer.allocateDirect(colorData.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();    
    mColors.put(colorData).position(0);

    mNormals = ByteBuffer.allocateDirect(normalData.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();    
    mNormals.put(normalData).position(0);

    mTextureCoordinates = ByteBuffer.allocateDirect(textureCoordinateData.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    mTextureCoordinates.put(textureCoordinateData).position(0);
    //********************************************
}
}

SpaceShip

package mycompany.OpenGLES20_2DEngine;

public class SpaceShip extends GameObject{

public SpaceShip() {
    spriteResId = R.drawable.spaceship;
    boundingBox = new BoundingBox(null);
}
}

Upvotes: 0

Views: 581

Answers (1)

MrMysterious2502
MrMysterious2502

Reputation: 105

Got it. I added the spaceship to the room AFTER I loaded it's bitmap (from the room).

    //Load The Level******************************
    //Create a new room
    room = new Room(800,600, 0);
    //Load game objects
    SpaceShip user = new SpaceShip();
    **//Load sprites
    for(int i=0;i<room.numberOfGameObjects;i++) {
        room.gameObjects[i].spriteGLIndex = room.gameObjects[i].loadSprite(context, room.gameObjects[i].spriteResId);   
    }
    //Add them to the room
    room.addGameObject(user);**
    //********************************************

Upvotes: 0

Related Questions