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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.14 static const char RCSid[] = "$Id: face.c,v 2.13 2016/09/16 15:09:21 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * face.c - routines dealing with polygonal faces.
6 greg 2.6 */
7    
8 greg 2.7 #include "copyright.h"
9 greg 1.1
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 greg 2.3 #ifdef SMLFLT
28 greg 2.9 #define VERTEPS 1e-3 /* allowed vertex error */
29 greg 2.3 #else
30 greg 2.9 #define VERTEPS 1e-5 /* allowed vertex error */
31 greg 2.3 #endif
32 greg 1.1
33    
34     FACE *
35 greg 2.13 getface( /* get arguments for a face */
36     OBJREC *o
37     )
38 greg 1.1 {
39     double d1;
40 greg 2.10 int smalloff, badvert;
41 greg 1.1 FVECT v1, v2, v3;
42 greg 2.13 FACE *f;
43     int i;
44 greg 1.1
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 greg 1.3 o->os = (char *)f; /* save face */
56    
57 greg 1.1 f->va = o->oargs.farg;
58     f->nv = o->oargs.nfargs / 3;
59 greg 2.4 /* check for last==first */
60 greg 2.14 if (f->nv > 3 && dist2(VERTEX(f,0),VERTEX(f,f->nv-1)) <= FTINY*FTINY)
61 greg 2.4 f->nv--;
62 greg 1.1 /* compute area and normal */
63     f->norm[0] = f->norm[1] = f->norm[2] = 0.0;
64 greg 2.5 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 greg 1.1 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 greg 1.2 f->offset = 0.0;
81 greg 1.1 f->ax = 0;
82     return(f);
83     }
84     f->area *= 0.5;
85 greg 1.2 /* compute offset */
86 greg 1.1 badvert = 0;
87 greg 1.2 f->offset = DOT(f->norm, VERTEX(f,0));
88 greg 2.10 smalloff = fabs(f->offset) <= VERTEPS;
89 greg 1.1 for (i = 1; i < f->nv; i++) {
90     d1 = DOT(f->norm, VERTEX(f,i));
91 greg 2.10 if (smalloff)
92     badvert += fabs(d1 - f->offset/i) > VERTEPS;
93     else
94     badvert += fabs(1.0 - d1*i/f->offset) > VERTEPS;
95 greg 1.2 f->offset += d1;
96 greg 1.1 }
97 greg 1.5 f->offset /= (double)f->nv;
98 greg 2.9 if (f->nv > 3 && badvert)
99 greg 1.1 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 greg 2.6 void
110 greg 2.13 freeface( /* free memory associated with face */
111     OBJREC *o
112     )
113 greg 1.1 {
114 greg 1.4 if (o->os == NULL)
115     return;
116 greg 1.1 free(o->os);
117     o->os = NULL;
118     }
119    
120    
121 greg 2.6 int
122 greg 2.13 inface( /* determine if point is in face */
123     FVECT p,
124     FACE *f
125     )
126 greg 1.1 {
127     int ncross, n;
128     double x, y;
129 greg 2.8 int tst;
130 greg 2.13 int xi, yi;
131     RREAL *p0, *p1;
132 greg 1.1
133 greg 2.12 if ((xi = f->ax + 1) >= 3) xi -= 3;
134     if ((yi = xi + 1) >= 3) yi -= 3;
135 greg 1.1 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 greg 2.8 if ((p0[yi] > y) ^ (p1[yi] > y)) {
144     tst = (p0[xi] > x) + (p1[xi] > x);
145     if (tst == 2)
146 greg 1.1 ncross++;
147 greg 2.8 else if (tst)
148 greg 1.1 ncross += (p1[yi] > p0[yi]) ^
149     ((p0[yi]-y)*(p1[xi]-x) >
150     (p0[xi]-x)*(p1[yi]-y));
151 greg 2.8 }
152 greg 1.1 p0 = p1;
153     p1 += 3;
154     }
155     return(ncross & 01);
156     }