00001 #include <vamos/body/Gauge.h>
00002
00003 #include <algorithm>
00004 #include <iostream>
00005 #include <functional>
00006
00007 using namespace Vamos_Geometry;
00008
00009 namespace Vamos_Body
00010 {
00011
00012
00013 Facade::Facade (double x, double y, double above, double width, double height,
00014 std::string image) :
00015 Gl_Texture_Image (image, true, true),
00016 m_x (x),
00017 m_y (y),
00018 m_above (above),
00019 m_width (width),
00020 m_height (height),
00021 m_list_index (glGenLists (1))
00022 {
00023 build_facade ();
00024 }
00025
00026 Facade::Facade (double center_x, double center_y, double above, double radius,
00027 std::string image) :
00028 Gl_Texture_Image (image, true, true)
00029 {
00030 m_above = above;
00031 m_width = 2.0 * radius * width_pixels () / height_pixels ();
00032 m_height = 2.0 * radius;
00033 m_x = center_x - m_width / 2.0;
00034 m_y = center_y - m_height / 2.0;
00035 m_list_index = glGenLists (1);
00036 build_facade ();
00037 }
00038
00039 void
00040 Facade::build_facade ()
00041 {
00042 clamp_to_edge ();
00043 glNewList (m_list_index, GL_COMPILE);
00044 build_image ();
00045 glEndList ();
00046 }
00047
00048 void
00049 Facade::build_image ()
00050 {
00051 activate ();
00052
00053 glColor3d (1.0, 1.0, 1.0);
00054 glBegin (GL_QUADS);
00055 glTexCoord2d (0.0, 0.0);
00056 glVertex3d (-m_above, -m_x, m_y + m_height);
00057 glTexCoord2d (1.0, 0.0);
00058 glVertex3d (-m_above, -m_x - m_width, m_y + m_height);
00059 glTexCoord2d (1.0, 1.0);
00060 glVertex3d (-m_above, -m_x - m_width, m_y);
00061 glTexCoord2d (0.0, 1.0);
00062 glVertex3d (-m_above, -m_x, m_y);
00063 glEnd ();
00064 }
00065
00066 void
00067 Facade::rotate (double degrees) const
00068 {
00069 glRotated (degrees, 1.0, 0.0, 0.0);
00070 }
00071
00072 void
00073 Facade::draw () const
00074 {
00075 glCallList (m_list_index);
00076 }
00077
00078
00079 Scaler::Scaler (double min_in, double min_out, double max_in, double max_out) :
00080 m_minimum_input (min_in),
00081 m_maximum_input (max_in),
00082 m_offset (min_out),
00083 m_factor ((max_out - min_out) / (max_in - min_in))
00084 {
00085 }
00086
00087 double
00088 Scaler::scale (double value_in)
00089 {
00090 value_in = std::max (m_minimum_input, value_in);
00091 value_in = std::min (m_maximum_input, value_in);
00092 return m_offset + (value_in - m_minimum_input) * m_factor;
00093 }
00094
00095
00096 Dial::Dial (double center_x, double center_y, double above, double radius,
00097 double min, double min_angle, double max, double max_angle,
00098 std::string face_image, std::string needle_image) :
00099 m_above (above),
00100 m_scaler (min, min_angle, max, max_angle),
00101 mp_face (0),
00102 m_center_x (center_x),
00103 m_center_y (center_y)
00104 {
00105 if (face_image != "")
00106 {
00107 mp_face = new Facade (center_x, center_y, above, radius, face_image);
00108 }
00109 if (needle_image != "")
00110 {
00111 mp_needle = new Facade (0.0, 0.0, above + 0.01, radius,
00112 needle_image);
00113 }
00114 }
00115
00116 Dial::~Dial ()
00117 {
00118 delete mp_needle;
00119 delete mp_face;
00120 }
00121
00122 void
00123 Dial::set (double value)
00124 {
00125 m_angle = m_scaler.scale (value);
00126 }
00127
00128 void
00129 Dial::draw () const
00130 {
00131 glPushMatrix ();
00132 mp_face->draw ();
00133 glTranslated (0.0, -m_center_x, m_center_y);
00134 mp_needle->rotate (m_angle);
00135 mp_needle->draw ();
00136 glPopMatrix ();
00137 }
00138
00139
00140 LED_Gauge::LED_Gauge (double x, double y, double above, double width,
00141 int elements, double min, double redline,
00142 std::string image, bool on_wheel) :
00143 m_x (x),
00144 m_y (y),
00145 m_above (above),
00146 m_width (width),
00147 m_elements (elements),
00148 m_min (min),
00149 m_range (redline - min),
00150 m_leds_on (0),
00151 m_list_index (glGenLists (1))
00152 {
00153 m_on_steering_wheel = on_wheel;
00154 mp_leds = new Gl_Texture_Image (image, true, true);
00155
00156 m_height = (0.5 * m_width * mp_leds->height_pixels ())
00157 / mp_leds->width_pixels ();
00158
00159 glNewList (m_list_index, GL_COMPILE);
00160
00161 mp_leds->activate ();
00162
00163 glTranslated (-m_above, -m_x, m_y);
00164
00165 glColor3d (1.0, 1.0, 1.0);
00166 glBegin (GL_QUADS);
00167 glTexCoord2d (0.0, 0.5);
00168 glVertex3d (0.0, 0.0, 0.0);
00169 glTexCoord2d (1.0, 0.5);
00170 glVertex3d (0.0, -m_width, 0.0);
00171 glTexCoord2d (1.0, 1.0);
00172 glVertex3d (0.0, -m_width, m_height);
00173 glTexCoord2d (0.0, 1.0);
00174 glVertex3d (0.0, 0.0, m_height);
00175 glEnd ();
00176
00177 glEndList ();
00178 }
00179
00180 LED_Gauge::~LED_Gauge ()
00181 {
00182 delete mp_leds;
00183 }
00184
00185 void
00186 LED_Gauge::set (double value)
00187 {
00188 m_leds_on = int ((value - m_min)*(m_elements - 1)/m_range + 1.0);
00189 m_leds_on = std::max (m_leds_on, 0);
00190 m_leds_on = std::min (m_leds_on, m_elements);
00191 }
00192
00193 void
00194 LED_Gauge::draw () const
00195 {
00196 glPushMatrix ();
00197
00198
00199 glCallList (m_list_index);
00200
00201
00202 double frac = double (m_leds_on) / m_elements;
00203
00204 mp_leds->activate ();
00205
00206 glColor3d (1.0, 1.0, 1.0);
00207 glBegin (GL_QUADS);
00208 glTexCoord2d (0.0, 0.5);
00209 glVertex3d (0.0, 0.0, 0.0);
00210 glTexCoord2d (frac, 0.5);
00211 glVertex3d (0.0, -m_width * frac, 0.0);
00212 glTexCoord2d (frac, 0.0);
00213 glVertex3d (0.0, -m_width * frac, m_height);
00214 glTexCoord2d (0.0, 0.0);
00215 glVertex3d (0.0, 0.0, m_height);
00216 glEnd ();
00217
00218 glPopMatrix ();
00219 }
00220
00221
00222 Digital_Gauge::Digital_Gauge (double x, double y, double above,
00223 double width, double height, size_t places,
00224 std::string digits, bool on_wheel) :
00225 m_x (x),
00226 m_y (y),
00227 m_above (above),
00228 m_width (width),
00229 m_height (height),
00230 m_places (places)
00231 {
00232 m_on_steering_wheel = on_wheel;
00233 m_digits.resize (places);
00234 mp_digits = new Gl_Texture_Image (digits, true, true);
00235 }
00236
00237 Digital_Gauge::~Digital_Gauge ()
00238 {
00239 delete mp_digits;
00240 }
00241
00242 void
00243 Digital_Gauge::set (double value)
00244 {
00245 int n = int (value);
00246 int denom = 1;
00247 int sub = 0;
00248 for (size_t index = 0; index < m_places; index++)
00249 {
00250 int m = denom * 10;
00251 int place = (n % m) / denom;
00252 m_digits [m_places - 1 - index] = place;
00253 denom = m;
00254 sub += place;
00255 }
00256 }
00257
00258 void
00259 Digital_Gauge::draw () const
00260 {
00261 mp_digits->activate ();
00262
00263 bool nonzero = false;
00264 for (size_t i = 0; i < m_places; i++)
00265 {
00266 int n = m_digits [i];
00267 if ((!nonzero) && (n == 0) && (i != (m_places - 1)))
00268 {
00269 continue;
00270 }
00271 nonzero = true;
00272
00273 double tex_x1 = n * 0.1;
00274 double tex_x2 = tex_x1 + 0.1;
00275
00276 double x1 = i * m_width / m_places;
00277 double x2 = x1 + m_width / m_places;
00278
00279 glColor3d (1.0, 1.0, 1.0);
00280 glBegin (GL_QUADS);
00281 glTexCoord2d (tex_x1, 1.0);
00282 glVertex3d (-m_above, -m_x - x1, m_y);
00283 glTexCoord2d (tex_x2, 1.0);
00284 glVertex3d (-m_above, -m_x - x2, m_y);
00285 glTexCoord2d (tex_x2, 0.0);
00286 glVertex3d (-m_above, -m_x - x2, m_y + m_height);
00287 glTexCoord2d (tex_x1, 0.0);
00288 glVertex3d (-m_above, -m_x - x1, m_y + m_height);
00289 glEnd ();
00290 }
00291 }
00292
00293
00294 Steering_Wheel::Steering_Wheel (double center_x, double center_y,
00295 double above, double radius,
00296 double min, double min_angle,
00297 double max, double max_angle,
00298 std::string image) :
00299 Facade (0.0, 0.0, above, radius, image),
00300 m_center_x (center_x),
00301 m_center_y (center_y),
00302 m_scaler (min, min_angle, max, max_angle)
00303 {
00304 }
00305
00306 void
00307 Steering_Wheel::set (double value)
00308 {
00309 m_angle = m_scaler.scale (value);
00310 }
00311
00312 void
00313 Steering_Wheel::draw () const
00314 {
00315 glTranslated (0.0, -m_center_x, m_center_y);
00316 rotate (m_angle);
00317 Facade::draw ();
00318 }
00319
00320
00321 Gear_Indicator::Gear_Indicator (double x, double y, double above,
00322 double width, double height,
00323 int numbers, std::string image,
00324 bool on_wheel) :
00325 m_number_width (1.0 / numbers),
00326 mp_numbers (0),
00327 m_x (x),
00328 m_y (y),
00329 m_above (above),
00330 m_width (width),
00331 m_height (height)
00332 {
00333 m_on_steering_wheel = on_wheel;
00334 if (image != "")
00335 {
00336 mp_numbers = new Gl_Texture_Image (image, true, true);
00337 }
00338 }
00339
00340 Gear_Indicator::~Gear_Indicator ()
00341 {
00342 delete mp_numbers;
00343 }
00344
00345 void
00346 Gear_Indicator::draw () const
00347 {
00348 mp_numbers->activate ();
00349
00350 double x1 = m_number_width * (m_gear + 1);
00351 double x2 = x1 + m_number_width;
00352
00353 glColor3d (1.0, 1.0, 1.0);
00354 glBegin (GL_QUADS);
00355 glTexCoord2d (x2, 1.0);
00356 glVertex3d (-m_above, -m_x, m_y);
00357 glTexCoord2d (x1, 1.0);
00358 glVertex3d (-m_above, -m_x + m_width, m_y);
00359 glTexCoord2d (x1, 0.0);
00360 glVertex3d (-m_above, -m_x + m_width, m_y + m_height);
00361 glTexCoord2d (x2, 0.0);
00362 glVertex3d (-m_above, -m_x, m_y + m_height);
00363 glEnd ();
00364 }
00365
00366
00367
00368 Gear_Shift::Gear_Shift (double x, double y, double z,
00369 double width, double height,
00370 const Vamos_Geometry::Three_Vector& rotation,
00371 const std::vector <Vamos_Geometry::Two_Point>&
00372 positions,
00373 std::string plate_image, std::string stick_image) :
00374 Gear_Indicator (x, y, z, width, height, 0, "", false),
00375 m_rotation (rotation),
00376 m_positions (positions),
00377 m_top_gear (m_positions.size () - 2),
00378 m_list_index (glGenLists (2))
00379 {
00380 mp_gate = new Gl_Texture_Image (plate_image, true, true);
00381 mp_stick = new Gl_Texture_Image (stick_image, true, true);
00382
00383 m_stick_width =
00384 m_width * mp_stick->width_pixels () / mp_gate->width_pixels ();
00385 m_stick_height =
00386 m_height * mp_stick->height_pixels () / mp_gate->height_pixels ();
00387
00388 glNewList (m_list_index, GL_COMPILE);
00389
00390 mp_gate->activate ();
00391
00392 glRotated (rotation [0], 0.0, -1.0, 0.0);
00393 glRotated (rotation [1], 0.0, 0.0, 1.0);
00394 glRotated (rotation [2], 1.0, 0.0, 0.0);
00395 glTranslated (-m_above, -m_x, m_y);
00396
00397 glColor3d (1.0, 1.0, 1.0);
00398 glBegin (GL_QUADS);
00399 glTexCoord2d (0.0, 0.0);
00400 glVertex3d (0.0, 0.0, 0.0);
00401 glTexCoord2d (1.0, 0.0);
00402 glVertex3d (0.0, -m_width, 0.0);
00403 glTexCoord2d (1.0, 1.0);
00404 glVertex3d (0.0, -m_width, m_height);
00405 glTexCoord2d (0.0, 1.0);
00406 glVertex3d (0.0, 0.0, m_height);
00407 glEnd ();
00408
00409 glTranslated (0.0, (-m_width + m_stick_width) / 2.0, m_height / 2.0);
00410 glEndList ();
00411
00412 glNewList (m_list_index + 1, GL_COMPILE);
00413
00414 mp_stick->activate ();
00415
00416 glRotated (-rotation [0], 0.0, -1.0, 0.0);
00417 glRotated (-rotation [1], 0.0, 0.0, 1.0);
00418 glRotated (-rotation [2], 1.0, 0.0, 0.0);
00419
00420 glColor3d (1.0, 1.0, 1.0);
00421 glBegin (GL_QUADS);
00422 glTexCoord2d (0.0, 1.0);
00423 glVertex3d (0.0, 0.0, 0.0);
00424 glTexCoord2d (1.0, 1.0);
00425 glVertex3d (0.0, -m_stick_width, 0.0);
00426 glTexCoord2d (1.0, 0.0);
00427 glVertex3d (0.0, -m_stick_width, m_stick_height);
00428 glTexCoord2d (0.0, 0.0);
00429 glVertex3d (0.0, 0.0, m_stick_height);
00430 glEnd ();
00431
00432 glEndList ();
00433 }
00434
00435 Gear_Shift::~Gear_Shift ()
00436 {
00437 delete mp_stick;
00438 delete mp_gate;
00439 }
00440
00441 void
00442 Gear_Shift::set (int gear)
00443 {
00444 m_gear = std::min (m_top_gear, gear);
00445 }
00446
00447 void
00448 Gear_Shift::draw () const
00449 {
00450 glPushMatrix ();
00451 glCallList (m_list_index);
00452 glTranslated (0.0, -m_positions [m_gear + 1].x, m_positions [m_gear + 1].y);
00453 glCallList (m_list_index + 1);
00454 glPopMatrix ();
00455 }
00456
00457
00458
00459 Dashboard::Dashboard (double x, double y, double z, double tilt) :
00460 m_x (x),
00461 m_y (y),
00462 m_z (z),
00463 m_tilt (tilt),
00464 mp_tachometer (0),
00465 mp_speedometer (0),
00466 mp_fuel_gauge (0),
00467 mp_gear_indicator (0),
00468 mp_steering_wheel (0)
00469 {
00470 }
00471
00472 Dashboard::~Dashboard ()
00473 {
00474 delete mp_steering_wheel;
00475 delete mp_gear_indicator;
00476 delete mp_fuel_gauge;
00477 delete mp_speedometer;
00478 delete mp_tachometer;
00479 for (std::vector <Facade*>::iterator it = ma_facades.begin ();
00480 it != ma_facades.end ();
00481 it++)
00482 {
00483 delete *it;
00484 }
00485 }
00486
00487 void
00488 Dashboard::add_tachometer (Gauge* tachometer)
00489 {
00490 delete mp_tachometer;
00491 mp_tachometer = tachometer;
00492 }
00493
00494 void
00495 Dashboard::add_speedometer (Gauge* speedometer)
00496 {
00497 delete mp_speedometer;
00498 mp_speedometer = speedometer;
00499 }
00500
00501 void
00502 Dashboard::add_fuel_gauge (Gauge* fuel_gauge)
00503 {
00504 delete mp_fuel_gauge;
00505 mp_fuel_gauge = fuel_gauge;
00506 }
00507
00508 void
00509 Dashboard::add_gear_indicator (Gear_Indicator* gear_indicator)
00510 {
00511 delete mp_gear_indicator;
00512 mp_gear_indicator = gear_indicator;
00513 }
00514
00515 void
00516 Dashboard::add_steering_wheel (Steering_Wheel* steering_wheel)
00517 {
00518 delete mp_steering_wheel;
00519 mp_steering_wheel = steering_wheel;
00520 }
00521
00522 void
00523 Dashboard::add_facade (Facade* facade)
00524 {
00525 ma_facades.push_back (facade);
00526 }
00527
00528 void
00529 Dashboard::set_tachometer (double rpm)
00530 {
00531 if (mp_tachometer != 0)
00532 {
00533 mp_tachometer->set (rpm);
00534 }
00535 }
00536
00537 void
00538 Dashboard::set_speedometer (double speed)
00539 {
00540 if (mp_speedometer != 0)
00541 {
00542 mp_speedometer->set (speed);
00543 }
00544 }
00545
00546 void
00547 Dashboard::set_fuel_gauge (double fuel)
00548 {
00549 if (mp_fuel_gauge != 0)
00550 {
00551 mp_fuel_gauge->set (fuel);
00552 }
00553 }
00554
00555 void
00556 Dashboard::set_gear_indicator (int gear)
00557 {
00558 if (mp_gear_indicator != 0)
00559 {
00560 mp_gear_indicator->set (gear);
00561 }
00562 }
00563
00564 void
00565 Dashboard::set_steering_wheel (double angle)
00566 {
00567 if (mp_steering_wheel != 0)
00568 {
00569 mp_steering_wheel->set (angle);
00570 }
00571 }
00572
00573 void
00574 Dashboard::draw () const
00575 {
00576 glTranslated (m_x, m_y, m_z);
00577
00578 std::for_each (ma_facades.begin (), ma_facades.end (),
00579 std::mem_fun (&Facade::draw));
00580
00581 glRotated (m_tilt, 0.0, 1.0, 0.0);
00582
00583 if ((mp_tachometer != 0) && !mp_tachometer->on_steering_wheel ())
00584 {
00585 mp_tachometer->draw ();
00586 }
00587 if ((mp_speedometer != 0) && !mp_speedometer->on_steering_wheel ())
00588 {
00589 mp_speedometer->draw ();
00590 }
00591 if ((mp_fuel_gauge != 0) && !mp_fuel_gauge->on_steering_wheel ())
00592 {
00593 mp_fuel_gauge->draw ();
00594 }
00595 if ((mp_gear_indicator != 0) && !mp_gear_indicator->on_steering_wheel ())
00596 {
00597 mp_gear_indicator->draw ();
00598 }
00599 if (mp_steering_wheel != 0)
00600 {
00601 mp_steering_wheel->draw ();
00602 }
00603
00604 glDisable (GL_DEPTH_TEST);
00605 if ((mp_tachometer != 0) && mp_tachometer->on_steering_wheel ())
00606 {
00607 mp_tachometer->draw ();
00608 }
00609 if ((mp_speedometer != 0) && mp_speedometer->on_steering_wheel ())
00610 {
00611 mp_speedometer->draw ();
00612 }
00613 if ((mp_fuel_gauge != 0) && mp_fuel_gauge->on_steering_wheel ())
00614 {
00615 mp_fuel_gauge->draw ();
00616 }
00617 if ((mp_gear_indicator != 0) && mp_gear_indicator->on_steering_wheel ())
00618 {
00619 mp_gear_indicator->draw ();
00620 }
00621 glEnable (GL_DEPTH_TEST);
00622 }
00623
00624 }