7 //====================== Top of HudLadder Class =======================
8 HudLadder :: HudLadder( string name,
29 float glide_slope_val,
33 dual_instr_item( x, y, width, height,
38 width_units ( (int)(span_units) ),
39 div_units ( (int)(major_div < 0? -major_div: major_div) ),
40 minor_div ( (int)(minor_div) ),
41 label_pos ( lbl_pos ),
42 scr_hole ( screen_hole ),
43 vmax ( span_units/2 ),
46 hudladder_type ( name ),
48 velocity_vector ( vel_vec ),
49 drift_marker ( drift ),
50 alpha_bracket ( alpha ),
51 energy_marker ( energy ),
52 climb_dive_marker ( climb ),
53 target_spot ( target ),
54 glide_slope_marker ( glide ),
55 glide_slope ( glide_slope_val),
56 energy_worm ( worm_energy),
57 waypoint_marker ( waypoint)
66 HudLadder :: ~HudLadder()
71 HudLadder( const HudLadder & image ) :
72 dual_instr_item ( (dual_instr_item &) image),
73 width_units ( image.width_units ),
74 div_units ( image.div_units ),
75 label_pos ( image.label_pos ),
76 scr_hole ( image.scr_hole ),
79 factor ( image.factor ),
80 hudladder_type ( image.hudladder_type),
82 velocity_vector ( image.velocity_vector),
83 drift_marker ( image.drift_marker),
84 alpha_bracket ( image.alpha_bracket),
85 energy_marker ( image.energy_marker),
86 climb_dive_marker ( image.climb_dive_marker),
87 target_spot ( image.target_spot),
88 glide_slope_marker ( image.glide_slope_marker),
89 glide_slope ( image.glide_slope),
90 energy_worm ( image.energy_worm),
91 waypoint_marker ( image.waypoint_marker)
94 HudLadder & HudLadder :: operator = ( const HudLadder & rhs )
96 if( !(this == &rhs)) {
97 (dual_instr_item &)(*this) = (dual_instr_item &)rhs;
98 width_units = rhs.width_units;
99 div_units = rhs.div_units;
100 label_pos = rhs.label_pos;
101 scr_hole = rhs.scr_hole;
105 hudladder_type = rhs.hudladder_type;
107 velocity_vector = rhs.velocity_vector;
108 drift_marker = rhs.drift_marker;
109 alpha_bracket = rhs.alpha_bracket;
110 energy_marker = rhs.energy_marker;
111 climb_dive_marker = rhs.climb_dive_marker;
112 target_spot = rhs.target_spot;
113 glide_slope_marker = rhs.glide_slope_marker;
114 glide_slope = rhs.glide_slope;
115 energy_worm = rhs.energy_worm;
116 waypoint_marker = rhs.waypoint_marker;
122 // Draws a climb ladder in the center of the HUD
125 void HudLadder :: draw( void )
132 float cosine, sine,xvvr,yvvr,Vxx,Vyy,Vzz,up_vel,ground_vel,actslope;
133 float Axx,Ayy,Azz,total_vel,pot_slope,t1,t2,psi,alpha,pla;
134 float vel_x,vel_y,drift;
137 bool climb_dive_ladder;
140 GLdouble eqn_top[4] = {0.0,-1.0,0.0,0.0};
141 GLdouble eqn_left[4] = {-1.0,0.0,0.0,100.0};
142 GLdouble eqn_right[4] = {1.0,0.0,0.0,100.0};
144 POINT centroid = get_centroid();
145 RECT box = get_location();
147 float half_span = box.right / 2.0;
148 float roll_value = current_ch2();
150 pla = get_throttleval();
152 int lgear,wown,wowm,ilcanclaw,ihook;
153 ilcanclaw = get_iaux1();
159 float pitch_value = current_ch1() * SGD_RADIANS_TO_DEGREES;
161 if(hudladder_type=="Climb/Dive Ladder") {
162 pitch_ladder = false;
163 climb_dive_ladder = true;
167 if(hudladder_type=="Pitch Ladder") {
169 climb_dive_ladder = false;
173 //**************************************************************
175 // define (0,0) as center of screen
176 glTranslatef( centroid.x, centroid.y, 0);
178 // OBJECT STATIC RETICLE
181 // Draw the FRL spot and line
183 #define FRL_DIAMOND_SIZE 2.0
184 glBegin(GL_LINE_LOOP);
185 glVertex2f( -FRL_DIAMOND_SIZE, 0.0);
186 glVertex2f(0.0, FRL_DIAMOND_SIZE);
187 glVertex2f( FRL_DIAMOND_SIZE, 0.0);
188 glVertex2f(0.0, -FRL_DIAMOND_SIZE);
190 glBegin(GL_LINE_STRIP);
191 glVertex2f(0, FRL_DIAMOND_SIZE);
194 #undef FRL_DIAMOND_SIZE
196 // TYPE WATERLINE_MARK (W shaped _ _ )
199 //****************************************************************
201 // Draw the target spot.
203 #define CENTER_DIAMOND_SIZE 6.0
204 glBegin(GL_LINE_LOOP);
205 glVertex2f( -CENTER_DIAMOND_SIZE, 0.0);
206 glVertex2f(0.0, CENTER_DIAMOND_SIZE);
207 glVertex2f( CENTER_DIAMOND_SIZE, 0.0);
208 glVertex2f(0.0, -CENTER_DIAMOND_SIZE);
210 #undef CENTER_DIAMOND_SIZE
213 //****************************************************************
214 //velocity vector reticle - computations
215 if(velocity_vector) {
224 if (psi > 180.0) psi = psi - 360;
226 total_vel = sqrt(Vxx*Vxx + Vyy*Vyy + Vzz*Vzz);
227 ground_vel = sqrt(Vxx*Vxx + Vyy*Vyy);
230 if (ground_vel < 2.0) {
231 if (fabs(up_vel) < 2.0) {
234 actslope = (up_vel/fabs(up_vel))*90.0;
237 actslope = atan(up_vel/ground_vel)*SGD_RADIANS_TO_DEGREES;
240 xvvr = (((atan2(Vyy,Vxx)*SGD_RADIANS_TO_DEGREES)-psi)*(640.0/45.0));
241 drift = ((atan2(Vyy,Vxx)*SGD_RADIANS_TO_DEGREES)-psi);
242 yvvr = ((actslope - pitch_value)*factor);
243 vel_y = ((actslope -pitch_value) * cos(roll_value) + drift*sin(roll_value))*factor;
244 vel_x = (-(actslope -pitch_value)*sin(roll_value) + drift*cos(roll_value))*(640/45.0);
245 // printf("%f %f %f %f\n",vel_x,vel_y,drift,psi);
246 //****************************************************************
247 // OBJECT MOVING RETICLE
248 // TYPE - DRIFT MARKER
252 glBegin(GL_LINE_STRIP);
253 glVertex2f((xvvr*25/120)-6, -4);
254 glVertex2f(xvvr*25/120, 8);
255 glVertex2f((xvvr*25/120)+6, -4);
259 //****************************************************************
260 // Clipping coordinates for ladder to be input from xml file
263 glClipPlane(GL_CLIP_PLANE0,eqn_top);
264 glEnable(GL_CLIP_PLANE0);
265 glClipPlane(GL_CLIP_PLANE1,eqn_left);
266 glEnable(GL_CLIP_PLANE1);
267 glClipPlane(GL_CLIP_PLANE2,eqn_right);
268 glEnable(GL_CLIP_PLANE2);
269 // glScissor(-100,-240,200,240);
270 // glEnable(GL_SCISSOR_TEST);
272 //****************************************************************
273 // OBJECT MOVING RETICLE
274 // TYPE VELOCITY VECTOR
277 glBegin(GL_LINE_LOOP); // Use polygon to approximate a circle
278 for(count=0; count<50; count++) {
279 cosine = 6 * cos(count * 2 * SGD_PI/50.0);
280 sine = 6 * sin(count * 2 * SGD_PI/50.0);
281 glVertex2f(cosine+vel_x, sine+vel_y);
284 //velocity vector reticle orientation lines
285 glBegin(GL_LINE_STRIP);
286 glVertex2f(vel_x-12, vel_y);
287 glVertex2f(vel_x-6, vel_y);
289 glBegin(GL_LINE_STRIP);
290 glVertex2f(vel_x+12, vel_y);
291 glVertex2f(vel_x+6, vel_y);
293 glBegin(GL_LINE_STRIP);
294 glVertex2f(vel_x, vel_y+12);
295 glVertex2f(vel_x, vel_y+6);
298 // OBJECT MOVING RETICLE
300 // ATTRIB - ON CONDITION
302 // undercarriage status
303 glBegin(GL_LINE_STRIP);
304 glVertex2f(vel_x+8, vel_y);
305 glVertex2f(vel_x+8, vel_y-4);
307 // OBJECT MOVING RETICLE
309 // ATTRIB - ON CONDITION
310 glBegin(GL_LINE_STRIP);
311 glVertex2f(vel_x-8, vel_y);
312 glVertex2f(vel_x-8, vel_y-4);
314 // OBJECT MOVING RETICLE
316 // ATTRIB - ON CONDITION
317 glBegin(GL_LINE_STRIP);
318 glVertex2f(vel_x, vel_y-6);
319 glVertex2f(vel_x, vel_y-10);
323 // OBJECT MOVING RETICLE
325 // ATTRIB - ON CONDITION
327 // arrestor hook status
328 glBegin(GL_LINE_STRIP);
329 glVertex2f(vel_x-4, vel_y-8);
330 glVertex2f(vel_x, vel_y-10);
331 glVertex2f(vel_x+4, vel_y-8);
334 }//if velocity_vector
336 //***************************************************************
337 // OBJECT MOVING RETICLE
338 // TYPE - SQUARE_BRACKET
339 // ATTRIB - ON CONDITION
343 glBegin(GL_LINE_STRIP);
344 glVertex2f(vel_x-20 , vel_y-(16-alpha)*factor);
345 glVertex2f(vel_x-17, vel_y-(16-alpha)*factor);
346 glVertex2f(vel_x-17, vel_y-(14-alpha)*factor);
347 glVertex2f(vel_x-20, vel_y-(14-alpha)*factor);
349 glBegin(GL_LINE_STRIP);
350 glVertex2f(vel_x+20 , vel_y-(16-alpha)*factor);
351 glVertex2f(vel_x+17, vel_y-(16-alpha)*factor);
352 glVertex2f(vel_x+17, vel_y-(14-alpha)*factor);
353 glVertex2f(vel_x+20, vel_y-(14-alpha)*factor);
357 //printf("xvr=%f,yvr=%f,Vx=%f,Vy=%f,Vz=%f\n",xvvr,yvvr,Vx,Vy,Vz);
358 //printf("Ax=%f,Ay=%f,Az=%f\n",Ax,Ay,Az);
359 //****************************************************************
360 // OBJECT MOVING RETICLE
361 // TYPE ENERGY_MARKERS
363 //energy markers - compute potential slope
365 if (total_vel < 5.0) {
369 t1 = up_vel/total_vel;
370 t2 = asin((Vxx*Axx + Vyy*Ayy + Vzz*Azz)/(9.81*total_vel));
372 pot_slope = ((t2/3)*SGD_RADIANS_TO_DEGREES)*factor + vel_y;
373 // if (pot_slope < (vel_y - 45)) pot_slope = vel_y-45;
374 // if (pot_slope > (vel_y + 45)) pot_slope = vel_y+45;
377 glBegin(GL_LINE_STRIP);
378 glVertex2f(vel_x-20, pot_slope-5);
379 glVertex2f(vel_x-15, pot_slope);
380 glVertex2f(vel_x-20, pot_slope+5);
382 glBegin(GL_LINE_STRIP);
383 glVertex2f(vel_x+20, pot_slope-5);
384 glVertex2f(vel_x+15, pot_slope);
385 glVertex2f(vel_x+20, pot_slope+5);
387 if (pla > (105.0/131.0)) {
388 glBegin(GL_LINE_STRIP);
389 glVertex2f(vel_x-24, pot_slope-5);
390 glVertex2f(vel_x-19, pot_slope);
391 glVertex2f(vel_x-24, pot_slope+5);
393 glBegin(GL_LINE_STRIP);
394 glVertex2f(vel_x+24, pot_slope-5);
395 glVertex2f(vel_x+19, pot_slope);
396 glVertex2f(vel_x+24, pot_slope+5);
400 //**********************************************************
402 // OBJECT STATIC RETICLE
404 // ATTRIB - ON CONDITION
406 if (ilcanclaw == 1) {
407 glBegin(GL_LINE_STRIP);
408 glVertex2f(-15, -134);
409 glVertex2f(15, -134);
411 // OBJECT MOVING RETICLE
413 // ATTRIB - ON CONDITION
414 glBegin(GL_LINE_STRIP);
415 glVertex2f(-6, -134);
416 glVertex2f(-6, t2*SGD_RADIANS_TO_DEGREES*4.0 - 134);
417 glVertex2f(+6, t2*SGD_RADIANS_TO_DEGREES*4.0 - 134);
420 // OBJECT MOVING RETICLE
422 // ATTRIB - ON CONDITION
423 glBegin(GL_LINE_LOOP);
424 glVertex2f(-6, actslope*4.0 - 134);
425 glVertex2f(0, actslope*4.0 -134 +3);
426 glVertex2f(6, actslope*4.0 - 134);
427 glVertex2f(0, actslope*4.0 -134 -3);
431 //*************************************************************
432 // OBJECT MOVING RETICLE
435 // Draw the locked velocity vector.
436 if(climb_dive_marker) {
437 glBegin(GL_LINE_LOOP);
438 glVertex2f( -3.0, 0.0+vel_y);
439 glVertex2f(0.0, 6.0+vel_y);
440 glVertex2f( 3.0, 0.0+vel_y);
441 glVertex2f(0.0, -6.0+vel_y);
445 //****************************************************************
447 if(climb_dive_ladder) {// CONFORMAL_HUD
449 vmin = pitch_value - (float)width_units;
450 vmax = pitch_value + (float)width_units;
452 glTranslatef( vel_x, vel_y, 0);
456 if (pitch_ladder) {//Default Hud
458 vmin = pitch_value - (float)width_units * 0.5f;
459 vmax = pitch_value + (float)width_units * 0.5f;
463 glRotatef(roll_value * SGD_RADIANS_TO_DEGREES, 0.0, 0.0, 1.0);
464 // FRL marker not rotated - this line shifted below
475 float text_offset = 4.0f ;
478 if(climb_dive_ladder)
479 zero_offset = 50.0f ;
482 zero_offset = 10.0f ;
484 fntFont *font = HUDtext->getFont();
485 float pointsize = HUDtext->getPointSize();
486 float italic = HUDtext->getSlant();
488 TextList.setFont( HUDtext );
491 StippleLineList.erase();
493 int last = FloatToInt(vmax)+1;
494 int i = FloatToInt(vmin);
498 for( ; i<last ; i++ ) {
500 y = (((float)(i - pitch_value) * factor) + .5f);
501 if( !(i % div_units )) { // At integral multiple of div
503 sprintf( TextLadder, "%d", i );
504 font->getBBox ( TextLadder, pointsize, italic,
505 &left, &right, &bot, &top ) ;
506 label_length = right - left;
507 label_length += text_offset;
508 label_height = (top - bot)/2.0f;
513 // Make zero point wider on left
515 x_ini -= zero_offset;
516 // Zero or above draw solid lines
517 Line(x_ini, y, x_end, y);
519 // Below zero draw dashed lines.
520 StippleLine(x_ini, y, x_end, y);
523 // Calculate the position of the left text and write it.
524 Text( x_ini-label_length, y-label_height, TextLadder );
525 Text( x_end+text_offset, y-label_height, TextLadder );
529 else // if(scr_hole )
530 { // Draw ladder with space in the middle of the lines
531 float hole = (float)((scr_hole)/2.0f);
533 x_end = -half_span + hole;
534 x_ini2= half_span - hole;
535 for( ; i<last ; i++ ) {
537 if(hudladder_type=="Pitch Ladder")
538 y = (((float)(i - pitch_value) * factor) + .5);
540 if(hudladder_type=="Climb/Dive Ladder")
541 y = (((float)(i - actslope) * factor) + .5);
543 if( !(i % div_units )) { // At integral multiple of div
545 sprintf( TextLadder, "%d", i );
546 font->getBBox ( TextLadder, pointsize, italic,
547 &left, &right, &bot, &top ) ;
548 label_length = right - left;
549 label_length += text_offset;
550 label_height = (top - bot)/2.0f;
551 // printf("l %f r %f b %f t %f\n",left, right, bot, top );
553 // Start by calculating the points and drawing the
559 // Make zero point wider on left
561 x_ini -= zero_offset;
562 x_end2 +=zero_offset;
564 if(climb_dive_ladder){
565 // Zero or above draw solid lines
566 Line(x_end, y-5.0, x_end, y);
567 Line(x_ini2, y-5.0, x_ini2, y);
571 Line(x_ini, y, x_end, y);
572 Line(x_ini2, y, x_end2, y);
575 // Below zero draw dashed lines.
576 if(climb_dive_ladder) {
577 Line(x_end, y+5.0, x_end, y);
578 Line(x_ini2, y+5.0, x_ini2, y);
580 StippleLine(x_ini, y, x_end, y);
581 StippleLine(x_ini2, y, x_end2, y);
584 // Now calculate the location of the left side label using
585 Text( x_ini-label_length, y-label_height, TextLadder );
586 Text (x_end2+text_offset, y-label_height, TextLadder );
591 // OBJECT LADDER MARK
593 // ATTRIB - ON CONDITION
594 // draw appraoch glide slope marker
595 if (glide_slope_marker) {
597 Line(-half_span+15, (glide_slope-actslope)*factor, -half_span + hole, (glide_slope-actslope)*factor);
598 Line(half_span-15, (glide_slope-actslope)*factor, half_span - hole, (glide_slope-actslope)*factor);
600 }// if glide_slope_marker
608 glEnable(GL_LINE_STIPPLE);
609 glLineStipple( 1, 0x00FF );
610 StippleLineList.draw( );
611 glDisable(GL_LINE_STIPPLE);
613 glDisable(GL_CLIP_PLANE0);
614 glDisable(GL_CLIP_PLANE1);
615 glDisable(GL_CLIP_PLANE2);
616 // glDisable(GL_SCISSOR_TEST);
618 //*************************************************************
619 //*************************************************************
620 if(waypoint_marker) {
621 //waypoint marker computation
622 float fromwp_lat,towp_lat,fromwp_lon,towp_lon,dist,delx,dely,hyp,theta,brg;
624 fromwp_lon = get_longitude()*SGD_DEGREES_TO_RADIANS;
625 fromwp_lat = get_latitude()*SGD_DEGREES_TO_RADIANS;
626 towp_lon = get_aux5()*SGD_DEGREES_TO_RADIANS;
627 towp_lat = get_aux6()*SGD_DEGREES_TO_RADIANS;
629 dist = acos(sin(fromwp_lat)*sin(towp_lat)+cos(fromwp_lat)*cos(towp_lat)*cos(fabs(fromwp_lon-towp_lon)));
630 delx= towp_lat - fromwp_lat;
631 dely = towp_lon - fromwp_lon;
632 hyp = sqrt(pow(delx,2)+pow(dely,2));
634 theta = asin(dely/hyp);
638 brg = theta*SGD_RADIANS_TO_DEGREES;
639 if (brg > 360.0) brg = 0.0;
640 if (delx < 0) brg = 180 - brg;
642 // {Brg = asin(cos(towp_lat)*sin(fabs(fromwp_lon-towp_lon))/ sin(dist));
643 // Brg = Brg * SGD_RADIANS_TO_DEGREES; }
644 dist = dist*SGD_RADIANS_TO_DEGREES * 60.0*1852.0; //rad->deg->nm->m
645 // end waypoint marker computation
646 //*********************************************************
647 // OBJECT MOVING RETICLE
650 if (fabs(brg-psi) > 10.0) {
652 glTranslatef( centroid.x, centroid.y, 0);
653 glTranslatef( vel_x, vel_y, 0);
654 glRotatef(brg - psi,0.0,0.0,-1.0);
655 glBegin(GL_LINE_LOOP);
656 glVertex2f(-2.5,20.0);
657 glVertex2f(-2.5,30.0);
658 glVertex2f(-5.0,30.0);
659 glVertex2f(0.0,35.0);
660 glVertex2f(5.0,30.0);
661 glVertex2f(2.5,30.0);
662 glVertex2f(2.5,20.0);
666 // waypoint marker on heading scale
667 if (fabs(brg-psi) < 12.0) {
668 glBegin(GL_LINE_LOOP);
669 glVertex2f(((brg-psi)*60/25)+320,240.0);
670 glVertex2f(((brg-psi)*60/25)+326,240.0-4);
671 glVertex2f(((brg-psi)*60/25)+323,240.0-4);
672 glVertex2f(((brg-psi)*60/25)+323,240.0-8);
673 glVertex2f(((brg-psi)*60/25)+317,240.0-8);
674 glVertex2f(((brg-psi)*60/25)+317,240.0-4);
675 glVertex2f(((brg-psi)*60/25)+314,240.0-4);
678 //*************************************************************
679 }// if waypoint_marker