Android OpenGL ES: Rotation against arbitrary axis? - android

I have a point cloud that I've rendered on the Android OpenGL-ES. I can translate it correctly (I think) but when I rotate it, I can't make it work like it want. I want it to rotate about the center of the point cloud (I have this 3D point), but I don't know how to do that.
public void onDrawFrame(GL10 gl) {
// Clears the screen and depth buffer.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Replace the current matrix with the identity matrix
gl.glLoadIdentity();
// Translates 4 units into the screen.
GLU.gluLookAt(gl, eyeX, eyeY, eyeZ,
centerX, centerY, centerZ,
upX, upY, upZ);
// rotate
gl.glRotatef(_xAngle, 1f, 0f, 0f);
gl.glRotatef(_yAngle, 0f, 1f, 0f);
gl.glRotatef(_zAngle, 0f, 0f, 1f);
gl.glTranslatef(_xTranslate, _yTranslate, _zTranslate);
// Draw things
ptCloud.draw(gl);
aBox.draw(gl);
}
I change the _translate and _angle variables in response to user interaction, and in turn the OpenGl would act upon them. You can see I run the draw routin on my prCloud right after my perspective is setup. I'll show you that:
public void draw(GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glPointSize(0.5f);
gl.glDrawArrays(GL10.GL_POINTS, 0, numVertices);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
As well as the create surface method, because I'm not sure if it affects anything:
public void onSurfaceChanged(GL10 gl, int width, int height) {
// Sets the current view port to the new size.
gl.glViewport(0, 0, width, height);
// Select the projection matrix
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset the projection matrix
gl.glLoadIdentity();
// Calculate the aspect ratio of the window
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.001f,
1000000.0f);
// Select the modelview matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Reset the modelview matrix
gl.glLoadIdentity();
}
Here are my lookat default variables:
private float eyeX = 20;
private float eyeY = -150;
private float eyeZ = 60;
private float centerX = 0;
private float centerY = 0;
private float centerZ = 0;
private float upX = 0;
private float upY = 0;
private float upZ = 1;
The points have been scaled to be in the range of (0,0,0) to (120,180,38). I also don't know how to find a eye position that will show the whole model provided random Maximum point values...
Can anyone guess why it won't rotate how I would expect?

Rotate after you translate!
Transformation works in the order you tell it to. If you rotate before you translate then the translation is affected by the rotation etc. If you translate before you rotate then the rotation is translated before rotating so it will be at the center of your object.
See these pages for more information:
http://www.3dcodingtutorial.com/Basic-OpenGL-functions/Translate-and-Rotate-functions.html
http://www.swiftless.com/tutorials/opengl/rotation.html
http://www.opengl.org/resources/faq/technical/transformations.htm
http://www.falloutsoftware.com/tutorials/gl/gl5.htm

Related

Convert OpenGL 3D point to 2D using GLU.glProject

