Logo Search packages:      
Sourcecode: acm version File versions  Download package

hud.c

/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1998  Riley Rainey
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 dated June, 1991.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program;  if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
 */

#include <math.h>
#include "pm.h"
#include "horizon.h"
#include <stdio.h>

extern void doScale(Viewport * vp, scaleControl * s, double value), doCompassScale(Viewport * vp, scaleControl * s, double value);
extern void ShortTransform(short_point_t *, short_matrix_t * m, short_point_t * b);
void      doLadder(craft * c, viewer * u, double vel);
extern void VMatrixToShortMatrix(VMatrix * v, short_matrix_t * s);
extern double magHeading(craft *);
extern int doWeaponDisplay(craft * c, viewer * u, int *x, int *y);

void
doHUD(craft * c, viewer * u)
{

      char      buffer[80];
      int       i, x, x1, y, scale, fth, scale1;
      double    vel;

      scale1 = (int) (u->scaleFactor * 2048.0);

      scale = (int) (12.0 * u->scaleFactor + 0.5);
      fth = (int) (18.0 * u->scaleFactor + 0.5);

      if (u->viewDirection.x < 0.90)
            return;

#ifdef notdef
      vel = mag(c->Cg);
      sprintf(buffer, "a=%.1f  b=%.1f", RADtoDEG(c->alpha),
                  RADtoDEG(c->beta));
#else
      if ((vel = mag(c->Cg)) < 50.0)
            sprintf(buffer, "a=0.0");
      else
            sprintf(buffer, "a=%.1f", RADtoDEG(c->alpha));
#endif

      /* Angle of Attack */
      x = 750 * scale1 / 2048;
      y = u->yCenter - u->velScale.length / 2 - (int) (u->scaleFactor * 50);
      VDrawStrokeString(u->v, x, y, buffer, strlen(buffer),
                                scale, &u->z);

      /* Accelerometer */
      x1 = 375 * scale1 / 2048;
      sprintf(buffer, "%4.1f", - c->G.z);
      VDrawStrokeString(u->v, x1, y, buffer, strlen(buffer),
                                scale, &u->z);

      /*  vertical velocity */
      x = 725 * scale1 / 2048;
      y = u->yCenter + u->velScale.length / 2 + (int) (u->scaleFactor * 14.0);
      sprintf(buffer, "%6d0", (int) (-c->Cg.z * 6.0));
      VDrawStrokeString(u->v, x, y, buffer, strlen(buffer),
                                scale, &u->z);

      /*  Compass, altititude and airspeed cards */
      doCompassScale(u->v, &(u->hdgScale), RADtoDEG(magHeading(c)) * 100.0);
      doScale(u->v, &(u->altScale), METERStoFEET(c->w.z));
      doScale(u->v, &(u->velScale), FPStoKTS(mag(c->Cg)));

      /* Mach number */
      if (c->mach >= 0.20) {
            sprintf(c->leftHUD[1], "   %4.2f", c->mach);
      }
      else {
            strcpy(c->leftHUD[1], "");
      }

      x = 395 * scale1 / 2048;
      y = u->yCenter - 3;
      VDrawStrokeString(u->v, x, y, "C", 1,
                                scale * 9 / 10, &u->z);

      x = 340 * scale1 / 2048;
      y = u->yCenter + u->velScale.length / 2 + (int) (u->scaleFactor * 50);

      doLadder(c, u, vel);

      for (i = 0; i < 5; ++i) {
            VDrawStrokeString(u->v, x, y, c->leftHUD[i],
                                      strlen(c->leftHUD[i]), scale, &u->z);
            y += fth;
      }

      x = 765 * scale1 / 2048;
      y = u->yCenter + u->velScale.length / 2 + (int) (u->scaleFactor * 50);

      for (i = 0; i < 5; ++i) {
            VDrawStrokeString(u->v, x, y, c->rightHUD[i],
                                      strlen(c->rightHUD[i]), scale, &u->z);
            y += fth;
      }

      return;

}

