ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.5
Committed: Mon Sep 14 10:33:46 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.4: +4 -82 lines
Log Message:
optimized normalizing calls and bug fix in triangle counting

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    
740    
741    
742     int
743 gwlarson 3.4 sedge_intersect(a0,a1,b0,b1)
744 gwlarson 3.1 FVECT a0,a1,b0,b1;
745     {
746     FVECT na,nb,avga,avgb,p;
747     double d;
748     int sb0,sb1,sa0,sa1;
749    
750     /* First test if edge b straddles great circle of a */
751     VCROSS(na,a0,a1);
752     d = DOT(na,b0);
753     sb0 = ZERO(d)?0:(d<0)? -1: 1;
754     d = DOT(na,b1);
755     sb1 = ZERO(d)?0:(d<0)? -1: 1;
756     /* edge b entirely on one side of great circle a: edges cannot intersect*/
757     if(sb0*sb1 > 0)
758     return(FALSE);
759     /* test if edge a straddles great circle of b */
760     VCROSS(nb,b0,b1);
761     d = DOT(nb,a0);
762     sa0 = ZERO(d)?0:(d<0)? -1: 1;
763     d = DOT(nb,a1);
764     sa1 = ZERO(d)?0:(d<0)? -1: 1;
765     /* edge a entirely on one side of great circle b: edges cannot intersect*/
766     if(sa0*sa1 > 0)
767     return(FALSE);
768    
769     /* Find one of intersection points of the great circles */
770     VCROSS(p,na,nb);
771     /* If they lie on same great circle: call an intersection */
772     if(ZERO_VEC3(p))
773     return(TRUE);
774    
775     VADD(avga,a0,a1);
776     VADD(avgb,b0,b1);
777     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
778     {
779     NEGATE_VEC3(p);
780     if(DOT(avga,p) < 0 || DOT(avgb,p) < 0)
781     return(FALSE);
782     }
783     if((!sb0 || !sb1) && (!sa0 || !sa1))
784     return(FALSE);
785     return(TRUE);
786     }
787 gwlarson 3.2
788    
789    
790     /* Find the normalized barycentric coordinates of p relative to
791     * triangle v0,v1,v2. Return result in coord
792     */
793     bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
794     double x1,y1,x2,y2,x3,y3;
795     double px,py;
796     double coord[3];
797     {
798     double a;
799    
800     a = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
801     coord[0] = ((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py)) / a;
802     coord[1] = ((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py)) / a;
803     coord[2] = 1.0 - coord[0] - coord[1];
804    
805     }
806    
807 gwlarson 3.4 bary_ith_child(coord,i)
808     double coord[3];
809     int i;
810     {
811    
812     switch(i){
813     case 0:
814     /* update bary for child */
815     coord[0] = 2.0*coord[0]- 1.0;
816     coord[1] *= 2.0;
817     coord[2] *= 2.0;
818     break;
819     case 1:
820     coord[0] *= 2.0;
821     coord[1] = 2.0*coord[1]- 1.0;
822     coord[2] *= 2.0;
823     break;
824     case 2:
825     coord[0] *= 2.0;
826     coord[1] *= 2.0;
827     coord[2] = 2.0*coord[2]- 1.0;
828     break;
829     case 3:
830     coord[0] = 1.0 - 2.0*coord[0];
831     coord[1] = 1.0 - 2.0*coord[1];
832     coord[2] = 1.0 - 2.0*coord[2];
833     break;
834     #ifdef DEBUG
835     default:
836     eputs("bary_ith_child():Invalid child\n");
837     break;
838     #endif
839     }
840     }
841    
842    
843 gwlarson 3.2 int
844 gwlarson 3.4 bary_child(coord)
845 gwlarson 3.2 double coord[3];
846     {
847     int i;
848    
849     if(coord[0] > 0.5)
850     {
851     /* update bary for child */
852     coord[0] = 2.0*coord[0]- 1.0;
853     coord[1] *= 2.0;
854     coord[2] *= 2.0;
855     return(0);
856     }
857     else
858     if(coord[1] > 0.5)
859     {
860     coord[0] *= 2.0;
861     coord[1] = 2.0*coord[1]- 1.0;
862     coord[2] *= 2.0;
863     return(1);
864     }
865     else
866     if(coord[2] > 0.5)
867     {
868     coord[0] *= 2.0;
869     coord[1] *= 2.0;
870     coord[2] = 2.0*coord[2]- 1.0;
871     return(2);
872     }
873     else
874     {
875     coord[0] = 1.0 - 2.0*coord[0];
876     coord[1] = 1.0 - 2.0*coord[1];
877     coord[2] = 1.0 - 2.0*coord[2];
878     return(3);
879     }
880     }
881    
882 gwlarson 3.4 /* Coord was the ith child of the parent: set the coordinate
883     relative to the parent
884     */
885     bary_parent(coord,i)
886     double coord[3];
887     int i;
888     {
889    
890     switch(i) {
891     case 0:
892     /* update bary for child */
893     coord[0] = coord[0]*0.5 + 0.5;
894     coord[1] *= 0.5;
895     coord[2] *= 0.5;
896     break;
897     case 1:
898     coord[0] *= 0.5;
899     coord[1] = coord[1]*0.5 + 0.5;
900     coord[2] *= 0.5;
901     break;
902    
903     case 2:
904     coord[0] *= 0.5;
905     coord[1] *= 0.5;
906     coord[2] = coord[2]*0.5 + 0.5;
907     break;
908    
909     case 3:
910     coord[0] = 0.5 - 0.5*coord[0];
911     coord[1] = 0.5 - 0.5*coord[1];
912     coord[2] = 0.5 - 0.5*coord[2];
913     break;
914     #ifdef DEBUG
915     default:
916     eputs("bary_parent():Invalid child\n");
917     break;
918     #endif
919     }
920     }
921    
922     bary_from_child(coord,child,next)
923     double coord[3];
924     int child,next;
925     {
926     #ifdef DEBUG
927     if(child <0 || child > 3)
928     {
929     eputs("bary_from_child():Invalid child\n");
930     return;
931     }
932     if(next <0 || next > 3)
933     {
934     eputs("bary_from_child():Invalid next\n");
935     return;
936     }
937     #endif
938     if(next == child)
939     return;
940    
941     switch(child){
942     case 0:
943     switch(next){
944     case 1:
945     coord[0] += 1.0;
946     coord[1] -= 1.0;
947     break;
948     case 2:
949     coord[0] += 1.0;
950     coord[2] -= 1.0;
951     break;
952     case 3:
953     coord[0] *= -1.0;
954     coord[1] = 1 - coord[1];
955     coord[2] = 1 - coord[2];
956     break;
957    
958     }
959     break;
960     case 1:
961     switch(next){
962     case 0:
963     coord[0] -= 1.0;
964     coord[1] += 1.0;
965     break;
966     case 2:
967     coord[1] += 1.0;
968     coord[2] -= 1.0;
969     break;
970     case 3:
971     coord[0] = 1 - coord[0];
972     coord[1] *= -1.0;
973     coord[2] = 1 - coord[2];
974     break;
975     }
976     break;
977     case 2:
978     switch(next){
979     case 0:
980     coord[0] -= 1.0;
981     coord[2] += 1.0;
982     break;
983     case 1:
984     coord[1] -= 1.0;
985     coord[2] += 1.0;
986     break;
987     case 3:
988     coord[0] = 1 - coord[0];
989     coord[1] = 1 - coord[1];
990     coord[2] *= -1.0;
991     break;
992     }
993     break;
994     case 3:
995     switch(next){
996     case 0:
997     coord[0] *= -1.0;
998     coord[1] = 1 - coord[1];
999     coord[2] = 1 - coord[2];
1000     break;
1001     case 1:
1002     coord[0] = 1 - coord[0];
1003     coord[1] *= -1.0;
1004     coord[2] = 1 - coord[2];
1005     break;
1006     case 2:
1007     coord[0] = 1 - coord[0];
1008     coord[1] = 1 - coord[1];
1009     coord[2] *= -1.0;
1010     break;
1011     }
1012     break;
1013     }
1014     }
1015    
1016 gwlarson 3.2 int
1017     max_index(v)
1018     FVECT v;
1019     {
1020     double a,b,c;
1021     int i;
1022    
1023     a = fabs(v[0]);
1024     b = fabs(v[1]);
1025     c = fabs(v[2]);
1026     i = (a>=b)?((a>=c)?0:2):((b>=c)?1:2);
1027     return(i);
1028     }
1029    
1030 gwlarson 3.4 int
1031     closest_point_in_tri(p0,p1,p2,p,p0id,p1id,p2id)
1032     FVECT p0,p1,p2,p;
1033     int p0id,p1id,p2id;
1034     {
1035     double d,d1;
1036     int i;
1037    
1038     d = DIST_SQ(p,p0);
1039     d1 = DIST_SQ(p,p1);
1040     if(d < d1)
1041     {
1042     d1 = DIST_SQ(p,p2);
1043     i = (d1 < d)?p2id:p0id;
1044     }
1045     else
1046     {
1047     d = DIST_SQ(p,p2);
1048     i = (d < d1)? p2id:p1id;
1049     }
1050     return(i);
1051     }
1052 gwlarson 3.2
1053    
1054    
1055    
1056    
1057    
1058 gwlarson 3.1