Related
I'm creating a curtain like animation triggered by onTouchEvent() where u can drag one end of a square to make it bigger or smaller.
My only problem is that instead of having a square on the entire screen, I get a small line on the top of the screen and i can expand and de-expand that line.
Why won't this code draw a square?
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
gl.glLoadIdentity(); // reset the matrix to its default state
gl.glOrthof(0, height, width, 0, -3, 8);
}
Vertices:
private float vertices[] = {
-1.0f, 1.0f, 0.0f, // 0, Top Left
-1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, -1.0f, 0.0f, // 2, Bottom Right
1.0f, 1.0f, 0.0f, // 3, Top Right
};
// The order we like to connect them.
private short[] indices = { 0, 1, 2, 0, 2, 3 };
And the draw method in Square:
public void draw(GL10 gl,float x,float y) {
// Counter-clockwise winding.
gl.glFrontFace(GL10.GL_CCW); // OpenGL docs
//Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//Enable vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
//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);
}
You are missing this? after setting the projection mode.
gl.glMatrixMode(GL10.GL_MODELVIEW); // set modelview matrix to identity.
gl.glLoadIdentity();
I am drawing the 3D object but its not drawing correctly. Original 3D file does not have diagonally but When I am drawing then its showing the diagonal. Please help me to why its drawing the diagonal.
See this link : http://i.stack.imgur.com/Q4plC.png
Code
public void draw(GL10 gl) {
//gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glDrawArrays(3, 0, v.size()/3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
model.loadGLTexture(gl, context);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glClearColor(1.0f, 0.0f, 1.0f, 1.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_NICEST);
gl.glShadeModel(GL10.GL_SMOOTH);
}
/**
* Here we do our drawing
*/
public void onDrawFrame(GL10 gl) {
//Clear Screen And Depth Buffer
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, 0); //Move down 1.2 Unit And Into The Screen 6.0
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
model.draw(gl); //Draw the square
xrot += xspeed;
yrot += yspeed;
}
/**
* If the surface changes, reset the view
*/
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
//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, width/height, 0.1f, 500.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
}
Thanks in advance.
Check the exact order of the vertices in vertexBuffer.
If the order jumped over the diagonal way on the rectangle, it will draw the diagonal line.
I found different Stackoverflow-Questons, but I don't see what I'm doing wrong in my code, because the 2D "_floorhelper" texture doesn't show up on the screen. I would like to used it as a HUD element:
Trying to use Ortho for drawing 2D
https://stackoverflow.com/questions/9406753/android-opengl-gluortho2d-keep-original-shape-of-an-object
Android - Draw 3D then 2D with openGL ES
this is my setup:
public void gameSetup(GameActivity activity, GL10 gl) {
_floorhelper = new Mesh( gl, 4, false, true, false );
_floorhelper.texCoord(1, 1);
_floorhelper.vertex(-1, 0, 1 );
_floorhelper.texCoord(1, 0);
_floorhelper.vertex(1, 0, 1 );
_floorhelper.texCoord(0, 0);
_floorhelper.vertex(1, 0, -1 );
_floorhelper.texCoord(0, 1);
_floorhelper.vertex(-1, 0, -1);
try {
InputStream is = getResources().openRawResource(getResources().getIdentifier("levels", "raw", getPackageName()));
levelBitmap = BitmapFactory.decodeStream(is);
levelTexture = new Texture(gl, levelBitmap, TextureFilter.Linear, TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge);
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
setTractFloor(gl);
float[] lightColor = { 1, 1, 1, 1 };
float[] ambientLightColor = { 0.0f, 0.0f, 0.0f, 1 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientLightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightColor, 0);
}
public void gameLoop(GameActivity activity, GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, activity.getViewportWidth(), activity.getViewportHeight());
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable( GL10.GL_CULL_FACE );
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float aspectRatio = (float) activity.getViewportWidth() / activity.getViewportHeight();
GLU.gluPerspective(gl, 67, aspectRatio, 1, 100);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, _scaleFactor, 5.0f, _scaleFactor, 0.0f, 0.0f, 0.0f, 0, 1, 0);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
float[] direction = { 1.5f, 0.5f, 0, 0 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, direction, 0);
gl.glEnable(GL10.GL_COLOR_MATERIAL);
// rotation
gl.glRotatef(135, 0, 1, 0);
gl.glEnable(GL10.GL_LINE_SMOOTH);
gl.glBlendFunc(GL10.GL_SRC_ALPHA_SATURATE, GL10.GL_ONE);
gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST); // no visible diff
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glColor4f(1, 1, 1, 1);
// translation
gl.glTranslatef(-_oldTouchY, 0, _oldTouchX);
// render
currentTractFloor.render();
// Draw 2D ontop of 3D - floorhelper
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0.0f, (float) activity.getViewportWidth(), 0.0f, (float)activity.getViewportHeight());
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glDisable(GL10.GL_COLOR_MATERIAL);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
levelTexture.bind();
_floorhelper.render(PrimitiveType.TriangleFan);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
}
After the Answer of Stefan Hanke I found the solution.
I've defined the vertices in the mesh wrong. So I always saw just the side of the mesh....
Thanks to Stefan Hanke.
//* Solution Code
public void gameSetup(GameActivity activity, GL10 gl) {
_floorhelper = new Mesh(gl, 4, false, true, false);
_floorhelper.texCoord(0, 1);
_floorhelper.vertex(50, 50, 0);
_floorhelper.texCoord(1, 1);
_floorhelper.vertex(1000, 50, 0);
_floorhelper.texCoord(1, 0);
_floorhelper.vertex(1000, 1000, 0);
_floorhelper.texCoord(0, 0);
_floorhelper.vertex(50, 1000, 0);
try {
InputStream is = getResources().openRawResource(getResources().getIdentifier("levels", "raw", getPackageName()));
levelBitmap = BitmapFactory.decodeStream(is);
levelTexture = new Texture(gl, levelBitmap, TextureFilter.Linear, TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge);
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
setTractFloor(gl);
float[] lightColor = { 1, 1, 1, 1 };
float[] ambientLightColor = { 0.0f, 0.0f, 0.0f, 1 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientLightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightColor, 0);
}
public void gameLoop(GameActivity activity, GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, activity.getViewportWidth(), activity.getViewportHeight());
gl.glClearColor(0.18f, 0.68f, 1.0f, 1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_CULL_FACE );
setPerspective(activity, gl);
GLU.gluLookAt(gl, getScaleFactor(), 5.0f, getScaleFactor(), 0.0f, 0.0f, 0.0f, 0, 1, 0);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
float[] direction = { 1.5f, 0.5f, 0, 0 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, direction, 0);
gl.glEnable(GL10.GL_COLOR_MATERIAL);
// rotation
gl.glRotatef(135, 0, 1, 0);
gl.glEnable(GL10.GL_LINE_SMOOTH);
gl.glBlendFunc(GL10.GL_SRC_ALPHA_SATURATE, GL10.GL_ONE);
gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST); // no visible diff
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glColor4f(1, 1, 1, 1);
// translation
gl.glTranslatef(-_oldTouchY, 0, _oldTouchX);
// render
currentTractFloor.render();
// levels
setOrtho2D(activity, gl);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
levelTexture.bind();
_floorhelper.render(PrimitiveType.TriangleFan);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
}
private void setPerspective(GameActivity activity, GL10 gl) {
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float aspectRatio = (float) activity.getViewportWidth() / activity.getViewportHeight();
GLU.gluPerspective(gl, 67, aspectRatio, 1, 100);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
private void setOrtho2D(GameActivity activity, GL10 gl) {
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
// set ortho view
gl.glOrthof(0.0f,(float) activity.getViewportWidth(), 0.0f, (float)activity.getViewportHeight(), -1.0f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
}
Looks like the matrix setup is incorrect. The meshes vertices all have y=0. With no ModelView matrix whatsoever, you will look at the front edge of the whole mesh. If you remove the second matrix setup from the code -- as you did in your comment to Vincents post -- , the ModelView will be a concoction of the previous gl* calls.
It could be that you didn't define the normals of the vertices of your Mesh.
I'm new to OpenGL and I can't figure out how to use gluLookAt. Below is my source -- Any help will be much appreciated.
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);
gl.glEnable(GL10.GL_LIGHT0);
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
gl.glDisable(GL10.GL_DITHER);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
cube.loadGLTexture(gl, this.context);
}
public void onDrawFrame(GL10 gl) {
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
GLU.gluLookAt(gl, xrot, yrot, 0.0f, 0.0f, xrot, yrot, 0.0f, 0.0f, 0.0f);
//Clear Screen And Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity(); //Reset The Current Modelview Matrix
//Check if the light flag has been set to enable/disable lighting
if(light) {
gl.glEnable(GL10.GL_LIGHTING);
} else {
gl.glDisable(GL10.GL_LIGHTING);
}
//Check if the blend flag has been set to enable/disable blending
if(blend) {
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 On ( NEW )
gl.glEnable(GL10.GL_DEPTH_TEST); //Turn Depth Testing Off ( NEW )
}
//Drawing
gl.glTranslatef(0.0f, 0.0f, z); //Move z units into the screen
gl.glScalef(0.8f, 0.8f, 0.8f); //Scale the Cube to 80 percent, otherwise it would be too large for the screen
//Rotate around the axis based on the rotation matrix (rotation, x, y, z)
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
cube.draw(gl, filter); //Draw the Cube
//Change rotation factors
xrot += xspeed;
yrot += yspeed;
}
/**
* If the surface changes, reset the view
*/
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
//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
}
Two things I can see. One, since glulookat is defined as
gluLookAt ( eyeX , eyeY , eyeZ , centerX , centerY , centerZ , upX , upY , upZ )
Your call should be changed to be GLU.gluLookAt(gl, xrot, yrot, 0.0f, 0.0f, xrot, yrot, 0.0f, 1.0f, 0.0f);
Notice the new up vector '0.0, 1.0, 0.0'. Basically says the y-axis is where you want 'up' to be.
Also, you seem to be using rotation values for the rest of the call. The first triplet should be the position of where you are looking, and the second vector should be a reference position, normally where your viewer is. Look at http://developer.android.com/reference/android/opengl/GLU.html
Second issue, if you call loadIdentity after a glulookat call, I am pretty sure since it is loading the identity matrix, you will loose the transform that glulookat performs. So try adding glulookat after you have placed your geometry.
Here is what I am basically saying in code:
public void onDrawFrame(GL10 gl) {
//cleaned up the reset code
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//Check if the light flag has been set to enable/disable lighting
if(light) {
gl.glEnable(GL10.GL_LIGHTING);
} else {
gl.glDisable(GL10.GL_LIGHTING);
}
//Check if the blend flag has been set to enable/disable blending
if(blend) {
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 On ( NEW )
gl.glEnable(GL10.GL_DEPTH_TEST); //Turn Depth Testing Off ( NEW )
}
//Drawing
gl.glTranslatef(0.0f, 0.0f, z); //Move z units into the screen
gl.glScalef(0.8f, 0.8f, 0.8f); //Scale the Cube to 80 percent, otherwise it would be too large for the screen
//Rotate around the axis based on the rotation matrix (rotation, x, y, z)
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
//change the perspective matrix to look at the rotating cube (0,0,z), from (0,0,0)
//with (0,1,0) as the up vector
GLU.gluLookAt(gl, 0.0f, 0.0, z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
cube.draw(gl, filter); //Draw the Cube
//Change rotation factors
xrot += xspeed;
yrot += yspeed;
}
I am just trying to understand what is going on here. I have a textured quad on the screen but I am really confused why it takes up the entire screen. If my texture is 64X64 and I wanted a quad at the top left of the screen that was 64X64 what would I need to change? Is my viewport or my vertices positions causing it to take up the whole screen?
With changes so far:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
myquad.loadGLTexture(gl, this.context);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(gl.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glDisable(GL10.GL_DEPTH_TEST);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
width=w;
height=h;
gl.glViewport(0, 0, w, h);
gl.glLoadIdentity();
gl.glOrthof(0.0f, w, 0, h, -1.0f, 1.0f);
}
public void onDrawFrame(GL10 gl) {
// define the color we want to be displayed as the "clipping wall"
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// clear the color buffer to show the ClearColor we called above...
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glLoadIdentity();
myquad.Draw(gl);
//gl.glTranslatef(.5f, 2.0f, 0.0f);
//gl.glScalef(.5f, .5f, 0);
}
private float vertices[] = {
// Vertices for the square
-1.0f, -1.0f, 0.0f, // 0. left-bottom
1.0f, -1.0f, 0.0f, // 1. right-bottom
-1.0f, 1.0f, 0.0f, // 2. left-top
1.0f, 1.0f, 0.0f // 3. right-top
};
private float texture[] = {
//Mapping coordinates for the vertices
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
};
public void Draw(GL10 gl)
{
// set the color for the triangle
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
//Enable the vertex and texture state
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texturebuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexbuffer);
//gl.glTranslatex(-20, 0, 0);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
}
Right now you have your projection set up wrong. If you want to draw as if you were dealing with pixels, you would want...
this line
gl.glOrthof(0.0f, w, -h, 0.0f, -1.0f, 1.0f);
to be more like this
gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);
where width and height are the size of your context in pixels.
EDIT:
gl.glOrthof(0.0f, w, -h, 0.0f, -1.0f, 1.0f);
has to be called after each call to glLoadIdentity().
Now you have to adjust your vertex coords. As right now they are set up to render a 1px by 1px box 1px outside the bottom left corner of the screen.