ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/face.c
Revision: 2.11
Committed: Thu Jun 26 00:58:09 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.10: +2 -2 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

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