I have an OpenGL scene with a sphere having a radius of 1, and the camera being at the center of the sphere (it's a 360° picture viewer). The user can rotate the sphere by panning.
Now I need to display 2D pins "attached" to some parts of the picture. To do so, I want to convert the 3D coordinates of my pins into 2D screen coordinates, to add the pin image at that screen coordinates.
I'm using GLU.glProject and the following classes from android-apidemo:
MatrixGrabber
MatrixStack
MatrixTrackingGL
I save the projection matrix in the onSurfaceChanged method and the model-view matrix in the onDraw method (after having drawn my sphere). Then I feed GLU.glProject with them when the user rotates the sphere to update the pins position.
When I pan horizontally, the pins pan correctly, but when I pan vertically, the texture pans "faster" than the pin image (like if the pin was closer to the camera than the sphere).
Here are some relevant parts of my code:
public class CustomRenderer implements GLSurfaceView.Renderer {
MatrixGrabber mMatrixGrabber = new MatrixGrabber();
private float[] mModelView = null;
private float[] mProjection = null;
[...]
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// Get the sizes:
float side = Math.max(width, height);
int x = (int) (width - side) / 2;
int y = (int) (height - side) / 2;
// Set the viewport:
gl.glViewport(x, y, (int) side, (int) side);
// Set the perspective:
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, FIELD_OF_VIEW_Y, 1, Z_NEAR, Z_FAR);
// Grab the projection matrix:
mMatrixGrabber.getCurrentProjection(gl);
mProjection = mMatrixGrabber.mProjection;
// Set to MODELVIEW mode:
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void onDrawFrame(GL10 gl) {
// Load the texture if needed:
if(mTextureToLoad != null) {
mSphere.loadGLTexture(gl, mTextureToLoad);
mTextureToLoad = null;
}
// Clear:
gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
// Rotate the scene:
gl.glRotatef( (1 - mRotationY + 0.25f) * 360, 1, 0, 0); // 0.25 is used to adjust the texture position
gl.glRotatef( (1 - mRotationX + 0.25f) * 360, 0, 1, 0); // 0.25 is used to adjust the texture position
// Draw the sphere:
mSphere.draw(gl);
// Grab the model-view matrix:
mMatrixGrabber.getCurrentModelView(gl);
mModelView = mMatrixGrabber.mModelView;
}
public float[] getScreenCoords(float x, float y, float z) {
if(mModelView == null || mProjection == null) return null;
float[] result = new float[3];
int[] view = new int[] {0, 0, (int) mSurfaceViewSize.getWidth(), (int) mSurfaceViewSize.getHeight()};
GLU.gluProject(x, y, z,
mModelView, 0,
mProjection, 0,
view, 0,
result, 0);
result[1] = mSurfaceViewSize.getHeight() - result[1];
return result;
}
}
I use the result of the getScreenCoords method to display my pins. The y value is wrong.
What am I doing wrong?

Learning camera OpenGl ES 2.0

I am trying to understand how camera works on OpenGL ES, so I am tryng to look at the same point with the two differents types, Matrix.frustumM and Matrix.orthoM
I will like to know what exactly I am doing when use Matrix.frustumM or orthoM, I know that I apply them to the ProjectionMatrix but I dont understand what defines the parameters(left,right,bottom,top,near,far of what? it is supposed to be the screen of the phone? ) same with orthoM
I want to draw a square on the screen on 0,0,0 with 1f of height and weight(like 2D just to test the cameras)
but if I do onSurfaceCreated
final float eyeX = 2f;
final float eyeY = 5f;
final float eyeZ = 8f;
final float lookX = 2f;
final float lookY = 5f;
final float lookZ = 0.0f;
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
onSurfaceChanged
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 = 25.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
That is what i saw onn phone
Draw function:
public void dibujarBackground()
{
// Draw a plane
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBackgroundDataHandle);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.0f,2.0f, 0.0f);
drawBackground();
}
private void drawBackground()
{
coordinate.drawBackground(mPositionHandle, mNormalHandle, 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);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniform3f(mLightPosHandle,Light.mLightPosInEyeSpace[0], Light.mLightPosInEyeSpace[1], Light.mLightPosInEyeSpace[2]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
Coords of the square:
final float[] backgroundPositionData = {
// In OpenGL counter-clockwise winding is default.
0f, 1f, 0.0f,
0f, 0f, 0.0f,
1f, 1f, 0.0f,
0f, 0f, 0.0f,
1f, 0f, 0.0f,
1f, 1f, 0.0f,
};
final float[] backgroundNormalData = {
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, };
final float[] backgroundTextureCoordinateData = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f, };
Overall what you get in the end is a single matrix which is used to multiply the positions so that the visible fragments are in range [-1,1] in all 3 dimensions. That means if you use no matrix or use the identity the coordinates will need to be in this range to be visible. So the 3 matrix computations you are using are actually only conveniences to help you achieve a correct transformation:
Ortho is an orthographical transformation. This means the visual representation of x and y screen coordinates are not effected by the z coordinate at all. Visually that means the object does not appear smaller when it is further. The values you insert into this convenience method are border values (left, right, top, bottom) which means a rectangle with same coordinates will take exactly the full screen. These values are mostly used to be the same as your view coordinate system (left = 0, right = screenWidth, top = 0, bottom = screenHeight). Also there are near and far parameters which represent the clipping planes so that positions smaller then near or further then far are not visible. This projection is mostly used for 2D drawing.
Frustum matrix is designed so that the x and y coordinates are reduced with increasing z. This means an object will appear smaller when further. The border parameters are connected to the near parameter so that the rectangle with border coordinates having z at near will appear as full screen. The near must be larger then zero in this case or the result is unpredictable. The far promoter is just a clipping plane but same as with ortho the pixels are clipped if z value is smaller then near or larger then far. The border parameters are best computed with the field of view (angle) and screen aspect ratio. You use the tang function to compute border parameters to get the desired effect. This method is mostly used for 3D drawing.
LookAt is a convenience which is used to transform all the objects to such positions and orientations that they appear to be effected by the camera position. Though this method is defined with vectors you may imagine it having a vector position and rotations. What this does it creates a matrix that will rotate all the objects by -rotations and translate them by -position.
Overall the usage then is pretty simple. Each position should first be multiplied by the model matrix which is the matrix representing the model position in your scene. Then multiplied by the matrix received with lookAt to simulate the camera. Then multiplied by the projection matrix which in most cases is either the ortho or the frustum. The optimization then is to multiply the matrices first on the CPU and then have the positions multiplied by them on the GPU. Some variations then persist where you split the matrix to the "model view matrix" and the "projection matrix". This is used to compute things like lighting effect where the position must not be effected by the projection matrix.

Box2d jitter when camera follows

I am developing a box2d game on android and when the opengl camera follows the player the player jitters quite badly. When the camera is stationary, it appears to be fine. I tried box2d interpolation and that seemed to help slightly. Any suggestions?
public static void setCamera() {
// Position the eye behind the origin.
float eyeX = cameraX;
float eyeY = cameraY;
float eyeZ = cameraZoom;
// We are looking toward the distance
float lookX = cameraX;
float lookY = cameraY;
float lookZ = -5.0f;
// Set our up vector. This is where our head would be pointing were we
// holding the camera.
float upX = 0.0f;
float upY = 1.0f;
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);
// Matrix.scaleM(mViewMatrix, 0, cameraZoom, cameraZoom, 0f);
// Matrix.orthoM(mProjectionMatrix, 0, left, right, top, bottom, near,
// far);
// Matrix.setLookAtM(mViewMatrix, 0, 1, 0, 1.0f, 1.0f, 0f, 0f, 0f, 1.0f,
// 0.0f);
}

