home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / COMMON / FACE.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  3KB  |  139 lines

  1. /* Copyright (c) 1991 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)face.c 2.2 10/2/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  face.c - routines dealing with polygonal faces.
  9.  *
  10.  *     8/30/85
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  "object.h"
  16.  
  17. #include  "face.h"
  18.  
  19. /*
  20.  *    A face is given as a list of 3D vertices.  The normal
  21.  *  direction and therefore the surface orientation is determined
  22.  *  by the ordering of the vertices.  Looking in the direction opposite
  23.  *  the normal (at the front of the face), the vertices will be
  24.  *  listed in counter-clockwise order.
  25.  *    There is no checking done to insure that the edges do not cross
  26.  *  one another.  This was considered too expensive and should be unnecessary.
  27.  *  The last vertex is automatically connected to the first.
  28.  */
  29.  
  30. #define  VERTEPS    1e-4        /* allowed vertex error */
  31.  
  32.  
  33. FACE *
  34. getface(o)            /* get arguments for a face */
  35. OBJREC  *o;
  36. {
  37.     double  d1;
  38.     int  badvert;
  39.     FVECT  v1, v2, v3;
  40.     register FACE  *f;
  41.     register int  i;
  42.  
  43.     if ((f = (FACE *)o->os) != NULL)
  44.         return(f);            /* already done */
  45.  
  46.     f = (FACE *)malloc(sizeof(FACE));
  47.     if (f == NULL)
  48.         error(SYSTEM, "out of memory in makeface");
  49.  
  50.     if (o->oargs.nfargs < 9 || o->oargs.nfargs % 3)
  51.         objerror(o, USER, "bad # arguments");
  52.  
  53.     o->os = (char *)f;            /* save face */
  54.  
  55.     f->va = o->oargs.farg;
  56.     f->nv = o->oargs.nfargs / 3;
  57.                         /* compute area and normal */
  58.     f->norm[0] = f->norm[1] = f->norm[2] = 0.0;
  59.     v1[0] = v1[1] = v1[2] = 0.0;
  60.     for (i = 1; i < f->nv; i++) {
  61.         v2[0] = VERTEX(f,i)[0] - VERTEX(f,0)[0];
  62.         v2[1] = VERTEX(f,i)[1] - VERTEX(f,0)[1];
  63.         v2[2] = VERTEX(f,i)[2] - VERTEX(f,0)[2];
  64.         fcross(v3, v1, v2);
  65.         f->norm[0] += v3[0];
  66.         f->norm[1] += v3[1];
  67.         f->norm[2] += v3[2];
  68.         VCOPY(v1, v2);
  69.     }
  70.     f->area = normalize(f->norm);
  71.     if (f->area == 0.0) {
  72.         objerror(o, WARNING, "zero area");    /* used to be fatal */
  73.         f->offset = 0.0;
  74.         f->ax = 0;
  75.         return(f);
  76.     }
  77.     f->area *= 0.5;
  78.                         /* compute offset */
  79.     badvert = 0;
  80.     f->offset = DOT(f->norm, VERTEX(f,0));
  81.     for (i = 1; i < f->nv; i++) {
  82.         d1 = DOT(f->norm, VERTEX(f,i));
  83.         badvert += fabs(d1 - f->offset/i) > VERTEPS;
  84.         f->offset += d1;
  85.     }
  86.     f->offset /= (double)f->nv;
  87.     if (badvert)
  88.         objerror(o, WARNING, "non-planar vertex");
  89.                         /* find axis */
  90.     f->ax = fabs(f->norm[0]) > fabs(f->norm[1]) ? 0 : 1;
  91.     if (fabs(f->norm[2]) > fabs(f->norm[f->ax]))
  92.         f->ax = 2;
  93.  
  94.     return(f);
  95. }
  96.  
  97.  
  98. freeface(o)            /* free memory associated with face */
  99. OBJREC  *o;
  100. {
  101.     if (o->os == NULL)
  102.         return;
  103.     free(o->os);
  104.     o->os = NULL;
  105. }
  106.  
  107.  
  108. inface(p, f)            /* determine if point is in face */
  109. FVECT  p;
  110. FACE  *f;
  111. {
  112.     int  ncross, n;
  113.     double  x, y;
  114.     register int  xi, yi;
  115.     register FLOAT  *p0, *p1;
  116.  
  117.     xi = (f->ax+1)%3;
  118.     yi = (f->ax+2)%3;
  119.     x = p[xi];
  120.     y = p[yi];
  121.     n = f->nv;
  122.     p0 = f->va + 3*(n-1);        /* connect last to first */
  123.     p1 = f->va;
  124.     ncross = 0;
  125.                     /* positive x axis cross test */
  126.     while (n--) {
  127.         if ((p0[yi] > y) ^ (p1[yi] > y))
  128.             if (p0[xi] > x && p1[xi] > x)
  129.                 ncross++;
  130.             else if (p0[xi] > x || p1[xi] > x)
  131.                 ncross += (p1[yi] > p0[yi]) ^
  132.                         ((p0[yi]-y)*(p1[xi]-x) >
  133.                         (p0[xi]-x)*(p1[yi]-y));
  134.         p0 = p1;
  135.         p1 += 3;
  136.     }
  137.     return(ncross & 01);
  138. }
  139.