Jump to content
  • Advertisement
Sign in to follow this  
yinyuanqings

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

This topic is 2436 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 !!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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)"

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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 ..

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!