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

place.c

/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1997  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 "pm.h"

static VPoint origin =
{0.0, 0.0, 0.0};

void
placeCraft(Viewport * v, 
               craft * c, 
               viewer *u,
               craft * obj, 
               VPolygon ** poly, 
               long *cnt)
{

      int       i, k, n;
      long      j;
      VPoint   *q, tmp, tmp1, center, nc;
      VMatrix   mtx, mtx1, m, m1;
      VPolygon **p, *p1;
      double    dist;
      int       aspect, offset;
      VObject  *op;

      j = *cnt;

/*
 *  Build a transformation matrix to convert from object to world coordinates.
 */

      if ((obj->flags & FL_FIXED_OBJECT) == 0) {

            VIdentMatrix(&m);

            VRotate(&m, YRotation, DEGtoRAD(90.0));
            VRotate(&m, YRotation, obj->w.latitude);
            VRotate(&m, ZRotation, obj->w.longitude);

            buildEulerMatrix(obj->curRoll,
                                     obj->curPitch,
                                     obj->curHeading,
                                     &m1);

            VMatrixMultByRank(&m1, &m, &mtx, 3);

            VTranslatePoint(&mtx, obj->Sg);
      }
      else {
            VIdentMatrix(&mtx);
      }

/*
 *  If the object uses a special method to render itself, call that procedure.
 */

      if (obj->cinfo->placeProc != NULL) {
            (*obj->cinfo->placeProc) (v, obj, &mtx, poly, cnt);
            return;
      }

/*
 *  Build a matrix to transform from world to eye coordinate systems.
 */

      VMatrixMult(&mtx, &v->eyeSpace, &mtx1);

/*
 *  Reject the object if is completely outside any of the clipping planes
 */

      if (obj->flags & FL_FIXED_OBJECT)
            tmp = obj->cinfo->object->center;
      else
            VTransform(&obj->cinfo->object->center, &mtx, &tmp);

      VTransform(&tmp, &u->v->eyeSpace, &center);
      for (i = 0; i < 4; ++i) {
            dist = VPointToClipPlaneDistance(&center,
                                                             &(u->v->clipNormals[i]));
            if (dist > obj->cinfo->object->extent)
                  return;
      }

      op = obj->cinfo->object;
      n = op->numPolys;
      p = op->polygon;
      if (op->order) {
            VTransform(&origin, &mtx1, &nc);
            VTransform_(&_VUnitVectorI, &mtx1, &op->xaxis);
            VTransform_(&_VUnitVectorJ, &mtx1, &op->yaxis);
            VTransform_(&_VUnitVectorK, &mtx1, &op->zaxis);
            aspect = VComputeObjectAspect(op, &nc);
#ifdef notdef
            printf("%s: %s\n", op->name, VGetAspectName(aspect));
#endif
            offset = aspect * n;
      }

      for (i = 0; i < n; ++i) {

/*
 *  Here is an opportunity to cull back-facing polygons without
 *  copying or transforming them. tmp1 becomes the transformed coordinates
 *  of the first vertex in the polygon.
 */

            p1 = (op->order) ? p[op->order[offset + i]] : p[i];

            VTransform(&p1->vertex[0], &mtx1, &tmp1);
            if (p1->flags & PolyNormalValid) {
                  VTransform_(&p1->normal, &mtx1, &tmp);
            }
            if (p1->flags & PolyClipBackface) {
                  if (VDotProd(&tmp1, &tmp) >= 0.0) {
                        continue;
                  }
            }

/*
 *  Beyond the culling distance?  Don't plot this polygon
 */

            if (p1->flags & PolyUseCullDistance) {
                  if (sqrt(tmp1.x * tmp1.x + tmp1.y * tmp1.y + tmp1.z * tmp1.z) >
                        p1->cullDistance) {
                        continue;
                  }
            }

            poly[j] = VCopyPolygon(p1);

/*
 *  First copy the normal vector and the transformed first point, then loop
 *  over all remaining points.
 */

            if (poly[j]->flags & PolyNormalValid) {
                  poly[j]->normal = tmp;
            }

            q = poly[j]->vertex;

/*
 *  First, copy the previously transformed first vertex.
 */

            *q = tmp1;
            q++;

/*
 *  Now transform and copy the remaining vertices.
 */

            for (k = 1; k < poly[j]->numVtces; (++k, ++q)) {
                  VTransform(q, &mtx1, &tmp);
                  *q = tmp;
            }
            ++j;
      }

      *cnt = j;
}

/*
 *  OBSOLETE CODE: we no longer need this function.  We used to transform
 *  objects to their world coordinates and then transform them to eye
 *  coordinates.  Those are now consolidated into one step.
 *
 *  Place an object in world space based on the template object description,
 *  Euler angles, and [xyz] location.  This procedure is called only once
 *  for each fixed object (in init.c).
 */

#ifdef notdef

void
placeObject(obj)
craft    *obj;
{

      register int i, j, n;
      VPoint   *q, tmp;
      VMatrix   mtx;
      VPolygon **p;
      VObject  *newObj;

      VIdentMatrix(&mtx);
      if (obj->curRoll != 0.0)
            VRotate(&mtx, XRotation, obj->curRoll);
      if (obj->curPitch != 0.0)
            VRotate(&mtx, YRotation, -obj->curPitch);
      if (obj->curHeading != 0.0)
            VRotate(&mtx, ZRotation, obj->curHeading);
      VTranslatePoint(&mtx, obj->Sg);

      if (obj->cinfo->placeProc != NULL) {
            fprintf(stderr, "This object cannot be placed this way.\n");
            exit(1);
      }

      newObj = VCopyObject(obj->cinfo->object);

      n = newObj->numPolys;
      p = newObj->polygon;
      for (i = 0; i < n; ++i) {
            for ((j = 0, q = p[i]->vertex); j < p[i]->numVtces; (++j, ++q)) {
                  VTransform(q, &mtx, &tmp);
                  *q = tmp;
            }
            if (p[i]->flags & PolyNormalValid) {
                  VTransform(&p[i]->normal, &mtx, &tmp);
                  p[i]->normal = tmp;
                  p[i]->normal.x -= mtx.m[0][3];
                  p[i]->normal.y -= mtx.m[1][3];
                  p[i]->normal.z -= mtx.m[2][3];

            }
      }

      VTransform(&newObj->center, &mtx, &tmp);
      newObj->center = tmp;

      obj->cinfo->object = newObj;

      obj->flags |= FL_FIXED_OBJECT;
}

#endif

Generated by  Doxygen 1.6.0   Back to index