ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_geom.c
Revision: 3.12
Committed: Thu Jun 10 15:22:22 1999 UTC (24 years, 10 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.11: +66 -321 lines
Log Message:
Implemented sample quadtree in place of triangle quadtree
Made geometric predicates more robust
Added #define LORES which utilizes a single precision floating point
  sample array, the default is a double sample array
Added topology DEBUG commands (for DEBUG > 1)
Made code optimizations

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 double dp,dp1;
40 int test,test1;
41 FVECT nv0,nv1,nv2;
42 FVECT cp01,cp12,cp;
43
44 /* test sign of (v0Xv1)X(v1Xv2). v1 */
45 /* un-Simplified: */
46 VCOPY(nv0,v0);
47 normalize(nv0);
48 VCOPY(nv1,v1);
49 normalize(nv1);
50 VCOPY(nv2,v2);
51 normalize(nv2);
52
53 VCROSS(cp01,nv0,nv1);
54 VCROSS(cp12,nv1,nv2);
55 VCROSS(cp,cp01,cp12);
56 normalize(cp);
57 dp1 = DOT(cp,nv1);
58 if(dp1 <= 1e-8 || dp1 >= (1-1e-8)) /* Test if on other side,or colinear*/
59 test1 = FALSE;
60 else
61 test1 = TRUE;
62
63 dp = nv0[2]*nv1[0]*nv2[1] - nv0[2]*nv1[1]*nv2[0] - nv0[0]*nv1[2]*nv2[1]
64 + nv0[0]*nv1[1]*nv2[2] + nv0[1]*nv1[2]*nv2[0] - nv0[1]*nv1[0]*nv2[2];
65
66 if(dp <= 1e-8 || dp1 >= (1-1e-8))
67 test = FALSE;
68 else
69 test = TRUE;
70
71 if(test != test1)
72 fprintf(stderr,"test %f simplified %f\n",dp1,dp);
73 return(test1);
74 }
75
76 /* calculates the normal of a face contour using Newell's formula. e
77
78 a = SUMi (yi - yi+1)(zi + zi+1);
79 b = SUMi (zi - zi+1)(xi + xi+1)
80 c = SUMi (xi - xi+1)(yi + yi+1)
81 */
82 double
83 tri_normal(v0,v1,v2,n,norm)
84 FVECT v0,v1,v2,n;
85 int norm;
86 {
87 double mag;
88
89 n[0] = (v0[2] + v1[2]) * (v0[1] - v1[1]) +
90 (v1[2] + v2[2]) * (v1[1] - v2[1]) +
91 (v2[2] + v0[2]) * (v2[1] - v0[1]);
92
93 n[1] = (v0[2] - v1[2]) * (v0[0] + v1[0]) +
94 (v1[2] - v2[2]) * (v1[0] + v2[0]) +
95 (v2[2] - v0[2]) * (v2[0] + v0[0]);
96
97 n[2] = (v0[1] + v1[1]) * (v0[0] - v1[0]) +
98 (v1[1] + v2[1]) * (v1[0] - v2[0]) +
99 (v2[1] + v0[1]) * (v2[0] - v0[0]);
100
101 if(!norm)
102 return(0);
103
104 mag = normalize(n);
105
106 return(mag);
107 }
108
109
110 tri_plane_equation(v0,v1,v2,peqptr,norm)
111 FVECT v0,v1,v2;
112 FPEQ *peqptr;
113 int norm;
114 {
115 tri_normal(v0,v1,v2,FP_N(*peqptr),norm);
116
117 FP_D(*peqptr) = -(DOT(FP_N(*peqptr),v0));
118 }
119
120
121 /* returns TRUE if ray from origin in direction v intersects plane defined
122 * by normal plane_n, and plane_d. If plane is not parallel- returns
123 * intersection point if r != NULL. If tptr!= NULL returns value of
124 * t, if parallel, returns t=FHUGE
125 */
126 int
127 intersect_vector_plane(v,peq,tptr,r)
128 FVECT v;
129 FPEQ peq;
130 double *tptr;
131 FVECT r;
132 {
133 double t,d;
134 int hit;
135 /*
136 Plane is Ax + By + Cz +D = 0:
137 plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
138 */
139
140 /* line is l = p1 + (p2-p1)t, p1=origin */
141
142 /* Solve for t: */
143 d = -(DOT(FP_N(peq),v));
144 if(ZERO(d))
145 {
146 t = FHUGE;
147 hit = 0;
148 }
149 else
150 {
151 t = FP_D(peq)/d;
152 if(t < 0 )
153 hit = 0;
154 else
155 hit = 1;
156 if(r)
157 {
158 r[0] = v[0]*t;
159 r[1] = v[1]*t;
160 r[2] = v[2]*t;
161 }
162 }
163 if(tptr)
164 *tptr = t;
165 return(hit);
166 }
167
168 int
169 intersect_ray_plane(orig,dir,peq,pd,r)
170 FVECT orig,dir;
171 FPEQ peq;
172 double *pd;
173 FVECT r;
174 {
175 double t,d;
176 int hit;
177 /*
178 Plane is Ax + By + Cz +D = 0:
179 plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
180 */
181 /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
182 t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
183 line is l = p1 + (p2-p1)t
184 */
185 /* Solve for t: */
186 d = DOT(FP_N(peq),dir);
187 if(ZERO(d))
188 return(0);
189 t = -(DOT(FP_N(peq),orig) + FP_D(peq))/d;
190
191 if(t < 0)
192 hit = 0;
193 else
194 hit = 1;
195
196 if(r)
197 VSUM(r,orig,dir,t);
198
199 if(pd)
200 *pd = t;
201 return(hit);
202 }
203
204
205 int
206 intersect_ray_oplane(orig,dir,n,pd,r)
207 FVECT orig,dir;
208 FVECT n;
209 double *pd;
210 FVECT r;
211 {
212 double t,d;
213 int hit;
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 d= DOT(n,dir);
224 if(ZERO(d))
225 return(0);
226 t = -(DOT(n,orig))/d;
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 /* Assumption: know crosses plane:dont need to check for 'on' case */
241 intersect_edge_coord_plane(v0,v1,w,r)
242 FVECT v0,v1;
243 int w;
244 FVECT r;
245 {
246 FVECT dv;
247 int wnext;
248 double t;
249
250 VSUB(dv,v1,v0);
251 t = -v0[w]/dv[w];
252 r[w] = 0.0;
253 wnext = (w+1)%3;
254 r[wnext] = v0[wnext] + dv[wnext]*t;
255 wnext = (w+2)%3;
256 r[wnext] = v0[wnext] + dv[wnext]*t;
257 }
258
259 int
260 intersect_edge_plane(e0,e1,peq,pd,r)
261 FVECT e0,e1;
262 FPEQ peq;
263 double *pd;
264 FVECT r;
265 {
266 double t;
267 int hit;
268 FVECT d;
269 /*
270 Plane is Ax + By + Cz +D = 0:
271 plane[0] = A,plane[1] = B,plane[2] = C,plane[3] = D
272 */
273 /* A(orig[0] + dxt) + B(orig[1] + dyt) + C(orig[2] + dzt) + pd = 0
274 t = -(DOT(plane_n,orig)+ plane_d)/(DOT(plane_n,d))
275 line is l = p1 + (p2-p1)t
276 */
277 /* Solve for t: */
278 VSUB(d,e1,e0);
279 t = -(DOT(FP_N(peq),e0) + FP_D(peq))/(DOT(FP_N(peq),d));
280 if(t < 0)
281 hit = 0;
282 else
283 hit = 1;
284
285 VSUM(r,e0,d,t);
286
287 if(pd)
288 *pd = t;
289 return(hit);
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],v0,v1);
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],v1,v2);
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],v2,v0);
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 set_sidedness_tests(t0,t1,t2,p0,p1,p2,test,sides,nset,n)
357 FVECT t0,t1,t2,p0,p1,p2;
358 int test[3];
359 int sides[3][3];
360 int nset;
361 FVECT n[3];
362 {
363 int t;
364 double d;
365
366
367 /* p=0 */
368 test[0] = 0;
369 if(sides[0][0] == GT_INVALID)
370 {
371 if(!NTH_BIT(nset,0))
372 VCROSS(n[0],t0,t1);
373 /* Test the point for sidedness */
374 d = DOT(n[0],p0);
375 if(d >= 0.0)
376 SET_NTH_BIT(test[0],0);
377 }
378 else
379 if(sides[0][0] != GT_INTERIOR)
380 SET_NTH_BIT(test[0],0);
381
382 if(sides[0][1] == GT_INVALID)
383 {
384 if(!NTH_BIT(nset,1))
385 VCROSS(n[1],t1,t2);
386 /* Test the point for sidedness */
387 d = DOT(n[1],p0);
388 if(d >= 0.0)
389 SET_NTH_BIT(test[0],1);
390 }
391 else
392 if(sides[0][1] != GT_INTERIOR)
393 SET_NTH_BIT(test[0],1);
394
395 if(sides[0][2] == GT_INVALID)
396 {
397 if(!NTH_BIT(nset,2))
398 VCROSS(n[2],t2,t0);
399 /* Test the point for sidedness */
400 d = DOT(n[2],p0);
401 if(d >= 0.0)
402 SET_NTH_BIT(test[0],2);
403 }
404 else
405 if(sides[0][2] != GT_INTERIOR)
406 SET_NTH_BIT(test[0],2);
407
408 /* p=1 */
409 test[1] = 0;
410 /* t=0*/
411 if(sides[1][0] == GT_INVALID)
412 {
413 if(!NTH_BIT(nset,0))
414 VCROSS(n[0],t0,t1);
415 /* Test the point for sidedness */
416 d = DOT(n[0],p1);
417 if(d >= 0.0)
418 SET_NTH_BIT(test[1],0);
419 }
420 else
421 if(sides[1][0] != GT_INTERIOR)
422 SET_NTH_BIT(test[1],0);
423
424 /* t=1 */
425 if(sides[1][1] == GT_INVALID)
426 {
427 if(!NTH_BIT(nset,1))
428 VCROSS(n[1],t1,t2);
429 /* Test the point for sidedness */
430 d = DOT(n[1],p1);
431 if(d >= 0.0)
432 SET_NTH_BIT(test[1],1);
433 }
434 else
435 if(sides[1][1] != GT_INTERIOR)
436 SET_NTH_BIT(test[1],1);
437
438 /* t=2 */
439 if(sides[1][2] == GT_INVALID)
440 {
441 if(!NTH_BIT(nset,2))
442 VCROSS(n[2],t2,t0);
443 /* Test the point for sidedness */
444 d = DOT(n[2],p1);
445 if(d >= 0.0)
446 SET_NTH_BIT(test[1],2);
447 }
448 else
449 if(sides[1][2] != GT_INTERIOR)
450 SET_NTH_BIT(test[1],2);
451
452 /* p=2 */
453 test[2] = 0;
454 /* t = 0 */
455 if(sides[2][0] == GT_INVALID)
456 {
457 if(!NTH_BIT(nset,0))
458 VCROSS(n[0],t0,t1);
459 /* Test the point for sidedness */
460 d = DOT(n[0],p2);
461 if(d >= 0.0)
462 SET_NTH_BIT(test[2],0);
463 }
464 else
465 if(sides[2][0] != GT_INTERIOR)
466 SET_NTH_BIT(test[2],0);
467 /* t=1 */
468 if(sides[2][1] == GT_INVALID)
469 {
470 if(!NTH_BIT(nset,1))
471 VCROSS(n[1],t1,t2);
472 /* Test the point for sidedness */
473 d = DOT(n[1],p2);
474 if(d >= 0.0)
475 SET_NTH_BIT(test[2],1);
476 }
477 else
478 if(sides[2][1] != GT_INTERIOR)
479 SET_NTH_BIT(test[2],1);
480 /* t=2 */
481 if(sides[2][2] == GT_INVALID)
482 {
483 if(!NTH_BIT(nset,2))
484 VCROSS(n[2],t2,t0);
485 /* Test the point for sidedness */
486 d = DOT(n[2],p2);
487 if(d >= 0.0)
488 SET_NTH_BIT(test[2],2);
489 }
490 else
491 if(sides[2][2] != GT_INTERIOR)
492 SET_NTH_BIT(test[2],2);
493 }
494
495 double
496 point_on_sphere(ps,p,c)
497 FVECT ps,p,c;
498 {
499 double d;
500 VSUB(ps,p,c);
501 d= normalize(ps);
502 return(d);
503 }
504
505 int
506 point_in_stri(v0,v1,v2,p)
507 FVECT v0,v1,v2,p;
508 {
509 double d;
510 FVECT n;
511
512 VCROSS(n,v0,v1);
513 /* Test the point for sidedness */
514 d = DOT(n,p);
515 if(d > 0.0)
516 return(FALSE);
517
518 /* Test next edge */
519 VCROSS(n,v1,v2);
520 /* Test the point for sidedness */
521 d = DOT(n,p);
522 if(d > 0.0)
523 return(FALSE);
524
525 /* Test next edge */
526 VCROSS(n,v2,v0);
527 /* Test the point for sidedness */
528 d = DOT(n,p);
529 if(d > 0.0)
530 return(FALSE);
531 /* Must be interior to the pyramid */
532 return(GT_INTERIOR);
533 }
534
535
536 int
537 ray_intersect_tri(orig,dir,v0,v1,v2,pt)
538 FVECT orig,dir;
539 FVECT v0,v1,v2;
540 FVECT pt;
541 {
542 FVECT p0,p1,p2,p;
543 FPEQ peq;
544 int type;
545
546 VSUB(p0,v0,orig);
547 VSUB(p1,v1,orig);
548 VSUB(p2,v2,orig);
549
550 if(point_in_stri(p0,p1,p2,dir))
551 {
552 /* Intersect the ray with the triangle plane */
553 tri_plane_equation(v0,v1,v2,&peq,FALSE);
554 return(intersect_ray_plane(orig,dir,peq,NULL,pt));
555 }
556 return(FALSE);
557 }
558
559
560 calculate_view_frustum(vp,hv,vv,horiz,vert,near,far,fnear,ffar)
561 FVECT vp,hv,vv;
562 double horiz,vert,near,far;
563 FVECT fnear[4],ffar[4];
564 {
565 double height,width;
566 FVECT t,nhv,nvv,ndv;
567 double w2,h2;
568 /* Calculate the x and y dimensions of the near face */
569 /* hv and vv are the horizontal and vertical vectors in the
570 view frame-the magnitude is the dimension of the front frustum
571 face at z =1
572 */
573 VCOPY(nhv,hv);
574 VCOPY(nvv,vv);
575 w2 = normalize(nhv);
576 h2 = normalize(nvv);
577 /* Use similar triangles to calculate the dimensions at z=near */
578 width = near*0.5*w2;
579 height = near*0.5*h2;
580
581 VCROSS(ndv,nvv,nhv);
582 /* Calculate the world space points corresponding to the 4 corners
583 of the front face of the view frustum
584 */
585 fnear[0][0] = width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0] ;
586 fnear[0][1] = width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
587 fnear[0][2] = width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
588 fnear[1][0] = -width*nhv[0] + height*nvv[0] + near*ndv[0] + vp[0];
589 fnear[1][1] = -width*nhv[1] + height*nvv[1] + near*ndv[1] + vp[1];
590 fnear[1][2] = -width*nhv[2] + height*nvv[2] + near*ndv[2] + vp[2];
591 fnear[2][0] = -width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
592 fnear[2][1] = -width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
593 fnear[2][2] = -width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
594 fnear[3][0] = width*nhv[0] - height*nvv[0] + near*ndv[0] + vp[0];
595 fnear[3][1] = width*nhv[1] - height*nvv[1] + near*ndv[1] + vp[1];
596 fnear[3][2] = width*nhv[2] - height*nvv[2] + near*ndv[2] + vp[2];
597
598 /* Now do the far face */
599 width = far*0.5*w2;
600 height = far*0.5*h2;
601 ffar[0][0] = width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
602 ffar[0][1] = width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
603 ffar[0][2] = width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
604 ffar[1][0] = -width*nhv[0] + height*nvv[0] + far*ndv[0] + vp[0] ;
605 ffar[1][1] = -width*nhv[1] + height*nvv[1] + far*ndv[1] + vp[1] ;
606 ffar[1][2] = -width*nhv[2] + height*nvv[2] + far*ndv[2] + vp[2] ;
607 ffar[2][0] = -width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
608 ffar[2][1] = -width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
609 ffar[2][2] = -width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
610 ffar[3][0] = width*nhv[0] - height*nvv[0] + far*ndv[0] + vp[0] ;
611 ffar[3][1] = width*nhv[1] - height*nvv[1] + far*ndv[1] + vp[1] ;
612 ffar[3][2] = width*nhv[2] - height*nvv[2] + far*ndv[2] + vp[2] ;
613 }
614
615 int
616 max_index(v,r)
617 FVECT v;
618 double *r;
619 {
620 double p[3];
621 int i;
622
623 p[0] = fabs(v[0]);
624 p[1] = fabs(v[1]);
625 p[2] = fabs(v[2]);
626 i = (p[0]>=p[1])?((p[0]>=p[2])?0:2):((p[1]>=p[2])?1:2);
627 if(r)
628 *r = p[i];
629 return(i);
630 }
631
632 int
633 closest_point_in_tri(p0,p1,p2,p,p0id,p1id,p2id)
634 FVECT p0,p1,p2,p;
635 int p0id,p1id,p2id;
636 {
637 double d,d1;
638 int i;
639
640 d = DIST_SQ(p,p0);
641 d1 = DIST_SQ(p,p1);
642 if(d < d1)
643 {
644 d1 = DIST_SQ(p,p2);
645 i = (d1 < d)?p2id:p0id;
646 }
647 else
648 {
649 d = DIST_SQ(p,p2);
650 i = (d < d1)? p2id:p1id;
651 }
652 return(i);
653 }
654
655 /* Find the normalized barycentric coordinates of p relative to
656 * triangle v0,v1,v2. Return result in coord
657 */
658 bary2d(x1,y1,x2,y2,x3,y3,px,py,coord)
659 double x1,y1,x2,y2,x3,y3;
660 double px,py;
661 double coord[3];
662 {
663 double a;
664
665 a = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
666 coord[0] = ((x2 - px) * (y3 - py) - (x3 - px) * (y2 - py)) / a;
667 coord[1] = ((x3 - px) * (y1 - py) - (x1 - px) * (y3 - py)) / a;
668 coord[2] = ((x1 - px) * (y2 - py) - (x2 - px) * (y1 - py)) / a;
669
670 }
671
672
673
674
675 bary_parent(coord,i)
676 BCOORD coord[3];
677 int i;
678 {
679 switch(i) {
680 case 0:
681 /* update bary for child */
682 coord[0] = (coord[0] >> 1) + MAXBCOORD4;
683 coord[1] >>= 1;
684 coord[2] >>= 1;
685 break;
686 case 1:
687 coord[0] >>= 1;
688 coord[1] = (coord[1] >> 1) + MAXBCOORD4;
689 coord[2] >>= 1;
690 break;
691
692 case 2:
693 coord[0] >>= 1;
694 coord[1] >>= 1;
695 coord[2] = (coord[2] >> 1) + MAXBCOORD4;
696 break;
697
698 case 3:
699 coord[0] = MAXBCOORD4 - (coord[0] >> 1);
700 coord[1] = MAXBCOORD4 - (coord[1] >> 1);
701 coord[2] = MAXBCOORD4 - (coord[2] >> 1);
702 break;
703 #ifdef DEBUG
704 default:
705 eputs("bary_parent():Invalid child\n");
706 break;
707 #endif
708 }
709 }
710
711 bary_from_child(coord,child,next)
712 BCOORD coord[3];
713 int child,next;
714 {
715 #ifdef DEBUG
716 if(child <0 || child > 3)
717 {
718 eputs("bary_from_child():Invalid child\n");
719 return;
720 }
721 if(next <0 || next > 3)
722 {
723 eputs("bary_from_child():Invalid next\n");
724 return;
725 }
726 #endif
727 if(next == child)
728 return;
729
730 switch(child){
731 case 0:
732 coord[0] = 0;
733 coord[1] = MAXBCOORD2 - coord[1];
734 coord[2] = MAXBCOORD2 - coord[2];
735 break;
736 case 1:
737 coord[0] = MAXBCOORD2 - coord[0];
738 coord[1] = 0;
739 coord[2] = MAXBCOORD2 - coord[2];
740 break;
741 case 2:
742 coord[0] = MAXBCOORD2 - coord[0];
743 coord[1] = MAXBCOORD2 - coord[1];
744 coord[2] = 0;
745 break;
746 case 3:
747 switch(next){
748 case 0:
749 coord[0] = 0;
750 coord[1] = MAXBCOORD2 - coord[1];
751 coord[2] = MAXBCOORD2 - coord[2];
752 break;
753 case 1:
754 coord[0] = MAXBCOORD2 - coord[0];
755 coord[1] = 0;
756 coord[2] = MAXBCOORD2 - coord[2];
757 break;
758 case 2:
759 coord[0] = MAXBCOORD2 - coord[0];
760 coord[1] = MAXBCOORD2 - coord[1];
761 coord[2] = 0;
762 break;
763 }
764 break;
765 }
766 }
767
768 int
769 bary_child(coord)
770 BCOORD coord[3];
771 {
772 int i;
773
774 if(coord[0] > MAXBCOORD4)
775 {
776 /* update bary for child */
777 coord[0] = (coord[0]<< 1) - MAXBCOORD2;
778 coord[1] <<= 1;
779 coord[2] <<= 1;
780 return(0);
781 }
782 else
783 if(coord[1] > MAXBCOORD4)
784 {
785 coord[0] <<= 1;
786 coord[1] = (coord[1] << 1) - MAXBCOORD2;
787 coord[2] <<= 1;
788 return(1);
789 }
790 else
791 if(coord[2] > MAXBCOORD4)
792 {
793 coord[0] <<= 1;
794 coord[1] <<= 1;
795 coord[2] = (coord[2] << 1) - MAXBCOORD2;
796 return(2);
797 }
798 else
799 {
800 coord[0] = MAXBCOORD2 - (coord[0] << 1);
801 coord[1] = MAXBCOORD2 - (coord[1] << 1);
802 coord[2] = MAXBCOORD2 - (coord[2] << 1);
803 return(3);
804 }
805 }
806
807 int
808 bary_nth_child(coord,i)
809 BCOORD coord[3];
810 int i;
811 {
812
813 switch(i){
814 case 0:
815 /* update bary for child */
816 coord[0] = (coord[0]<< 1) - MAXBCOORD2;
817 coord[1] <<= 1;
818 coord[2] <<= 1;
819 break;
820 case 1:
821 coord[0] <<= 1;
822 coord[1] = (coord[1] << 1) - MAXBCOORD2;
823 coord[2] <<= 1;
824 break;
825 case 2:
826 coord[0] <<= 1;
827 coord[1] <<= 1;
828 coord[2] = (coord[2] << 1) - MAXBCOORD2;
829 break;
830 case 3:
831 coord[0] = MAXBCOORD2 - (coord[0] << 1);
832 coord[1] = MAXBCOORD2 - (coord[1] << 1);
833 coord[2] = MAXBCOORD2 - (coord[2] << 1);
834 break;
835 }
836 }
837
838
839