# include <windows.h>
#endif
+#include <stdio.h> // sprintf
#include <string.h>
#include <plib/ssg.h>
#define WIN_W 1024
#define WIN_H 768
-#ifdef defined( NONE ) && defined( _MSC_VER )
+#if defined( NONE ) && defined( _MSC_VER )
# pragma message( "A sloppy coder has defined NONE as a macro!!!" )
# undef NONE
#elif defined( NONE )
# undef NONE
#endif
-
\f
////////////////////////////////////////////////////////////////////////
// Local functions.
bool
fgPanelVisible ()
{
- return ((current_panel != 0) &&
- (current_panel->getVisibility()) &&
- (globals->get_viewmgr()->get_current() == 0) &&
- (globals->get_current_view()->get_view_offset() == 0.0));
+ return (fgGetBool("/sim/virtual-cockpit") ||
+ ((current_panel != 0) &&
+ (current_panel->getVisibility()) &&
+ (globals->get_viewmgr()->get_current() == 0) &&
+ (globals->get_current_view()->get_view_offset() == 0.0)));
}
FGPanel * current_panel = NULL;
static fntRenderer text_renderer;
-
+static fntTexFont *default_font;
+static fntTexFont *led_font;
/**
* Constructor.
void
FGPanel::init ()
{
- // NO-OP
+ SGPath base_path;
+ char* envp = ::getenv( "FG_FONTS" );
+ if ( envp != NULL ) {
+ base_path.set( envp );
+ } else {
+ base_path.set( globals->get_fg_root() );
+ base_path.append( "Fonts" );
+ }
+
+ SGPath fntpath;
+
+ // Install the default font
+ fntpath = base_path;
+ fntpath.append( "typewriter.txf" );
+ default_font = new fntTexFont ;
+ default_font -> load ( (char *)fntpath.c_str() ) ;
+
+ // Install the LED font
+ fntpath = base_path;
+ fntpath.append( "led.txf" );
+ led_font = new fntTexFont ;
+ led_font -> load ( (char *)fntpath.c_str() ) ;
}
* Update the panel.
*/
void
-FGPanel::update ()
+FGPanel::update (int dt)
{
// Do nothing if the panel isn't visible.
- if (!fgPanelVisible())
+ if ( !fgPanelVisible() ) {
return;
+ }
// If the mouse is down, do something
if (_mouseDown) {
y_offset += y_adjust;
}
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
- // gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glTranslated(x_offset, y_offset, 0);
-
- // Draw the background
+ if(fgGetBool("/sim/virtual-cockpit")) {
+ setupVirtualCockpit();
+ } else {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
+ // gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glTranslated(x_offset, y_offset, 0);
+ }
+
+ // Draw the background
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
} else {
glColor4f(0.7, 0.2, 0.2, 1.0);
}
- glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
- // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBegin(GL_POLYGON);
- glTexCoord2f(0.0, 0.0); glVertex3f(WIN_X, WIN_Y, 0);
- glTexCoord2f(1.0, 0.0); glVertex3f(WIN_X + _width, WIN_Y, 0);
- glTexCoord2f(1.0, 1.0); glVertex3f(WIN_X + _width, WIN_Y + _height, 0);
- glTexCoord2f(0.0, 1.0); glVertex3f(WIN_X, WIN_Y + _height, 0);
- glEnd();
+ if (_bg != 0) {
+ glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
+ // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0.0, 0.0); glVertex3f(WIN_X, WIN_Y, 0);
+ glTexCoord2f(1.0, 0.0); glVertex3f(WIN_X + _width, WIN_Y, 0);
+ glTexCoord2f(1.0, 1.0); glVertex3f(WIN_X + _width, WIN_Y + _height, 0);
+ glTexCoord2f(0.0, 1.0); glVertex3f(WIN_X, WIN_Y + _height, 0);
+ glEnd();
+ } else {
+ for (int i = 0; i < 4; i ++) {
+ // top row of textures...(1,3,5,7)
+ glBindTexture(GL_TEXTURE_2D, _mbg[i*2]->getHandle());
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0.0, 0.0); glVertex3f(WIN_X + (_width/4) * i, WIN_Y + (_height/2), 0);
+ glTexCoord2f(1.0, 0.0); glVertex3f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2), 0);
+ glTexCoord2f(1.0, 1.0); glVertex3f(WIN_X + (_width/4) * (i+1), WIN_Y + _height, 0);
+ glTexCoord2f(0.0, 1.0); glVertex3f(WIN_X + (_width/4) * i, WIN_Y + _height, 0);
+ glEnd();
+ // bottom row of textures...(2,4,6,8)
+ glBindTexture(GL_TEXTURE_2D, _mbg[(i*2)+1]->getHandle());
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0.0, 0.0); glVertex3f(WIN_X + (_width/4) * i, WIN_Y, 0);
+ glTexCoord2f(1.0, 0.0); glVertex3f(WIN_X + (_width/4) * (i+1), WIN_Y, 0);
+ glTexCoord2f(1.0, 1.0); glVertex3f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2), 0);
+ glTexCoord2f(0.0, 1.0); glVertex3f(WIN_X + (_width/4) * i, WIN_Y + (_height/2), 0);
+ glEnd();
+ }
+
+ }
// Draw the instruments.
instrument_list_type::const_iterator current = _instruments.begin();
for ( ; current != end; current++) {
FGPanelInstrument * instr = *current;
- glLoadIdentity();
- glTranslated(x_offset, y_offset, 0);
+ glPushMatrix();
glTranslated(instr->getXPos(), instr->getYPos(), 0);
instr->draw();
+ glPopMatrix();
+ }
+
+ if(fgGetBool("/sim/virtual-cockpit")) {
+ cleanupVirtualCockpit();
+ } else {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
ssgForceBasicState();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
+void
+FGPanel::setupVirtualCockpit()
+{
+ int i;
+ FGViewer* view = globals->get_current_view();
+
+ // Generate corners for the panel quad. Put the top edge of the
+ // panel 1m in and 6 degrees down from the forward direction, and
+ // make the whole thing 60 degrees wide. In principle, these
+ // should be settable per-panel, so that you can have lots of
+ // panel objects plastered about the cockpit in realistic
+ // positions and orientations.
+ float a[3], b[3], c[3];
+ float pw = tan(30*SGD_DEGREES_TO_RADIANS);
+ float ph = 2 * pw * (float)_height/(float)_width;
+ float ptop = -tan(6*SGD_DEGREES_TO_RADIANS);
+ a[0] = -pw; a[1] = ptop-ph; a[2] = -1; // bottom left
+ b[0] = pw; b[1] = ptop-ph; b[2] = -1; // bottom right
+ c[0] = -pw; c[1] = ptop; c[2] = -1; // top left
+
+ // A standard projection, in meters, with especially close clip
+ // planes.
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPerspective(view->get_v_fov(), 1/view->get_aspect_ratio(),
+ 0.01, 100);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ // Generate a "look at" matrix using OpenGL (!) coordinate
+ // conventions.
+ float lookat[3];
+ float pitch = view->get_view_tilt();
+ float rot = view->get_view_offset();
+ lookat[0] = -sin(rot);
+ lookat[1] = sin(pitch) / cos(pitch);
+ lookat[2] = -cos(rot);
+ if(fabs(lookat[1]) > 9999) lookat[1] = 9999; // FPU sanity
+ gluLookAt(0, 0, 0, lookat[0], lookat[1], lookat[2], 0, 1, 0);
+
+ // Translate the origin to the location of the panel quad
+ glTranslatef(a[0], a[1], a[2]);
+
+ // Generate a matrix to translate unit square coordinates from the
+ // panel to real world coordinates. Use a transposed basis for
+ // the panel quad. Note: this matrix is relatively expensive to
+ // compute, and is invariant. Consider precomputing and storing
+ // it. Also, consider using the plib vector math routines, so the
+ // reuse junkies don't yell at me. (Fine, I hard-coded a cross
+ // product. Just shoot me and be done with it.)
+ float u[3], v[3], w[3], m[16];
+ for(i=0; i<3; i++) u[i] = b[i] - a[i]; // U = B - A
+ for(i=0; i<3; i++) v[i] = c[i] - a[i]; // V = C - A
+ w[0] = u[1]*v[2] - v[1]*u[2]; // W = U x V
+ w[1] = u[2]*v[0] - v[2]*u[0];
+ w[2] = u[0]*v[1] - v[0]*u[1];
+
+ m[0] = u[0]; m[4] = v[0]; m[8] = w[0]; m[12] = 0; // |Ux Vx Wx|
+ m[1] = u[1]; m[5] = v[1]; m[9] = w[1]; m[13] = 0; // m = |Uy Vy Wy|
+ m[2] = u[2]; m[6] = v[2]; m[10] = w[2]; m[14] = 0; // |Uz Vz Wz|
+ m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
+ glMultMatrixf(m);
+
+ // Finally, a scaling factor to map the panel's width and height
+ // to the unit square.
+ glScalef(1./_width, 1./_height, 1);
+
+ // Now, turn off the Z buffer. The panel code doesn't need
+ // it, and we're using different clip planes anyway (meaning we
+ // can't share it without glDepthRange() hackery or much
+ // framebuffer bandwidth wasteage)
+ glDisable(GL_DEPTH_TEST);
+}
+
+void
+FGPanel::cleanupVirtualCockpit()
+{
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
/**
* Set the panel's visibility.
_bg = texture;
}
+/**
+ * Set the panel's multiple background textures.
+ */
+void
+FGPanel::setMultiBackground (ssgTexture * texture, int idx)
+{
+ _bg = 0;
+ _mbg[idx] = texture;
+}
/**
* Set the panel's x-offset.
FGPanelTransformation::~FGPanelTransformation ()
{
+ delete table;
}
if (test()) {
for (int i = 0; i < (int)_layers.size(); i++) {
glPushMatrix();
- glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
+ if(!fgGetBool("/sim/virtual-cockpit"))
+ glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
_layers[i]->draw();
glPopMatrix();
}
////////////////////////////////////////////////////////////////////////
FGTextLayer::FGTextLayer (int w, int h)
- : FGInstrumentLayer(w, h), _pointSize(14.0)
+ : FGInstrumentLayer(w, h), _pointSize(14.0), _font_name("default")
{
_then.stamp();
_color[0] = _color[1] = _color[2] = 0.0;
glPushMatrix();
glColor4fv(_color);
transform();
- text_renderer.setFont(guiFntHandle);
+ if ( _font_name == "led" ) {
+ text_renderer.setFont(led_font);
+ } else {
+ text_renderer.setFont(guiFntHandle);
+ }
text_renderer.setPointSize(_pointSize);
text_renderer.begin();
text_renderer.start3f(0, 0, 0);
_pointSize = size;
}
+void
+FGTextLayer::setFontName(const string &name)
+{
+ _font_name = name;
+}
+
+
void
FGTextLayer::setFont(fntFont * font)
{
\f
// end of panel.cxx
+
+