Sphere get bended when moving on X-Y surface, In perspective projection

Started by
10 comments, last by yinyuanqings 12 years, 4 months ago
Hi everyone,

I'm a beginner playing with OPENGL ES on Android now. Now I'm hung on a problem , please read and see what's wrong:[font=Wingdings][/font]



What I want to do, should be quite simple :



1. Setup the view using perspective projection ( call glFrustum API)

2. Draw a sphere at {0,0,-3}

3. Use glTranslatef(X-2, Y-2, -3) to move the sphere at the X-Y surface.



It works fine at #1 and #2, as the image I attach



But when I call glTranslatef(X-2 , Y-2 , -3) , the sphere get bened :) got the same result on both Android mobile and emulator.



The sphere’s vertices are imported from 3D MAX generated file. I suspect the root cause is from the Open GL ES projection matrix’s setup.



Here’s how I setup the projection matrix:



[size=2] [size=2]public[size=2] [size=2]void[size=2] onSurfaceChanged(GL10 gl, [size=2]int[size=2] width, [size=2]int[size=2] height) {[size=2]


[size=2] gl.glViewport(0, 0, width, height);[size=2]


[size=2] gl.glMatrixMode(GL10.[size=2]GL_PROJECTION[size=2]);[size=2]


[size=2] gl.glLoadIdentity();[size=2]


[size=2] [size=2]ratio[size=2] = ([size=2]float[size=2]) width / height;[size=2]


[size=2] gl.glFrustumf(-[size=2]ratio[size=2], [size=2]ratio[size=2], -[size=2]1[size=2], [size=2]1[size=2], [size=2]2[size=2], [size=2]15[size=2]); [size=2]


[size=2] gl.glMatrixMode(GL10.[size=2]GL_MODELVIEW[size=2]);[size=2]


[size=2] }

And it look bad only to Sphere ,, when moving a cube it just works fine.

Really grateful to any suggestion !!
Advertisement
Looks like you have a matrix ordering problem here. It doesn't necessarily have to be a problem with projection.

Could you post your drawing code (using the appropriate tags)?

I suspect you have some scaling as well which might be influenced by the translate due to wrong ordering.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Hi Lord_Evil,

Thanks for your suggest. Here's the code snippet:


public class MyGLRender implements Renderer {
this.sphere = GlObject3D.consturctFromObjectFile(res, "data/Sphere.obj");

@Override
public void onDrawFrame(GL10 gl) {
initScene(gl);
sphere.draw(gl); //Draw sphere
}

/**
* Initialize scene each time at onDrawFrame(GL10 gl)
* @param gl
*/
protected void initScene(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, 0);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0, 0, 0, 0);

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.glHint(GL10.GL_POINT_SMOOTH_HINT, GL10.GL_NICEST);
}

public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
ratio = (float) width / height;
gl.glFrustumf(-ratio*basicUnit, ratio*basicUnit, -basicUnit, basicUnit, near, far);
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
}


And this is code snippet of "sphere.draw" method:

public void draw(GL10 gl)
{
gl.glTranslatef( -2,-2,0); //Move to left-top of the screen

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, this.normalsBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, this.verticesBuffer.capacity()/3);
}



What "Sphere.draw(gl)" do is simply apply the vertex parsed from "data/Sphere.obj" file, using "glVertexPointer" and "glDrawArrays" API. And I don't think this "problem" related to "glNormalPointer" , because I tried take off "glNormalPointer" and I still get a bended sphere when calling "Translate(X, Y)"
This is the "Sphere.obj" file. I generated it from 3d max 2011.

I have to rename it to "Sphere.txt" since the Forum disallow "obj" uploaded
The problem could be caused by the viewing angle being too large, this will cause distortions near the edges of the screen. You may want to use gluPerspective instead of glFrustum, it's much more intuitive to use in most cases.

EDIT:
On another note, the call to glTranslateF(0, 0, 0) in initScene does nothing. The translate, rotate and scale functions 'add' to the current matrix, so a translation/rotation of zero or a scale of 1 have no effect.
You will always get some bending with a perspective where the sphere is close to the camera. You can make it better by decreasing the field of view and moving the camera further away, or use orthographic projection to get rid of it (camera infinitely far away).

If you use a digital camera to take a photograph of a tennis ball for example, you will get the same effect if it's in the corner of the picture.

You will always get some bending with a perspective where the sphere is close to the camera. You can make it better by decreasing the field of view and moving the camera further away, or use orthographic projection to get rid of it (camera infinitely far away).

If you use a digital camera to take a photograph of a tennis ball for example, you will get the same effect if it's in the corner of the picture.



Hi Eric, is it possible in OpenGL ES, that I define a perspective projection , but when in draw() , I define some object to be drawn/view in orthographic projection ? I can't believe sphere get bended always when being placed at the corner of screen, and I'm so curious how the game solve such problems - I am a WOW fun and I saw objects being drawn fantastically perfect. But of couse that is base on the assumption that WOW use OpenGL to build its engine ..
What is the value of 'basicUnit'? It simply looks like you're using a very wide FOV (wide-angle lens).

What is the value of 'basicUnit'? It simply looks like you're using a very wide FOV (wide-angle lens).


Oh I missed that code

float basicUnit = 10f;

That is to define the length unit along X and Y axis.
Rene, yes, when I turn to call gluPerspective instead of glFrustum, the sphere looks more smooth and less bending than the case of "glFrustum". i wonder what's the key to totally solve the problem?

Can I define a projection matrix by myself rather than through the given API to gain a better "view angle" for my project?

This topic is closed to new replies.

Advertisement