ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.7
Committed: Tue Oct 6 18:16:53 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.6: +270 -52 lines
Log Message:
new triangulate routine
added smTestSample to check for occlusion
added frustum culling before rebuild
changed base quadtree to use octahedron and created new point locate
added "sample active" flags and implemented LRU replacement
started handling case of too many triangles
set sizes are now unbounded
changed all quadtree pointers to quadtrees

File Contents

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