# include <config.h>
#endif
+#include <simgear/math/vector.hxx>
#include <Main/viewer.hxx>
#include "HUD.hxx"
_div_units(int(fabs(n->getFloatValue("divisions")))),
_scr_hole(n->getIntValue("screen-hole")),
_compression(n->getFloatValue("compression-factor")),
+ _dynamic_origin(n->getBoolValue("enable-dynamic-origin")),
+ _clip_plane(n->getBoolValue("enable-clip-plane")),
_frl(n->getBoolValue("enable-fuselage-ref-line")),
_target_spot(n->getBoolValue("enable-target-spot")),
+ _target_markers(n->getBoolValue("enable-target-markers")),
_velocity_vector(n->getBoolValue("enable-velocity-vector")),
_drift_marker(n->getBoolValue("enable-drift-marker")),
_alpha_bracket(n->getBoolValue("enable-alpha-bracket")),
float roll_value = _roll.getFloatValue() * SGD_DEGREES_TO_RADIANS;
float pitch_value = _pitch.getFloatValue();
- float alpha;
-
- bool pitch_ladder;
- bool climb_dive_ladder;
- bool clip_plane;
-
- if (_type == CLIMB_DIVE) {
- pitch_ladder = false;
- climb_dive_ladder = true;
- clip_plane = true;
-
- } else { // _type == PITCH
- pitch_ladder = true;
- climb_dive_ladder = false;
- clip_plane = false;
- }
//**************************************************************
glPushMatrix();
float Axx = 0.0, Ayy = 0.0, Azz = 0.0, total_vel = 0.0, pot_slope, t1;
float up_vel, ground_vel, actslope = 0.0, psi = 0.0;
float vel_x = 0.0, vel_y = 0.0, drift;
+ float alpha;
if (_velocity_vector) {
drift = get__beta();
//****************************************************************
// Clipping coordinates for ladder to be input from xml file
- // Clip hud ladder
- if (clip_plane) {
+ // Clip hud ladder. FIXME, these should be configurable, but they
+ // have always been hardcoded here.
+ if (_clip_plane) {
GLdouble eqn_top[4] = {0.0, -1.0, 0.0, 0.0};
GLdouble eqn_left[4] = {-1.0, 0.0, 0.0, 100.0};
GLdouble eqn_right[4] = {1.0, 0.0, 0.0, 100.0};
glEnable(GL_CLIP_PLANE1);
glClipPlane(GL_CLIP_PLANE2, eqn_right);
glEnable(GL_CLIP_PLANE2);
- // glScissor(-100,-240, 200, 240);
- // glEnable(GL_SCISSOR_TEST);
}
//****************************************************************
#endif
} // if _velocity_vector
+ // draw hud markers on top of each AI/MP target
+ if (_target_markers) {
+ SGPropertyNode *models = globals->get_props()->getNode("/ai/models", true);
+ for (int i = 0; i < models->nChildren(); i++) {
+ SGPropertyNode *chld = models->getChild(i);
+ string name;
+ name = chld->getName();
+ if (name == "aircraft" || name == "multiplayer") {
+ string callsign = chld->getStringValue("callsign");
+ if (callsign != "") {
+ float h_deg = chld->getFloatValue("radar/h-offset");
+ float v_deg = chld->getFloatValue("radar/v-offset");
+ float pos_x = (h_deg * cos(roll_value) -
+ v_deg * sin(roll_value)) * _compression;
+ float pos_y = (v_deg * cos(roll_value) +
+ h_deg * sin(roll_value)) * _compression;
+ draw_circle(pos_x, pos_y, 8);
+ }
+ }
+ }
+ }
//***************************************************************
// OBJECT MOVING RETICLE
//****************************************************************
- if (climb_dive_ladder) { // CONFORMAL_HUD
- _vmin = pitch_value - _width_units;
- _vmax = pitch_value + _width_units;
- glTranslatef(vel_x, vel_y, 0);
-
- } else { // pitch_ladder - Default Hud
+ if (_dynamic_origin) {
+ // ladder moves with alpha/beta offset projected onto horizon
+ // line (so that the horizon line always aligns with the
+ // actual horizon.
+ _vmin = pitch_value - _width_units * 0.5f;
+ _vmax = pitch_value + _width_units * 0.5f;
+ {
+ // the hud ladder center point should move relative to alpha/beta
+ // however the horizon line should always stay on the horizon. We
+ // project the alpha/beta offset onto the horizon line to get the
+ // result we want.
+ sgdVec3 p1; // result
+ sgdVec3 p; sgdSetVec3(p, vel_x, vel_y, 0.0);
+ sgdVec3 p0; sgdSetVec3(p0, 0.0, 0.0, 0.0);
+ sgdVec3 d; sgdSetVec3(d, cos(roll_value), sin(roll_value), 0.0);
+ sgdClosestPointToLine(p1, p, p0, d);
+ glTranslatef(p1[0], p1[1], 0);
+ }
+ } else {
+ // ladder position is fixed relative to the center of the screen.
_vmin = pitch_value - _width_units * 0.5f;
_vmax = pitch_value + _width_units * 0.5f;
}
glRotatef(roll_value * SGD_RADIANS_TO_DEGREES, 0.0, 0.0, 1.0);
// FRL marker not rotated - this line shifted below
float half_span = _w / 2.0;
- float y = 0;
+ float y = 0, y_end = 0;
float x_ini, x_ini2;
float x_end, x_end2;
if (_div_units) {
const int BUFSIZE = 8;
char buf[BUFSIZE];
- float label_length;
- float label_height;
- float left;
- float right;
- float bot;
- float top;
- float text_offset = 4.0f;
- float zero_offset = 0.0;
-
- if (climb_dive_ladder)
- zero_offset = 50.0f; // horizon line is wider by this much (hard coded ??)
- else
- zero_offset = 10.0f;
-
- fntFont *font = _hud->_font_renderer->getFont(); // FIXME
- float pointsize = _hud->_font_renderer->getPointSize();
- float italic = _hud->_font_renderer->getSlant();
+ const float zero_offset = 50.0f; // horizon line is wider by this much
_locTextList.setFont(_hud->_font_renderer);
_locTextList.erase();
if (!(i % _div_units)) { // At integral multiple of div
snprintf(buf, BUFSIZE, "%d", i);
- font->getBBox(buf, pointsize, italic, &left, &right, &bot, &top);
- label_length = right + left;
- label_height = (top + bot) / 2.0f;
-
x_ini = -half_span;
- if (i >= 0) {
- // Make zero point wider on left
- if (i == 0)
- x_ini -= zero_offset;
+ if (i == 0) {
+ draw_line(x_ini - zero_offset, y, x_end + zero_offset, y);
+ continue;
+ } else if (i > 0) {
// Zero or above draw solid lines
draw_line(x_ini, y, x_end, y);
if (i == 90 && _zenith)
- draw_zenith(x_ini, x_end, y);
+ draw_zenith(0.0, y);
} else {
// Below zero draw dashed lines.
draw_stipple_line(x_ini, y, x_end, y);
if (i == -90 && _nadir)
- draw_nadir(x_ini, x_end, y);
+ draw_nadir(0.0, y);
}
- // Calculate the position of the left text and write it.
- draw_text(x_ini - text_offset - label_length + 2.5/*hack*/, y - label_height, buf);
- draw_text(x_end + text_offset, y - label_height, buf);
+ draw_text(x_ini - 4, y, buf, VCENTER|RIGHT);
+ draw_text(x_end + 4, y, buf, VCENTER|LEFT);
}
}
x_ini2 = half_span - hole;
for (; i < last; i++) {
- if (_type == PITCH)
+ if (_type == PITCH) {
y = float(i - pitch_value) * _compression + .5;
- else // _type == CLIMB_DIVE
+ } else { // _type == CLIMB_DIVE
y = float(i - actslope) * _compression + .5;
+ }
if (!(i % _div_units)) { // At integral multiple of div
snprintf(buf, BUFSIZE, "%d", i);
- font->getBBox(buf, pointsize, italic, &left, &right, &bot, &top);
- label_length = right + left;
- label_height = (top + bot) / 2.0f;
- //printf("%s -- l %f r %f b %f t %f\n", buf, left, right, bot, top);
// Start by calculating the points and drawing the
// left side lines.
x_ini = -half_span;
x_end2 = half_span;
+ y_end = y;
+
+ if (i == 0) {
+ // make zero point wider
+ x_ini -= zero_offset;
+ x_end2 += zero_offset;
+
+ draw_line(x_ini, y, x_end, y);
+ draw_line(x_ini2, y, x_end2, y);
+
+ draw_text(x_ini - 2.0, y, buf, VCENTER|RIGHT);
+ draw_text(x_end2 + 2.0, y, buf, VCENTER|LEFT);
+
+ } else if (i > 0) {
+ // draw climb bar vertical lines
+ draw_line(x_ini, y - 5.0, x_ini, y);
+ draw_line(x_end2, y - 5.0, x_end2, y);
- if (i >= 0) {
- // Make zero point wider on left
- if (i == 0) {
- x_ini -= zero_offset;
- x_end2 += zero_offset;
- }
- //draw climb bar vertical lines
- if (climb_dive_ladder) {
- // Zero or above draw solid lines
- draw_line(x_end, y - 5.0, x_end, y);
- draw_line(x_ini2, y - 5.0, x_ini2, y);
- }
// draw pitch / climb bar
draw_line(x_ini, y, x_end, y);
draw_line(x_ini2, y, x_end2, y);
+ draw_text(x_ini + 0.5, y - 0.5, buf, TOP|LEFT);
+ draw_text(x_end2 - 0.5, y - 0.5, buf, TOP|RIGHT);
+
if (i == 90 && _zenith)
- draw_zenith(x_ini2, x_end, y);
+ draw_zenith(0.0, y);
} else { // i < 0
+ float alpha = i * SG_DEGREES_TO_RADIANS / 2.0;
+ y_end = y + (x_end - x_ini) * sin(alpha);
+
+ float w = (x_end - x_ini) * cos(alpha);
+ x_ini = x_end - w;
+ x_end2 = x_ini2 + w;
+
// draw dive bar vertical lines
- if (climb_dive_ladder) {
- draw_line(x_end, y + 5.0, x_end, y);
- draw_line(x_ini2, y + 5.0, x_ini2, y);
- }
+ draw_line(x_end, y + 5.0, x_end, y);
+ draw_line(x_ini2, y + 5.0, x_ini2, y);
// draw pitch / dive bars
- draw_stipple_line(x_ini, y, x_end, y);
- draw_stipple_line(x_ini2, y, x_end2, y);
+ draw_stipple_line(x_end, y, x_ini, y_end);
+ draw_stipple_line(x_ini2, y, x_end2, y_end);
+
+ float yoffs = 1.0 + (y - y_end) / 4.0; // too hackish?
+ draw_text(x_ini + 3.0, y_end + yoffs, buf, BOTTOM|HCENTER);
+ // right number shifted in a little more, because of the minus
+ draw_text(x_end2 - 4.0, y_end + yoffs, buf, BOTTOM|HCENTER);
if (i == -90 && _nadir)
- draw_nadir(x_ini2, x_end, y);
+ draw_nadir(0.0, y);
}
-
- // Now calculate the location of the left side label using
- draw_text(x_ini - text_offset - label_length + 2.5/*hack*/, y - label_height, buf);
- draw_text(x_end2 + text_offset, y - label_height, buf);
}
}
glDisable(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE1);
glDisable(GL_CLIP_PLANE2);
- // glDisable(GL_SCISSOR_TEST);
glPopMatrix();
//*************************************************************
if (fabs(brg - psi) < 12.0) {
if (!_hat) {
glBegin(GL_LINE_LOOP);
- glVertex2f(((brg - psi) * 60 / 25) + 320, 240.0);
- glVertex2f(((brg - psi) * 60 / 25) + 326, 240.0 - 4);
- glVertex2f(((brg - psi) * 60 / 25) + 323, 240.0 - 4);
- glVertex2f(((brg - psi) * 60 / 25) + 323, 240.0 - 8);
- glVertex2f(((brg - psi) * 60 / 25) + 317, 240.0 - 8);
- glVertex2f(((brg - psi) * 60 / 25) + 317, 240.0 - 4);
- glVertex2f(((brg - psi) * 60 / 25) + 314, 240.0 - 4);
+ GLfloat x = (brg - psi) * 60 / 25;
+ glVertex2f(x + 320, 240.0);
+ glVertex2f(x + 326, 240.0 - 4);
+ glVertex2f(x + 323, 240.0 - 4);
+ glVertex2f(x + 323, 240.0 - 8);
+ glVertex2f(x + 317, 240.0 - 8);
+ glVertex2f(x + 317, 240.0 - 4);
+ glVertex2f(x + 314, 240.0 - 4);
glEnd();
} else { // if (_hat)
/******************************************************************/
-// draws the zenith symbol for highest possible climb angle (i.e. 90 degree climb angle)
+// draws the zenith symbol (highest possible climb angle i.e. 90 degree climb angle)
//
-void HUD::Ladder::draw_zenith(float xfirst, float xlast, float yvalue)
+void HUD::Ladder::draw_zenith(float x, float y)
{
- float xcentre = (xfirst + xlast) / 2.0;
- float ycentre = yvalue;
-
- draw_line(xcentre - 9.0, ycentre, xcentre - 3.0, ycentre + 1.3);
- draw_line(xcentre - 9.0, ycentre, xcentre - 3.0, ycentre - 1.3);
+ draw_line(x - 9.0, y, x - 3.0, y + 1.3);
+ draw_line(x - 9.0, y, x - 3.0, y - 1.3);
- draw_line(xcentre + 9.0, ycentre, xcentre + 3.0, ycentre + 1.3);
- draw_line(xcentre + 9.0, ycentre, xcentre + 3.0, ycentre - 1.3);
+ draw_line(x + 9.0, y, x + 3.0, y + 1.3);
+ draw_line(x + 9.0, y, x + 3.0, y - 1.3);
- draw_line(xcentre, ycentre + 9.0, xcentre - 1.3, ycentre + 3.0);
- draw_line(xcentre, ycentre + 9.0, xcentre + 1.3, ycentre + 3.0);
+ draw_line(x, y + 9.0, x - 1.3, y + 3.0);
+ draw_line(x, y + 9.0, x + 1.3, y + 3.0);
- draw_line(xcentre - 3.9, ycentre + 3.9, xcentre - 3.0, ycentre + 1.3);
- draw_line(xcentre - 3.9, ycentre + 3.9, xcentre - 1.3, ycentre + 3.0);
+ draw_line(x - 3.9, y + 3.9, x - 3.0, y + 1.3);
+ draw_line(x - 3.9, y + 3.9, x - 1.3, y + 3.0);
- draw_line(xcentre + 3.9, ycentre + 3.9, xcentre + 1.3, ycentre+3.0);
- draw_line(xcentre + 3.9, ycentre + 3.9, xcentre + 3.0, ycentre+1.3);
+ draw_line(x + 3.9, y + 3.9, x + 1.3, y + 3.0);
+ draw_line(x + 3.9, y + 3.9, x + 3.0, y + 1.3);
- draw_line(xcentre - 3.9, ycentre - 3.9, xcentre - 3.0, ycentre-1.3);
- draw_line(xcentre - 3.9, ycentre - 3.9, xcentre - 1.3, ycentre-2.6);
+ draw_line(x - 3.9, y - 3.9, x - 3.0, y - 1.3);
+ draw_line(x - 3.9, y - 3.9, x - 1.3, y - 2.6);
- draw_line(xcentre + 3.9, ycentre - 3.9, xcentre + 3.0, ycentre-1.3);
- draw_line(xcentre + 3.9, ycentre - 3.9, xcentre + 1.3, ycentre-2.6);
+ draw_line(x + 3.9, y - 3.9, x + 3.0, y - 1.3);
+ draw_line(x + 3.9, y - 3.9, x + 1.3, y - 2.6);
- draw_line(xcentre - 1.3, ycentre - 2.6, xcentre, ycentre - 27.0);
- draw_line(xcentre + 1.3, ycentre - 2.6, xcentre, ycentre - 27.0);
+ draw_line(x - 1.3, y - 2.6, x, y - 27.0);
+ draw_line(x + 1.3, y - 2.6, x, y - 27.0);
}
// draws the nadir symbol (lowest possible dive angle i.e. 90 degree dive angle))
//
-void HUD::Ladder::draw_nadir(float xfirst, float xlast, float yvalue)
+void HUD::Ladder::draw_nadir(float x, float y)
{
- float xcentre = (xfirst + xlast) / 2.0;
- float ycentre = yvalue;
const float R = 7.5;
- draw_circle(xcentre, ycentre, R);
- draw_line(xcentre, ycentre + R, xcentre, ycentre + 22.5); // line above the circle
- draw_line(xcentre - R, ycentre, xcentre + R, ycentre); // line at middle of circle
+ draw_circle(x, y, R);
+ draw_line(x, y + R, x, y + 22.5); // line above the circle
+ draw_line(x - R, y, x + R, y); // line at middle of circle
float theta = asin(2.5 / R);
float theta1 = asin(5.0 / R);
float x1, y1, x2, y2;
- x1 = xcentre + R * cos(theta);
- y1 = ycentre + 2.5;
- x2 = xcentre + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) - theta);
- y2 = ycentre + 2.5;
+ x1 = x + R * cos(theta);
+ y1 = y + 2.5;
+ x2 = x + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) - theta);
+ y2 = y + 2.5;
draw_line(x1, y1, x2, y2);
- x1 = xcentre + R * cos(theta1);
- y1 = ycentre + 5.0;
- x2 = xcentre + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) - theta1);
- y2 = ycentre + 5.0;
+ x1 = x + R * cos(theta1);
+ y1 = y + 5.0;
+ x2 = x + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) - theta1);
+ y2 = y + 5.0;
draw_line(x1, y1, x2, y2);
- x1 = xcentre + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) + theta);
- y1 = ycentre - 2.5;
- x2 = xcentre + R * cos((360.0 * SGD_DEGREES_TO_RADIANS) - theta);
- y2 = ycentre - 2.5;
+ x1 = x + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) + theta);
+ y1 = y - 2.5;
+ x2 = x + R * cos((360.0 * SGD_DEGREES_TO_RADIANS) - theta);
+ y2 = y - 2.5;
draw_line(x1, y1, x2, y2);
- x1 = xcentre + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) + theta1);
- y1 = ycentre - 5.0;
- x2 = xcentre + R * cos((360.0 * SGD_DEGREES_TO_RADIANS) - theta1);
- y2 = ycentre - 5.0;
+ x1 = x + R * cos((180.0 * SGD_DEGREES_TO_RADIANS) + theta1);
+ y1 = y - 5.0;
+ x2 = x + R * cos((360.0 * SGD_DEGREES_TO_RADIANS) - theta1);
+ y2 = y - 5.0;
draw_line(x1, y1, x2, y2);
}