PDA

View Full Version : 3D Animation Problem

Rodrigo
07-30-2010, 01:14 PM
Hi guys.
I'm new in OpenGL and I'm having some trouble showing the scene that I'm drawing.
My work is to create 20 cubes that affects each other by gravitional force, changing their speed and position in the space. That calculation is ok and working.

But in the function :
gluLookAt(0,0,400, 0,0,0, 0,1,0);
I choose the camera position at position 400 in z.
My cubes are being created respecting the range position of [-10,10] in z axe.
When I run my program a lot of cubes stay out the scene and then appear while they move over the xyz space as they were beyond the position 300 of the cam.
But the biggest problem is that those cubes get deformed as they get closer to the cam and look like parallelepipeds.

I don't know what the problem is, but I suspect that it's the values in gluLookAt and gluPerspective which receive the parameters (angle,w/h,2.0,700.0).
I've chosen values for angle between [45,150] but out this range it gets worse.

Does anybody have an idea of what that could be?
Here is my code if anybody wants to take a look:

#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <windows.h>
#include <gl/glut.h>

#define PTS 10
#define LIMITES 100
#define LIMITEV 10
#define LIMITEA 20
#define LIMITEM 200
#define RELOGIO 0.001

//CONST_GRAV 6,673 * exp10(-11) m^3 kg^-1 s^-2

struct ponto{
double x,y,z;
double xtmp,ytmp,ztmp;
double vx,vy,vz;
double vxtmp,vytmp,vztmp;
double ax,ay,az;
double fx,fy,fz;
double massa;
};

struct ponto p[PTS];

GLfloat angle, fAspect;

void Desenha(void)
{
int i;

glMatrixMode(GL_MODELVIEW);

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(1.0f, 0.0f, 0.0f);

for(i=0;i<PTS;i++)
{
glPushMatrix();

glTranslatef(p[i].x,p[i].y,p[i].z);

glutWireCube(10.0);

glPopMatrix();
}

glutSwapBuffers();
}

void Inicializa (void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
angle=150;
}

void EspecificaParametrosVisualizacao(void)
{
glMatrixMode(GL_PROJECTION);

gluPerspective(angle,fAspect,0.1,700.0);

glMatrixMode(GL_MODELVIEW);

gluLookAt(0,0,400, 0,0,0, 0,1,0);
}

void Timer(int value)
{
int i,j;
double ftmp;

for(i=0;i<PTS;i++){

p[i].fx = p[i].fy = p[i].fz = 0;

for(j=0;j<PTS;j++){
double dij;
dij = sqrt((p[j].x - p[i].x)*(p[j].x - p[i].x) +
(p[j].y - p[i].y)*(p[j].y - p[i].y) +
(p[j].z - p[i].z)*(p[j].z - p[i].z));
if(i!=j){
ftmp = 100 * p[i].massa * p[j].massa/dij;
p[i].fx += (p[j].x - p[i].x)*ftmp/dij;
p[i].fy += (p[j].y - p[i].y)*ftmp/dij;
p[i].fz += (p[j].z - p[i].z)*ftmp/dij;
}
}
p[i].ax = p[i].fx/p[i].massa;
p[i].ay = p[i].fy/p[i].massa;
p[i].az = p[i].fz/p[i].massa;
}

for(i=0;i<PTS;i++){
p[i].vxtmp = p[i].vx + p[i].ax*RELOGIO;
p[i].vytmp = p[i].vy + p[i].ay*RELOGIO;
p[i].vztmp = p[i].vz + p[i].az*RELOGIO;

p[i].xtmp = p[i].x + p[i].vx*RELOGIO + p[i].ax*RELOGIO*RELOGIO/2;
p[i].ytmp = p[i].y + p[i].vy*RELOGIO + p[i].ay*RELOGIO*RELOGIO/2;
p[i].ztmp = p[i].z + p[i].vz*RELOGIO + p[i].az*RELOGIO*RELOGIO/2;
}

for(i=0;i<PTS;i++){
p[i].vx = p[i].vxtmp;
p[i].vy = p[i].vytmp;
p[i].vz = p[i].vztmp;

p[i].x = p[i].xtmp;
p[i].y = p[i].ytmp;
p[i].z = p[i].ztmp;
}

glutPostRedisplay();
glutTimerFunc(1,Timer, 1);
}

void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
if ( h == 0 ) h = 1;

glViewport(0, 0, w, h);

fAspect = (GLfloat)w/(GLfloat)h;

