ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.6
Committed: Wed Sep 16 18:16:28 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.5: +209 -25 lines
Log Message:
implemented integer triangle tracing

File Contents

# User Rev Content
1 gwlarson 3.1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * sm_geom.c
9     */
10    
11     #include "standard.h"
12     #include "sm_geom.h"
13    
14     tri_centroid(v0,v1,v2,c)
15     FVECT v0,v1,v2,c;
16     {
17     /* Average three triangle vertices to give centroid: return in c */
18     c[0] = (v0[0] + v1[0] + v2[0])/3.0;
19     c[1] = (v0[1] + v1[1] + v2[1])/3.0;
20     c[2] = (v0[2] + v1[2] + v2[2])/3.0;
21     }
22    
23    
24     int
25     vec3_equal(v1,v2)
26     FVECT v1,v2;
27     {
28     return(EQUAL(v1[0],v2[0]) && EQUAL(v1[1],v2[1])&& EQUAL(v1[2],v2[2]));
29     }
30    
31    
32     int
33     convex_angle(v0,v1,v2)
34     FVECT v0,v1,v2;
35     {
36     FVECT cp01,cp12,cp;
37    
38     /* test sign of (v0Xv1)X(v1Xv2). v1 */
39     VCROSS(cp01,v0,v1);
40     VCROSS(cp12,v1,v2);
41     VCROSS(cp,cp01,cp12);
42 gwlarson 3.4 if(DOT(cp,v1) < 0.0)
43 gwlarson 3.1 return(FALSE);
44     return(TRUE);
45     }
46    
47     /* calculates the normal of a face contour using Newell's formula. e
48    
49     a = SUMi (yi - yi+1)(zi + zi+1)
50     b = SUMi (zi - zi+1)(xi + xi+1)
51     c = SUMi (xi - xi+1)(yi + yi+1)
52     */
53     double
54     tri_normal(v0,v1,v2,n,norm)
55     FVECT v0,v1,v2,n;
56 gwlarson 3.4 int norm;
57 gwlarson 3.1 {
58     double mag;
59    
60     n[0] = (v0[2] + v1[2]) * (v0[1] - v1[1]) +
61     (v1[2] + v2[2]) * (v1[1] - v2[1]) +
62     (v2[2] + v0[2]) * (v2[1] - v0[1]);
63    
64     n[1] = (v0[2] - v1[2]) * (v0[0] + v1[0]) +
65     (v1[2] - v2[2]) * (v1[0] + v2[0]) +
66     (v2[2] - v0[2]) * (v2[0] + v0[0]);
67    
68    
69     n[2] = (v0[1] + v1[1]) * (v0[0] - v1[0]) +
70     (v1[1] + v2[1]) * (v1[0] - v2[0]) +
71     (v2[1] + v0[1]) * (v2[0] - v0[0]);
72    
73     if(!norm)
74     return(0);
75    
76    
77     mag = normalize(n);
78    
79     return(mag);
80     }
81    
82    
83     tri_plane_equation(v0,v1,v2,n,nd,norm)
84     FVECT v0,v1,v2,n;
85     double *nd;
86 gwlarson 3.4 int norm;
87 gwlarson 3.1 {
88     tri_normal(v0,v1,v2,n,norm);
89    
90     *nd = -(DOT(n,v0));
91     }
92    
93     /* From quad_edge-code */
94     int
95     point_in_circle_thru_origin(p,p0,p1)
96     FVECT p;
97     FVECT p0,p1;
98     {
99    
100     double dp0,dp1;
101     double dp,det;
102    
103     dp0 = DOT_VEC2(p0,p0);
104     dp1 = DOT_VEC2(p1,p1);
105     dp = DOT_VEC2(p,p);
106    
107     det = -dp0*CROSS_VEC2(p1,p) + dp1*CROSS_VEC2(p0,p) - dp*CROSS_VEC2(p0,p1);
108    
109     return (det > 0);
110     }
111    
112    
113    
114     point_on_sphere(ps,p,c)
115     FVECT ps,p,c;
116     {
117     VSUB(ps,p,c);
118     normalize(ps);
119     }
120    
121    
122 gwlarson 3.4 /* returns TRUE if ray from origin in direction v intersects plane defined
123     * by normal plane_n, and plane_d. If plane is not parallel- returns
124     * intersection point if r != NULL. If tptr!= NULL returns value of
125     * t, if parallel, returns t=FHUGE
126     */
127 gwlarson 3.1 int
128 gwlarson 3.2 intersect_vector_plane(v,plane_n,plane_d,tptr,r)
129 gwlarson 3.1 FVECT v,plane_n;
130     double plane_d;
131 gwlarson 3.2 double *tptr;
132 gwlarson 3.1 FVECT r;
133     {
134 gwlarson 3.4 double t,d;
135 gwlarson 3.1 int hit;
136     /*
137     Plane is Ax + By + Cz +D = 0:
138     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
139     */
140    
141     /* line is l = p1 + (p2-p1)t, p1=origin */
142    
143     /* Solve for t: */
144 gwlarson 3.4 d = -(DOT(plane_n,v));
145     if(ZERO(d))
146     {
147     t = FHUGE;
148     hit = 0;
149     }
150     else
151     {
152     t = plane_d/d;
153     if(t < 0 )
154     hit = 0;
155     else
156     hit = 1;
157     if(r)
158     {
159     r[0] = v[0]*t;
160     r[1] = v[1]*t;
161     r[2] = v[2]*t;
162     }
163     }
164 gwlarson 3.2 if(tptr)
165     *tptr = t;
166 gwlarson 3.1 return(hit);
167     }
168    
169     int
170     intersect_ray_plane(orig,dir,plane_n,plane_d,pd,r)
171     FVECT orig,dir;
172     FVECT plane_n;
173     double plane_d;
174     double *pd;
175     FVECT r;
176     {
177     double t;
178     int hit;
179     /*
180     Plane is Ax + By + Cz +D = 0:
181     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
182     */
183 gwlarson 3.2 /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
184     t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
185     line is l = p1 + (p2-p1)t
186     */
187 gwlarson 3.1 /* Solve for t: */
188     t = -(DOT(plane_n,orig) + plane_d)/(DOT(plane_n,dir));
189 gwlarson 3.4 if(t < 0)
190     hit = 0;
191     else
192 gwlarson 3.1 hit = 1;
193 gwlarson 3.4
194     if(r)
195     VSUM(r,orig,dir,t);
196    
197     if(pd)
198     *pd = t;
199     return(hit);
200     }
201    
202    
203     int
204     intersect_edge_plane(e0,e1,plane_n,plane_d,pd,r)
205     FVECT e0,e1;
206     FVECT plane_n;
207     double plane_d;
208     double *pd;
209     FVECT r;
210     {
211     double t;
212     int hit;
213     FVECT d;
214     /*
215     Plane is Ax + By + Cz +D = 0:
216     plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
217     */
218     /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
219     t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
220     line is l = p1 + (p2-p1)t
221     */
222     /* Solve for t: */
223     VSUB(d,e1,e0);
224     t = -(DOT(plane_n,e0) + plane_d)/(DOT(plane_n,d));
225     if(t < 0)
226     hit = 0;
227 gwlarson 3.1 else
228 gwlarson 3.4 hit = 1;
229 gwlarson 3.1
230 gwlarson 3.4 VSUM(r,e0,d,t);
231 gwlarson 3.1
232     if(pd)
233     *pd = t;
234     return(hit);
235     }
236    
237    
238     int
239     point_in_cone(p,p0,p1,p2)
240     FVECT p;
241     FVECT p0,p1,p2;
242     {
243     FVECT n;
244     FVECT np,x_axis,y_axis;
245     double d1,d2,d;
246    
247     /* Find the equation of the circle defined by the intersection
248     of the cone with the plane defined by p1,p2,p3- project p into
249     that plane and do an in-circle test in the plane
250     */
251    
252     /* find the equation of the plane defined by p1-p3 */
253     tri_plane_equation(p0,p1,p2,n,&d,FALSE);
254    
255     /* define a coordinate system on the plane: the x axis is in
256     the direction of np2-np1, and the y axis is calculated from
257     n cross x-axis
258     */
259     /* Project p onto the plane */
260 gwlarson 3.4 /* NOTE: check this: does sideness check?*/
261 gwlarson 3.1 if(!intersect_vector_plane(p,n,d,NULL,np))
262     return(FALSE);
263    
264     /* create coordinate system on plane: p2-p1 defines the x_axis*/
265     VSUB(x_axis,p1,p0);
266     normalize(x_axis);
267     /* The y axis is */
268     VCROSS(y_axis,n,x_axis);
269     normalize(y_axis);
270    
271     VSUB(p1,p1,p0);
272     VSUB(p2,p2,p0);
273     VSUB(np,np,p0);
274    
275     p1[0] = VLEN(p1);
276     p1[1] = 0;
277    
278     d1 = DOT(p2,x_axis);
279     d2 = DOT(p2,y_axis);
280     p2[0] = d1;
281     p2[1] = d2;
282    
283     d1 = DOT(np,x_axis);
284     d2 = DOT(np,y_axis);
285     np[0] = d1;
286     np[1] = d2;
287    
288     /* perform the in-circle test in the new coordinate system */
289     return(point_in_circle_thru_origin(np,p1,p2));
290     }
291    
292     int
293 gwlarson 3.4 point_set_in_stri(v0,v1,v2,p,n,nset,sides)
294 gwlarson 3.1 FVECT v0,v1,v2,p;
295     FVECT n[3];
296 gwlarson 3.4 int *nset;
297     int sides[3];
298 gwlarson 3.1
299     {
300 gwlarson 3.4 double d;
301 gwlarson 3.1 /* Find the normal to the triangle ORIGIN:v0:v1 */
302     if(!NTH_BIT(*nset,0))
303     {
304     VCROSS(n[0],v1,v0);
305     SET_NTH_BIT(*nset,0);
306     }
307     /* Test the point for sidedness */
308     d = DOT(n[0],p);
309    
310 gwlarson 3.4 if(d > 0.0)
311     {
312     sides[0] = GT_OUT;
313     sides[1] = sides[2] = GT_INVALID;
314     return(FALSE);
315 gwlarson 3.1 }
316     else
317     sides[0] = GT_INTERIOR;
318    
319     /* Test next edge */
320     if(!NTH_BIT(*nset,1))
321     {
322     VCROSS(n[1],v2,v1);
323     SET_NTH_BIT(*nset,1);
324     }
325     /* Test the point for sidedness */
326     d = DOT(n[1],p);
327 gwlarson 3.4 if(d > 0.0)
328 gwlarson 3.1 {
329     sides[1] = GT_OUT;
330     sides[2] = GT_INVALID;
331     return(FALSE);
332     }
333     else
334     sides[1] = GT_INTERIOR;
335     /* Test next edge */
336     if(!NTH_BIT(*nset,2))
337     {
338     VCROSS(n[2],v0,v2);
339     SET_NTH_BIT(*nset,2);
340     }
341     /* Test the point for sidedness */
342     d = DOT(n[2],p);
343 gwlarson 3.4 if(d > 0.0)
344 gwlarson 3.1 {
345 gwlarson 3.4 sides[2] = GT_OUT;
346     return(FALSE);
347 gwlarson 3.1 }
348     else
349     sides[2] = GT_INTERIOR;
350     /* Must be interior to the pyramid */
351     return(GT_INTERIOR);
352     }
353    
354    
355    
356    
357     int
358 gwlarson 3.4 point_in_stri(v0,v1,v2,p)
359 gwlarson 3.1 FVECT v0,v1,v2,p;
360     {
361 gwlarson 3.4 double d;
362 gwlarson 3.1 FVECT n;
363    
364     VCROSS(n,v1,v0);
365     /* Test the point for sidedness */
366     d = DOT(n,p);
367 gwlarson 3.4 if(d > 0.0)
368     return(FALSE);
369    
370 gwlarson 3.1 /* Test next edge */
371     VCROSS(n,v2,v1);
372     /* Test the point for sidedness */
373     d = DOT(n,p);
374 gwlarson 3.4 if(d > 0.0)
375 gwlarson 3.1 return(FALSE);
376    
377     /* Test next edge */
378     VCROSS(n,v0,v2);
379     /* Test the point for sidedness */
380     d = DOT(n,p);
381 gwlarson 3.4 if(d > 0.0)
382 gwlarson 3.1 return(FALSE);
383     /* Must be interior to the pyramid */
384 gwlarson 3.4 return(GT_INTERIOR);
385 gwlarson 3.1 }
386    
387     int
388 gwlarson 3.4 vertices_in_stri(t0,t1,t2,p0,p1,p2,nset,n,avg,pt_sides)
389 gwlarson 3.1 FVECT t0,t1,t2,p0,p1,p2;
390 gwlarson 3.4 int *nset;
391 gwlarson 3.1 FVECT n[3];
392     FVECT avg;
393 gwlarson 3.4 int pt_sides[3][3];
394 gwlarson 3.1
395     {
396 gwlarson 3.4 int below_plane[3],test;
397 gwlarson 3.1
398     SUM_3VEC3(avg,t0,t1,t2);
399     *nset = 0;
400     /* Test vertex v[i] against triangle j*/
401     /* Check if v[i] lies below plane defined by avg of 3 vectors
402     defining triangle
403     */
404    
405     /* test point 0 */
406 gwlarson 3.4 if(DOT(avg,p0) < 0.0)
407 gwlarson 3.1 below_plane[0] = 1;
408     else
409 gwlarson 3.4 below_plane[0] = 0;
410 gwlarson 3.1 /* Test if b[i] lies in or on triangle a */
411 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p0,n,nset,pt_sides[0]);
412 gwlarson 3.1 /* If pts[i] is interior: done */
413     if(!below_plane[0])
414     {
415     if(test == GT_INTERIOR)
416     return(TRUE);
417     }
418     /* Now test point 1*/
419    
420 gwlarson 3.4 if(DOT(avg,p1) < 0.0)
421 gwlarson 3.1 below_plane[1] = 1;
422     else
423     below_plane[1]=0;
424     /* Test if b[i] lies in or on triangle a */
425 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p1,n,nset,pt_sides[1]);
426 gwlarson 3.1 /* If pts[i] is interior: done */
427     if(!below_plane[1])
428     {
429     if(test == GT_INTERIOR)
430     return(TRUE);
431     }
432    
433     /* Now test point 2 */
434 gwlarson 3.4 if(DOT(avg,p2) < 0.0)
435 gwlarson 3.1 below_plane[2] = 1;
436     else
437 gwlarson 3.4 below_plane[2] = 0;
438 gwlarson 3.1 /* Test if b[i] lies in or on triangle a */
439 gwlarson 3.4 test = point_set_in_stri(t0,t1,t2,p2,n,nset,pt_sides[2]);
440 gwlarson 3.1
441     /* If pts[i] is interior: done */
442     if(!below_plane[2])
443     {
444     if(test == GT_INTERIOR)
445     return(TRUE);
446     }
447    
448     /* If all three points below separating plane: trivial reject */
449     if(below_plane[0] && below_plane[1] && below_plane[2])
450     return(FALSE);
451     /* Now check vertices in a against triangle b */
452     return(FALSE);
453     }
454    
455    
456     set_sidedness_tests(t0,t1,t2,p0,p1,p2,test,sides,nset,n)
457     FVECT t0,t1,t2,p0,p1,p2;
458 gwlarson 3.4 int test[3];
459     int sides[3][3];
460     int nset;
461 gwlarson 3.1 FVECT n[3];
462     {
463 gwlarson 3.4 int t;
464 gwlarson 3.1 double d;
465    
466    
467     /* p=0 */
468     test[0] = 0;
469     if(sides[0][0] == GT_INVALID)
470     {
471     if(!NTH_BIT(nset,0))
472     VCROSS(n[0],t1,t0);
473     /* Test the point for sidedness */
474     d = DOT(n[0],p0);
475 gwlarson 3.4 if(d >= 0.0)
476 gwlarson 3.1 SET_NTH_BIT(test[0],0);
477     }
478     else
479     if(sides[0][0] != GT_INTERIOR)
480     SET_NTH_BIT(test[0],0);
481    
482     if(sides[0][1] == GT_INVALID)
483     {
484     if(!NTH_BIT(nset,1))
485     VCROSS(n[1],t2,t1);
486     /* Test the point for sidedness */
487     d = DOT(n[1],p0);
488 gwlarson 3.4 if(d >= 0.0)
489 gwlarson 3.1 SET_NTH_BIT(test[0],1);
490     }
491     else
492     if(sides[0][1] != GT_INTERIOR)
493     SET_NTH_BIT(test[0],1);
494    
495     if(sides[0][2] == GT_INVALID)
496     {
497     if(!NTH_BIT(nset,2))
498     VCROSS(n[2],t0,t2);
499     /* Test the point for sidedness */
500     d = DOT(n[2],p0);
501 gwlarson 3.4 if(d >= 0.0)
502 gwlarson 3.1 SET_NTH_BIT(test[0],2);
503     }
504     else
505     if(sides[0][2] != GT_INTERIOR)
506     SET_NTH_BIT(test[0],2);
507    
508     /* p=1 */
509     test[1] = 0;
510     /* t=0*/
511     if(sides[1][0] == GT_INVALID)
512     {
513     if(!NTH_BIT(nset,0))
514     VCROSS(n[0],t1,t0);
515     /* Test the point for sidedness */
516     d = DOT(n[0],p1);
517 gwlarson 3.4 if(d >= 0.0)
518 gwlarson 3.1 SET_NTH_BIT(test[1],0);
519     }
520     else
521     if(sides[1][0] != GT_INTERIOR)
522     SET_NTH_BIT(test[1],0);
523    
524     /* t=1 */
525     if(sides[1][1] == GT_INVALID)
526     {
527     if(!NTH_BIT(nset,1))
528     VCROSS(n[1],t2,t1);
529     /* Test the point for sidedness */
530     d = DOT(n[1],p1);
531 gwlarson 3.4 if(d >= 0.0)
532 gwlarson 3.1 SET_NTH_BIT(test[1],1);
533     }
534     else
535     if(sides[1][1] != GT_INTERIOR)
536     SET_NTH_BIT(test[1],1);
537    
538     /* t=2 */
539     if(sides[1][2] == GT_INVALID)
540     {
541     if(!NTH_BIT(nset,2))
542     VCROSS(n[2],t0,t2);
543     /* Test the point for sidedness */
544     d = DOT(n[2],p1);
545 gwlarson 3.4 if(d >= 0.0)
546 gwlarson 3.1 SET_NTH_BIT(test[1],2);
547     }
548     else
549     if(sides[1][2] != GT_INTERIOR)
550     SET_NTH_BIT(test[1],2);
551    
552     /* p=2 */
553     test[2] = 0;
554     /* t = 0 */
555     if(sides[2][0] == GT_INVALID)
556     {
557     if(!NTH_BIT(nset,0))
558     VCROSS(n[0],t1,t0);
559     /* Test the point for sidedness */
560     d = DOT(n[0],p2);
561 gwlarson 3.4 if(d >= 0.0)
562 gwlarson 3.1 SET_NTH_BIT(test[2],0);
563     }
564     else
565     if(sides[2][0] != GT_INTERIOR)
566     SET_NTH_BIT(test[2],0);
567     /* t=1 */
568     if(sides[2][1] == GT_INVALID)
569     {
570     if(!NTH_BIT(nset,1))
571     VCROSS(n[1],t2,t1);
572     /* Test the point for sidedness */
573     d = DOT(n[1],p2);
574 gwlarson 3.4 if(d >= 0.0)
575 gwlarson 3.1 SET_NTH_BIT(test[2],1);
576     }
577     else
578     if(sides[2][1] != GT_INTERIOR)
579     SET_NTH_BIT(test[2],1);
580     /* t=2 */
581     if(sides[2][2] == GT_INVALID)
582     {
583     if(!NTH_BIT(nset,2))
584     VCROSS(n[2],t0,t2);
585     /* Test the point for sidedness */
586     d = DOT(n[2],p2);
587 gwlarson 3.4 if(d >= 0.0)
588 gwlarson 3.1 SET_NTH_BIT(test[2],2);
589     }
590     else
591     if(sides[2][2] != GT_INTERIOR)
592     SET_NTH_BIT(test[2],2);
593     }
594    
595    
596     int
597 gwlarson 3.4 stri_intersect(a1,a2,a3,b1,b2,b3)
598 gwlarson 3.1 FVECT a1,a2,a3,b1,b2,b3;
599     {
600 gwlarson 3.4 int which,test,n_set[2];
601     int sides[2][3][3],i,j,inext,jnext;
602     int tests[2][3];
603 gwlarson 3.1 FVECT n[2][3],p,avg[2];
604    
605     /* Test the vertices of triangle a against the pyramid formed by triangle
606     b and the origin. If any vertex of a is interior to triangle b, or
607     if all 3 vertices of a are ON the edges of b,return TRUE. Remember
608     the results of the edge normal and sidedness tests for later.
609     */
610 gwlarson 3.4 if(vertices_in_stri(a1,a2,a3,b1,b2,b3,&(n_set[0]),n[0],avg[0],sides[1]))
611 gwlarson 3.1 return(TRUE);
612    
613 gwlarson 3.4 if(vertices_in_stri(b1,b2,b3,a1,a2,a3,&(n_set[1]),n[1],avg[1],sides[0]))
614 gwlarson 3.1 return(TRUE);
615    
616    
617     set_sidedness_tests(b1,b2,b3,a1,a2,a3,tests[0],sides[0],n_set[1],n[1]);
618     if(tests[0][0]&tests[0][1]&tests[0][2])
619     return(FALSE);
620    
621     set_sidedness_tests(a1,a2,a3,b1,b2,b3,tests[1],sides[1],n_set[0],n[0]);
622     if(tests[1][0]&tests[1][1]&tests[1][2])
623     return(FALSE);
624    
625     for(j=0; j < 3;j++)
626     {
627     jnext = (j+1)%3;
628     /* IF edge b doesnt cross any great circles of a, punt */
629     if(tests[1][j] & tests[1][jnext])
630     continue;
631     for(i=0;i<3;i++)
632     {
633     inext = (i+1)%3;
634     /* IF edge a doesnt cross any great circles of b, punt */
635     if(tests[0][i] & tests[0][inext])
636     continue;
637     /* Now find the great circles that cross and test */
638     if((NTH_BIT(tests[0][i],j)^(NTH_BIT(tests[0][inext],j)))
639     && (NTH_BIT(tests[1][j],i)^NTH_BIT(tests[1][jnext],i)))
640     {
641     VCROSS(p,n[0][i],n[1][j]);
642    
643     /* If zero cp= done */
644     if(ZERO_VEC3(p))
645     continue;
646     /* check above both planes */
647     if(DOT(avg[0],p) < 0 || DOT(avg[1],p) < 0)
648     {
649     NEGATE_VEC3(p);
650     if(DOT(avg[0],p) < 0 || DOT(avg[1],p) < 0)
651     continue;
652     }
653     return(TRUE);
654     }
655     }
656     }
657     return(FALSE);
658     }
659    
660     int
661 gwlarson 3.4 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
662 gwlarson 3.1 FVECT orig,dir;
663     FVECT v0,v1,v2;
664     FVECT pt;
665     {
666     FVECT p0,p1,p2,p,n;
667     double pd;
668 gwlarson 3.4 int type;
669    
670 gwlarson 3.5 VSUB(p0,v0,orig);
671     VSUB(p1,v1,orig);
672     VSUB(p2,v2,orig);
673    
674 gwlarson 3.4 if(point_in_stri(p0,p1,p2,dir))
675 gwlarson 3.1 {
676     /* Intersect the ray with the triangle plane */
677     tri_plane_equation(v0,v1,v2,n,&pd,FALSE);
678 gwlarson 3.4 return(intersect_ray_plane(orig,dir,n,pd,NULL,pt));
679 gwlarson 3.1 }
680 gwlarson 3.4 return(FALSE);
681 gwlarson 3.1 }
682    
683    
684     calculate_view_frustum(vp,hv,vv,horiz,vert,near,far,fnear,ffar)
685     FVECT vp,hv,vv;
686     double horiz,vert,near,far;
687     FVECT fnear[4],ffar[4];
688     {
689     double height,width;
690     FVECT t,nhv,nvv,ndv;
691     double w2,h2;
692     /* Calculate the x and y dimensions of the near face */
693     /* hv and vv are the horizontal and vertical vectors in the
694     view frame-the magnitude is the dimension of the front frustum
695     face at z =1
696     */
697     VCOPY(nhv,hv);
698     VCOPY(nvv,vv);
699     w2 = normalize(nhv);
700     h2 = normalize(nvv);
701     /* Use similar triangles to calculate the dimensions at z=near */
702     width = near*0.5*w2;
703     height = near*0.5*h2;
704    
705     VCROSS(ndv,nvv,nhv);
706     /* Calculate the world space points corresponding to the 4 corners
707     of the front face of the view frustum
708     */
709     fnear[0][0] = width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0] ;
710     fnear[0][1] = width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
711     fnear[0][2] = width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
712     fnear[1][0] = -width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0];
713     fnear[1][1] = -width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
714     fnear[1][2] = -width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
715     fnear[2][0] = -width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
716     fnear[2][1] = -width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
717     fnear[2][2] = -width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
718     fnear[3][0] = width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
719     fnear[3][1] = width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
720     fnear[3][2] = width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
721    
722     /* Now do the far face */
723     width = far*0.5*w2;
724     height = far*0.5*h2;
725     ffar[0][0] = width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
726     ffar[0][1] = width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
727     ffar[0][2] = width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
728     ffar[1][0] = -width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
729     ffar[1][1] = -width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
730     ffar[1][2] = -width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
731     ffar[2][0] = -width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
732     ffar[2][1] = -width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
733     ffar[2][2] = -width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
734     ffar[3][0] = width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
735     ffar[3][1] = width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
736     ffar[3][2] = width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
737     }
738    
739 gwlarson 3.6 int
740     max_index(v,r)
741     FVECT v;
742     double *r;
743     {
744     double p[3];
745     int i;
746 gwlarson 3.1
747 gwlarson 3.6 p[0] = fabs(v[0]);
748     p[1] = fabs(v[1]);
749     p[2] = fabs(v[2]);
750     i = (p[0]>=p[1])?((p[0]>=p[2])?0:2):((p[1]>=p[2])?1:2);
751     if(r)
752     *r = p[i];
753     return(i);
754     }
755 gwlarson 3.1
756 gwlarson 3.6 int
757     closest_point_in_tri(p0,p1,p2,p,p0id,p1id,p2id)
758     FVECT p0,p1,p2,p;
759     int p0id,p1id,p2id;
760     {
761     double d,d1;
762     int i;
763    
764     d = DIST_SQ(p,p0);
765     d1 = DIST_SQ(p,p1);
766     if(d < d1)
767     {
768     d1 = DIST_SQ(p,p2);
769     i = (d1 < d)?p2id:p0id;
770     }
771     else
772     {
773     d = DIST_SQ(p,p2);
774     i = (d < d1)? p2id:p1id;
775     }
776     return(i);
777     }
778 gwlarson 3.1
779 gwlarson 3.6
780 gwlarson 3.1 int
781 gwlarson 3.4 sedge_intersect(a0,a1,b0,b1)
782 gwlarson 3.1 FVECT a0,a1,b0,b1;
783     {
784     FVECT na,nb,avga,avgb,p;
785     double d;
786     int sb0,sb1,sa0,sa1;
787    
788     /* First test if edge b straddles great circle of a */
789     VCROSS(na,a0,a1);
790     d = DOT(na,b0);
791     sb0 = ZERO(d)?0:(d<0)? -1: 1;
792     d = DOT(na,b1);
793     sb1 = ZERO(d)?0:(d<0)? -1: 1;
794     /* edge b entirely on one side of great circle a: edges cannot intersect*/
795     if(sb0*sb1 > 0)
796     return(FALSE);
797     /* test if edge a straddles great circle of b */
798     VCROSS(nb,b0,b1);
799     d = DOT(nb,a0);
800     sa0 = ZERO(d)?0:(d<0)? -1: 1;
801     d = DOT(nb,a1);
802     sa1 = ZERO(d)?0:(d<0)? -1: 1;
803     /* edge a entirely on one side of great circle b: edges cannot intersect*/
804     if(sa0*sa1 > 0)
805     return(FALSE);
806    
807     /* Find one of intersection points of the great circles */
808     VCROSS(p,na,nb);
809     /* If they lie on same great circle: call an intersection */
810     if(ZERO_VEC3(p))
811     return(TRUE);
812    
813     VADD(avga,a0,a1);
814     VADD(avgb,b0,b1);
815     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
816     {
817     NEGATE_VEC3(p);
818     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
819     return(FALSE);
820     }
821     if((!sb0 || !sb1) && (!sa0 || !sa1))
822     return(FALSE);
823     return(TRUE);
824     }
825 gwlarson 3.2
826    
827    
828     /* Find the normalized barycentric coordinates of p relative to
829     * triangle v0,v1,v2. Return result in coord
830     */
831     bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
832     double x1,y1,x2,y2,x3,y3;
833     double px,py;
834     double coord[3];
835     {
836     double a;
837    
838     a = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
839     coord[0] = ((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py)) / a;
840     coord[1] = ((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py)) / a;
841 gwlarson 3.6 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
842 gwlarson 3.2
843     }
844    
845 gwlarson 3.4 bary_ith_child(coord,i)
846     double coord[3];
847     int i;
848     {
849    
850     switch(i){
851     case 0:
852     /* update bary for child */
853     coord[0] = 2.0*coord[0]- 1.0;
854     coord[1] *= 2.0;
855     coord[2] *= 2.0;
856     break;
857     case 1:
858     coord[0] *= 2.0;
859     coord[1] = 2.0*coord[1]- 1.0;
860     coord[2] *= 2.0;
861     break;
862     case 2:
863     coord[0] *= 2.0;
864     coord[1] *= 2.0;
865     coord[2] = 2.0*coord[2]- 1.0;
866     break;
867     case 3:
868     coord[0] = 1.0 - 2.0*coord[0];
869     coord[1] = 1.0 - 2.0*coord[1];
870     coord[2] = 1.0 - 2.0*coord[2];
871     break;
872     #ifdef DEBUG
873     default:
874     eputs("bary_ith_child():Invalid child\n");
875     break;
876     #endif
877     }
878     }
879    
880    
881 gwlarson 3.2 int
882 gwlarson 3.4 bary_child(coord)
883 gwlarson 3.2 double coord[3];
884     {
885     int i;
886    
887     if(coord[0] > 0.5)
888     {
889     /* update bary for child */
890     coord[0] = 2.0*coord[0]- 1.0;
891     coord[1] *= 2.0;
892     coord[2] *= 2.0;
893     return(0);
894     }
895     else
896     if(coord[1] > 0.5)
897     {
898     coord[0] *= 2.0;
899     coord[1] = 2.0*coord[1]- 1.0;
900     coord[2] *= 2.0;
901     return(1);
902     }
903     else
904     if(coord[2] > 0.5)
905     {
906     coord[0] *= 2.0;
907     coord[1] *= 2.0;
908     coord[2] = 2.0*coord[2]- 1.0;
909     return(2);
910     }
911     else
912     {
913     coord[0] = 1.0 - 2.0*coord[0];
914     coord[1] = 1.0 - 2.0*coord[1];
915     coord[2] = 1.0 - 2.0*coord[2];
916     return(3);
917     }
918     }
919    
920 gwlarson 3.4 /* Coord was the ith child of the parent: set the coordinate
921     relative to the parent
922     */
923     bary_parent(coord,i)
924     double coord[3];
925     int i;
926     {
927    
928     switch(i) {
929     case 0:
930     /* update bary for child */
931     coord[0] = coord[0]*0.5 + 0.5;
932     coord[1] *= 0.5;
933     coord[2] *= 0.5;
934     break;
935     case 1:
936     coord[0] *= 0.5;
937     coord[1] = coord[1]*0.5 + 0.5;
938     coord[2] *= 0.5;
939     break;
940    
941     case 2:
942     coord[0] *= 0.5;
943     coord[1] *= 0.5;
944     coord[2] = coord[2]*0.5 + 0.5;
945     break;
946    
947     case 3:
948     coord[0] = 0.5 - 0.5*coord[0];
949     coord[1] = 0.5 - 0.5*coord[1];
950     coord[2] = 0.5 - 0.5*coord[2];
951     break;
952     #ifdef DEBUG
953     default:
954     eputs("bary_parent():Invalid child\n");
955     break;
956     #endif
957     }
958     }
959    
960     bary_from_child(coord,child,next)
961     double coord[3];
962     int child,next;
963     {
964     #ifdef DEBUG
965     if(child <0 || child > 3)
966     {
967     eputs("bary_from_child():Invalid child\n");
968     return;
969     }
970     if(next <0 || next > 3)
971     {
972     eputs("bary_from_child():Invalid next\n");
973     return;
974     }
975     #endif
976     if(next == child)
977     return;
978    
979     switch(child){
980     case 0:
981     switch(next){
982     case 1:
983     coord[0] += 1.0;
984     coord[1] -= 1.0;
985     break;
986     case 2:
987     coord[0] += 1.0;
988     coord[2] -= 1.0;
989     break;
990     case 3:
991     coord[0] *= -1.0;
992     coord[1] = 1 - coord[1];
993     coord[2] = 1 - coord[2];
994     break;
995    
996     }
997     break;
998     case 1:
999     switch(next){
1000     case 0:
1001     coord[0] -= 1.0;
1002     coord[1] += 1.0;
1003     break;
1004     case 2:
1005     coord[1] += 1.0;
1006     coord[2] -= 1.0;
1007     break;
1008     case 3:
1009     coord[0] = 1 - coord[0];
1010     coord[1] *= -1.0;
1011     coord[2] = 1 - coord[2];
1012     break;
1013     }
1014     break;
1015     case 2:
1016     switch(next){
1017     case 0:
1018     coord[0] -= 1.0;
1019     coord[2] += 1.0;
1020     break;
1021     case 1:
1022     coord[1] -= 1.0;
1023     coord[2] += 1.0;
1024     break;
1025     case 3:
1026     coord[0] = 1 - coord[0];
1027     coord[1] = 1 - coord[1];
1028     coord[2] *= -1.0;
1029     break;
1030     }
1031     break;
1032     case 3:
1033     switch(next){
1034     case 0:
1035     coord[0] *= -1.0;
1036     coord[1] = 1 - coord[1];
1037     coord[2] = 1 - coord[2];
1038     break;
1039     case 1:
1040     coord[0] = 1 - coord[0];
1041     coord[1] *= -1.0;
1042     coord[2] = 1 - coord[2];
1043     break;
1044     case 2:
1045     coord[0] = 1 - coord[0];
1046     coord[1] = 1 - coord[1];
1047     coord[2] *= -1.0;
1048     break;
1049     }
1050     break;
1051     }
1052     }
1053    
1054 gwlarson 3.6
1055     baryi_parent(coord,i)
1056     BCOORD coord[3];
1057     int i;
1058 gwlarson 3.2 {
1059    
1060 gwlarson 3.6 switch(i) {
1061     case 0:
1062     /* update bary for child */
1063     coord[0] = (coord[0] >> 1) + MAXBCOORD2;
1064     coord[1] >>= 1;
1065     coord[2] >>= 1;
1066     break;
1067     case 1:
1068     coord[0] >>= 1;
1069     coord[1] = (coord[1] >> 1) + MAXBCOORD2;
1070     coord[2] >>= 1;
1071     break;
1072    
1073     case 2:
1074     coord[0] >>= 1;
1075     coord[1] >>= 1;
1076     coord[2] = (coord[2] >> 1) + MAXBCOORD2;
1077     break;
1078    
1079     case 3:
1080     coord[0] = MAXBCOORD2 - (coord[0] >> 1);
1081     coord[1] = MAXBCOORD2 - (coord[1] >> 1);
1082     coord[2] = MAXBCOORD2 - (coord[2] >> 1);
1083     break;
1084     #ifdef DEBUG
1085     default:
1086     eputs("baryi_parent():Invalid child\n");
1087     break;
1088     #endif
1089     }
1090 gwlarson 3.2 }
1091    
1092 gwlarson 3.6 baryi_from_child(coord,child,next)
1093     BCOORD coord[3];
1094     int child,next;
1095     {
1096     #ifdef DEBUG
1097     if(child <0 || child > 3)
1098     {
1099     eputs("baryi_from_child():Invalid child\n");
1100     return;
1101     }
1102     if(next <0 || next > 3)
1103     {
1104     eputs("baryi_from_child():Invalid next\n");
1105     return;
1106     }
1107     #endif
1108     if(next == child)
1109     return;
1110    
1111     switch(child){
1112     case 0:
1113     coord[0] = 0;
1114     coord[1] = MAXBCOORD - coord[1];
1115     coord[2] = MAXBCOORD - coord[2];
1116     break;
1117     case 1:
1118     coord[0] = MAXBCOORD - coord[0];
1119     coord[1] = 0;
1120     coord[2] = MAXBCOORD - coord[2];
1121     break;
1122     case 2:
1123     coord[0] = MAXBCOORD - coord[0];
1124     coord[1] = MAXBCOORD - coord[1];
1125     coord[2] = 0;
1126     break;
1127     case 3:
1128     switch(next){
1129     case 0:
1130     coord[0] = 0;
1131     coord[1] = MAXBCOORD - coord[1];
1132     coord[2] = MAXBCOORD - coord[2];
1133     break;
1134     case 1:
1135     coord[0] = MAXBCOORD - coord[0];
1136     coord[1] = 0;
1137     coord[2] = MAXBCOORD - coord[2];
1138     break;
1139     case 2:
1140     coord[0] = MAXBCOORD - coord[0];
1141     coord[1] = MAXBCOORD - coord[1];
1142     coord[2] = 0;
1143     break;
1144     }
1145     break;
1146     }
1147     }
1148    
1149 gwlarson 3.4 int
1150 gwlarson 3.6 baryi_child(coord)
1151     BCOORD coord[3];
1152 gwlarson 3.4 {
1153 gwlarson 3.6 int i;
1154    
1155     if(coord[0] > MAXBCOORD2)
1156     {
1157     /* update bary for child */
1158     coord[0] = (coord[0]<< 1) - MAXBCOORD;
1159     coord[1] <<= 1;
1160     coord[2] <<= 1;
1161     return(0);
1162     }
1163     else
1164     if(coord[1] > MAXBCOORD2)
1165 gwlarson 3.4 {
1166 gwlarson 3.6 coord[0] <<= 1;
1167     coord[1] = (coord[1] << 1) - MAXBCOORD;
1168     coord[2] <<= 1;
1169     return(1);
1170 gwlarson 3.4 }
1171     else
1172 gwlarson 3.6 if(coord[2] > MAXBCOORD2)
1173     {
1174     coord[0] <<= 1;
1175     coord[1] <<= 1;
1176     coord[2] = (coord[2] << 1) - MAXBCOORD;
1177     return(2);
1178     }
1179     else
1180     {
1181     coord[0] = MAXBCOORD - (coord[0] << 1);
1182     coord[1] = MAXBCOORD - (coord[1] << 1);
1183     coord[2] = MAXBCOORD - (coord[2] << 1);
1184     return(3);
1185     }
1186     }
1187    
1188     /* convert barycentric coordinate b in [-eps,1+eps] to [0,MAXLONG],
1189     dir unbounded to [-MAXLONG,MAXLONG]
1190     */
1191     bary_dtol(b,db,bi,dbi,t)
1192     double b[3],db[3][3];
1193     BCOORD bi[3];
1194     BDIR dbi[3][3];
1195     TINT t[3];
1196     {
1197     int i,id,j;
1198     double d;
1199    
1200     for(i=0; i < 2;i++)
1201     {
1202     if(b[i] <= 0.0)
1203 gwlarson 3.4 {
1204 gwlarson 3.6 bi[i]= 0;
1205 gwlarson 3.4 }
1206 gwlarson 3.6 else
1207     if(b[i] >= 1.0)
1208     {
1209     bi[i]= MAXBCOORD;
1210     }
1211     else
1212     bi[i] = (BCOORD)(b[i]*MAXBCOORD);
1213     }
1214     bi[2] = MAXBCOORD - bi[0] - bi[1];
1215    
1216     if(bi[2] < 0)
1217     {
1218     bi[2] = 0;
1219     bi[1] = MAXBCOORD - bi[0];
1220     }
1221     for(j=0; j< 3; j++)
1222     {
1223     if(t[j]==0)
1224     continue;
1225     if(t[j] == HUGET)
1226     max_index(db[j],&d);
1227     for(i=0; i< 3; i++)
1228     if(t[j] != HUGET)
1229     dbi[j][i] = (BDIR)(db[j][i]*MAXBDIR);
1230     else
1231     dbi[j][i] = (BDIR)(db[j][i]/d*MAXBDIR);
1232     }
1233 gwlarson 3.4 }
1234 gwlarson 3.6
1235    
1236 gwlarson 3.2
1237    
1238    
1239    
1240    
1241    
1242 gwlarson 3.1