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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * sm_geom.c
6 * some geometric utility routines
7 */
8
9 #include "standard.h"
10 #include "sm_geom.h"
11
12 /*
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 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 /*
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 */
97 double
98 tri_normal(v0,v1,v2,n,norm)
99 FVECT v0,v1,v2,n;
100 int norm;
101 {
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 (v2[2] - v0[2]) * (v2[0] + v0[0]);
110 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 /*
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 tri_plane_equation(v0,v1,v2,peqptr,norm)
128 FVECT v0,v1,v2;
129 FPEQ *peqptr;
130 int norm;
131 {
132 tri_normal(v0,v1,v2,FP_N(*peqptr),norm);
133 FP_D(*peqptr) = -(DOT(FP_N(*peqptr),v0));
134 }
135
136 /*
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 int
155 intersect_ray_plane(orig,dir,peq,pd,r)
156 FVECT orig,dir;
157 FPEQ peq;
158 double *pd;
159 FVECT r;
160 {
161 double t,d;
162 int hit;
163
164 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 hit = 0;
171 else
172 hit = 1;
173 if(r)
174 VSUM(r,orig,dir,t);
175
176 if(pd)
177 *pd = t;
178 return(hit);
179 }
180
181 /*
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 double
188 point_on_sphere(ps,p,c)
189 FVECT ps,p,c;
190 {
191 double d;
192
193 VSUB(ps,p,c);
194 d = normalize(ps);
195 return(d);
196 }
197
198 /*
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 int
208 point_in_stri(v0,v1,v2,p)
209 FVECT v0,v1,v2,p;
210 {
211 double d;
212 FVECT n;
213
214 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 return(TRUE);
233 }
234
235 /*
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 int
244 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
245 FVECT orig,dir;
246 FVECT v0,v1,v2;
247 FVECT pt;
248 {
249 FVECT p0,p1,p2,p;
250 FPEQ peq;
251 int type;
252
253 VSUB(p0,v0,orig);
254 VSUB(p1,v1,orig);
255 VSUB(p2,v2,orig);
256
257 if(point_in_stri(p0,p1,p2,dir))
258 {
259 /* Intersect the ray with the triangle plane */
260 tri_plane_equation(v0,v1,v2,&peq,FALSE);
261 return(intersect_ray_plane(orig,dir,peq,NULL,pt));
262 }
263 return(FALSE);
264 }
265
266 /*
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 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
331 /*
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 */
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 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
350
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366