EspecificaParametrosVisualizacao();
}

int main(void)
{

int i;

srand(time(NULL));

for(i=0;i<PTS;i++){
p[i].x = (rand()%(2*LIMITES+1)) - LIMITES;
p[i].y = (rand()%(2*LIMITES+1)) - LIMITES;
p[i].z = (rand()%(2*LIMITES+1)) - LIMITES;

p[i].vx = (rand()%(2*LIMITEV+1)) - LIMITEV;
p[i].vy = (rand()%(2*LIMITEV+1)) - LIMITEV;
p[i].vz = (rand()%(2*LIMITEV+1)) - LIMITEV;

p[i].massa = (rand()%(LIMITEM)) + 200;

}

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1000,800);
glutCreateWindow("Interação Gravitacional");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutTimerFunc(1, Timer, 1);
Inicializa();
glutMainLoop();

return 0;
}

marshats
07-30-2010, 11:00 PM
you are undoing the gluLookAt by loading an identity matrix in your display function. This means you are not positioning your camera where you think you are which causes unexpected results. Actually this identity matrix is forcing your camera at 0,0,0 looking towards 0,0,-1 with the up vector as 0,1,0. Try commenting it out and it may make more sense ie as in the following

void Desenha(void)
{
int i;

//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity(); // this is killing gluLookAt!

After seeing that, you may also want to try reducing angle=90 to reduce some of the projection exaggerated effects.

Rodrigo
08-01-2010, 09:35 AM
Thanks, I'll try it later.
But why the cubes change their forms? Is it because of the angle?
I'd like to eliminate these deformations.

Rosario Leonardi
08-01-2010, 09:53 AM
A FOV of 150° on the Y axis means a FOV of 200° no the X. O_O
The prospective (the real one) introduce fish eye effect, this effect is not very notable on the center of the image with small angle (less then 90°), but for larger angle introduce a strong distortion.
OpenGL use a linear transformation to approximate this behaviour. Linear approximation that FAIL over the 120° and have a singularity at 180° and is completelly out of sense over 180°.

Check this:
http://strlen.com/gfxengine/fisheyequake/compare.html

Rodrigo
08-02-2010, 05:59 AM
I commented those 2 lines and it's much better now.
But it kept the deformation.
So a put a smaller angle, 45º and it's even better.
But I still don't get it. Why does this angle cause deformation? Is there a way to eliminate deformation at all?
I'm confused because I saw in some examples people using the angle to zoom in and zoom out. It would make more sense to me to do this with the camera.

marshats
08-02-2010, 06:37 AM
If you want no deformation of the image, use glOrtho (http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml) instead of gluPerspective().

You might benefit from reading Redbook, Chapter 3 (http://glprogramming.com/red/chapter03.html). Note especially the section on Orthographic Projection and compare Fig 3-15 with 3-13. You can then better achieve the zoom in/out effect by using glScale instead of changing the angle.

Also, I suggest running the projection example at Nate Robbin's tutorial (http://www.gamedev.net/reference/articles/article839.asp). You can toggle between different projection types by right-mouse clicking on the "Perspective" text in the lower pane. Experiment with moving the camera location and observe the different distortion effect (or not with glOrtho). For instance with gluPerspective( 140, 1, 0.1, 10) and eye @ 0,0,0,7 -- notice how the viewing volume is very close to the object and there is a large angle -- this causes the distortion. Compare this with glOrtho(-1.2,1.2 -1.2,1.2, 0.25,3.5) and eye still @ 0,0,0.7. Then maybe try changing the 0.7 for the z-eye coordinate notice how the viewing volume moves and how it affect gluPerspective results whereas gluOrtho does not care what the eye-z value is (provided the object is still in the viewing volume of course).

The method you mentioned of using angle to zoom in conjunction with glPerspective works (without slight projection distortion) if the camera is far away from the object -- not the case in your code example. Try in the Nate Robbins tutorial gluPerspective(29,1,0,1,10) and eye@0,0,4.5. Then adjust fovy between say 1 and 120 -- this will show little distortion and zooming effect.

Rodrigo
08-02-2010, 07:55 AM
I think that glOrtho doesn't work for me, because I can't see if the object is getting far away from the camera.
I want far objects to get smaller when they get far, but when they are close to the camera and in the left or right side of the scene, I don't want them to be deformed.

The first solution seems to work nice with low angles, but not with high. Maybe it really shouldn't work with high angles. I just dind't understand very well how it works...