ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/face.c
Revision: 2.4
Committed: Thu Aug 24 20:54:54 1995 UTC (28 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +4 -1 lines
Log Message:
added check for last vertex connected to first

File Contents

# Content
1 /* Copyright (c) 1995 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ 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 #ifdef SMLFLT
31 #define VERTEPS 1e-2 /* allowed vertex error */
32 #else
33 #define VERTEPS 1e-4 /* allowed vertex error */
34 #endif
35
36
37 FACE *
38 getface(o) /* get arguments for a face */
39 OBJREC *o;
40 {
41 double d1;
42 int badvert;
43 FVECT v1, v2, v3;
44 register FACE *f;
45 register int i;
46
47 if ((f = (FACE *)o->os) != NULL)
48 return(f); /* already done */
49
50 f = (FACE *)malloc(sizeof(FACE));
51 if (f == NULL)
52 error(SYSTEM, "out of memory in makeface");
53
54 if (o->oargs.nfargs < 9 || o->oargs.nfargs % 3)
55 objerror(o, USER, "bad # arguments");
56
57 o->os = (char *)f; /* save face */
58
59 f->va = o->oargs.farg;
60 f->nv = o->oargs.nfargs / 3;
61 /* check for last==first */
62 if (dist2(VERTEX(f,0),VERTEX(f,f->nv-1)) <= FTINY*FTINY)
63 f->nv--;
64 /* compute area and normal */
65 f->norm[0] = f->norm[1] = f->norm[2] = 0.0;
66 v1[0] = v1[1] = v1[2] = 0.0;
67 for (i = 1; i < f->nv; i++) {
68 v2[0] = VERTEX(f,i)[0] - VERTEX(f,0)[0];
69 v2[1] = VERTEX(f,i)[1] - VERTEX(f,0)[1];
70 v2[2] = VERTEX(f,i)[2] - VERTEX(f,0)[2];
71 fcross(v3, v1, v2);
72 f->norm[0] += v3[0];
73 f->norm[1] += v3[1];
74 f->norm[2] += v3[2];
75 VCOPY(v1, v2);
76 }
77 f->area = normalize(f->norm);
78 if (f->area == 0.0) {
79 objerror(o, WARNING, "zero area"); /* used to be fatal */
80 f->offset = 0.0;
81 f->ax = 0;
82 return(f);
83 }
84 f->area *= 0.5;
85 /* compute offset */
86 badvert = 0;
87 f->offset = DOT(f->norm, VERTEX(f,0));
88 for (i = 1; i < f->nv; i++) {
89 d1 = DOT(f->norm, VERTEX(f,i));
90 badvert += fabs(d1 - f->offset/i) > VERTEPS;
91 f->offset += d1;
92 }
93 f->offset /= (double)f->nv;
94 if (badvert)
95 objerror(o, WARNING, "non-planar vertex");
96 /* find axis */
97 f->ax = fabs(f->norm[0]) > fabs(f->norm[1]) ? 0 : 1;
98 if (fabs(f->norm[2]) > fabs(f->norm[f->ax]))
99 f->ax = 2;
100
101 return(f);
102 }
103
104
105 freeface(o) /* free memory associated with face */
106 OBJREC *o;
107 {
108 if (o->os == NULL)
109 return;
110 free(o->os);
111 o->os = NULL;
112 }
113
114
115 inface(p, f) /* determine if point is in face */
116 FVECT p;
117 FACE *f;
118 {
119 int ncross, n;
120 double x, y;
121 register int xi, yi;
122 register FLOAT *p0, *p1;
123
124 xi = (f->ax+1)%3;
125 yi = (f->ax+2)%3;
126 x = p[xi];
127 y = p[yi];
128 n = f->nv;
129 p0 = f->va + 3*(n-1); /* connect last to first */
130 p1 = f->va;
131 ncross = 0;
132 /* positive x axis cross test */
133 while (n--) {
134 if ((p0[yi] > y) ^ (p1[yi] > y))
135 if (p0[xi] > x && p1[xi] > x)
136 ncross++;
137 else if (p0[xi] > x || p1[xi] > x)
138 ncross += (p1[yi] > p0[yi]) ^
139 ((p0[yi]-y)*(p1[xi]-x) >
140 (p0[xi]-x)*(p1[yi]-y));
141 p0 = p1;
142 p1 += 3;
143 }
144 return(ncross & 01);
145 }