ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.13
Committed: Sat Feb 22 02:07:25 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6P1, rad3R5, rad3R6
Changes since 3.12: +155 -628 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 gwlarson 3.1 #ifndef lint
2 greg 3.13 static const char RCSid[] = "$Id$";
3 gwlarson 3.1 #endif
4     /*
5     * sm_geom.c
6 greg 3.13 * some geometric utility routines
7 gwlarson 3.1 */
8    
9     #include "standard.h"
10     #include "sm_geom.h"
11    
12 greg 3.13 /*
13     * int
14     * pt_in_cone(p,a,b,c)
15     * : test if point p lies in cone defined by a,b,c and origin
16     * double p[3]; : point to test
17     * double a[3],b[3],c[3]; : points forming triangle
18     *
19     * Assumes apex at origin, a,b,c are unit vectors defining the
20     * triangle which the cone circumscribes. Assumes p is also normalized
21     * Test is implemented as:
22     * r = (b-a)X(c-a)
23     * in = (p.r) > (a.r)
24     * The center of the cone is r, and corresponds to the triangle normal.
25     * p.r is the proportional to the cosine of the angle between p and the
26     * the cone center ray, and a.r to the radius of the cone. If the cosine
27     * of the angle for p is greater than that for a, the angle between p
28     * and r is smaller, and p lies in the cone.
29     */
30     int
31     pt_in_cone(p,a,b,c)
32     double p[3],a[3],b[3],c[3];
33     {
34     double r[3];
35     double pr,ar;
36     double ab[3],ac[3];
37    
38     #ifdef DEBUG
39     #if DEBUG > 1
40     {
41     double l;
42     VSUB(ab,b,a);
43     normalize(ab);
44     VSUB(ac,c,a);
45     normalize(ac);
46     VCROSS(r,ab,ac);
47     l = normalize(r);
48     /* l = sin@ between ab,ac - if 0 vectors are colinear */
49     if( l <= COLINEAR_EPS)
50     {
51     eputs("pt in cone: null triangle:returning FALSE\n");
52     return(FALSE);
53     }
54     }
55     #endif
56     #endif
57    
58     VSUB(ab,b,a);
59     VSUB(ac,c,a);
60     VCROSS(r,ab,ac);
61    
62     pr = DOT(p,r);
63     ar = DOT(a,r);
64     /* Need to check for equality for degeneracy of 4 points on circle */
65     if( pr > ar *( 1.0 + EQUALITY_EPS))
66     return(TRUE);
67     else
68     return(FALSE);
69     }
70    
71     /*
72     * tri_centroid(v0,v1,v2,c)
73     * : Average triangle vertices to give centroid: return in c
74     *FVECT v0,v1,v2,c; : triangle vertices(v0,v1,v2) and vector to hold result(c)
75     */
76 gwlarson 3.1 tri_centroid(v0,v1,v2,c)
77     FVECT v0,v1,v2,c;
78     {
79     c[0] = (v0[0] + v1[0] + v2[0])/3.0;
80     c[1] = (v0[1] + v1[1] + v2[1])/3.0;
81     c[2] = (v0[2] + v1[2] + v2[2])/3.0;
82     }
83    
84    
85 greg 3.13 /*
86     * double
87     * tri_normal(v0,v1,v2,n,norm) : Calculates the normal of a face contour using
88     * Newell's formula.
89     * FVECT v0,v1,v2,n; : Triangle vertices(v0,v1,v2) and vector for result(n)
90     * int norm; : If true result is normalized
91     *
92     * Triangle normal is calculated using the following:
93     * A = SUMi (yi - yi+1)(zi + zi+1);
94     * B = SUMi (zi - zi+1)(xi + xi+1)
95     * C = SUMi (xi - xi+1)(yi + yi+1)
96 gwlarson 3.1 */
97     double
98     tri_normal(v0,v1,v2,n,norm)
99     FVECT v0,v1,v2,n;
100 gwlarson 3.4 int norm;
101 gwlarson 3.1 {
102     double mag;
103    
104     n[0] = (v0[2] + v1[2]) * (v0[1] - v1[1]) +
105     (v1[2] + v2[2]) * (v1[1] - v2[1]) +
106     (v2[2] + v0[2]) * (v2[1] - v0[1]);
107     n[1] = (v0[2] - v1[2]) * (v0[0] + v1[0]) +
108     (v1[2] - v2[2]) * (v1[0] + v2[0]) +
109 gwlarson 3.9 (v2[2] - v0[2]) * (v2[0] + v0[0]);
110 gwlarson 3.1 n[2] = (v0[1] + v1[1]) * (v0[0] - v1[0]) +
111     (v1[1] + v2[1]) * (v1[0] - v2[0]) +
112     (v2[1] + v0[1]) * (v2[0] - v0[0]);
113     if(!norm)
114     return(0);
115     mag = normalize(n);
116     return(mag);
117     }
118    
119 greg 3.13 /*
120     * tri_plane_equation(v0,v1,v2,peqptr,norm)
121     * : Calculates the plane equation (A,B,C,D) for triangle
122     * v0,v1,v2 ( Ax + By + Cz = D)
123     * FVECT v0,v1,v2; : Triangle vertices
124     * FPEQ *peqptr; : ptr to structure to hold result
125     * int norm; : if TRUE, return unit normal
126     */
127 gwlarson 3.7 tri_plane_equation(v0,v1,v2,peqptr,norm)
128 gwlarson 3.12 FVECT v0,v1,v2;
129 gwlarson 3.7 FPEQ *peqptr;
130 gwlarson 3.4 int norm;
131 gwlarson 3.1 {
132 gwlarson 3.7 tri_normal(v0,v1,v2,FP_N(*peqptr),norm);
133     FP_D(*peqptr) = -(DOT(FP_N(*peqptr),v0));
134 gwlarson 3.1 }
135    
136 greg 3.13 /*
137     * int
138     * intersect_ray_plane(orig,dir,peq,pd,r)
139     * : Intersects ray (orig,dir) with plane (peq). Returns TRUE
140     * if intersection occurs. If r!=NULL, sets with resulting i
141     * intersection point, and pd is set with parametric value of the
142     * intersection.
143     * FVECT orig,dir; : vectors defining the ray
144     * FPEQ peq; : plane equation
145     * double *pd; : holds resulting parametric intersection point
146     * FVECT r; : holds resulting intersection point
147     *
148     * Plane is Ax + By + Cz +D = 0:
149     * A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
150     * t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
151     * line is l = p1 + (p2-p1)t
152     * Solve for t
153     */
154 gwlarson 3.1 int
155 gwlarson 3.7 intersect_ray_plane(orig,dir,peq,pd,r)
156 gwlarson 3.1 FVECT orig,dir;
157 gwlarson 3.7 FPEQ peq;
158 gwlarson 3.1 double *pd;
159     FVECT r;
160     {
161 gwlarson 3.8 double t,d;
162 gwlarson 3.1 int hit;
163 greg 3.13
164 gwlarson 3.8 d = DOT(FP_N(peq),dir);
165     if(ZERO(d))
166     return(0);
167     t = -(DOT(FP_N(peq),orig) + FP_D(peq))/d;
168    
169     if(t < 0)
170 gwlarson 3.4 hit = 0;
171     else
172 gwlarson 3.1 hit = 1;
173 gwlarson 3.4 if(r)
174     VSUM(r,orig,dir,t);
175    
176     if(pd)
177     *pd = t;
178     return(hit);
179     }
180    
181 greg 3.13 /*
182     * double
183     * point_on_sphere(ps,p,c) : normalize p relative to sphere with center c
184     * FVECT ps,p,c; : ps Holds result vector,p is the original point,
185     * and c is the sphere center
186     */
187 gwlarson 3.12 double
188     point_on_sphere(ps,p,c)
189     FVECT ps,p,c;
190     {
191     double d;
192 greg 3.13
193     VSUB(ps,p,c);
194     d = normalize(ps);
195     return(d);
196 gwlarson 3.12 }
197 gwlarson 3.1
198 greg 3.13 /*
199     * int
200     * point_in_stri(v0,v1,v2,p) : Return TRUE if p is in pyramid defined by
201     * tri v0,v1,v2 and origin
202     * FVECT v0,v1,v2,p; :Triangle vertices(v0,v1,v2) and point in question(p)
203     *
204     * Tests orientation of p relative to each edge (v0v1,v1v2,v2v0), if it is
205     * inside of all 3 edges, returns TRUE, else FALSE.
206     */
207 gwlarson 3.1 int
208 gwlarson 3.12 point_in_stri(v0,v1,v2,p)
209     FVECT v0,v1,v2,p;
210 gwlarson 3.1 {
211 gwlarson 3.12 double d;
212     FVECT n;
213 gwlarson 3.9
214 gwlarson 3.12 VCROSS(n,v0,v1);
215     /* Test the point for sidedness */
216     d = DOT(n,p);
217     if(d > 0.0)
218     return(FALSE);
219     /* Test next edge */
220     VCROSS(n,v1,v2);
221     /* Test the point for sidedness */
222     d = DOT(n,p);
223     if(d > 0.0)
224     return(FALSE);
225     /* Test next edge */
226     VCROSS(n,v2,v0);
227     /* Test the point for sidedness */
228     d = DOT(n,p);
229     if(d > 0.0)
230     return(FALSE);
231     /* Must be interior to the pyramid */
232 greg 3.13 return(TRUE);
233 gwlarson 3.12 }
234 gwlarson 3.1
235 greg 3.13 /*
236     * int
237     * ray_intersect_tri(orig,dir,v0,v1,v2,pt)
238     * : test if ray orig-dir intersects triangle v0v1v2, result in pt
239     * FVECT orig,dir; : Vectors defining ray origin and direction
240     * FVECT v0,v1,v2; : Triangle vertices
241     * FVECT pt; : Intersection point (if any)
242     */
243 gwlarson 3.1 int
244 gwlarson 3.4 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
245 gwlarson 3.1 FVECT orig,dir;
246     FVECT v0,v1,v2;
247     FVECT pt;
248     {
249 gwlarson 3.7 FVECT p0,p1,p2,p;
250     FPEQ peq;
251 gwlarson 3.4 int type;
252    
253 gwlarson 3.5 VSUB(p0,v0,orig);
254     VSUB(p1,v1,orig);
255     VSUB(p2,v2,orig);
256    
257 gwlarson 3.4 if(point_in_stri(p0,p1,p2,dir))
258 gwlarson 3.1 {
259     /* Intersect the ray with the triangle plane */
260 gwlarson 3.7 tri_plane_equation(v0,v1,v2,&peq,FALSE);
261     return(intersect_ray_plane(orig,dir,peq,NULL,pt));
262 gwlarson 3.1 }
263 gwlarson 3.4 return(FALSE);
264 gwlarson 3.1 }
265    
266 greg 3.13 /*
267     * calculate_view_frustum(vp,hv,vv,horiz,vert,near,far,fnear,ffar)
268     * : Calculate vertices defining front and rear clip rectangles of
269     * view frustum defined by vp,hv,vv,horiz,vert,near, and far and
270     * return in fnear and ffar.
271     * FVECT vp,hv,vv; : Viewpoint(vp),hv and vv are the horizontal and
272     * vertical vectors in the view frame-magnitude is
273     * the dimension of the front frustum face at z =1
274     * double horiz,vert,near,far; : View angle horizontal and vertical(horiz,vert)
275     * and distance to the near,far clipping planes
276     * FVECT fnear[4],ffar[4]; : holds results
277     *
278     */
279 gwlarson 3.1 calculate_view_frustum(vp,hv,vv,horiz,vert,near,far,fnear,ffar)
280     FVECT vp,hv,vv;
281     double horiz,vert,near,far;
282     FVECT fnear[4],ffar[4];
283     {
284     double height,width;
285     FVECT t,nhv,nvv,ndv;
286     double w2,h2;
287     /* Calculate the x and y dimensions of the near face */
288     VCOPY(nhv,hv);
289     VCOPY(nvv,vv);
290     w2 = normalize(nhv);
291     h2 = normalize(nvv);
292     /* Use similar triangles to calculate the dimensions at z=near */
293     width = near*0.5*w2;
294     height = near*0.5*h2;
295    
296     VCROSS(ndv,nvv,nhv);
297     /* Calculate the world space points corresponding to the 4 corners
298     of the front face of the view frustum
299     */
300     fnear[0][0] = width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0] ;
301     fnear[0][1] = width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
302     fnear[0][2] = width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
303     fnear[1][0] = -width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0];
304     fnear[1][1] = -width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
305     fnear[1][2] = -width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
306     fnear[2][0] = -width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
307     fnear[2][1] = -width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
308     fnear[2][2] = -width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
309     fnear[3][0] = width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
310     fnear[3][1] = width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
311     fnear[3][2] = width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
312    
313     /* Now do the far face */
314     width = far*0.5*w2;
315     height = far*0.5*h2;
316     ffar[0][0] = width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
317     ffar[0][1] = width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
318     ffar[0][2] = width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
319     ffar[1][0] = -width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
320     ffar[1][1] = -width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
321     ffar[1][2] = -width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
322     ffar[2][0] = -width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
323     ffar[2][1] = -width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
324     ffar[2][2] = -width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
325     ffar[3][0] = width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
326     ffar[3][1] = width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
327     ffar[3][2] = width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
328     }
329    
330 gwlarson 3.2
331 greg 3.13 /*
332     * bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
333     * : Find the normalized barycentric coordinates of p relative to
334     * triangle v0,v1,v2. Return result in coord
335     * double x1,y1,x2,y2,x3,y3; : defines triangle vertices 1,2,3
336     * double px,py; : coordinates of pt
337     * double coord[3]; : result
338 gwlarson 3.2 */
339     bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
340     double x1,y1,x2,y2,x3,y3;
341     double px,py;
342     double coord[3];
343     {
344     double a;
345    
346     a = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
347     coord[0] = ((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py)) / a;
348     coord[1] = ((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py)) / a;
349 gwlarson 3.6 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
350 gwlarson 3.2
351     }
352    
353 gwlarson 3.4
354    
355 gwlarson 3.2
356    
357 gwlarson 3.6
358    
359    
360    
361 greg 3.13
362    
363    
364 gwlarson 3.2
365    
366 gwlarson 3.1