ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.8
Committed: Wed Nov 11 12:05:38 1998 UTC (25 years, 5 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.7: +42 -43 lines
Log Message:
new triangulation code
changed triangle vertex order to CCW
changed numbering of triangle neighbors to match quadtree
fixed tone-mapping bug
removed errant printf() statements
redid logic for adding and testing samples with new epsilon

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