ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/face.c
Revision: 2.14
Committed: Sun Jun 14 02:10:44 2020 UTC (3 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.13: +2 -2 lines
Log Message:
Added check for triangle before removing "redundant" vertex

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: face.c,v 2.13 2016/09/16 15:09:21 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( /* get arguments for a face */
36 OBJREC *o
37 )
38 {
39 double d1;
40 int smalloff, badvert;
41 FVECT v1, v2, v3;
42 FACE *f;
43 int i;
44
45 if ((f = (FACE *)o->os) != NULL)
46 return(f); /* already done */
47
48 f = (FACE *)malloc(sizeof(FACE));
49 if (f == NULL)
50 error(SYSTEM, "out of memory in makeface");
51
52 if (o->oargs.nfargs < 9 || o->oargs.nfargs % 3)
53 objerror(o, USER, "bad # arguments");
54
55 o->os = (char *)f; /* save face */
56
57 f->va = o->oargs.farg;
58 f->nv = o->oargs.nfargs / 3;
59 /* check for last==first */
60 if (f->nv > 3 && dist2(VERTEX(f,0),VERTEX(f,f->nv-1)) <= FTINY*FTINY)
61 f->nv--;
62 /* compute area and normal */
63 f->norm[0] = f->norm[1] = f->norm[2] = 0.0;
64 v1[0] = VERTEX(f,1)[0] - VERTEX(f,0)[0];
65 v1[1] = VERTEX(f,1)[1] - VERTEX(f,0)[1];
66 v1[2] = VERTEX(f,1)[2] - VERTEX(f,0)[2];
67 for (i = 2; 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 smalloff = fabs(f->offset) <= VERTEPS;
89 for (i = 1; i < f->nv; i++) {
90 d1 = DOT(f->norm, VERTEX(f,i));
91 if (smalloff)
92 badvert += fabs(d1 - f->offset/i) > VERTEPS;
93 else
94 badvert += fabs(1.0 - d1*i/f->offset) > VERTEPS;
95 f->offset += d1;
96 }
97 f->offset /= (double)f->nv;
98 if (f->nv > 3 && badvert)
99 objerror(o, WARNING, "non-planar vertex");
100 /* find axis */
101 f->ax = fabs(f->norm[0]) > fabs(f->norm[1]) ? 0 : 1;
102 if (fabs(f->norm[2]) > fabs(f->norm[f->ax]))
103 f->ax = 2;
104
105 return(f);
106 }
107
108
109 void
110 freeface( /* free memory associated with face */
111 OBJREC *o
112 )
113 {
114 if (o->os == NULL)
115 return;
116 free(o->os);
117 o->os = NULL;
118 }
119
120
121 int
122 inface( /* determine if point is in face */
123 FVECT p,
124 FACE *f
125 )
126 {
127 int ncross, n;
128 double x, y;
129 int tst;
130 int xi, yi;
131 RREAL *p0, *p1;
132
133 if ((xi = f->ax + 1) >= 3) xi -= 3;
134 if ((yi = xi + 1) >= 3) yi -= 3;
135 x = p[xi];
136 y = p[yi];
137 n = f->nv;
138 p0 = f->va + 3*(n-1); /* connect last to first */
139 p1 = f->va;
140 ncross = 0;
141 /* positive x axis cross test */
142 while (n--) {
143 if ((p0[yi] > y) ^ (p1[yi] > y)) {
144 tst = (p0[xi] > x) + (p1[xi] > x);
145 if (tst == 2)
146 ncross++;
147 else if (tst)
148 ncross += (p1[yi] > p0[yi]) ^
149 ((p0[yi]-y)*(p1[xi]-x) >
150 (p0[xi]-x)*(p1[yi]-y));
151 }
152 p0 = p1;
153 p1 += 3;
154 }
155 return(ncross & 01);
156 }