Hud drawing

Hello everybody.

I’m making an x-wing type game, and I need help drawing the hud, so that it remains stable and in front of the camara.

I thought that maybe with the camara pos and camaralookat pos, I can create a normal vector the plane where the hud should be, but I can’t manage to create that plane, so any help with the maths involved would be really appreciated.

Thanks in advance.
Tomas.

In my engine, I have an implementation of the LookAt() function from MESA, and in that logic I retain the camera’s basis vectors for use later.

Here’s my logic:

// --------------------------------------------------------------------------
// This routine will generate a lookAt matrix provided that the eye position,
// a viewing target have been set. An internal “up” vector may also be set,
// but defaults to the {0,1,0} vector. The result is stored in m_viewMat:
// --------------------------------------------------------------------------
inline void LookAt( void )
{
// create a rotation matrix by calculating a camera direction vector,
// and then using that to generate the remaining vectors for a rotation mat:

// m_basisZ vector is the direction vector from target to the eye:
m_basisZ = m_eye - m_target;
m_basisZ.Normalize();

// make sure the source data for the up vector is not modified:
m_basisY = m_up;

// m_basisX = m_basisY % m_basisZ;  // cross product... same as my old CrossProductFVector( &y, &z, &x ); x is the result
// m_basisY = m_basisZ % m_basisX;  // cross x & z to insure that we're perpendictular
//
m_basisX = m_basisY.Cross( m_basisZ );
m_basisY = m_basisZ.Cross( m_basisX );

// normalize these guys:
m_basisX.Normalize();
m_basisY.Normalize();

// directly set the values to construct a rotation matrix:
// glow::Mat4f rotMat;
CMat4f rotMat;

rotMat.SetVal( 0,0, m_basisX.GetX() ); rotMat.SetVal( 0,1, m_basisX.GetY() );  
rotMat.SetVal( 1,0, m_basisY.GetX() ); rotMat.SetVal( 1,1, m_basisY.GetY() );  
rotMat.SetVal( 2,0, m_basisZ.GetX() ); rotMat.SetVal( 2,1, m_basisZ.GetY() );  
rotMat.SetVal( 3,0, 0.0f );            rotMat.SetVal( 3,1, 0.0f );      

rotMat.SetVal( 0,2, m_basisX.GetZ() );  rotMat.SetVal( 0,3, 0.0f ); 
rotMat.SetVal( 1,2, m_basisY.GetZ() );  rotMat.SetVal( 1,3, 0.0f ); 
rotMat.SetVal( 2,2, m_basisZ.GetZ() );  rotMat.SetVal( 2,3, 0.0f ); 
rotMat.SetVal( 3,2, 0.0f );             rotMat.SetVal( 3,3, 1.0f );

// construct a translation matrix:
// glow::Mat4f tranMat;
CMat4f tranMat;
tranMat.SetTranslation( -m_eye.GetX(), -m_eye.GetY(), -m_eye.GetZ() );

// finally generate our lookAt matrix:
// m_viewMat = rotMat * tranMat;
m_viewMat = rotMat.CMat4fMult( tranMat );

}

// -------------------- get the last calculated x,y,z basis vectors -----------------
inline void GetBasisVectors( CVec3f *leftRight, CVec3f *upDown, CVec3f *inOut )
{
*leftRight = m_basisX;
*upDown = m_basisY;
*inOut = m_basisZ;
}

Note that ‘leftRight’ points to the right, ‘upDown’ points up and ‘inOut’ points into the camera (out of the screen.)

These are normalized vectors, so you can simply get these basis vectors, and then you’ll know your various directions relative to the current camera view.

This logic right here will calculate the 4 corners of your screen at that near clipping plane in world coordinates:

// calculate the x,y max,min bounds for the near clipping plane:
double ymax = gApp->GetCameraZNear() * tan( gApp->GetCameraFOV() * CMath: [img]http://www.opengl.org/discussion_boards/ubb/tongue.gif[/img]i / 360.0 );
double ymin = -ymax;
double xmin = ymin * gApp->GetCameraAspect();
double xmax = ymax * gApp->GetCameraAspect();

// get direction vectors for the current view:
CVec3f leftRight, upDown, inOut;
gApp->GetCameraBasis( &leftRight, &upDown, &inOut );
// 'inOut' points in, towards the camera but we want it to point outwards:
inOut.Negate();

// figure out the coord that is the world space screen center:
CVec3f cameraPosition = gApp->GetCameraPosition();
CVec3f worldSpaceScreenCenter( cameraPosition );
worldSpaceScreenCenter += (inOut * gApp->GetCameraZNear());

// calculate the near clip plane frustum corner coordinates:
CVec3f topLeft( worldSpaceScreenCenter ), 
       topRight( worldSpaceScreenCenter ), 
       botLeft( worldSpaceScreenCenter ), 
       botRight( worldSpaceScreenCenter );

// project the 'top' points up:
topLeft  += (upDown * ymax);
topRight += (upDown * ymax);

// project the 'bottom' points down:
botLeft  += (upDown * ymin);
botRight += (upDown * ymin);

// project the 'left' points left:
topLeft += (leftRight * xmin);
botLeft += (leftRight * xmin);

// project the 'right' points right:
topRight += (leftRight * xmax);
botRight += (leftRight * xmax);

There may be easier ways to calculate this, but it seemed so simple, I like this method.

Once you have the 4 corners at the near clip plane, just nudge them back a tad (so they don’t get clipped) and draw your hud. (Nudge back further if you have a 3D hud )

-Blake

Very strange, this discussion board software put a smiley face inside one of my above equasions (previous post.)

It may do it again here:

CMath: i / 360.0

that should read CMath colon colon pi / 360.0

:P:P:P:PP:P:P:P:P:P:P:P:P:PP:P:P:P:P

-Blake

Instead of translating the HUD into 3D space, why not switch GL into an orthographic projection draw the HUD, and then switch it back afterwards.

I second this previous post. Just change your modelview and projection matrices.

I agree as well, change to Ortho then back again.
Here are the commands I’m using in the Sim I’m working on…
It’s programmed in Delphi, but the OpenGL commands aren’t any different.

glMatrixMode(GL_PROJECTION); // Set up Perspective Clipping Volume
glLoadIdentity;
gluPerspective(zoom, aspect, Cnear, CFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
gluLookAt(AX,Alti,AZ, AX-CX,Alti+CY,AZ-CZ, 0,1,0); // Point the camera

 Draw 3D Environment

glDepthMask(GL_FALSE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluOrtho2D(0, Form3.ClientWidth-1, 0, Form3.ClientHeight-1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity; // Lower Left Corner of Screen = (0,0)

 Disable OpenGL Lighting so the HUD colors come out looking right...

 Draw HUD

glDepthMask(GL_TRUE);

Thanks for the help.

In the end I did it in a different way, I draw the hud inside the code that draws the ship, so it mantains all the rotations, translations, etc… that way I just have to draw it in the standard position and it shows ok indepently of what’s the orientation and position of the ship.