gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > gluLookAtf32 vs. glRotate/glTranslate

#145206 - a128 - Mon Nov 12, 2007 5:30 pm

I use gluLookAtf32() for my camera system..which works fine and smooth

When I use a inverse transformation system for my camera (which yields to the same output)

via
glRotate(360-angle) //inverse angle
glTransform(-eye)

it suffers from NON-smooth rotations even when I interpolate between the "inverse angle"

any suggestions?

#145209 - sajiimori - Mon Nov 12, 2007 7:46 pm

If you're doing 3 separate rotations (along the X, Y, and Z axes), note that earlier rotations affect later ones. It's order-dependent, and difficult to achieve smooth interpolations in the most general case.

Here's another thread about it. Though I don't like the solution that Noda ended up using, it has some good replies from a few people.

http://forum.gbadev.org/viewtopic.php?t=14394

#145279 - a128 - Tue Nov 13, 2007 4:19 pm

Now I use quaternion for my camera transformations

Code:


   m3x3 rot;

        q1.FromEuler(rot_x,360-Heading,0); //x,y,z rot
   q1.CreateMatrix(rot);

   glMultMatrix3x3(&rot);

   MATRIX_TRANSLATE=-eye_.X();//get the 20:12 values
      MATRIX_TRANSLATE=-eye_.Y();//get the 20:12 values
      MATRIX_TRANSLATE=-eye_.Z();//get the 20:12 values


which works quite smooth

if I use in FromEuler() fixed point sin/cos from libnds it's NON-smooth again!!

Code:

void Quaternion::FromEuler(dfloat ex,dfloat ey,dfloat ez)
// Create a quaternion from Euler angles. Angles are applied in the order XYZ,
// while another order may be more appropriate.
// Code after an example from GDMag, march '98, pp 18. (modified somewhat)
{
    dfloat rx,ry,rz;
    Quaternion qx,qy,qz;

   #if 1
    // Get half angles
    Fixed ti=(ex*0.5f);
    Fixed tj=(ey*0.5f);
    Fixed tk=(ez*0.5f);
    // Quaternion
    qx.x=Fixed::sin(ti);
    qx.y=0;
    qx.z=0;
    qx.w=Fixed::cos(ti);
    qy.x=0;
    qy.y=Fixed::sin(tj);
    qy.z=0;
    qy.w=Fixed::cos(tj);
    qz.x=0;
    qz.y=0;
    qz.z=Fixed::sin(tk);
    qz.w=Fixed::cos(tk);
#else
  // Convert angles to radians
    rx=(ex*(float)M_PI)/(360/2);
    ry=(ey*(float)M_PI)/(360/2);
   rz=(ez*(float)M_PI)/(360/2);
   // Get half angles
    float ti=(rx*0.5f).Float();
    float tj=(ry*0.5f).Float();
    float tk=(rz*0.5f).Float();
    // Quaternion
    qx.x=sinf(ti);
    qx.y=0;
    qx.z=0;
    qx.w=cosf(ti);
    qy.x=0;
    qy.y=sinf(tj);
    qy.z=0;
    qy.w=cosf(tj);
    qz.x=0;
    qz.y=0;
    qz.z=sinf(tk);
    qz.w=cosf(tk);
#endif
    Multiply(&qx,&qy);
    Multiply(&qz);
}

#145280 - a128 - Tue Nov 13, 2007 4:35 pm

the only smooth "third person" camera I know is
Code:
 
   
    camera = pos;

    // Translate the forward vector to the origin
    // in relation to look.
    Vec3 tempMeasure = pos -forward;

    tempMeasure.Normalize();
   
    camera = camera + ( tempMeasure * camera_distance);
       
      gluLookAtf32(camera.x,camera.y+2,camera.z,
                                  pos.x, pos.y ,pos.z.,
                                     0, inttof32(1), 0);



I guess it's smooth because of gluLookAt() normalizes all vectors and using those three othronormal vectors it constructs the correct transformation.

#145382 - sajiimori - Wed Nov 14, 2007 6:12 pm

As soon as you introduce Euler angles, you've got order dependency. This is fine in some situations, and not in others. If they're causing you trouble, skip the Euler angles entirely, and use e.g. axis-angle pairs. Quaternions convert naturally to and from axis-angle format.

If I understand what you're doing correctly, gluLookAtf32 is working well because you can linearly interpolate the camera position and lookat position, and that usually looks pretty good, whereas interpolating pitch/yaw/roll often looks bad.

But hey, gluLookAtf32 might make a lot of sense for a 3rd-person view! It's there to be used. :)

#158915 - a128 - Fri Jun 20, 2008 8:23 pm

Mario Kart DS has a simple but effective third person view.
The camera is fixed behind the player kart.

If you steer or jump, you notice some lag of the camera position.
This lag let you see that the kart steers or jumps.

Here is a code which does this

Code:


//Y is UP


#define RELAXATION(target, prev, rate) \
do { \
target = (prev) + (rate) * ((target) - (prev)) ; \
prev = (target); \
} while (0)


const Vec3 pos=KART_POSITION;
Fixed a=KART_HEADING_DEGREE;
dt=1.0f/FPS; //timestep per frame

if (first_start) {
olda_=a;
}

//interpolate the heading of the kart

RELAXATION(a,olda_,dt*8);

//Note: I use float sinf/cosf which has a greater resolution then the fixpoint SIN/COS
//without the float code you will see the camera jumping..

//position eye behind the kart
eye_.x = camera_distance*sinf(a*DEGTORAD)+pos.x;
eye_.y = pos.y;
eye_.z = camera_distance*cosf(a*DEGTORAD)+pos.z;

eye_.y+= camera_height;

look=pos;
look.y+=camera_height_view;

if (first_start) {
lasteye_=eye_;
lastlook_=look;
}

//only interpolate the y position (up/down)

RELAXATION(eye_.y,lasteye_.y,dt*8);
RELAXATION(look.y,lastlook_.y,dt*8);

gluLookAtf32(eye_.x.value,eye_.y.value,eye_.z.value,
look.x.value,look.y.value,look.z.value,
0,inttof32(1),0); //Y is UP