The top image is the undesired result (it also seems to flicker).
The bottom image is what I would like the render to look like on ALL devices.
Hello, I seem to be having problems with rendering a textured square to my galaxy s4, but not on my my gt p3113 tablet...
Here is the code from my GLRenderer:
#Override
public void onDrawFrame(GL10 gl)
{
manObjects.draw(gl, 0, 0);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
if (height == 0)
{ // Prevent A Divide By Zero By
height = 1; // Making Height Equal One
}
gl.glViewport(0, 0, width, height); // Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); // Select The Projection Matrix
gl.glLoadIdentity(); // Reset The Projection Matrix
// respect the height:width ratio of the window.
GLU.gluOrtho2D(gl, -1f, 1f, 1.6f, -1.6f);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Select The Modelview Matrix
gl.glLoadIdentity(); // Reset The Modelview Matrix
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// Settings
gl.glEnable(GL10.GL_TEXTURE_2D); // Enable Texture Mapping
gl.glShadeModel(GL10.GL_SMOOTH); // Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
gl.glClearDepthf(1.0f); // Depth Buffer Setup
// Really Nice Perspective Calculations
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glEnable(GL10.GL_BLEND); // Enable blending
gl.glDisable(GL10.GL_DEPTH_TEST); // Disable depth test
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
// Load textures
manObjects.load(gl, mContext);
}
Anyone have any ideas as to why this is happening? And more specifically why it works on one device and not on the other?
Draw code:
public void draw(GL10 gl, float x, float y)
{
gl.glLoadIdentity();
gl.glBindTexture(GL10.GL_TEXTURE_2D, texPointers[0]);
tSquare[0].draw(gl);
}
public void drawBLACK(GL10 gl)
{
gl.glLoadIdentity();
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
gl.glScalef(1f, 1.6f, 1);
gl.glColor4f(0, 0, 0, 1);
tSquare[0].draw(gl);
gl.glColor4f(1, 1, 1, 1);
}
tSquare[0].draw(gl):
public void draw(GL10 gl)
{
//Enable the vertex, texture and normal state
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Point to our buffers
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
here is an example of my onDrawFrame, try making your gl calls in onDrawFrame instead
first make
public int width, height;
then
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
this.width = width;
this.height = height;
}
then onDrawFrame something like this
#Override
public void onDrawFrame(GL10 gl)
{
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_TEXTURE_2D);
manObjects.draw(gl, 0, 0);
}
Possible solution:
I have added another draw before the call that draws the star. This added draw call draws a giant black rectangle that covers the entire screen...
I feel like I'm only masking the problem and not really fixing it...
Thoughts?
Related
I would like to know how to bind different textures to different models or how to improve my code.
My code:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glLoadIdentity();
GLU.gluPerspective(gl, 25.0f, (view.getWidth() * 1f) / view.getHeight(), 1, 100);
GLU.gluLookAt(gl, 0f, 8f, 12f, 0.0f, 0.0f, 0.0f, 0.0f, 25.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
loadTexture(gl, context, R.drawable.grndf);
loadTexture(gl, context, R.drawable.skintrip);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
}
private int[] mTexture = new int[2];
private void loadTexture(GL10 gl, Context mContext, int mTex) {
gl.glGenTextures(1, mTexture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture[0]);
Bitmap bitmap;
bitmap = BitmapFactory.decodeResource(mContext.getResources(), mTex);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();}
As already said in the comment, there is no concept like a model or a object. OpenGL is a state machine, which means that at every draw-call the current state is used. So if you want to have two draw-calls using different textures, then you have to make sure that at every draw-call the correct texture is bound:
glBindTexture(GL_TEXTURE_2D, texture1);
glDraw*... //First draw call using texture1
glBindTexture(GL_TEXTURE_2D, texture2);
glDraw*... //Second draw call using texture2
I am making an application for Android with OpenGL-Es following Nehe's tutorial. I have a cube with a texture and my problem is that I want to change it by pressing a button (I have 2 textures in the folder "raw"). I think this is due to my variable imagenes in which I save the route of my images (R.raw.imagen and R.raw.imagen2 on MainActivity.java) only charge the image once at the start of the application, so even if I change the variable later in my function onClick() the texture remains the same.
What I tried to do is making a switch in the class TextureCube.java looking my variable imagenes in the function where I load the texture so it should charge the first image at the start of the application and then if I press the button change it to the other image because of the code onClick().
The image never change because I printed the variable imagenes. I don't know what I am doing wrong.
MainActivity:
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (get_imagenes() == R.raw.imagen) {
imagenes = R.raw.imagen2;
b.setText("image2");
} else if (get_imagenes() == R.raw.imagen2) {
imagenes = R.raw.imagen;
b.setText("image1");
}
}
});
TextureCube:
// Construct an input stream to texture image
switch (main.imagenes) {
case R.raw.imagen:
is = context.getResources().openRawResource(R.raw.imagen);
break;
case R.raw.imagen2:
is = context.getResources().openRawResource(R.raw.imagen2);
break;
}
I left the rest of the code of the application here.Here is my code of the MainActivity:
public class MainActivity extends AppCompatActivity {
private GLSurfaceView glView;
private TextureCube cube;
int imagenes = R.raw.imagen;
Button b;
Bitmap bitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//GLSurfaceView
glView = new MyGLSurfaceView(this);
cube = new TextureCube();
setContentView(glView);
createButtons();
}
public void createButtons() {
//ButtonB
LinearLayout ll = new LinearLayout(this);
b = new Button(this);
b.setText("Change Texture");
ll.addView(b);
ll.setGravity(Gravity.BOTTOM | Gravity.CENTER);
this.addContentView(ll, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (get_imagenes() == R.raw.imagen) {
imagenes = R.raw.imagen2;
b.setText("image2");
} else if (get_imagenes() == R.raw.imagen2) {
imagenes = R.raw.imagen;
b.setText("image1");
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
// Call back when the activity is going into the background
#Override
protected void onPause() {
super.onPause();
glView.onPause();
}
// Call back after onPause()
#Override
protected void onResume() {
super.onResume();
glView.onResume();
}
public int get_imagenes() {
return imagenes;
}
}
My code of the Renderer:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Context context;
private TextureCube cube;
private MainActivity main;
// For controlling cube's z-position, x and y angles and speeds
float angleX = 0;
float angleY = 0;
float speedX = 0;
float speedY = 0;
float z = -6.0f;
int currentTextureFilter = 0; // Texture filter
// Lighting (NEW)
boolean lightingEnabled = false; // Is lighting on? (NEW)
private float[] lightAmbient = {0.5f, 0.5f, 0.5f, 1.0f};
private float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
private float[] lightPosition = {0.0f, 0.0f, 2.0f, 1.0f};
// Blending (NEW)
boolean blendingEnabled = false; // Is blending on? (NEW)
// Constructor
public MyGLRenderer(Context context) {
this.context = context; // Get the application context (NEW)
cube = new TextureCube();
}
// Call back when the surface is first created or re-created.
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Set color's clear-value to black
//gl.glClearColor(0f, 0f, 0f, 1.0f);
gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest
gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden surface removal
gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice perspective view
gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color
gl.glDisable(GL10.GL_DITHER); // Disable dithering for better performance
// Setup Texture, each time the surface is created (NEW)
cube.loadTexture(gl, context); // Load image into Texture (NEW)
gl.glEnable(GL10.GL_TEXTURE_2D); // Enable texture (NEW)
// Setup lighting GL_LIGHT1 with ambient and diffuse lights (NEW)
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient, 0);
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse, 0);
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition, 0);
gl.glEnable(GL10.GL_LIGHT1); // Enable Light 1 (NEW)
gl.glEnable(GL10.GL_LIGHT0); // Enable the default Light 0 (NEW)
// Setup Blending (NEW)
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.5f); // Full brightness, 50% alpha (NEW)
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); // Select blending function (NEW)
}
// Call back after onSurfaceCreated() or whenever the window's size changes.
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) height = 1; // To prevent divide by zero
float aspect = (float)width / height;
// Set the viewport (display area) to cover the entire window
gl.glViewport(0, 0, width, height);
// Setup perspective projection, with aspect ratio matches viewport
gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix
gl.glLoadIdentity(); // Reset projection matrix
// Use perspective projection
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix
gl.glLoadIdentity(); // Reset
}
#Override
public void onDrawFrame(GL10 gl) {
// Clear color and depth buffers
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
if (lightingEnabled) { //Enable lighting
gl.glEnable(GL10.GL_LIGHTING);
} else {
gl.glDisable(GL10.GL_LIGHTING);
}
if (blendingEnabled) { //Enable blending
gl.glEnable(GL10.GL_BLEND); // Turn blending on (NEW)
gl.glDisable(GL10.GL_DEPTH_TEST); // Turn depth testing off (NEW)
} else {
gl.glDisable(GL10.GL_BLEND); // Turn blending off (NEW)
gl.glEnable(GL10.GL_DEPTH_TEST); // Turn depth testing on (NEW)
}
// ----- Render the Cube ----- //
gl.glLoadIdentity(); // Reset the model-view matrix
gl.glTranslatef(0.0f, 0.0f, z); // Translate into the screen (NEW)
gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
cube.draw(gl);
// Update the rotational angle after each refresh (NEW)
angleX += speedX; // (NEW)
angleY += speedY; // (NEW)
}
}
GLSurfaceView:
public class MyGLSurfaceView extends GLSurfaceView {
MyGLRenderer renderer;
MainActivity main;
private final float TOUCH_SCALE_FACTOR = 180.0f / 320.0f;
private float previousX;
private float previousY;
//Allocate and set the renderer
public MyGLSurfaceView(Context context) {
super(context);
renderer = new MyGLRenderer(context);
this.setRenderer(renderer);
this.requestFocus();
this.setFocusableInTouchMode(true);
}
// Handler for key event
#Override
public boolean onKeyUp(int keyCode, KeyEvent evt) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT: // Decrease Y-rotational speed
renderer.speedY += 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT: // Increase Y-rotational speed
renderer.speedY -= 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_UP: // Decrease X-rotational speed
renderer.speedX += 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_DOWN: // Increase X-rotational speed
renderer.speedX -= 0.1f;
break;
case KeyEvent.KEYCODE_A: // Zoom out (decrease z)
renderer.z -= 0.2f;
break;
case KeyEvent.KEYCODE_Z: // Zoom in (increase z)
renderer.z += 0.2f;
break;
case KeyEvent.KEYCODE_B: // Toggle Blending on/off (NEW)
renderer.blendingEnabled = !renderer.blendingEnabled;
break;
case KeyEvent.KEYCODE_L: // Toggle lighting on/off (NEW)
renderer.lightingEnabled = !renderer.lightingEnabled;
break;
}
return true;
}
// Handler for touch event
#Override
public boolean onTouchEvent(final MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
float deltaX, deltaY;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// Modify rotational angles according to movement
deltaX = currentX - previousX;
deltaY = currentY - previousY;
renderer.angleX += deltaY * TOUCH_SCALE_FACTOR;
renderer.angleY += deltaX * TOUCH_SCALE_FACTOR;
break;
}
// Save current x, y
previousX = currentX;
previousY = currentY;
return true; // Event handled
}
}
And here TextureCube:
public class TextureCube {
private FloatBuffer vertexBuffer; //Buffer for vertex-array
private FloatBuffer texBuffer; //Buffer for texture-coords-array (NEW)
private MainActivity main = new MainActivity();
private float[] vertices = { //Vertices for a face
-1.0f, -1.0f, 0.0f, //left-bottom-front
1.0f, -1.0f, 0.0f, //right-bottom-front
-1.0f, 1.0f, 0.0f, //left-top-front
1.0f, 1.0f, 0.0f //right-top-front
};
float[] texCoords = { // Texture coords
0.0f, 1.0f, //left-bottom
1.0f, 1.0f, //right-bottom
0.0f, 0.0f, //left-top
1.0f, 0.0f //right-top (
};
int[] textureIDs = new int[1]; //new
public TextureCube() {
// Setup vertex-array buffer
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0); // Rewind
// Setup texture-array buffer
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
}
// Draw the cube
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise orientation
gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display)
//Enable vertex and texture client
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable texture-coords-array (NEW)
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)
//Draw all the faces
//Front
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
//Left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
//Back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
//Right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
//Top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
//Bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Disable texture-coords-array (NEW)
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
// Load an image into GL texture
public void loadTexture(GL10 gl, Context context) {
gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array new
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); // Bind to texture ID
// Set up texture filters
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
InputStream is = new InputStream() {
#Override
public int read() throws IOException {
return 0;
}
};
// Construct an input stream to texture image
switch (main.imagenes) {
case R.raw.imagen:
is = context.getResources().openRawResource(R.raw.imagen);
break;
case R.raw.imagen2:
is = context.getResources().openRawResource(R.raw.imagen2);
break;
}
Log.d("prueba","imagenes"+main.imagenes);
Bitmap bitmap;
try {
// Read and decode input as bitmap
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
}
}
// Build Texture from loaded bitmap for the currently-bind texture ID
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
At program init, you need to load the 2 bitmaps and upload those as 2 new textures to the GPU (glGenTextures / glBindTexture / GLUtils.texImage2D), this should give you two different textureIDs: textureIDs[0] and textureIDs[1].
Then when you draw the cube in public void draw(GL10 gl)you need to add a call to glBindTexture using either textureIDs[0] or textureIDs[1] depending on your button state.
You current code is only loading one of the 2 textures to GPU, the second one is only loaded to RAM when clicking the button. And also you forgot to call glBindTexture in the draw function for the cube.
-- EDIT --
Trying to explain better with some come :
First you need to load the two images to OpenGL textures when program is initialized, instead of loading the second one only when pressing the button.
This will make things easier to handle and will avoid creating any memory leak. So I create a new loadTextures function wich does that:
// you need 2 texture IDs now ...
int NB_GL_TEXTURES = 2;
int[] textureIDs = new int[NB_GL_TEXTURES];
// tool function to load a texture to OpenGL
public void loadTexture(GL10 gl, Context context, InputStream is, int GL_id_slot) {
// decode is to a Bitmap
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
}
}
// tell OpenGL what is the current GL texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[GL_id_slot]);
// Set up texture filters for current GL texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// load the bitmap into current GL texture
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// destroy the bitmap
bitmap.recycle();
}
// Loads the two images into two OpenGL textures
public void loadTextures(GL10 gl, Context context) {
// generate 2 GL textures IDs => textureIDs[0], textureIDs[1]
gl.glGenTextures(NB_GL_TEXTURES, textureIDs, 0);
// load imagen into GL tex of id textureIDs[0]
InputStream is_bitmap_0 = context.getResources().openRawResource(R.raw.imagen);
loadTexture(gl, context, is_bitmap_0, 0);
// load imagen2 into GL tex of id textureIDs[1]
InputStream is_bitmap_1 = context.getResources().openRawResource(R.raw.imagen2);
loadTexture(gl, context, is_bitmap_1, 1);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// ...
// Setup the 2 GL Textures, each time the surface is created
gl.glEnable(GL10.GL_TEXTURE_2D);
cube.loadTextures(gl, context);
// ...
}
Next step is to change the cube render code to call glBindTexture at each frame, passing it the correct GL texture ID:
// Draw the cube
public void draw(GL10 gl) {
// ...
//Enable vertex and texture client
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable texture-coords-array (NEW)
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)
// choose which texture to use on the cube
int GL_id_slot = 0;
if (main.imagenes == R.raw.imagen)
GL_id_slot = 0;
else if (main.imagenes == R.raw.imagen2)
GL_id_slot = 1;
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[GL_id_slot]);
//Draw all the faces
// ...
}
I want to rotate my cube and add 4 buttons to speed up speed down move up and move down. Could you help me? The color is yellow. 4 buttons under cube.cube should rotate about y axis.
public class MyGLRenderer implements Renderer {
Context context;
Cube cube;
public MyGLRenderer(Context context) {
this.context = context;
cube = new Cube();
}
// Call back when the surface is first created or re-created
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// clear-value for color and depth, enabling depth-test, etc.
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black
}
// Call back after onSurfaceCreated() or whenever the window's size changes
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0)
height = 1;
float aspect = (float) width / height;
// Set the viewport (display area) to cover the entire window
gl.glViewport(0, 0, width, height);
// Select projection matrix: projection matrix or model-view matrix
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset projection matrix
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f);
// Select model-view matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Reset
gl.glLoadIdentity();
}
// Call back to draw the current frame.
#Override
public void onDrawFrame(GL10 gl) {
// Clear color and depth buffers using clear-value set earlier
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Reset model-view matrix
gl.glLoadIdentity();
// Translate into the screen
gl.glTranslatef(0.0f, 0.0f, -5.0f);
// Draw cube
cube.draw(gl);
}
}
this is what you are looking for: https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml and you have to place it in front of glTranslatef
I have a class file called MarkerCustom. MarkerCustom has a constructor that takes three variables of different types.
public MarkerCustom(int myInt, String, myString, BitmapData myBitmap) {
From my main Main activity i want to load a GLSurface view that will take an ArrayList of every instance of MarkerCustom that i will want to load into the GLSurface along with the data that will be passed into each instance of MarkerCustom's constructor.
Lets call the Array List myMarkers;
i need myMarkers to look like this:
myMarkers[0] = [1, "hello", bitMapData1]
myMarkers[1] = [66, "johnHandy", bitmapData2]
i am fairly new to java and its casting ect confuses me a bit having come from AS3
EDIT
So following AKhill's answer below i have edited my GLSurfaceView to accept an ArrayList as shown below. But the MarkerCustom Class needs to be created from each listed in that ArrayList in the constructor in a manner that its is accessible in the onSurfaceCreate and the onDrawFrame method of the GLSurfaceView
Please see those methods and the for loops/comments in this class below:
public class GLLayer extends GLSurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback, Renderer {
private Context context;
ArrayList <MarkerCustom> locationTags;
private PhoneOrientation phoneOri;
public GLLayer(Context context, int orientation, ArrayList<MarkerCustom> custMarkers) {
super(context);
locationTags = custMarkers;
this.context = context;
phoneOri=new PhoneOrientation(context); // sensor manager and interpreter
for(int i =0; i<locationTags.size(); i++){
//Need to create a an instance of each MarkerCustom
// something like MarkerCustom locationTags[i]; = new MarkerCustom (its params);
}
this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
this.setRenderer(this);
phoneOri.start(context, orientation);
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
GLU.gluLookAt(gl,0, 0, 0, 0, 0, 0, 0, 0, 0);
float floatMat[]=phoneOri.getMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadMatrixf(floatMat, 0);
for(int i=0;i<loacationTags.size();i++){
gl.glPushMatrix();
//locationTags[i].draw(gl);
gl.glLoadMatrixf(floatMat,0);
}
gl.glPushMatrix();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) {
height = 1;
}
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 35.0f, (float)width / (float)height, 5.0f, 200.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 1.0f, 5.0f, 0, 0, 0, 0, 1.0f, 0);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
for(int i=0;i<locationTags.size();i++){
//call each MarkerCustom's loadGLTexture Method
//locationTags[i].loadGLTexture(gl, this.context);
}
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_SMOOTH);
}
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
}
And Just for reference here is my MarkerCustom class
public class MarkerCustom {
public float xPos;
public float yPos;
public float zPos;
public float yaw;
public float pitch;
public Bitmap tagImage;
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
0.0f, -10.0f, -10.0f, // V1 - bottom left
0.0f, -10.0f, 10.0f, // V2 - top left
0.0f, 10.0f, -10.0f, // V3 - bottom right
0.0f, 10.0f, 10.0f // V4 - top right
};
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
public MarkerCustom(float x, float y, float z, float yawAngle, float pitchAngle, Bitmap bitmap) {
xPos = x;
yPos = y;
zPos = z;
yaw = yawAngle;
pitch = pitchAngle;
tagImage = bitmap;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
/** The texture pointer */
private int[] textures = new int[1];
public void loadGLTexture(GL10 gl, Context context) {
// loading texture
// Enable blending using premultiplied alpha.
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
// generate one texture pointer
gl.glGenTextures(1, textures, 0);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, tagImage, 0);
// Clean up
tagImage.recycle();
}
public void draw(GL10 gl) {
// bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
Try this.
List<MarkerCustom> myList=new ArrayList<MarkerCustom>();
MarkerCustom entry1=new MarkerCustom(myInt, myString, myBitmap);
MarkerCustom entry2=new MarkerCustom(myInt, myString, myBitmap);
myList.add(entry1);
myList.add(entry2);
Shorthand:
List<MarkerCustom> markerList = Arrays.asList(
new MarkerCustom(1, "hello", bitMapData1),
new MarkerCustom(66, "johnHandy", bitMapData2))
};
In this case I think it's easier to create a class Marker (for instance) that has three attributes.
For example:
class Marker {
int var1;
String var2;
BitmapData var3; }
This way, you are able to store an ArrayList of Markers (ArrayList), and you can access all the information you need.
I am attempting to replace the Canvas-based rendering system that I already have with the faster opengl-es surface, however, I can't seem to get an openGL renderer to conform in such a way that it acts as 2d field, rather than a perspective view.
My current code for the renderer looks as follows:
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0.0f, width, 0.0f, height, 0.0f, 1.0f);
gl.glShadeModel(GL10.GL_FLAT);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
gl.glShadeModel(GL10.GL_FLAT);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glDisable(GL10.GL_DITHER);
gl.glDisable(GL10.GL_LIGHTING);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
}
How would I setup the renderer so that the translate transformation would match up with the pixels on the screen? (so translating 5 to the right would move it 5 pixels)
Please note that in openGL that Y co-ordinate is inverted. Otherwise all is the same.
As for the correct flags, I recommend you check out the open source android game replica island: http://code.google.com/p/replicaisland/
Here's what I use in my own code:
public void onSurfaceChanged(GL10 gl, int width, int height)
{
mViewWidth = width;
mViewHeight = height;
gl.glViewport(0, 0, mViewWidth, mViewHeight);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, mViewWidth, mViewHeight, 0);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glShadeModel(GL10.GL_FLAT);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glViewport(0, 0, mViewWidth, mViewHeight);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glShadeModel(GL10.GL_FLAT);
gl.glEnable(GL10.GL_TEXTURE_2D);
GLU.gluOrtho2D(gl, 0, mViewWidth, mViewHeight, 0);
}
Where mViewWidth & mViewHeight are the size of the display.