X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCockpit%2Fpanel.cxx;h=bee42a477766ecd75ba3cf9e3eaccf26fa62c670;hb=d982efc4c4d166e144023664b8ac1c63233f5f82;hp=de6fd02b510e2ee68f783f8d7e0adfbe052cf546;hpb=b8fc42d8247138cf7088644c254aea758254b0bb;p=flightgear.git diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index de6fd02b5..bee42a477 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -57,7 +57,6 @@ # undef NONE #endif - //////////////////////////////////////////////////////////////////////// // Local functions. @@ -84,10 +83,16 @@ get_aspect_adjust (int xsize, int ysize) bool fgPanelVisible () { - return ((current_panel != 0) && - (current_panel->getVisibility()) && - (globals->get_viewmgr()->get_current() == 0) && - (globals->get_current_view()->get_view_offset() == 0.0)); + if(current_panel == 0) + return false; + if(current_panel->getVisibility() == 0) + return false; + if(globals->get_viewmgr()->get_current() != 0) + return false; + if(globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0 && + !fgGetBool("/sim/virtual-cockpit")) + return false; + return true; } @@ -175,7 +180,6 @@ FGPanel::FGPanel () _mouseInstrument(0), _width(WIN_W), _height(int(WIN_H * 0.5768 + 1)), _x_offset(0), _y_offset(0), _view_height(int(WIN_H * 0.4232)), - _bound(false), _jitter(0.0), _xsize_node(fgGetNode("/sim/startup/xsize", true)), _ysize_node(fgGetNode("/sim/startup/ysize", true)) @@ -189,8 +193,6 @@ FGPanel::FGPanel () */ FGPanel::~FGPanel () { - if (_bound) - unbind(); for (instrument_list_type::iterator it = _instruments.begin(); it != _instruments.end(); it++) { @@ -247,15 +249,10 @@ FGPanel::init () void FGPanel::bind () { - fgTie("/sim/panel/visibility", &_visibility); fgSetArchivable("/sim/panel/visibility"); - fgTie("/sim/panel/x-offset", &_x_offset); fgSetArchivable("/sim/panel/x-offset"); - fgTie("/sim/panel/y-offset", &_y_offset); fgSetArchivable("/sim/panel/y-offset"); - fgTie("/sim/panel/jitter", &_jitter); fgSetArchivable("/sim/panel/jitter"); - _bound = true; } @@ -265,10 +262,6 @@ FGPanel::bind () void FGPanel::unbind () { - fgUntie("/sim/panel/visibility"); - fgUntie("/sim/panel/x-offset"); - fgUntie("/sim/panel/y-offset"); - _bound = false; } @@ -276,8 +269,14 @@ FGPanel::unbind () * Update the panel. */ void -FGPanel::update (int dt) +FGPanel::update (double dt) { + // TODO: cache the nodes + _visibility = fgGetBool("/sim/panel/visibility"); + _x_offset = fgGetInt("/sim/panel/x-offset"); + _y_offset = fgGetInt("/sim/panel/y-offset"); + _jitter = fgGetFloat("/sim/panel/jitter"); + // Do nothing if the panel isn't visible. if ( !fgPanelVisible() ) { return; @@ -330,19 +329,23 @@ FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) 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); @@ -354,16 +357,40 @@ FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) } 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(); @@ -371,20 +398,112 @@ FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) 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->getPitchOffset_deg() * SGD_DEGREES_TO_RADIANS; + float rot = view->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS; + 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. @@ -415,6 +534,15 @@ FGPanel::setBackground (ssgTexture * texture) _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. @@ -454,7 +582,7 @@ FGPanel::doMouseAction (int button, int updown, int x, int y) if (updown == 1) { _mouseDown = false; _mouseInstrument = 0; - return true; + return false; } // Scale for the real window size. @@ -485,8 +613,7 @@ FGPanel::doMouseAction (int button, int updown, int x, int y) _mouseX = x - ix; _mouseY = y - iy; // Always do the action once. - _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY); - return true; + return _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY); } } return false; @@ -659,9 +786,15 @@ void FGLayeredInstrument::draw () { if (test()) { + float z = 0.1f; + float z_inc = 0.01; + bool vc = fgGetBool("/sim/virtual-cockpit"); for (int i = 0; i < (int)_layers.size(); i++) { glPushMatrix(); - glTranslatef(0.0, 0.0, (i / 100.0) + 0.1); + if(!vc) { + glTranslatef(0.0, 0.0, z); + z += z_inc; + } _layers[i]->draw(); glPopMatrix(); } @@ -879,7 +1012,29 @@ FGTextLayer::draw () text_renderer.start3f(0, 0, 0); _now.stamp(); - if (_now - _then > 100000) { + long diff = _now - _then; +#if 0 + // It would be nice to keep this #ifdef'd stuff for (04/18/2002 + + // a couple days) as I verify my solution to the panel text + // drawing problem is actually correct. -CLO + cout << "time diff = " << diff << endl; + if ( _now - _then < 0 ) { + cout << "Eeek, the past is now in the future!" << endl; + cout << "Now = " << _now.get_seconds() << " seconds " + << _now.get_usec() << "usecs" << endl; + cout << "Past = " << _then.get_seconds() << " seconds " + << _then.get_usec() << "usecs" << endl; + exit(-1); + } +#endif + if (diff > 100000 || diff < 0 ) { + // ( diff < 0 ) is a sanity check and indicates our time stamp + // difference math probably overflowed. We can handle a max + // difference of 35.8 minutes since the returned value is in + // usec. So if the panel is left off longer than that we can + // over flow the math with it is turned back on. This (diff < + // 0) catches that situation, get's us out of trouble, and + // back on track. recalc_value(); _then = _now; } @@ -947,7 +1102,7 @@ FGTextLayer::Chunk::Chunk (const string &text, const string &fmt) : _type(FGTextLayer::TEXT), _fmt(fmt) { _text = text; - if (_fmt == "") + if (_fmt.empty()) _fmt = "%s"; } @@ -955,7 +1110,7 @@ FGTextLayer::Chunk::Chunk (ChunkType type, const SGPropertyNode * node, const string &fmt, float mult) : _type(type), _fmt(fmt), _mult(mult) { - if (_fmt == "") { + if (_fmt.empty()) { if (type == TEXT_VALUE) _fmt = "%s"; else @@ -968,12 +1123,13 @@ const char * FGTextLayer::Chunk::getValue () const { if (test()) { + _buf[0] = '\0'; switch (_type) { case TEXT: sprintf(_buf, _fmt.c_str(), _text.c_str()); return _buf; case TEXT_VALUE: - sprintf(_buf, _fmt.c_str(), _node->getStringValue().c_str()); + sprintf(_buf, _fmt.c_str(), _node->getStringValue()); break; case DOUBLE_VALUE: sprintf(_buf, _fmt.c_str(), _node->getFloatValue() * _mult); @@ -1019,3 +1175,6 @@ FGSwitchLayer::draw () // end of panel.cxx + + +