ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/face.c
Revision: 2.12
Committed: Thu Mar 2 16:51:54 2006 UTC (18 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad4R2, rad4R1, rad4R0, rad3R8, rad3R9, rad4R2P1
Changes since 2.11: +3 -3 lines
Log Message:
Made some minor optimizations in face intersection code

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id: face.c,v 2.11 2003/06/26 00:58:09 schorsch 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     getface(o) /* get arguments for a face */
36     OBJREC *o;
37     {
38     double d1;
39 greg 2.10 int smalloff, badvert;
40 greg 1.1 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 greg 1.3 o->os = (char *)f; /* save face */
55    
56 greg 1.1 f->va = o->oargs.farg;
57     f->nv = o->oargs.nfargs / 3;
58 greg 2.4 /* check for last==first */
59     if (dist2(VERTEX(f,0),VERTEX(f,f->nv-1)) <= FTINY*FTINY)
60     f->nv--;
61 greg 1.1 /* compute area and normal */
62     f->norm[0] = f->norm[1] = f->norm[2] = 0.0;
63 greg 2.5 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 greg 1.1 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 greg 1.2 f->offset = 0.0;
80 greg 1.1 f->ax = 0;
81     return(f);
82     }
83     f->area *= 0.5;
84 greg 1.2 /* compute offset */
85 greg 1.1 badvert = 0;
86 greg 1.2 f->offset = DOT(f->norm, VERTEX(f,0));
87 greg 2.10 smalloff = fabs(f->offset) <= VERTEPS;
88 greg 1.1 for (i = 1; i < f->nv; i++) {
89     d1 = DOT(f->norm, VERTEX(f,i));
90 greg 2.10 if (smalloff)
91     badvert += fabs(d1 - f->offset/i) > VERTEPS;
92     else
93     badvert += fabs(1.0 - d1*i/f->offset) > VERTEPS;
94 greg 1.2 f->offset += d1;
95 greg 1.1 }
96 greg 1.5 f->offset /= (double)f->nv;
97 greg 2.9 if (f->nv > 3 && badvert)
98 greg 1.1 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 greg 2.6 void
109 greg 1.1 freeface(o) /* free memory associated with face */
110     OBJREC *o;
111     {
112 greg 1.4 if (o->os == NULL)
113     return;
114 greg 1.1 free(o->os);
115     o->os = NULL;
116     }
117    
118    
119 greg 2.6 int
120 greg 1.1 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 greg 2.8 int tst;
127 greg 1.1 register int xi, yi;
128 schorsch 2.11 register RREAL *p0, *p1;
129 greg 1.1
130 greg 2.12 if ((xi = f->ax + 1) >= 3) xi -= 3;
131     if ((yi = xi + 1) >= 3) yi -= 3;
132 greg 1.1 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 greg 2.8 if ((p0[yi] > y) ^ (p1[yi] > y)) {
141     tst = (p0[xi] > x) + (p1[xi] > x);
142     if (tst == 2)
143 greg 1.1 ncross++;
144 greg 2.8 else if (tst)
145 greg 1.1 ncross += (p1[yi] > p0[yi]) ^
146     ((p0[yi]-y)*(p1[xi]-x) >
147     (p0[xi]-x)*(p1[yi]-y));
148 greg 2.8 }
149 greg 1.1 p0 = p1;
150     p1 += 3;
151     }
152     return(ncross & 01);
153     }