1 // panel.cxx - default, 2D single-engine prop instrument panel
3 // Written by David Megginson, started January 2000.
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 #include <simgear/xgl.h>
35 #include <simgear/logstream.hxx>
36 #include <simgear/fgpath.hxx>
38 #include <Main/options.hxx>
39 #include <Objects/texload.h>
40 #include <Autopilot/autopilot.hxx>
42 #include "cockpit.hxx"
48 #define SIX_SPACING (SIX_W + 5)
53 ////////////////////////////////////////////////////////////////////////
54 // Implementation of FGPanel.
55 ////////////////////////////////////////////////////////////////////////
57 FGPanel * FGPanel::OurPanel = 0;
64 FG_LOG(FG_GENERAL, FG_ALERT, "Multiple panels");
71 FGPath tpath(current_options.get_fg_root());
72 tpath.append("Textures/Panel/panel-bg.rgb");
73 _bg = new ssgTexture((char *)tpath.c_str(), false, false);
75 _airspeed = new FGAirspeedIndicator(x, y);
77 _horizon = new FGHorizon(x, y);
79 _altimeter = new FGAltimeter(x, y);
82 _coordinator = new FGTurnCoordinator(x, y);
84 _gyro = new FGGyroCompass(x, y);
86 _vertical = new FGVerticalVelocity(x, y);
89 _rpm = new FGRPMGauge(x, y);
92 _flaps = new FGFlapIndicator(x, y);
109 FGPanel::get_height () const
115 FGPanel::ReInit (int x, int y, int finx, int finy)
121 _panel_h = (int)((finy - y) * 0.5768 + 1);
125 FGPanel::Update () const
127 // glPushAttrib(GL_ALL_ATTRIB_BITS);
129 glMatrixMode(GL_PROJECTION);
132 gluOrtho2D(_x, _x + _w, _y, _y + _h);
134 glMatrixMode(GL_MODELVIEW);
138 // Draw the background
139 glDisable(GL_LIGHTING);
140 glEnable(GL_TEXTURE_2D);
141 if ( _bg->getHandle() >= 0 ) {
142 glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
144 cout << "invalid texture handle in FGPanel::Update()" << endl;
146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
148 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
150 glTexCoord2f(0.0, 0.0); glVertex3f(_x, _y, 0);
151 glTexCoord2f(10.0, 0.0); glVertex3f(_x + _w, _y, 0);
152 glTexCoord2f(10.0, 5.0); glVertex3f(_x + _w, _y + _panel_h, 0);
153 glTexCoord2f(0.0, 5.0); glVertex3f(_x, _y + _panel_h, 0);
156 // Draw the instruments.
158 glTranslated(_airspeed->getXPos(), _airspeed->getYPos(), 0);
162 glTranslated(_horizon->getXPos(), _horizon->getYPos(), 0);
166 glTranslated(_altimeter->getXPos(), _altimeter->getYPos(), 0);
170 glTranslated(_coordinator->getXPos(), _coordinator->getYPos(), 0);
171 _coordinator->draw();
174 glTranslated(_gyro->getXPos(), _gyro->getYPos(), 0);
178 glTranslated(_vertical->getXPos(), _vertical->getYPos(), 0);
182 glTranslated(_rpm->getXPos(), _rpm->getYPos(), 0);
186 glTranslated(_flaps->getXPos(), _flaps->getYPos(), 0);
189 glMatrixMode(GL_PROJECTION);
191 glMatrixMode(GL_MODELVIEW);
196 // ssgForceBasicState();
201 ////////////////////////////////////////////////////////////////////////
202 // Implementation of FGPanelInstrument.
203 ////////////////////////////////////////////////////////////////////////
206 FGPanelInstrument::FGPanelInstrument ()
212 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
218 FGPanelInstrument::~FGPanelInstrument ()
223 FGPanelInstrument::setPosition (int x, int y)
230 FGPanelInstrument::setSize (int w, int h)
237 FGPanelInstrument::getXPos () const
243 FGPanelInstrument::getYPos () const
250 ////////////////////////////////////////////////////////////////////////
251 // Implementation of FGTexturedInstrument.
252 ////////////////////////////////////////////////////////////////////////
254 FGTexturedInstrument::FGTexturedInstrument (int x, int y, int w, int h)
255 : FGPanelInstrument(x, y, w, h)
257 for (int i = 0; i < MAX_LAYERS; i++) {
262 FGTexturedInstrument::~FGTexturedInstrument ()
264 // FIXME: maybe free textures
268 FGTexturedInstrument::addLayer (int layer, const char * textureName)
270 FGPath tpath(current_options.get_fg_root());
271 tpath.append(textureName);
272 ssgTexture * texture = new ssgTexture((char *)tpath.c_str(), false, false);
273 cerr << "Loaded texture " << textureName << endl;
274 addLayer(layer, texture);
278 FGTexturedInstrument::addLayer (int layer, ssgTexture * texture)
280 _layers[layer] = true;
281 _textures[layer] = texture;
282 _rotation[layer] = 0.0;
283 _xoffset[layer] = _yoffset[layer] = 0;
284 _xcenter[layer] = _ycenter[layer] = 0;
288 FGTexturedInstrument::setLayerCenter (int layer, int x, int y)
295 FGTexturedInstrument::setLayerRot (int layer, double rotation) const
297 _rotation[layer] = rotation;
301 FGTexturedInstrument::setLayerOffset (int layer, int xoff, int yoff) const
303 _xoffset[layer] = xoff;
304 _yoffset[layer] = yoff;
308 FGTexturedInstrument::hasLayer (int layer) const
310 return _layers[layer];
314 FGTexturedInstrument::draw () const
316 glEnable(GL_TEXTURE_2D);
322 glMatrixMode(GL_MODELVIEW);
323 for (i = 0; i < MAX_LAYERS; i++) {
326 glTranslated(_xcenter[i], _ycenter[i], 0);
327 glRotatef(0.0 - _rotation[i], 0.0, 0.0, 1.0);
328 glTranslated(_xoffset[i], _yoffset[i], 0);
329 if ( _textures[i]->getHandle() >= 0 ) {
330 glBindTexture(GL_TEXTURE_2D, _textures[i]->getHandle());
332 cout << "invalid texture handle in FGTexturedInstrument::draw()"
335 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
337 // FIXME: is this really correct
339 glTexCoord2f(0.0, 0.0); glVertex3f(-w2, -h2, i / 100.0 + 0.1);
340 glTexCoord2f(1.0, 0.0); glVertex3f(w2, -h2, i / 100.0 + 0.1);
341 glTexCoord2f(1.0, 1.0); glVertex3f(w2, h2, i / 100.0 + 0.1);
342 glTexCoord2f(0.0, 1.0); glVertex3f(-w2, h2, i / 100.0 + 0.1);
348 glDisable(GL_TEXTURE_2D);
353 ////////////////////////////////////////////////////////////////////////
354 // Implementation of FGAirspeedIndicator.
355 ////////////////////////////////////////////////////////////////////////
357 FGAirspeedIndicator::FGAirspeedIndicator (int x, int y)
358 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
360 addLayer(0, "Textures/Panel/airspeed.rgb");
361 addLayer(1, "Textures/Panel/long-needle.rgb");
364 FGAirspeedIndicator::~FGAirspeedIndicator ()
369 FGAirspeedIndicator::draw () const
371 double speed = get_speed();
374 } else if (speed > 220.0) {
377 double angle = speed / 20.0 * 36.0 - 54.0;
378 setLayerRot(1, angle);
379 FGTexturedInstrument::draw();
384 ////////////////////////////////////////////////////////////////////////
385 // Implementation of FGHorizon.
386 ////////////////////////////////////////////////////////////////////////
388 FGHorizon::FGHorizon (int x, int y)
389 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
391 addLayer(0, "Textures/Panel/horizon-bg.rgb");
392 addLayer(1, "Textures/Panel/horizon-float.rgb");
393 addLayer(2, "Textures/Panel/horizon-rim.rgb");
394 addLayer(3, "Textures/Panel/horizon-fg.rgb");
397 FGHorizon::~FGHorizon ()
402 FGHorizon::draw () const
404 double rot = get_roll() * RAD_TO_DEG;
405 double pitch = get_pitch() * RAD_TO_DEG;
408 else if (pitch < -20)
410 int yoffset = 0 - (pitch * ((1.5 / 160.0) * _h));
411 setLayerRot(0, 0 - rot);
412 setLayerRot(1, 0 - rot);
413 setLayerOffset(1, 0, yoffset);
414 setLayerRot(2, 0 - rot);
415 FGTexturedInstrument::draw();
420 ////////////////////////////////////////////////////////////////////////
421 // Implementation of FGAltimeter.
422 ////////////////////////////////////////////////////////////////////////
424 // TODO: add 10,000 bug
426 FGAltimeter::FGAltimeter (int x, int y)
427 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
429 addLayer(0, "Textures/Panel/altimeter.rgb");
430 addLayer(1, "Textures/Panel/long-needle.rgb");
431 addLayer(2, "Textures/Panel/short-needle.rgb");
432 addLayer(3, "Textures/Panel/bug.rgb");
435 FGAltimeter::~FGAltimeter ()
440 FGAltimeter::draw () const
442 long altitude = get_altitude();
443 setLayerRot(1, (altitude % 1000) / 1000.0 * 360.0);
444 setLayerRot(2, (altitude % 10000) / 10000.0 * 360.0);
445 setLayerRot(3, (altitude % 100000) / 100000.0 * 360.0);
446 FGTexturedInstrument::draw();
451 ////////////////////////////////////////////////////////////////////////
452 // Implementation of FGTurnCoordinator.
453 ////////////////////////////////////////////////////////////////////////
455 // TODO: add slip/skid ball
457 FGTurnCoordinator::FGTurnCoordinator (int x, int y)
458 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
460 addLayer(0, "Textures/Panel/turn-bg.rgb");
461 addLayer(1, "Textures/Panel/turn.rgb");
462 addLayer(2, "Textures/Panel/ball.rgb");
465 FGTurnCoordinator::~FGTurnCoordinator ()
470 FGTurnCoordinator::draw () const
473 // FIXME: this should be turn, maybe
474 double rot = get_roll() * RAD_TO_DEG;
477 else if (rot < -30.0)
482 // FIXME: totally bogus values
483 double slip = get_sideslip() * 450;
486 } else if (slip < -45) {
489 setLayerRot(2, 0 - slip);
491 FGTexturedInstrument::draw();
496 ////////////////////////////////////////////////////////////////////////
497 // Implementation of FGGyroCompass.
498 ////////////////////////////////////////////////////////////////////////
500 // TODO: add heading bug
502 FGGyroCompass::FGGyroCompass (int x, int y)
503 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
505 addLayer(0, "Textures/Panel/gyro-bg.rgb");
506 addLayer(1, "Textures/Panel/bug.rgb");
507 addLayer(2, "Textures/Panel/gyro-fg.rgb");
510 FGGyroCompass::~FGGyroCompass ()
515 FGGyroCompass::draw () const
517 setLayerRot(0, 0.0 - get_heading());
518 setLayerRot(1, 0.0 - get_heading() + fgAPget_TargetHeading());
519 FGTexturedInstrument::draw();
524 ////////////////////////////////////////////////////////////////////////
525 // Implementation of FGVerticalVelocity.
526 ////////////////////////////////////////////////////////////////////////
528 FGVerticalVelocity::FGVerticalVelocity (int x, int y)
529 : FGTexturedInstrument(x, y, SIX_W, SIX_W)
531 addLayer(0, "Textures/Panel/vertical.rgb");
532 addLayer(1, "Textures/Panel/long-needle.rgb");
535 FGVerticalVelocity::~FGVerticalVelocity ()
540 FGVerticalVelocity::draw () const
542 double climb = get_climb_rate() / 500.0;
545 } else if (climb > 4.0) {
548 double rot = (climb * 42.0) + 270.0;
549 // FIXME: why inverted?
551 FGTexturedInstrument::draw();
556 ////////////////////////////////////////////////////////////////////////
557 // Implementation of FGRPMGauge.
558 ////////////////////////////////////////////////////////////////////////
560 FGRPMGauge::FGRPMGauge (int x, int y)
561 : FGTexturedInstrument(x, y, SMALL_W, SMALL_W)
563 addLayer(0, "Textures/Panel/rpm.rgb");
564 addLayer(1, "Textures/Panel/long-needle.rgb");
567 FGRPMGauge::~FGRPMGauge ()
572 FGRPMGauge::draw () const
574 double rot = get_throttleval() * 300 - 150;
576 FGTexturedInstrument::draw();
581 ////////////////////////////////////////////////////////////////////////
582 // Implementation of FGFlapIndicator.
583 ////////////////////////////////////////////////////////////////////////
585 FGFlapIndicator::FGFlapIndicator (int x, int y)
586 : FGTexturedInstrument(x, y, SMALL_W, SMALL_W)
588 addLayer(0, "Textures/Panel/flaps.rgb");
589 addLayer(1, "Textures/Panel/long-needle.rgb");
590 setLayerCenter(1, 0 - (SMALL_W / 4) + (SMALL_W / 16), 0);
593 FGFlapIndicator::~FGFlapIndicator ()
598 FGFlapIndicator::draw () const
600 double rot = controls.get_flaps() * 120 + 30;
602 FGTexturedInstrument::draw();