android/openGL: fill a 2d viewport with a square

What I've managed to accomplish so far is:
Initialise the GLSurfaceView/Renderer
Draw a triangle on the screen
Render a square/rectangle on the screen
Add a bitmap texture to the screen
Ensure PNG transparency is honoured when rendering
Automatically scale the triangles so they show up correctly for all screen sizes
However, after fixing the scaled triangles, the background rectangle (with texture) no longer fills up the screen.
I've been stuck on this for a while now and absolutely baffled to the point I have thrown in the towel.
The main parts I'm unsure about is the use of glFrustumf() and gluLookAt().
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
gl.glLoadIdentity(); // reset the matrix to its default state
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix
}
#Override
public void onDrawFrame(GL10 gl) {
// Clear the screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// Set GL_MODELVIEW transformation mode
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity(); // reset the matrix to its default state
// When using GL_MODELVIEW, you must set the camera view
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);
bg.draw(gl);
// ...
}
If anybody has a moment to take a look at the problem, I've uploaded the files to https://bitbucket.org/koonkii/test_opengl/src so you don't have to recreate the code by copy-pasting.
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);
Try to change -5f to 0, what you're saying here is displace the camera 5 units back, therefore unless you're doing an orthogonal projection (which I think you're not, try checking out this) what OpenGL is doing is scaling your background polygon according to your perspective view, and you see it as 'smaller'.
If you do an orthogonal projection, no matter how much you move your camera in the z axis, you will always see it the same size. This is useful for 2D OpenGL-based games, so do check out the link above.
EDIT: gluPerspective and glOrtho
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
gluPerspective has a parameter called 'fovy', which is basically the 'Field of View in the Y axis'. The field of view expresses the amount of space the camera can see, basically 'expanding' or 'contracting' whatever vertices happen to be before it. A typical human eye has a 45º FOV.
The zNear and zFar express the near and far frustum limits, the frustum being an invisible 'box' which determines which vertices are outside the viewing area.
Aspect determines the ratio between the width and height of the camera.
glOrtho is a special case of gluPerspective in the sense that the FOV is always 0.
gl.glOrthof(0.0f, (float) width, (float) height, 0.0f, 1.0f, -1.0f);
The first four parameters specify the size of the clipping plane (normally the size of the screen), the other two values specifiy the frustum near and far (which you don't need unless you want to hide objects by placing them 'far away'.
I hope this cleared it up a bit for you.
Alright, after a good nights sleep and applying RedOrav's advice regarding orthogonal projection, I did more browsing into it and got it working!
The code snippets given by RedOrav did actually work, however after switching to the orthogonal projection I was still drawing the squares and triangles as small as 0.15f in width. Barely be visible as it's less than 1 pixel wide!
After changing the background/square/triangle code to something more reasonable (30.0f), they showed up!
Played around with the code a bit more and got positioning working properly. I've submitted the code to bitbucket for those who want to check out a working copy of the project.
The reason why I needed G.getYPos() is because the bottom coordinate = 0, and top is screen height. Couldn't figure out a nicer way of inverting it without turning all the textures upside-down.
The important initialisation parts are:
Global helper
public class G {
public static float ratio;
public static int width, height;
/** The texture pointer */
public static int[] textures = new int[3];
final static int TEXTURE_DEFAULT = 0;
final static int TEXTURE_BG = 1;
final static int TEXTURE_ANDROID = 2;
final static int TEXTURE_TURTLE = 3;
/**
* Since (bottom = 0, top = height), we need to invert the values so they make sense logically.
*/
public static int getYPos(int top) {
return G.height - top;
}
}
Renderer class
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
this.loadGLTextures(gl);
gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); //Red Background
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
// Save these for global use.
G.width = width;
G.height = height;
G.ratio = (float) width / height;
// Set up orthogonal viewport and make adjustments for screen ratio
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, width, 0, height); // The parameters are weird but bottom = 0 so we need an inverter function G.
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// Start setting up the constructs we need
bg = new Background();
squares = new ArrayList<Square>();
squares.add(new Square(width / 2, G.getYPos(0))); // middle/top of the screen
squares.add(new Square(width / 2, G.height /2)); // center of the screen
triangles = new ArrayList<Triangle>();
triangles.add(new Triangle(0, G.getYPos(0))); // top left
triangles.add(new Triangle(width, G.getYPos(height))); // bottom right
triangles.add(new Triangle(width /2, height /2)); // middle
}
#Override
public void onDrawFrame(GL10 gl) {
// Clear the screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
bg.draw(gl);
for (Square s : squares) {
s.draw(gl);
}
// Draw correctly scaled triangles
for (Triangle t : triangles) {
t.draw(gl);
}
try {
Thread.sleep(400);
}
catch (InterruptedException e) {
}
}
/**
* Loads the textures up.
*/
public void loadGLTextures(GL10 gl) {
int[] texture_map = new int[] { R.drawable.bg_game, R.drawable.ic_launcher };
Bitmap bitmap;
// generate one texture pointer, keep 0 as blank/default
gl.glGenTextures(texture_map.length, G.textures, 0);
for (int i = 0; i < texture_map.length; i++) {
// loading texture
bitmap = BitmapFactory.decodeResource(context.getResources(), texture_map[i]);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[i +1]);
// 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, bitmap, 0);
// Clean up
bitmap.recycle();
}
}
Background class
p
ublic class Background {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.0f, 0.0f, // V1 - bottom left
-1.0f, 1.0f, 0.0f, // V2 - top left
1.0f, -1.0f, 0.0f, // V3 - bottom right
1.0f, 1.0f, 0.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 Background() {
// Recalculate the vertices so they fit the screen
vertices[0] = 0; // v1 left
vertices[1] = G.height; // v1 bottom
vertices[3] = 0; // v2 left
vertices[4] = 0; // v2 top
vertices[6] = G.width; // v3 right
vertices[7] = G.height; // v3 bottom
vertices[9] = G.width; // v4 right
vertices[10] = 0; // v4 top
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;
// Bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_BG]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// 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);
gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
}
}
Square class
Very similar to background except it has a position and applies alpha transparency.
public class Square {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.0f, 0.0f, // V1 - bottom left
-1.0f, 1.0f, 0.0f, // V2 - top left
1.0f, -1.0f, 0.0f, // V3 - bottom right
1.0f, 1.0f, 0.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 Square(float posX, float posY) {
float w = 30f;
float h = w;
vertices[0] = posX - w; // left
vertices[3] = posX - w;
vertices[6] = posX + w; // right
vertices[9] = posX + w;
vertices[1] = posY - h; // top
vertices[4] = posY + h;
vertices[7] = posY - h; // bottom
vertices[10] = posY + h;
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
/** The draw method for the square with the GL context */
public void draw(GL10 gl) {
// Enable alpha transparency
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
// bind the previously generated texture
gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_ANDROID]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// reset the colour for the square
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// 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);
// Disable alpha transparency
gl.glDisable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);
gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
}
}
Triangle class
public class Triangle {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z)
0.5f, -0.5f, 0.0f, // V2 - second vertex
0.0f, 0.5f, 0.0f // V3 - third vertex
};
public Triangle(float posX, float posY) {
int w = 30;
int h = w;
vertices[0] = posX - (w/2); // left
vertices[3] = posX + (w/2); // right
vertices[6] = posX; // middle
vertices[1] = posY - (h/2); // bottom
vertices[4] = posY - (h/2); // bottom
vertices[7] = posY + (h/2); // top
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = vertexByteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// set the colour for the triangle
gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
// Reset the colour
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
Hope this helps anyone else having similar issues with starting OpenGL.

OpenGL ES object shape is not drawing properly in earlier version of android honeycomb

Im drawing a circle and even if i draw a basic shape (eg.square, diamond) using java opengl ES in android.
If I run the application in honeycomb the shape is coming fine but if I run it in gingerbread with the shape few more unnecessary points where getting drawn(it getting scattered) and if I keep on executing it rarely it comes without those points.
My Renderer class,
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -5.0f);
gl.glRotatef(-100, 1.0f, 0.0f, 0.0f);
gl.glRotatef(40, 1.0f, 0.0f, 0.0f);
mCircle= new Circle();
Circle.setCirclePoints(1.5f,4, 1, 360);
Circle.draw(gl);
}
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);
gl.glLoadIdentity();
gl.glOrthof(-6.5f, +6.5f, -6.5f, 6.5f, 6.5f, -6.5f);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glClearColor(0,0,0,0);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
}
In my Circle Class
public void setCirclePoints(float radius, int slices, int stacks,
float angle)
ByteBuffer vbb = ByteBuffer.allocateDirect(((slices+2)* 3 * 4));
vbb.order(ByteOrder.nativeOrder());
mSliceVertexBuffer = vbb.asFloatBuffer();
mSliceVertexBuffer.put(0.0f);
mSliceVertexBuffer.put(0.0f);
mSliceVertexBuffer.put(nsign * radius);
for (int j = 0; j <= slices; j++) {
theta = j * dtheta;
x = (float) 1.25f * (float) (Math.cos(theta + dupTheta));
y = (float) Math.sin(theta + dupTheta);
z = nsign;
mSliceVertexBuffer.put(x * radius);
mSliceVertexBuffer.put(y * radius);
mSliceVertexBuffer.put(z * radius);
}
}
public void draw(GL10 gl){
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mSliceVertexBuffer);
gl.glColor4f(212,21,54,34);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0,sliceCount);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
Im really clue less.. I dont know why its not drawing properly in android version <3.0.
edit: I tried to solve it, I found that when I'm trying to plot the points, few vertex are going out of the viewport(may be infinity, I dont know) in android 2.3.3, but for the same points in android 3.0 it drawing the proper shape.
Help me out.
x = (float) 1.25f * (float) (Math.cos(theta + dupTheta));
What's that factor 1.25 supposed to mean? If your circle is coming out as an ellipse, then that's because your projection matrix doesn't take into account window aspect.
I made a blunder mistake
The issue was in
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0,sliceCount);
where the sliceCount is total number of points x,y,z. I divided that one by 3.
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0,sliceCount/3);

Categories

Resources