void
doLadder(craft * c, viewer * u, double vel)
{

      int       a1, a2, a3, a4, a5, plotFPM, npath;
      XSegment  seg[400];
      XRectangle rect[1];
      int       i, j, k, kmax, windX, windY, w, tx, ty, scale, x, y;
      VPoint    tmp, tmp1, t1;
      VMatrix   m;
      double    v, d;
      short_matrix_t im;
      short_point_t it1, it2;
      short_fixed_t limit;
      register short xscale, yscale;
      extern void buildEulerMatrix(double roll, double pitch, double heading, VMatrix * m);

      limit = (short) (0.92 * UNITY);

      scale = (int) (12.0 * u->scaleFactor + 0.5);

      rect[0].x = u->xCenter - (int) (137.5 * u->scaleFactor + 0.5);
      rect[0].y = u->yCenter - (int) (116.0 * u->scaleFactor + 0.5);
      rect[0].width = (unsigned short) (275.0 * u->scaleFactor + 0.5);
      rect[0].height = (unsigned short) (252.0 * u->scaleFactor + 0.5);


      npath = sizeof(horizon_path) / sizeof(horizon_path[0]);

/*
 *  Build a transformation matrix to be used to display the flight
 *  path ladder (artificial horizon).
 *
 *  One thing we do is to keep the ladder centered on the flight path
 *  marker.  The correction angle "v" is calculated to make that happen.
 */

      if (fabs(c->Cg.x) < 5.0 && fabs(c->Cg.y) < 5.0) {
            v = 0.0;
      }
      else {
            t1.x = cos(c->curHeading) * c->Cg.x +
                  sin(c->curHeading) * c->Cg.y;
            t1.y = -sin(c->curHeading) * c->Cg.x +
                  cos(c->curHeading) * c->Cg.y;
            v = atan2(t1.y, t1.x);
      }

      VIdentMatrix(&m);
      VRotate(&m, ZRotation, v);
      VRotate(&m, YRotation, -c->curPitch);
      VRotate(&m, XRotation, c->curRoll);
      VMatrixToShortMatrix(&m, &im);

      xscale = (short) u->v->Scale.x >> 2;
      yscale = (short) u->v->Scale.y >> 2;

/*
 *  Our horizon structure is a list of point paths on a unit circle.  Traverse
 *  that structure, transforming each set of points into screen coordinates,
 *  and add a segment entry for each one that'll be displayed.
 */

      for (i = 0, j = 0; j < npath; ++j) {
            k = horizon_path[j].vertex_start;
            ShortTransform((short_point_t *) &horizon_vertex[k],
                  &im, &it1);
            if (it1.x > limit) {
                  kmax = k + horizon_path[j].vertex_count;
                  for (++k; k < kmax; ++k) {
                        ShortTransform((short_point_t *) &horizon_vertex[k],
                              &im, &it2);
                        if (it2.x > limit) {
                              seg[i].x1 = u->xCenter + (xscale * it1.y / it1.x);
                              seg[i].y1 = u->yCenter - (yscale * it1.z / it1.x);
                              seg[i].x2 = u->xCenter + (xscale * it2.y / it2.x);
                              seg[i++].y2 = u->yCenter - (yscale * it2.z / it2.x);
                        }
                        it1 = it2;
                  }
            }
      }

      /*u->v->w->clip.x1 = rect[0].x;
      u->v->w->clip.y1 = rect[0].y;
      u->v->w->clip.x2 = rect[0].x + rect[0].width - 1;
      u->v->w->clip.y2 = rect[0].y + rect[0].height - 1;*/

      VSetClipRect (u->v, rect[0].x, rect[0].y, rect[0].x + rect[0].width - 1,
                   rect[0].y + rect[0].height - 1);
                  

/*
 *  Determine the location of the flight path marker
 */

      VReverseTransform_(&c->Cg, &c->trihedral, &tmp);

      plotFPM = 1;

      if (vel < 50.0 || tmp.x == 0.0) {
            windX = u->xCenter;
            windY = u->yCenter;
      }
      else if (tmp.x > 0.0) {
            windX = u->xCenter + ((int) (tmp.y * u->v->Scale.x / tmp.x) / 4);
            windY = u->yCenter + ((int) (tmp.z * u->v->Scale.y / tmp.x) / 4);
      }
      else
            plotFPM = 0;

      if (plotFPM) {

            a1 = (int) (18.0 * u->scaleFactor + 0.5);
            a2 = (int) (9.0 * u->scaleFactor + 0.5);
            a3 = (int) (15.0 * u->scaleFactor + 0.5);

            seg[i].x1 = windX - a1;
            seg[i].y1 = windY;
            seg[i].x2 = windX - a2;
            seg[i++].y2 = windY;

            seg[i].x1 = windX + a1;
            seg[i].y1 = windY;
            seg[i].x2 = windX + a2;
            seg[i++].y2 = windY;

            seg[i].x1 = windX;
            seg[i].y1 = windY - a2;
            seg[i].x2 = windX;
            seg[i++].y2 = windY - a1;
      }

/*
 *  Gather weapon display info (and maybe draw a reticle).
 */

      x = y = -1;
      doWeaponDisplay(c, u, &x, &y);

/*
 *  Draw a target designator around the current primary radar target.
 */

      if (c->curRadarTarget >= 0) {

            w = (int) (DESIGNATOR_SIZE * u->scaleFactor);

            VTransform(&ptbl[c->curRadarTarget].Sg, &c->XYZtoNED, &tmp1);
            VReverseTransform_(&tmp1, &c->trihedral, &tmp);

/* radar target is assumed to be ahead of us (tmp.z > 0.0) */

            tx = (u->v->Middl.x + ((int) (tmp.y * u->v->Scale.x / tmp.x)) >> 2);
            ty = (u->v->Middl.y + ((int) (tmp.z * u->v->Scale.y / tmp.x)) >> 2);

            d = sqrt((double) ((x - tx) * (x - tx) + (y - ty) * (y - ty)));

/*
 *  If no LCOS reticle is was plotted or if the distance to the LCOS reticle is
 *  sufficient, then plot a radar target designator box.
 */

            if (x == -1 || d > w * 2.5) {

                  seg[i].x1 = tx - w;
                  seg[i].y1 = ty - w;
                  seg[i].x2 = tx + w;
                  seg[i++].y2 = ty - w;

                  seg[i].x1 = tx + w;
                  seg[i].y1 = ty - w;
                  seg[i].x2 = tx + w;
                  seg[i++].y2 = ty + w;

                  seg[i].x1 = tx + w;
                  seg[i].y1 = ty + w;
                  seg[i].x2 = tx - w;
                  seg[i++].y2 = ty + w;

                  seg[i].x1 = tx - w;
                  seg[i].y1 = ty + w;
                  seg[i].x2 = tx - w;
                  seg[i++].y2 = ty - w;
            }
      }

      VDrawSegments(u->v, seg, i, (unsigned short) (u->v->pixel[HUDPixel]));

      VDrawArc(u->v, u->xCenter - 2, u->yCenter - 2, 4, 4, 0, 360 * 64,
                   (unsigned short) (u->v->pixel[HUDPixel]));

      if (plotFPM) {
            a4 = (int) (16.0 * u->scaleFactor + 0.5);
            a5 = (a4 + 1) / 2;
            VDrawArc(u->v, windX - a5, windY - a5, a4, a4, 0, 360 * 64,
                         (unsigned short) (u->v->pixel[HUDPixel]));
      }

      /* u->v->w->clip.x1 = 0;
      u->v->w->clip.y1 = 0;
      u->v->w->clip.x2 = u->v->w->width - 1;
      u->v->w->clip.y2 = u->v->w->height - 1; */

      VSetClipRect (u->v, 0, 0, -1, -1);

      return;
}

Generated by  Doxygen 1.6.0   Back to index