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

# 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 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 if(DOT(cp,v1) < 0.0)
43 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 int norm;
57 {
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 int norm;
87 {
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 /* 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 int
128 intersect_vector_plane(v,plane_n,plane_d,tptr,r)
129 FVECT v,plane_n;
130 double plane_d;
131 double *tptr;
132 FVECT r;
133 {
134 double t,d;
135 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 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 if(tptr)
165 *tptr = t;
166 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 /* 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 /* Solve for t: */
188 t = -(DOT(plane_n,orig) + plane_d)/(DOT(plane_n,dir));
189 if(t < 0)
190 hit = 0;
191 else
192 hit = 1;
193
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 else
228 hit = 1;
229
230 VSUM(r,e0,d,t);
231
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 /* NOTE: check this: does sideness check?*/
261 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 point_set_in_stri(v0,v1,v2,p,n,nset,sides)
294 FVECT v0,v1,v2,p;
295 FVECT n[3];
296 int *nset;
297 int sides[3];
298
299 {
300 double d;
301 /* 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 if(d > 0.0)
311 {
312 sides[0] = GT_OUT;
313 sides[1] = sides[2] = GT_INVALID;
314 return(FALSE);
315 }
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 if(d > 0.0)
328 {
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 if(d > 0.0)
344 {
345 sides[2] = GT_OUT;
346 return(FALSE);
347 }
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 point_in_stri(v0,v1,v2,p)
359 FVECT v0,v1,v2,p;
360 {
361 double d;
362 FVECT n;
363
364 VCROSS(n,v1,v0);
365 /* Test the point for sidedness */
366 d = DOT(n,p);
367 if(d > 0.0)
368 return(FALSE);
369
370 /* Test next edge */
371 VCROSS(n,v2,v1);
372 /* Test the point for sidedness */
373 d = DOT(n,p);
374 if(d > 0.0)
375 return(FALSE);
376
377 /* Test next edge */
378 VCROSS(n,v0,v2);
379 /* Test the point for sidedness */
380 d = DOT(n,p);
381 if(d > 0.0)
382 return(FALSE);
383 /* Must be interior to the pyramid */
384 return(GT_INTERIOR);
385 }
386
387 int
388 vertices_in_stri(t0,t1,t2,p0,p1,p2,nset,n,avg,pt_sides)
389 FVECT t0,t1,t2,p0,p1,p2;
390 int *nset;
391 FVECT n[3];
392 FVECT avg;
393 int pt_sides[3][3];
394
395 {
396 int below_plane[3],test;
397
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 if(DOT(avg,p0) < 0.0)
407 below_plane[0] = 1;
408 else
409 below_plane[0] = 0;
410 /* Test if b[i] lies in or on triangle a */
411 test = point_set_in_stri(t0,t1,t2,p0,n,nset,pt_sides[0]);
412 /* 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 if(DOT(avg,p1) < 0.0)
421 below_plane[1] = 1;
422 else
423 below_plane[1]=0;
424 /* Test if b[i] lies in or on triangle a */
425 test = point_set_in_stri(t0,t1,t2,p1,n,nset,pt_sides[1]);
426 /* 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 if(DOT(avg,p2) < 0.0)
435 below_plane[2] = 1;
436 else
437 below_plane[2] = 0;
438 /* Test if b[i] lies in or on triangle a */
439 test = point_set_in_stri(t0,t1,t2,p2,n,nset,pt_sides[2]);
440
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 int test[3];
459 int sides[3][3];
460 int nset;
461 FVECT n[3];
462 {
463 int t;
464 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 if(d >= 0.0)
476 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 if(d >= 0.0)
489 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 if(d >= 0.0)
502 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 if(d >= 0.0)
518 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 if(d >= 0.0)
532 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 if(d >= 0.0)
546 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 if(d >= 0.0)
562 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 if(d >= 0.0)
575 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 if(d >= 0.0)
588 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 stri_intersect(a1,a2,a3,b1,b2,b3)
598 FVECT a1,a2,a3,b1,b2,b3;
599 {
600 int which,test,n_set[2];
601 int sides[2][3][3],i,j,inext,jnext;
602 int tests[2][3];
603 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 if(vertices_in_stri(a1,a2,a3,b1,b2,b3,&(n_set[0]),n[0],avg[0],sides[1]))
611 return(TRUE);
612
613 if(vertices_in_stri(b1,b2,b3,a1,a2,a3,&(n_set[1]),n[1],avg[1],sides[0]))
614 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 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
662 FVECT orig,dir;
663 FVECT v0,v1,v2;
664 FVECT pt;
665 {
666 FVECT p0,p1,p2,p,n;
667 double pd;
668 int type;
669
670 VSUB(p0,v0,orig);
671 VSUB(p1,v1,orig);
672 VSUB(p2,v2,orig);
673
674 if(point_in_stri(p0,p1,p2,dir))
675 {
676 /* Intersect the ray with the triangle plane */
677 tri_plane_equation(v0,v1,v2,n,&pd,FALSE);
678 return(intersect_ray_plane(orig,dir,n,pd,NULL,pt));
679 }
680 return(FALSE);
681 }
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 int
740 max_index(v,r)
741 FVECT v;
742 double *r;
743 {
744 double p[3];
745 int i;
746
747 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
756 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
779
780 int
781 sedge_intersect(a0,a1,b0,b1)
782 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
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 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
842
843 }
844
845 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 int
882 bary_child(coord)
883 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 /* 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
1055 baryi_parent(coord,i)
1056 BCOORD coord[3];
1057 int i;
1058 {
1059
1060 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 }
1091
1092 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 int
1150 baryi_child(coord)
1151 BCOORD coord[3];
1152 {
1153 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 {
1166 coord[0] <<= 1;
1167 coord[1] = (coord[1] << 1) - MAXBCOORD;
1168 coord[2] <<= 1;
1169 return(1);
1170 }
1171 else
1172 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 {
1204 bi[i]= 0;
1205 }
1206 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 }
1234
1235
1236
1237
1238
1239
1240
1241
1242