ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_qtree.c
Revision: 3.7
Committed: Tue Oct 6 18:18:54 1998 UTC (25 years, 6 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.6: +460 -882 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\

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_qtree.c: adapted from octree.c from radiance code
9 */
10 /*
11 * octree.c - routines dealing with octrees and cubes.
12 *
13 * 7/28/85
14 */
15
16 #include "standard.h"
17 #include "sm_flag.h"
18 #include "sm_geom.h"
19 #include "sm_qtree.h"
20
21 QUADTREE *quad_block[QT_MAX_BLK]; /* our quadtree */
22 static QUADTREE quad_free_list = EMPTY; /* freed octree nodes */
23 static QUADTREE treetop = 0; /* next free node */
24 int4 *quad_flag= NULL;
25
26 #ifdef TEST_DRIVER
27 extern FVECT Pick_v0[500],Pick_v1[500],Pick_v2[500];
28 extern int Pick_cnt,Pick_tri,Pick_samp;
29 extern FVECT Pick_point[500];
30
31
32 #endif
33 int Incnt=0;
34
35 QUADTREE
36 qtAlloc() /* allocate a quadtree */
37 {
38 register QUADTREE freet;
39
40 if ((freet = quad_free_list) != EMPTY)
41 {
42 quad_free_list = QT_NTH_CHILD(freet, 0);
43 return(freet);
44 }
45 freet = treetop;
46 if (QT_BLOCK_INDEX(freet) == 0)
47 {
48 if (QT_BLOCK(freet) >= QT_MAX_BLK)
49 return(EMPTY);
50 if ((quad_block[QT_BLOCK(freet)] = (QUADTREE *)malloc(
51 QT_BLOCK_SIZE*4*sizeof(QUADTREE))) == NULL)
52 error(SYSTEM,"qtAlloc(): Unable to allocate memory\n");
53
54 /* Realloc the per/node flags */
55 quad_flag = (int4 *)realloc((char *)quad_flag,
56 (QT_BLOCK(freet)+1)*((QT_BLOCK_SIZE+7)>>3));
57 if (quad_flag == NULL)
58 error(SYSTEM,"qtAlloc(): Unable to allocate memory\n");
59 }
60 treetop += 4;
61 return(freet);
62 }
63
64
65 qtClearAllFlags() /* clear all quadtree branch flags */
66 {
67 if (!treetop)
68 return;
69
70 /* Clear the node flags*/
71 bzero((char *)quad_flag, (QT_BLOCK(treetop-4)+1)*((QT_BLOCK_SIZE+7)>>3));
72 /* Clear set flags */
73 qtclearsetflags();
74 }
75
76 qtFree(qt) /* free a quadtree */
77 register QUADTREE qt;
78 {
79 register int i;
80
81 if (!QT_IS_TREE(qt))
82 {
83 qtfreeleaf(qt);
84 return;
85 }
86 for (i = 0; i < 4; i++)
87 qtFree(QT_NTH_CHILD(qt, i));
88 QT_NTH_CHILD(qt, 0) = quad_free_list;
89 quad_free_list = qt;
90 }
91
92
93 qtDone() /* free EVERYTHING */
94 {
95 register int i;
96
97 qtfreeleaves();
98 for (i = 0; i < QT_MAX_BLK; i++)
99 {
100 if (quad_block[i] == NULL)
101 break;
102 free((char *)quad_block[i]);
103 quad_block[i] = NULL;
104 }
105 /* Free the flags */
106 if (i) free((char *)quad_flag);
107 quad_flag = NULL;
108 quad_free_list = EMPTY;
109 treetop = 0;
110 }
111
112 QUADTREE
113 qtLocate_leaf(qt,bcoord)
114 QUADTREE qt;
115 BCOORD bcoord[3];
116 {
117 int i;
118
119 if(QT_IS_TREE(qt))
120 {
121 i = baryi_child(bcoord);
122
123 return(qtLocate_leaf(QT_NTH_CHILD(qt,i),bcoord));
124 }
125 else
126 return(qt);
127 }
128
129 /*
130 Return the quadtree node containing pt. It is assumed that pt is in
131 the root node qt with ws vertices q0,q1,q2 and plane equation peq.
132 */
133 QUADTREE
134 qtRoot_point_locate(qt,q0,q1,q2,peq,pt)
135 QUADTREE qt;
136 FVECT q0,q1,q2;
137 FPEQ peq;
138 FVECT pt;
139 {
140 int i,x,y;
141 FVECT i_pt;
142 double bcoord[3];
143 BCOORD bcoordi[3];
144
145 /* Will return lowest level triangle containing point: It the
146 point is on an edge or vertex: will return first associated
147 triangle encountered in the child traversal- the others can
148 be derived using triangle adjacency information
149 */
150 if(QT_IS_TREE(qt))
151 {
152 /* Find the intersection point */
153 intersect_vector_plane(pt,peq,NULL,i_pt);
154
155 x = FP_X(peq);
156 y = FP_Y(peq);
157 /* Calculate barycentric coordinates of i_pt */
158 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],bcoord);
159
160 /* convert to integer coordinate */
161 convert_dtol(bcoord,bcoordi);
162
163 i = baryi_child(bcoordi);
164
165 return(qtLocate_leaf(QT_NTH_CHILD(qt,i),bcoordi));
166 }
167 else
168 return(qt);
169 }
170
171
172
173
174 /* for triangle v0-v1-v2- returns a,b,c: children are:
175
176 v2 0: v0,a,c
177 /\ 1: a,v1,b
178 /2 \ 2: c,b,v2
179 c/____\b 3: b,c,a
180 /\ /\
181 /0 \3 /1 \
182 v0____\/____\v1
183 a
184 */
185
186
187 qtNth_child_tri(v0,v1,v2,a,b,c,i,r0,r1,r2)
188 FVECT v0,v1,v2;
189 FVECT a,b,c;
190 int i;
191 FVECT r0,r1,r2;
192 {
193
194 if(!a)
195 {
196 /* Caution: r's must not be equal to v's:will be incorrect */
197 switch(i){
198 case 0:
199 VCOPY(r0,v0);
200 EDGE_MIDPOINT_VEC3(r1,v0,v1);
201 EDGE_MIDPOINT_VEC3(r2,v2,v0);
202 break;
203 case 1:
204 EDGE_MIDPOINT_VEC3(r0,v0,v1);
205 VCOPY(r1,v1);
206 EDGE_MIDPOINT_VEC3(r2,v1,v2);
207 break;
208 case 2:
209 EDGE_MIDPOINT_VEC3(r0,v2,v0);
210 EDGE_MIDPOINT_VEC3(r1,v1,v2);
211 VCOPY(r2,v2);
212 break;
213 case 3:
214 EDGE_MIDPOINT_VEC3(r0,v1,v2);
215 EDGE_MIDPOINT_VEC3(r1,v2,v0);
216 EDGE_MIDPOINT_VEC3(r2,v0,v1);
217 break;
218 }
219 }
220 else
221 {
222 switch(i){
223 case 0:
224 VCOPY(r0,v0); VCOPY(r1,a); VCOPY(r2,c);
225 break;
226 case 1:
227 VCOPY(r0,a); VCOPY(r1,v1); VCOPY(r2,b);
228 break;
229 case 2:
230 VCOPY(r0,c); VCOPY(r1,b); VCOPY(r2,v2);
231 break;
232 case 3:
233 VCOPY(r0,b); VCOPY(r1,c); VCOPY(r2,a);
234 break;
235 }
236 }
237 }
238
239 /* Add triangle "id" to all leaf level cells that are children of
240 quadtree pointed to by "qtptr" with cell vertices "t1,t2,t3"
241 that it overlaps (vertex and edge adjacencies do not count
242 as overlapping). If the addition of the triangle causes the cell to go over
243 threshold- the cell is split- and the triangle must be recursively inserted
244 into the new child cells: it is assumed that "v1,v2,v3" are normalized
245 */
246
247 QUADTREE
248 qtRoot_add_tri(qt,q0,q1,q2,t0,t1,t2,id,n)
249 QUADTREE qt;
250 FVECT q0,q1,q2;
251 FVECT t0,t1,t2;
252 int id,n;
253 {
254 if(stri_intersect(q0,q1,q2,t0,t1,t2))
255 qt = qtAdd_tri(qt,q0,q1,q2,t0,t1,t2,id,n);
256
257 return(qt);
258 }
259
260 QUADTREE
261 qtRoot_remove_tri(qt,q0,q1,q2,t0,t1,t2,id,n)
262 QUADTREE qt;
263 FVECT q0,q1,q2;
264 FVECT t0,t1,t2;
265 int id,n;
266 {
267
268 if(stri_intersect(q0,q1,q2,t0,t1,t2))
269 qt = qtRemove_tri(qt,q0,q1,q2,t0,t1,t2,id,n);
270 return(qt);
271 }
272
273
274 QUADTREE
275 qtAdd_tri(qt,q0,q1,q2,t0,t1,t2,id,n)
276 QUADTREE qt;
277 FVECT q0,q1,q2;
278 FVECT t0,t1,t2;
279 int id;
280 int n;
281 {
282 FVECT a,b,c;
283 OBJECT tset[QT_MAXSET+1],*optr,*tptr;
284 FVECT r0,r1,r2;
285 int i;
286
287 /* if this is tree: recurse */
288 if(QT_IS_TREE(qt))
289 {
290 QT_SET_FLAG(qt);
291 n++;
292 qtSubdivide_tri(q0,q1,q2,a,b,c);
293
294 if(stri_intersect(t0,t1,t2,q0,a,c))
295 QT_NTH_CHILD(qt,0) = qtAdd_tri(QT_NTH_CHILD(qt,0),q0,a,c,t0,t1,t2,id,n);
296 if(stri_intersect(t0,t1,t2,a,q1,b))
297 QT_NTH_CHILD(qt,1) = qtAdd_tri(QT_NTH_CHILD(qt,1),a,q1,b,t0,t1,t2,id,n);
298 if(stri_intersect(t0,t1,t2,c,b,q2))
299 QT_NTH_CHILD(qt,2) = qtAdd_tri(QT_NTH_CHILD(qt,2),c,b,q2,t0,t1,t2,id,n);
300 if(stri_intersect(t0,t1,t2,b,c,a))
301 QT_NTH_CHILD(qt,3) = qtAdd_tri(QT_NTH_CHILD(qt,3),b,c,a,t0,t1,t2,id,n);
302 return(qt);
303 }
304 else
305 {
306 /* If this leave node emptry- create a new set */
307 if(QT_IS_EMPTY(qt))
308 qt = qtaddelem(qt,id);
309 else
310 {
311 /* If the set is too large: subdivide */
312 optr = qtqueryset(qt);
313
314 if(QT_SET_CNT(optr) < QT_SET_THRESHOLD)
315 qt = qtaddelem(qt,id);
316 else
317 {
318 if (n < QT_MAX_LEVELS)
319 {
320 /* If set size exceeds threshold: subdivide cell and
321 reinsert set tris into cell
322 */
323 /* CAUTION:If QT_SET_THRESHOLD << QT_MAXSET, and dont add
324 more than a few triangles before expanding: then are safe here
325 otherwise must check to make sure set size is < MAXSET,
326 or qtgetset could overflow os.
327 */
328 tptr = qtqueryset(qt);
329 if(QT_SET_CNT(tptr) > QT_MAXSET)
330 tptr = (OBJECT *)malloc((QT_SET_CNT(tptr)+1)*sizeof(OBJECT));
331 else
332 tptr = tset;
333 if(!tptr)
334 goto memerr;
335
336 qtgetset(tptr,qt);
337 n++;
338 qtfreeleaf(qt);
339 qtSubdivide(qt);
340 qt = qtAdd_tri(qt,q0,q1,q2,t0,t1,t2,id,n);
341
342 for(optr = QT_SET_PTR(tptr),i = QT_SET_CNT(tptr); i > 0; i--)
343 {
344 id = QT_SET_NEXT_ELEM(optr);
345 if(!qtTri_from_id(id,r0,r1,r2))
346 continue;
347 qt = qtAdd_tri(qt,q0,q1,q2,r0,r1,r2,id,n);
348 }
349 if(tptr != tset)
350 free(tptr);
351 }
352 else
353 qt = qtaddelem(qt,id);
354 }
355 }
356 }
357 return(qt);
358 memerr:
359 error(SYSTEM,"qtAdd_tri():Unable to allocate memory");
360 }
361
362
363 QUADTREE
364 qtRemove_tri(qt,id,q0,q1,q2,t0,t1,t2)
365 QUADTREE qt;
366 int id;
367 FVECT q0,q1,q2;
368 FVECT t0,t1,t2;
369 {
370 FVECT a,b,c;
371
372 /* test if triangle (t0,t1,t2) overlaps cell triangle (v0,v1,v2) */
373 if(!stri_intersect(t0,t1,t2,q0,q1,q2))
374 return(qt);
375
376 /* if this is tree: recurse */
377 if(QT_IS_TREE(qt))
378 {
379 qtSubdivide_tri(q0,q1,q2,a,b,c);
380 QT_NTH_CHILD(qt,0) = qtRemove_tri(QT_NTH_CHILD(qt,0),id,t0,t1,t2,q0,a,c);
381 QT_NTH_CHILD(qt,1) = qtRemove_tri(QT_NTH_CHILD(qt,1),id,t0,t1,t2,a,q1,b);
382 QT_NTH_CHILD(qt,2) = qtRemove_tri(QT_NTH_CHILD(qt,2),id,t0,t1,t2,c,b,q2);
383 QT_NTH_CHILD(qt,3) = qtRemove_tri(QT_NTH_CHILD(qt,3),id,t0,t1,t2,b,c,a);
384 return(qt);
385 }
386 else
387 {
388 if(QT_IS_EMPTY(qt))
389 {
390 #ifdef DEBUG
391 eputs("qtRemove_tri(): triangle not found\n");
392 #endif
393 }
394 /* remove id from set */
395 else
396 {
397 if(!qtinset(qt,id))
398 {
399 #ifdef DEBUG
400 eputs("qtRemove_tri(): tri not in set\n");
401 #endif
402 }
403 else
404 qt = qtdelelem(qt,id);
405 }
406 }
407 return(qt);
408 }
409
410
411 QUADTREE
412 qtVisit_tri_interior(qt,q0,q1,q2,t0,t1,t2,n0,n1,n2,n,func,f,argptr)
413 QUADTREE qt;
414 FVECT q0,q1,q2;
415 FVECT t0,t1,t2;
416 FVECT n0,n1,n2;
417 int n;
418 int (*func)(),*f;
419 int *argptr;
420 {
421 FVECT a,b,c;
422
423 /* If qt Flag set, or qt vertices interior to t0t1t2-descend */
424 tree_modified:
425
426 if(QT_IS_TREE(qt))
427 {
428 if(QT_IS_FLAG(qt) || point_in_stri_n(n0,n1,n2,q0))
429 {
430 QT_SET_FLAG(qt);
431 qtSubdivide_tri(q0,q1,q2,a,b,c);
432 /* descend to children */
433 QT_NTH_CHILD(qt,0) = qtVisit_tri_interior(QT_NTH_CHILD(qt,0),
434 q0,a,c,t0,t1,t2,n0,n1,n2,n+1,func,f,argptr);
435 QT_NTH_CHILD(qt,1) = qtVisit_tri_interior(QT_NTH_CHILD(qt,1),
436 a,q1,b,t0,t1,t2,n0,n1,n2,n+1,func,f,argptr);
437 QT_NTH_CHILD(qt,2) = qtVisit_tri_interior(QT_NTH_CHILD(qt,2),
438 c,b,q2,t0,t1,t2,n0,n1,n2,n+1,func,f,argptr);
439 QT_NTH_CHILD(qt,3) = qtVisit_tri_interior(QT_NTH_CHILD(qt,3),
440 b,c,a,t0,t1,t2,n0,n1,n2,n+1,func,f,argptr);
441 }
442 }
443 else
444 if((!QT_IS_EMPTY(qt) && QT_LEAF_IS_FLAG(qt)) ||
445 point_in_stri_n(n0,n1,n2,q0))
446 {
447 func(&qt,f,argptr,q0,q1,q2,t0,t1,t2,n);
448 if(QT_FLAG_IS_MODIFIED(*f))
449 {
450 QT_SET_FLAG(qt);
451 goto tree_modified;
452 }
453 if(QT_IS_LEAF(qt))
454 QT_LEAF_SET_FLAG(qt);
455 else
456 if(QT_IS_TREE(qt))
457 QT_SET_FLAG(qt);
458 }
459 return(qt);
460 }
461
462
463
464 int
465 move_to_nbri(b,db0,db1,db2,tptr)
466 BCOORD b[3];
467 BDIR db0,db1,db2;
468 TINT *tptr;
469 {
470 TINT t,dt;
471 BCOORD bc;
472 int nbr;
473
474 nbr = -1;
475 *tptr = 0;
476 /* Advance to next node */
477 if(b[0]==0 && db0 < 0)
478 return(0);
479 if(b[1]==0 && db1 < 0)
480 return(1);
481 if(b[2]==0 && db2 < 0)
482 return(2);
483
484 if(db0 < 0)
485 {
486 bc = b[0]<<SHIFT_MAXBCOORD;
487 t = bc/-db0;
488 nbr = 0;
489 }
490 else
491 t = HUGET;
492 if(db1 < 0)
493 {
494 bc = b[1] <<SHIFT_MAXBCOORD;
495 dt = bc/-db1;
496 if( dt < t)
497 {
498 t = dt;
499 nbr = 1;
500 }
501 }
502 if(db2 < 0)
503 {
504 bc = b[2] << SHIFT_MAXBCOORD;
505 dt = bc/-db2;
506 if( dt < t)
507 {
508 t = dt;
509 nbr = 2;
510 }
511 }
512 *tptr = t;
513 return(nbr);
514 }
515
516 QUADTREE
517 qtVisit_tri_edges(qt,b,db0,db1,db2,db,wptr,nextptr,t,sign,sfactor,func,f,argptr)
518 QUADTREE qt;
519 BCOORD b[3];
520 BDIR db0,db1,db2,db[3][3];
521 int *wptr,*nextptr;
522 TINT t[3];
523 int sign,sfactor;
524 int (*func)();
525 int *f,*argptr;
526 {
527 int i,found;
528 QUADTREE child;
529 int nbr,next,w;
530 TINT t_g,t_l,t_i,l;
531
532 if(QT_IS_TREE(qt))
533 {
534 /* Find the appropriate child and reset the coord */
535 i = baryi_child(b);
536
537 QT_SET_FLAG(qt);
538
539 for(;;)
540 {
541 w = *wptr;
542 child = QT_NTH_CHILD(qt,i);
543 if(i != 3)
544 QT_NTH_CHILD(qt,i) =
545 qtVisit_tri_edges(child,b,db0,db1,db2,db,wptr,nextptr,t,sign,
546 sfactor+1,func,f,argptr);
547 else
548 /* If the center cell- must flip direction signs */
549 QT_NTH_CHILD(qt,i) =
550 qtVisit_tri_edges(child,b,-db0,-db1,-db2,db,wptr,nextptr,t,1-sign,
551 sfactor+1,func,f,argptr);
552
553 if(QT_FLAG_IS_DONE(*f))
554 return(qt);
555 if(*wptr != w)
556 {
557 w = *wptr;
558 db0 = db[w][0];db1 = db[w][1];db2 = db[w][2];
559 if(sign)
560 { db0 *= -1;db1 *= -1; db2 *= -1;}
561 }
562 /* If in same block: traverse */
563 if(i==3)
564 next = *nextptr;
565 else
566 if(*nextptr == i)
567 next = 3;
568 else
569 {
570 /* reset the barycentric coordinates in the parents*/
571 baryi_parent(b,i);
572 /* Else pop up to parent and traverse from there */
573 return(qt);
574 }
575 baryi_from_child(b,i,next);
576 i = next;
577 }
578 }
579 else
580 {
581 func(&qt,f,argptr);
582 if(QT_FLAG_IS_DONE(*f))
583 {
584 if(!QT_IS_EMPTY(qt))
585 QT_LEAF_SET_FLAG(qt);
586 return(qt);
587 }
588
589 if(!QT_IS_EMPTY(qt))
590 QT_LEAF_SET_FLAG(qt);
591 /* Advance to next node */
592 w = *wptr;
593 while(1)
594 {
595 nbr = move_to_nbri(b,db0,db1,db2,&t_i);
596
597 t_g = t_i >> sfactor;
598
599 if(t_g >= t[w])
600 {
601 if(w == 2)
602 {
603 QT_FLAG_SET_DONE(*f);
604 return(qt);
605 }
606 /* The edge fits in the cell- therefore the result of shifting
607 db by sfactor is guaranteed to be less than MAXBCOORD
608 */
609 /* Caution: (t[w]*db) must occur before divide by MAXBCOORD
610 since t[w] will always be < MAXBCOORD
611 */
612 l = t[w] << sfactor;
613 /* NOTE: Change divides to Shift and multiply by sign*/
614 b[0] += (l*db0)/MAXBCOORD;
615 b[1] += (l*db1)/MAXBCOORD;
616 b[2] += (l*db2)/MAXBCOORD;
617 w++;
618 db0 = db[w][0]; db1 = db[w][1]; db2 = db[w][2];
619 if(sign)
620 { db0 *= -1;db1 *= -1; db2 *= -1;}
621 }
622 else
623 {
624 /* Caution: (t_i*db) must occur before divide by MAXBCOORD
625 since t_i will always be < MAXBCOORD*/
626 /* NOTE: Change divides to Shift and by sign*/
627 b[0] += (t_i *db0) / MAXBCOORD;
628 b[1] += (t_i *db1) / MAXBCOORD;
629 b[2] += (t_i *db2) / MAXBCOORD;
630
631 t[w] -= t_g;
632 *wptr = w;
633 *nextptr = nbr;
634 return(qt);
635 }
636 }
637 }
638 }
639
640
641 QUADTREE
642 qtRoot_visit_tri_edges(qt,q0,q1,q2,peq,tri,i_pt,wptr,nextptr,func,f,argptr)
643 QUADTREE qt;
644 FVECT q0,q1,q2;
645 FPEQ peq;
646 FVECT tri[3],i_pt;
647 int *wptr,*nextptr;
648 int (*func)();
649 int *f,*argptr;
650 {
651 int x,y,z,w,i,j,first;
652 QUADTREE child;
653 FVECT c,d,v[3];
654 double b[4][3],db[3][3],et[3],exit_pt;
655 BCOORD bi[3];
656 TINT t[3];
657 BDIR dbi[3][3];
658
659 first =0;
660 w = *wptr;
661 if(w==-1)
662 {
663 first = 1;
664 *wptr = w = 0;
665 }
666 /* Project the origin onto the root node plane */
667
668 t[0] = t[1] = t[2] = 0;
669 /* Find the intersection point of the origin */
670 /* map to 2d by dropping maximum magnitude component of normal */
671
672 x = FP_X(peq);
673 y = FP_Y(peq);
674 z = FP_Z(peq);
675 /* Calculate barycentric coordinates for current vertex */
676 if(!first)
677 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[3]);
678 else
679 /* Just starting: b[0] is the origin point: guaranteed to be valid b*/
680 {
681 intersect_vector_plane(tri[0],peq,&(et[0]),v[0]);
682 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[0][x],v[0][y],b[0]);
683 VCOPY(b[3],b[0]);
684 }
685
686 j = (w+1)%3;
687 intersect_vector_plane(tri[j],peq,&(et[j]),v[j]);
688 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[j][x],v[j][y],b[j]);
689 if(et[j] < 0.0)
690 {
691 VSUB(db[w],b[3],b[j]);
692 t[w] = HUGET;
693 }
694 else
695 {
696 /* NOTE: for stability: do not increment with ipt- use full dir and
697 calculate t: but for wrap around case: could get same problem?
698 */
699 VSUB(db[w],b[j],b[3]);
700 /* Check if the point is out side of the triangle: if so t[w] =HUGET */
701 if((fabs(b[j][0])>(FTINY+1.0)) ||(fabs(b[j][1])>(FTINY+1.0)) ||
702 (fabs(b[j][2])>(FTINY+1.0))||(b[j][0] <-FTINY) ||
703 (b[j][1]<-FTINY) ||(b[j][2]<-FTINY))
704 t[w] = HUGET;
705 else
706 {
707 /* The next point is in the triangle- so db values will be in valid
708 range and t[w]= MAXT
709 */
710 t[w] = MAXT;
711 if(j != 0)
712 for(;j < 3;j++)
713 {
714 i = (j+1)%3;
715 if(!first || i != 0)
716 {
717 intersect_vector_plane(tri[i],peq,&(et[i]),v[i]);
718 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[i][x],
719 v[i][y],b[i]);
720 }
721 if(et[i] < 0.0)
722 {
723 VSUB(db[j],b[j],b[i]);
724 t[j] = HUGET;
725 break;
726 }
727 else
728 {
729 VSUB(db[j],b[i],b[j]);
730 if((fabs(b[j][0])>(FTINY+1.0))||(fabs(b[j][1])>(FTINY+1.0)) ||
731 (fabs(b[j][2])>(FTINY+1.0))||(b[i][0] <-FTINY) ||
732 (b[i][1]<-FTINY) ||(b[i][2]<-FTINY))
733 {
734 t[j] = HUGET;
735 break;
736 }
737 else
738 t[j] = MAXT;
739 }
740 }
741 }
742 }
743 bary_dtol(b[3],db,bi,dbi,t,w);
744
745 /* trace the ray starting with this node */
746 qt = qtVisit_tri_edges(qt,bi,dbi[w][0],dbi[w][1],dbi[w][2],
747 dbi,wptr,nextptr,t,0,0,func,f,argptr);
748 if(!QT_FLAG_IS_DONE(*f))
749 {
750 b[3][0] = (double)bi[0]/(double)MAXBCOORD;
751 b[3][1] = (double)bi[1]/(double)MAXBCOORD;
752 b[3][2] = (double)bi[2]/(double)MAXBCOORD;
753 i_pt[x] = b[3][0]*q0[x] + b[3][1]*q1[x] + b[3][2]*q2[x];
754 i_pt[y] = b[3][0]*q0[y] + b[3][1]*q1[y] + b[3][2]*q2[y];
755 i_pt[z] = (-FP_N(peq)[x]*i_pt[x] - FP_N(peq)[y]*i_pt[y]-FP_D(peq))/FP_N(peq)[z];
756 }
757 return(qt);
758
759 }
760
761
762 QUADTREE
763 qtRoot_trace_ray(qt,q0,q1,q2,peq,orig,dir,nextptr,func,f,argptr)
764 QUADTREE qt;
765 FVECT q0,q1,q2;
766 FPEQ peq;
767 FVECT orig,dir;
768 int *nextptr;
769 int (*func)();
770 int *f,*argptr;
771 {
772 int x,y,z,nbr,w,i;
773 QUADTREE child;
774 FVECT v,i_pt;
775 double b[2][3],db[3],et[2],d,br[3];
776 BCOORD bi[3];
777 TINT t[3];
778 BDIR dbi[3][3];
779
780 /* Project the origin onto the root node plane */
781 t[0] = t[1] = t[2] = 0;
782
783 VADD(v,orig,dir);
784 /* Find the intersection point of the origin */
785 /* map to 2d by dropping maximum magnitude component of normal */
786 x = FP_X(peq);
787 y = FP_Y(peq);
788 z = FP_Z(peq);
789
790 /* Calculate barycentric coordinates for current vertex */
791 intersect_vector_plane(orig,peq,&(et[0]),i_pt);
792 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[0]);
793
794 intersect_vector_plane(v,peq,&(et[1]),i_pt);
795 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[1]);
796 if(et[1] < 0.0)
797 VSUB(db,b[0],b[1]);
798 else
799 VSUB(db,b[1],b[0]);
800 t[0] = HUGET;
801 convert_dtol(b[0],bi);
802 if(et[1]<0.0 || (fabs(b[1][0])>(FTINY+1.0)) ||(fabs(b[1][1])>(FTINY+1.0)) ||
803 (fabs(b[1][2])>(FTINY+1.0))||(b[1][0] <-FTINY) ||
804 (b[1][1]<-FTINY) ||(b[1][2]<-FTINY))
805 {
806 max_index(db,&d);
807 for(i=0; i< 3; i++)
808 dbi[0][i] = (BDIR)(db[i]/d*MAXBDIR);
809 }
810 else
811 for(i=0; i< 3; i++)
812 dbi[0][i] = (BDIR)(db[i]*MAXBDIR);
813 w=0;
814 /* trace the ray starting with this node */
815 qt = qtVisit_tri_edges(qt,bi,dbi[0][0],dbi[0][1],dbi[0][2], dbi,&w,
816 nextptr,t,0,0,func,f,argptr);
817 if(!QT_FLAG_IS_DONE(*f))
818 {
819 br[0] = (double)bi[0]/(double)MAXBCOORD;
820 br[1] = (double)bi[1]/(double)MAXBCOORD;
821 br[2] = (double)bi[2]/(double)MAXBCOORD;
822 orig[x] = br[0]*q0[x] + br[1]*q1[x] + br[2]*q2[x];
823 orig[y] = br[0]*q0[y] + br[1]*q1[y] + br[2]*q2[y];
824 orig[z]=(-FP_N(peq)[x]*orig[x] -
825 FP_N(peq)[y]*orig[y]-FP_D(peq))/FP_N(peq)[z];
826 }
827 return(qt);
828
829 }
830
831
832
833
834
835
836
837
838
839
840
841
842