ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_qtree.c
Revision: 3.5
Committed: Mon Sep 14 10:33:47 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.4: +3 -0 lines
Log Message:
optimized normalizing calls and bug fix in triangle counting

File Contents

# User Rev Content
1 gwlarson 3.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    
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 gwlarson 3.4 int4 *quad_flag= NULL;
25 gwlarson 3.1
26 gwlarson 3.4 #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     #endif
31    
32 gwlarson 3.1 QUADTREE
33     qtAlloc() /* allocate a quadtree */
34     {
35     register QUADTREE freet;
36    
37     if ((freet = quad_free_list) != EMPTY)
38     {
39     quad_free_list = QT_NTH_CHILD(freet, 0);
40     return(freet);
41     }
42     freet = treetop;
43     if (QT_BLOCK_INDEX(freet) == 0)
44     {
45     if (QT_BLOCK(freet) >= QT_MAX_BLK)
46     return(EMPTY);
47     if ((quad_block[QT_BLOCK(freet)] = (QUADTREE *)malloc(
48 gwlarson 3.3 QT_BLOCK_SIZE*4*sizeof(QUADTREE))) == NULL)
49 gwlarson 3.1 return(EMPTY);
50 gwlarson 3.4
51 gwlarson 3.3 quad_flag = (int4 *)realloc((char *)quad_flag,
52 gwlarson 3.4 (QT_BLOCK(freet)+1)*(QT_BLOCK_SIZE/8));
53 gwlarson 3.3 if (quad_flag == NULL)
54     return(EMPTY);
55 gwlarson 3.1 }
56     treetop += 4;
57     return(freet);
58     }
59    
60    
61 gwlarson 3.3 qtClearAllFlags() /* clear all quadtree branch flags */
62     {
63     if (!treetop) return;
64 gwlarson 3.4 bzero((char *)quad_flag, (QT_BLOCK(treetop-4)+1)*(QT_BLOCK_SIZE/8));
65 gwlarson 3.3 }
66    
67    
68 gwlarson 3.1 qtFree(qt) /* free a quadtree */
69     register QUADTREE qt;
70     {
71     register int i;
72    
73     if (!QT_IS_TREE(qt))
74     {
75     qtfreeleaf(qt);
76     return;
77     }
78     for (i = 0; i < 4; i++)
79     qtFree(QT_NTH_CHILD(qt, i));
80     QT_NTH_CHILD(qt, 0) = quad_free_list;
81     quad_free_list = qt;
82     }
83    
84    
85     qtDone() /* free EVERYTHING */
86     {
87     register int i;
88    
89 gwlarson 3.4 qtfreeleaves();
90 gwlarson 3.1 for (i = 0; i < QT_MAX_BLK; i++)
91     {
92 gwlarson 3.3 if (quad_block[i] == NULL)
93     break;
94     free((char *)quad_block[i]);
95 gwlarson 3.1 quad_block[i] = NULL;
96     }
97 gwlarson 3.3 if (i) free((char *)quad_flag);
98     quad_flag = NULL;
99 gwlarson 3.1 quad_free_list = EMPTY;
100     treetop = 0;
101     }
102    
103     QUADTREE
104 gwlarson 3.3 *qtLocate_leaf(qtptr,bcoord,t0,t1,t2)
105 gwlarson 3.1 QUADTREE *qtptr;
106 gwlarson 3.2 double bcoord[3];
107 gwlarson 3.3 FVECT t0,t1,t2;
108 gwlarson 3.2 {
109     int i;
110     QUADTREE *child;
111 gwlarson 3.3 FVECT a,b,c;
112 gwlarson 3.2
113     if(QT_IS_TREE(*qtptr))
114     {
115 gwlarson 3.4 i = bary_child(bcoord);
116     #ifdef DEBUG_TEST_DRIVER
117     qtSubdivide_tri(Pick_v0[Pick_cnt-1],Pick_v1[Pick_cnt-1],
118     Pick_v2[Pick_cnt-1],a,b,c);
119     qtNth_child_tri(Pick_v0[Pick_cnt-1],Pick_v1[Pick_cnt-1],
120     Pick_v2[Pick_cnt-1],a,b,c,i,
121     Pick_v0[Pick_cnt],Pick_v1[Pick_cnt],
122     Pick_v2[Pick_cnt]);
123     Pick_cnt++;
124     #endif
125    
126 gwlarson 3.2 child = QT_NTH_CHILD_PTR(*qtptr,i);
127 gwlarson 3.3 if(t0)
128     {
129     qtSubdivide_tri(t0,t1,t2,a,b,c);
130     qtNth_child_tri(t0,t1,t2,a,b,c,i,t0,t1,t2);
131     }
132     return(qtLocate_leaf(child,bcoord,t0,t1,t2));
133 gwlarson 3.2 }
134     else
135 gwlarson 3.3 return(qtptr);
136 gwlarson 3.2 }
137    
138    
139     QUADTREE
140 gwlarson 3.3 *qtRoot_point_locate(qtptr,v0,v1,v2,pt,t0,t1,t2)
141 gwlarson 3.2 QUADTREE *qtptr;
142     FVECT v0,v1,v2;
143 gwlarson 3.1 FVECT pt;
144 gwlarson 3.3 FVECT t0,t1,t2;
145 gwlarson 3.1 {
146 gwlarson 3.4 int d;
147 gwlarson 3.2 int i,x,y;
148 gwlarson 3.1 QUADTREE *child;
149 gwlarson 3.3 FVECT n,i_pt,a,b,c;
150 gwlarson 3.2 double pd,bcoord[3];
151 gwlarson 3.1
152     /* Determine if point lies within pyramid (and therefore
153     inside a spherical quadtree cell):GT_INTERIOR, on one of the
154     pyramid sides (and on cell edge):GT_EDGE(1,2 or 3),
155     or on pyramid vertex (and on cell vertex):GT_VERTEX(1,2, or 3).
156     For each triangle edge: compare the
157     point against the plane formed by the edge and the view center
158     */
159 gwlarson 3.4 d = point_in_stri(v0,v1,v2,pt);
160 gwlarson 3.1
161 gwlarson 3.4
162 gwlarson 3.1 /* Not in this triangle */
163     if(!d)
164 gwlarson 3.3 return(NULL);
165 gwlarson 3.1
166     /* Will return lowest level triangle containing point: It the
167     point is on an edge or vertex: will return first associated
168     triangle encountered in the child traversal- the others can
169     be derived using triangle adjacency information
170     */
171     if(QT_IS_TREE(*qtptr))
172     {
173 gwlarson 3.2 /* Find the intersection point */
174     tri_plane_equation(v0,v1,v2,n,&pd,FALSE);
175     intersect_vector_plane(pt,n,pd,NULL,i_pt);
176    
177     i = max_index(n);
178     x = (i+1)%3;
179     y = (i+2)%3;
180     /* Calculate barycentric coordinates of i_pt */
181     bary2d(v0[x],v0[y],v1[x],v1[y],v2[x],v2[y],i_pt[x],i_pt[y],bcoord);
182    
183 gwlarson 3.4 i = bary_child(bcoord);
184 gwlarson 3.2 child = QT_NTH_CHILD_PTR(*qtptr,i);
185 gwlarson 3.4 #ifdef DEBUG_TEST_DRIVER
186     Pick_cnt = 0;
187     VCOPY(Pick_v0[0],v0);
188     VCOPY(Pick_v1[0],v1);
189     VCOPY(Pick_v2[0],v2);
190     Pick_cnt++;
191     qtSubdivide_tri(Pick_v0[Pick_cnt-1],Pick_v1[Pick_cnt-1],
192     Pick_v2[Pick_cnt-1],a,b,c);
193     qtNth_child_tri(Pick_v0[Pick_cnt-1],Pick_v1[Pick_cnt-1],
194     Pick_v2[Pick_cnt-1],a,b,c,i,
195     Pick_v0[Pick_cnt],Pick_v1[Pick_cnt],
196     Pick_v2[Pick_cnt]);
197     Pick_cnt++;
198     #endif
199 gwlarson 3.3 if(t0)
200     {
201     qtSubdivide_tri(v0,v1,v2,a,b,c);
202     qtNth_child_tri(v0,v1,v2,a,b,c,i,t0,t1,t2);
203     }
204     return(qtLocate_leaf(child,bcoord,t0,t1,t2));
205 gwlarson 3.1 }
206     else
207     {
208 gwlarson 3.4 if(t0)
209     {
210     VCOPY(t0,v0);
211     VCOPY(t1,v1);
212     VCOPY(t2,v2);
213 gwlarson 3.1 }
214 gwlarson 3.4 return(qtptr);
215 gwlarson 3.1 }
216     }
217    
218 gwlarson 3.4
219 gwlarson 3.1 QUADTREE
220     qtSubdivide(qtptr)
221     QUADTREE *qtptr;
222     {
223     QUADTREE node;
224     node = qtAlloc();
225     QT_CLEAR_CHILDREN(node);
226     *qtptr = node;
227     return(node);
228     }
229    
230    
231     QUADTREE
232     qtSubdivide_nth_child(qt,n)
233     QUADTREE qt;
234     int n;
235     {
236     QUADTREE node;
237    
238     node = qtSubdivide(&(QT_NTH_CHILD(qt,n)));
239    
240     return(node);
241     }
242    
243 gwlarson 3.2 /* for triangle v0-v1-v2- returns a,b,c: children are:
244 gwlarson 3.1
245 gwlarson 3.2 v2 0: v0,a,c
246     /\ 1: a,v1,b
247     /2 \ 2: c,b,v2
248     c/____\b 3: b,c,a
249 gwlarson 3.1 /\ /\
250 gwlarson 3.2 /0 \3 /1 \
251     v0____\/____\v1
252 gwlarson 3.1 a
253     */
254    
255 gwlarson 3.2 qtSubdivide_tri(v0,v1,v2,a,b,c)
256     FVECT v0,v1,v2;
257 gwlarson 3.1 FVECT a,b,c;
258     {
259 gwlarson 3.2 EDGE_MIDPOINT_VEC3(a,v0,v1);
260     EDGE_MIDPOINT_VEC3(b,v1,v2);
261     EDGE_MIDPOINT_VEC3(c,v2,v0);
262 gwlarson 3.1 }
263    
264 gwlarson 3.2 qtNth_child_tri(v0,v1,v2,a,b,c,i,r0,r1,r2)
265     FVECT v0,v1,v2;
266 gwlarson 3.1 FVECT a,b,c;
267     int i;
268 gwlarson 3.2 FVECT r0,r1,r2;
269 gwlarson 3.1 {
270 gwlarson 3.4
271 gwlarson 3.1 switch(i){
272     case 0:
273 gwlarson 3.2 VCOPY(r0,v0); VCOPY(r1,a); VCOPY(r2,c);
274 gwlarson 3.1 break;
275     case 1:
276 gwlarson 3.2 VCOPY(r0,a); VCOPY(r1,v1); VCOPY(r2,b);
277 gwlarson 3.1 break;
278     case 2:
279 gwlarson 3.2 VCOPY(r0,c); VCOPY(r1,b); VCOPY(r2,v2);
280 gwlarson 3.1 break;
281     case 3:
282 gwlarson 3.2 VCOPY(r0,b); VCOPY(r1,c); VCOPY(r2,a);
283 gwlarson 3.1 break;
284     }
285     }
286    
287     /* Add triangle "id" to all leaf level cells that are children of
288     quadtree pointed to by "qtptr" with cell vertices "t1,t2,t3"
289     that it overlaps (vertex and edge adjacencies do not count
290     as overlapping). If the addition of the triangle causes the cell to go over
291     threshold- the cell is split- and the triangle must be recursively inserted
292     into the new child cells: it is assumed that "v1,v2,v3" are normalized
293     */
294    
295     int
296 gwlarson 3.4 qtRoot_add_tri(qtptr,q0,q1,q2,t0,t1,t2,id,n)
297 gwlarson 3.3 QUADTREE *qtptr;
298 gwlarson 3.4 FVECT q0,q1,q2;
299     FVECT t0,t1,t2;
300 gwlarson 3.3 int id;
301     int n;
302     {
303 gwlarson 3.4 int test;
304 gwlarson 3.3 int found;
305    
306 gwlarson 3.4 test = stri_intersect(q0,q1,q2,t0,t1,t2);
307 gwlarson 3.3 if(!test)
308     return(FALSE);
309    
310 gwlarson 3.4 found = qtAdd_tri(qtptr,q0,q1,q2,t0,t1,t2,id,n);
311    
312 gwlarson 3.3 return(found);
313     }
314    
315     int
316 gwlarson 3.4 qtAdd_tri(qtptr,q0,q1,q2,t0,t1,t2,id,n)
317 gwlarson 3.3 QUADTREE *qtptr;
318 gwlarson 3.4 FVECT q0,q1,q2;
319 gwlarson 3.3 FVECT t0,t1,t2;
320 gwlarson 3.1 int id;
321     int n;
322     {
323 gwlarson 3.4 int i,index,test,found;
324 gwlarson 3.1 FVECT a,b,c;
325 gwlarson 3.4 OBJECT os[QT_MAXSET+1],*optr;
326 gwlarson 3.1 QUADTREE qt;
327 gwlarson 3.2 FVECT r0,r1,r2;
328 gwlarson 3.1
329     found = 0;
330     /* if this is tree: recurse */
331     if(QT_IS_TREE(*qtptr))
332     {
333     n++;
334 gwlarson 3.4 qtSubdivide_tri(q0,q1,q2,a,b,c);
335     test = stri_intersect(t0,t1,t2,q0,a,c);
336 gwlarson 3.3 if(test)
337 gwlarson 3.4 found |= qtAdd_tri(QT_NTH_CHILD_PTR(*qtptr,0),q0,a,c,t0,t1,t2,id,n);
338     test = stri_intersect(t0,t1,t2,a,q1,b);
339 gwlarson 3.3 if(test)
340 gwlarson 3.4 found |= qtAdd_tri(QT_NTH_CHILD_PTR(*qtptr,1),a,q1,b,t0,t1,t2,id,n);
341     test = stri_intersect(t0,t1,t2,c,b,q2);
342 gwlarson 3.3 if(test)
343 gwlarson 3.4 found |= qtAdd_tri(QT_NTH_CHILD_PTR(*qtptr,2),c,b,q2,t0,t1,t2,id,n);
344     test = stri_intersect(t0,t1,t2,b,c,a);
345 gwlarson 3.3 if(test)
346 gwlarson 3.4 found |= qtAdd_tri(QT_NTH_CHILD_PTR(*qtptr,3),b,c,a,t0,t1,t2,id,n);
347 gwlarson 3.1 }
348     else
349     {
350     /* If this leave node emptry- create a new set */
351     if(QT_IS_EMPTY(*qtptr))
352 gwlarson 3.3 *qtptr = qtaddelem(*qtptr,id);
353 gwlarson 3.1 else
354     {
355     /* If the set is too large: subdivide */
356 gwlarson 3.4 optr = qtqueryset(*qtptr);
357    
358     if(QT_SET_CNT(optr) < QT_SET_THRESHOLD)
359     *qtptr = qtaddelem(*qtptr,id);
360 gwlarson 3.1 else
361     {
362     if (n < QT_MAX_LEVELS)
363     {
364     /* If set size exceeds threshold: subdivide cell and
365     reinsert set tris into cell
366     */
367 gwlarson 3.4 qtgetset(os,*qtptr);
368    
369     n++;
370     qtfreeleaf(*qtptr);
371     qtSubdivide(qtptr);
372     found = qtAdd_tri(qtptr,q0,q1,q2,t0,t1,t2,id,n);
373    
374     for(optr = QT_SET_PTR(os),i = QT_SET_CNT(os); i > 0; i--)
375     {
376     id = QT_SET_NEXT_ELEM(optr);
377     qtTri_from_id(id,NULL,NULL,NULL,r0,r1,r2,NULL,NULL,NULL);
378     found=qtAdd_tri(qtptr,q0,q1,q2,r0,r1,r2,id,n);
379 gwlarson 3.1 #ifdef DEBUG
380 gwlarson 3.4 if(!found)
381 gwlarson 3.1 eputs("qtAdd_tri():Reinsert-in parent but not children\n");
382     #endif
383 gwlarson 3.4 }
384     }
385 gwlarson 3.1 else
386 gwlarson 3.4 if(QT_SET_CNT(optr) < QT_MAXSET)
387 gwlarson 3.1 *qtptr = qtaddelem(*qtptr,id);
388     else
389     {
390     #ifdef DEBUG
391     eputs("qtAdd_tri():two many levels\n");
392     #endif
393     return(FALSE);
394     }
395     }
396     }
397     }
398     return(TRUE);
399     }
400    
401    
402     int
403 gwlarson 3.2 qtApply_to_tri_cells(qtptr,t0,t1,t2,v0,v1,v2,func,arg)
404 gwlarson 3.1 QUADTREE *qtptr;
405 gwlarson 3.2 FVECT t0,t1,t2;
406     FVECT v0,v1,v2;
407 gwlarson 3.1 int (*func)();
408 gwlarson 3.4 int *arg;
409 gwlarson 3.1 {
410 gwlarson 3.4 int test;
411 gwlarson 3.1 FVECT a,b,c;
412    
413 gwlarson 3.2 /* test if triangle (t0,t1,t2) overlaps cell triangle (v0,v1,v2) */
414 gwlarson 3.4 test = stri_intersect(t0,t1,t2,v0,v1,v2);
415 gwlarson 3.1
416     /* If triangles do not overlap: done */
417     if(!test)
418     return(FALSE);
419    
420     /* if this is tree: recurse */
421 gwlarson 3.4 func(qtptr,arg);
422    
423 gwlarson 3.1 if(QT_IS_TREE(*qtptr))
424     {
425 gwlarson 3.4 QT_SET_FLAG(*qtptr);
426     qtSubdivide_tri(v0,v1,v2,a,b,c);
427 gwlarson 3.2 qtApply_to_tri_cells(QT_NTH_CHILD_PTR(*qtptr,0),t0,t1,t2,v0,a,c,func,arg);
428     qtApply_to_tri_cells(QT_NTH_CHILD_PTR(*qtptr,1),t0,t1,t2,a,v1,b,func,arg);
429     qtApply_to_tri_cells(QT_NTH_CHILD_PTR(*qtptr,2),t0,t1,t2,c,b,v2,func,arg);
430     qtApply_to_tri_cells(QT_NTH_CHILD_PTR(*qtptr,3),t0,t1,t2,b,c,a,func,arg);
431 gwlarson 3.1 }
432     }
433    
434     int
435 gwlarson 3.2 qtRemove_tri(qtptr,id,t0,t1,t2,v0,v1,v2)
436 gwlarson 3.1 QUADTREE *qtptr;
437     int id;
438 gwlarson 3.2 FVECT t0,t1,t2;
439     FVECT v0,v1,v2;
440 gwlarson 3.1 {
441    
442 gwlarson 3.4 int test;
443 gwlarson 3.1 int i;
444     FVECT a,b,c;
445 gwlarson 3.4 OBJECT os[QT_MAXSET+1];
446 gwlarson 3.1
447 gwlarson 3.2 /* test if triangle (t0,t1,t2) overlaps cell triangle (v0,v1,v2) */
448 gwlarson 3.4 test = stri_intersect(t0,t1,t2,v0,v1,v2);
449 gwlarson 3.1
450     /* If triangles do not overlap: done */
451     if(!test)
452     return(FALSE);
453    
454     /* if this is tree: recurse */
455     if(QT_IS_TREE(*qtptr))
456     {
457 gwlarson 3.2 qtSubdivide_tri(v0,v1,v2,a,b,c);
458     qtRemove_tri(QT_NTH_CHILD_PTR(*qtptr,0),id,t0,t1,t2,v0,a,c);
459     qtRemove_tri(QT_NTH_CHILD_PTR(*qtptr,1),id,t0,t1,t2,a,v1,b);
460     qtRemove_tri(QT_NTH_CHILD_PTR(*qtptr,2),id,t0,t1,t2,c,b,v2);
461     qtRemove_tri(QT_NTH_CHILD_PTR(*qtptr,3),id,t0,t1,t2,b,c,a);
462 gwlarson 3.1 }
463     else
464     {
465     if(QT_IS_EMPTY(*qtptr))
466     {
467     #ifdef DEBUG
468     eputs("qtRemove_tri(): triangle not found\n");
469     #endif
470     }
471     /* remove id from set */
472     else
473     {
474 gwlarson 3.4 if(!qtinset(*qtptr,id))
475 gwlarson 3.1 {
476     #ifdef DEBUG
477     eputs("qtRemove_tri(): tri not in set\n");
478     #endif
479     }
480     else
481     {
482     *qtptr = qtdelelem(*qtptr,id);
483     }
484     }
485     }
486     return(TRUE);
487     }
488 gwlarson 3.4
489    
490     int
491     move_to_nbr(b,db0,db1,db2,tptr)
492     double b[3],db0,db1,db2;
493     double *tptr;
494     {
495     double t,dt;
496     int nbr;
497    
498     nbr = -1;
499     /* Advance to next node */
500     if(!ZERO(db0) && db0 < 0.0)
501     {
502     t = -b[0]/db0;
503     nbr = 0;
504     }
505     else
506     t = FHUGE;
507     if(!ZERO(db1) && db1 < 0.0 )
508     {
509     dt = -b[1]/db1;
510     if( dt < t)
511     {
512     t = dt;
513     nbr = 1;
514     }
515     }
516     if(!ZERO(db2) && db2 < 0.0 )
517     {
518     dt = -b[2]/db2;
519     if( dt < t)
520     {
521     t = dt;
522     nbr = 2;
523     }
524     }
525     *tptr = t;
526     return(nbr);
527     }
528    
529     int
530     qtTrace_edge(qtptr,b,db,orig,dir,max_t,func,arg1,arg2)
531     QUADTREE *qtptr;
532     double b[3],db[3];
533     FVECT orig,dir;
534     double max_t;
535     int (*func)();
536     int *arg1,arg2;
537     {
538    
539     int i,found;
540     QUADTREE *child;
541     int nbr,next;
542     double t;
543     #ifdef DEBUG_TEST_DRIVER
544    
545     FVECT a1,b1,c1;
546     int Pick_parent = Pick_cnt-1;
547     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
548     Pick_v2[Pick_parent],a1,b1,c1);
549    
550     #endif
551     if(QT_IS_TREE(*qtptr))
552     {
553     /* Find the appropriate child and reset the coord */
554     i = bary_child(b);
555    
556     QT_SET_FLAG(*qtptr);
557    
558     for(;;)
559     {
560     child = QT_NTH_CHILD_PTR(*qtptr,i);
561    
562     if(i != 3)
563     {
564    
565     db[0] *= 2.0;db[1] *= 2.0; db[2] *= 2.0;
566     nbr = qtTrace_edge(child,b,db,orig,dir,max_t,func,arg1,arg2);
567     db[0] *= 0.5;db[1] *= 0.5; db[2] *= 0.5;
568     }
569     else
570     {
571     db[0] *=-2.0;db[1] *= -2.0; db[2] *= -2.0;
572     /* If the center cell- must flip direction signs */
573     nbr = qtTrace_edge(child,b,db,orig,dir,max_t,func,arg1,arg2);
574     db[0] *=-0.5;db[1] *= -0.5; db[2] *= -0.5;
575     }
576     if(nbr == QT_DONE)
577     return(nbr);
578    
579     /* If in same block: traverse */
580     if(i==3)
581     next = nbr;
582     else
583     if(nbr == i)
584     next = 3;
585     else
586     {
587     /* reset the barycentric coordinates in the parents*/
588     bary_parent(b,i);
589     /* Else pop up to parent and traverse from there */
590     return(nbr);
591     }
592     bary_from_child(b,i,next);
593     i = next;
594     }
595     }
596     else
597     {
598     #ifdef DEBUG_TEST_DRIVER
599     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
600     Pick_v2[Pick_parent],a1,b1,c1,i,
601     Pick_v0[Pick_cnt],Pick_v1[Pick_cnt],
602     Pick_v2[Pick_cnt]);
603     Pick_cnt++;
604     #endif
605    
606     if(func(qtptr,arg1,arg2) == QT_DONE)
607     return(QT_DONE);
608    
609     /* Advance to next node */
610     /* NOTE: Optimize: should only have to check 1/2 */
611     nbr = move_to_nbr(b,db[0],db[1],db[2],&t);
612    
613     if(t >= max_t)
614     return(QT_DONE);
615     if(nbr != -1)
616     {
617     b[0] += t * db[0];
618     b[1] += t * db[1];
619     b[2] += t * db[2];
620     db[0] *= (1.0 - t);
621     db[1] *= (1.0 - t);
622     db[2] *= (1.0 - t);
623     }
624     return(nbr);
625     }
626    
627     }
628    
629    
630     int
631     qtTrace_ray(qtptr,b,db0,db1,db2,orig,dir,func,arg1,arg2)
632     QUADTREE *qtptr;
633     double b[3],db0,db1,db2;
634     FVECT orig,dir;
635     int (*func)();
636     int *arg1,arg2;
637     {
638    
639     int i,found;
640     QUADTREE *child;
641     int nbr,next;
642     double t;
643     #ifdef DEBUG_TEST_DRIVER
644    
645     FVECT a1,b1,c1;
646     int Pick_parent = Pick_cnt-1;
647     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
648     Pick_v2[Pick_parent],a1,b1,c1);
649    
650     #endif
651     if(QT_IS_TREE(*qtptr))
652     {
653     /* Find the appropriate child and reset the coord */
654     i = bary_child(b);
655    
656     QT_SET_FLAG(*qtptr);
657    
658     for(;;)
659     {
660     child = QT_NTH_CHILD_PTR(*qtptr,i);
661    
662     if(i != 3)
663     nbr = qtTrace_ray(child,b,db0,db1,db2,orig,dir,func,arg1,arg2);
664     else
665     /* If the center cell- must flip direction signs */
666     nbr =qtTrace_ray(child,b,-db0,-db1,-db2,orig,dir,func,arg1,arg2);
667     if(nbr == QT_DONE)
668     return(nbr);
669    
670     /* If in same block: traverse */
671     if(i==3)
672     next = nbr;
673     else
674     if(nbr == i)
675     next = 3;
676     else
677     {
678     /* reset the barycentric coordinates in the parents*/
679     bary_parent(b,i);
680     /* Else pop up to parent and traverse from there */
681     return(nbr);
682     }
683     bary_from_child(b,i,next);
684     i = next;
685     }
686     }
687     else
688     {
689     #ifdef DEBUG_TEST_DRIVER
690     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
691     Pick_v2[Pick_parent],a1,b1,c1,i,
692     Pick_v0[Pick_cnt],Pick_v1[Pick_cnt],
693     Pick_v2[Pick_cnt]);
694     Pick_cnt++;
695     #endif
696    
697     if(func(qtptr,orig,dir,arg1,arg2) == QT_DONE)
698     return(QT_DONE);
699    
700     /* Advance to next node */
701     /* NOTE: Optimize: should only have to check 1/2 */
702     nbr = move_to_nbr(b,db0,db1,db2,&t);
703    
704     if(nbr != -1)
705     {
706     b[0] += t * db0;
707     b[1] += t * db1;
708     b[2] += t * db2;
709     }
710     return(nbr);
711     }
712    
713     }
714    
715     int
716     qtRoot_trace_ray(qtptr,q0,q1,q2,orig,dir,func,arg1,arg2)
717     QUADTREE *qtptr;
718     FVECT q0,q1,q2;
719     FVECT orig,dir;
720     int (*func)();
721     int *arg1,arg2;
722     {
723     int i,x,y,nbr;
724     QUADTREE *child;
725     FVECT n,c,i_pt,d;
726     double pd,b[3],db[3],t;
727     /* Determine if point lies within pyramid (and therefore
728     inside a spherical quadtree cell):GT_INTERIOR, on one of the
729     pyramid sides (and on cell edge):GT_EDGE(1,2 or 3),
730     or on pyramid vertex (and on cell vertex):GT_VERTEX(1,2, or 3).
731     For each triangle edge: compare the
732     point against the plane formed by the edge and the view center
733     */
734     i = point_in_stri(q0,q1,q2,orig);
735    
736     /* Not in this triangle */
737     if(!i)
738     return(INVALID);
739     /* Project the origin onto the root node plane */
740    
741     /* Find the intersection point of the origin */
742     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
743     intersect_vector_plane(orig,n,pd,NULL,i_pt);
744     /* project the dir as well */
745     VADD(c,orig,dir);
746     intersect_vector_plane(c,n,pd,&t,c);
747    
748     /* map to 2d by dropping maximum magnitude component of normal */
749     i = max_index(n);
750     x = (i+1)%3;
751     y = (i+2)%3;
752     /* Calculate barycentric coordinates of orig */
753     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b);
754     /* Calculate barycentric coordinates of dir */
755     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],c[x],c[y],db);
756     if(t < 0.0)
757     VSUB(db,b,db);
758     else
759     VSUB(db,db,b);
760    
761    
762     #ifdef DEBUG_TEST_DRIVER
763     VCOPY(Pick_v0[Pick_cnt],q0);
764     VCOPY(Pick_v1[Pick_cnt],q1);
765     VCOPY(Pick_v2[Pick_cnt],q2);
766     Pick_cnt++;
767     #endif
768    
769     /* trace the ray starting with this node */
770     nbr = qtTrace_ray(qtptr,b,db[0],db[1],db[2],orig,dir,func,arg1,arg2);
771     return(nbr);
772    
773     }
774    
775    
776     int
777     qtRoot_trace_edge(qtptr,q0,q1,q2,orig,dir,max_t,func,arg1,arg2)
778     QUADTREE *qtptr;
779     FVECT q0,q1,q2;
780     FVECT orig,dir;
781     double max_t;
782     int (*func)();
783     int *arg1,arg2;
784     {
785     int i,x,y,nbr;
786     QUADTREE *child;
787     FVECT n,c,i_pt,d;
788     double pd,b[3],db[3],t;
789     /* Determine if point lies within pyramid (and therefore
790     inside a spherical quadtree cell):GT_INTERIOR, on one of the
791     pyramid sides (and on cell edge):GT_EDGE(1,2 or 3),
792     or on pyramid vertex (and on cell vertex):GT_VERTEX(1,2, or 3).
793     For each triangle edge: compare the
794     point against the plane formed by the edge and the view center
795     */
796     i = point_in_stri(q0,q1,q2,orig);
797    
798     /* Not in this triangle */
799     if(!i)
800     return(-1);
801     /* Project the origin onto the root node plane */
802    
803     /* Find the intersection point of the origin */
804     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
805     intersect_vector_plane(orig,n,pd,NULL,i_pt);
806     /* project the dir as well */
807     VADD(c,orig,dir);
808     intersect_vector_plane(c,n,pd,&t,c);
809    
810     /* map to 2d by dropping maximum magnitude component of normal */
811     i = max_index(n);
812     x = (i+1)%3;
813     y = (i+2)%3;
814     /* Calculate barycentric coordinates of orig */
815     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b);
816     /* Calculate barycentric coordinates of dir */
817     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],c[x],c[y],db);
818     if(t < 0.0)
819     VSUB(db,b,db);
820     else
821     VSUB(db,db,b);
822    
823    
824     #ifdef DEBUG_TEST_DRIVER
825     VCOPY(Pick_v0[Pick_cnt],q0);
826     VCOPY(Pick_v1[Pick_cnt],q1);
827     VCOPY(Pick_v2[Pick_cnt],q2);
828     Pick_cnt++;
829     #endif
830     /* trace the ray starting with this node */
831     nbr = qtTrace_edge(qtptr,b,db,orig,d,max_t,func,arg1,arg2);
832     return(nbr);
833    
834     }
835    
836    
837     qtVisit_tri_interior(qtptr,q0,q1,q2,t0,t1,t2,n,func,arg1,arg2)
838     QUADTREE *qtptr;
839     FVECT q0,q1,q2;
840     FVECT t0,t1,t2;
841     int n;
842     int (*func)();
843     int *arg1,arg2;
844     {
845     int i,found,test;
846     QUADTREE *child;
847     FVECT c0,c1,c2,a,b,c;
848     OBJECT os[QT_MAXSET+1],*optr;
849     int w;
850    
851     /* If qt Flag set, or qt vertices interior to t0t1t2-descend */
852     tree_modified:
853    
854     if(QT_IS_TREE(*qtptr))
855     {
856     if(QT_IS_FLAG(*qtptr) || point_in_stri(t0,t1,t2,q0))
857     {
858     QT_SET_FLAG(*qtptr);
859     qtSubdivide_tri(q0,q1,q2,a,b,c);
860     /* descend to children */
861     for(i=0;i < 4; i++)
862     {
863     child = QT_NTH_CHILD_PTR(*qtptr,i);
864     qtNth_child_tri(q0,q1,q2,a,b,c,i,c0,c1,c2);
865     qtVisit_tri_interior(child,c0,c1,c2,t0,t1,t2,n+1,
866     func,arg1,arg2);
867     }
868     }
869     }
870     else
871     {
872     /* NOTE THIS IN TRI TEST Could be replaced by a flag */
873     if(!QT_IS_EMPTY(*qtptr))
874     {
875     if(qtinset(*qtptr,arg2))
876     if(func(qtptr,q0,q1,q2,t0,t1,t2,n,arg1,arg2)==QT_MODIFIED)
877     goto tree_modified;
878     else
879     return;
880     }
881     if(point_in_stri(t0,t1,t2,q0) )
882     if(func(qtptr,q0,q1,q2,t0,t1,t2,n,arg1,arg2)==QT_MODIFIED)
883     goto tree_modified;
884     }
885     }
886    
887    
888    
889    
890    
891    
892     int
893     qtVisit_tri_edges(qtptr,b,db,wptr,sfactor,func,arg1,arg2)
894     QUADTREE *qtptr;
895     double b[3],db[3][3];
896     int *wptr;
897     double sfactor;
898     int (*func)();
899     int *arg1,arg2;
900     {
901     int i,found;
902     QUADTREE *child;
903     int nbr,next,w;
904     double t;
905     #ifdef DEBUG_TEST_DRIVER
906     FVECT a1,b1,c1;
907     int Pick_parent = Pick_cnt-1;
908     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
909     Pick_v2[Pick_parent],a1,b1,c1);
910     #endif
911    
912     if(QT_IS_TREE(*qtptr))
913     {
914     /* Find the appropriate child and reset the coord */
915     i = bary_child(b);
916    
917     QT_SET_FLAG(*qtptr);
918    
919     for(;;)
920     {
921     w = *wptr;
922     child = QT_NTH_CHILD_PTR(*qtptr,i);
923    
924     if(i != 3)
925     {
926    
927     db[w][0] *= 2.0;db[w][1] *= 2.0; db[w][2] *= 2.0;
928     nbr = qtVisit_tri_edges(child,b,db,wptr,sfactor*2.0,
929     func,arg1,arg2);
930     w = *wptr;
931     db[w][0] *= 0.5;db[w][1] *= 0.5; db[w][2] *= 0.5;
932     }
933     else
934     {
935     db[w][0] *=-2.0;db[w][1] *= -2.0; db[w][2] *= -2.0;
936     /* If the center cell- must flip direction signs */
937     nbr = qtVisit_tri_edges(child,b,db,wptr,sfactor*(-2.0),
938     func,arg1,arg2);
939     w = *wptr;
940     db[w][0] *=-0.5;db[w][1] *= -0.5; db[w][2] *= -0.5;
941     }
942     if(nbr == QT_DONE)
943     return(nbr);
944    
945     /* If in same block: traverse */
946     if(i==3)
947     next = nbr;
948     else
949     if(nbr == i)
950     next = 3;
951     else
952     {
953     /* reset the barycentric coordinates in the parents*/
954     bary_parent(b,i);
955     /* Else pop up to parent and traverse from there */
956     return(nbr);
957     }
958     bary_from_child(b,i,next);
959     i = next;
960     }
961     }
962     else
963     {
964     #ifdef DEBUG_TEST_DRIVER
965     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
966     Pick_v2[Pick_parent],a1,b1,c1,i,Pick_v0[Pick_cnt],
967     Pick_v1[Pick_cnt],Pick_v2[Pick_cnt]);
968     Pick_cnt++;
969     #endif
970    
971     if(func(qtptr,arg1,arg2) == QT_DONE)
972     return(QT_DONE);
973    
974     /* Advance to next node */
975     /* NOTE: Optimize: should only have to check 1/2 */
976     w = *wptr;
977     while(1)
978     {
979     nbr = move_to_nbr(b,db[w][0],db[w][1],db[w][2],&t);
980    
981     if(t >= 1.0)
982     {
983     if(w == 2)
984     return(QT_DONE);
985     b[0] += db[w][0];
986     b[1] += db[w][1];
987     b[2] += db[w][2];
988     w++;
989     db[w][0] *= sfactor;
990     db[w][1] *= sfactor;
991     db[w][2] *= sfactor;
992     }
993     else
994     if(nbr != INVALID)
995     {
996     b[0] += t * db[w][0];
997     b[1] += t * db[w][1];
998     b[2] += t * db[w][2];
999     db[w][0] *= (1.0 - t);
1000     db[w][1] *= (1.0 - t);
1001     db[w][2] *= (1.0 - t);
1002     *wptr = w;
1003     return(nbr);
1004     }
1005     else
1006     return(INVALID);
1007     }
1008     }
1009    
1010     }
1011    
1012    
1013     int
1014     qtRoot_visit_tri_edges(qtptr,q0,q1,q2,tri,dir,wptr,func,arg1,arg2)
1015     QUADTREE *qtptr;
1016     FVECT q0,q1,q2;
1017     FVECT tri[3],dir[3];
1018     int *wptr;
1019     int (*func)();
1020     int *arg1,arg2;
1021     {
1022     int i,x,y,nbr,w;
1023     QUADTREE *child;
1024     FVECT n,c,i_pt,d;
1025     double pd,b[3][3],db[3][3],t;
1026    
1027     w = *wptr;
1028    
1029     /* Project the origin onto the root node plane */
1030    
1031     /* Find the intersection point of the origin */
1032     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
1033     /* map to 2d by dropping maximum magnitude component of normal */
1034     i = max_index(n);
1035     x = (i+1)%3;
1036     y = (i+2)%3;
1037     /* Calculate barycentric coordinates for current vertex */
1038    
1039     for(i=0;i < 3; i++)
1040     {
1041     /* If processing 3rd edge-dont need info for t1 */
1042     if(i==1 && w==2)
1043     continue;
1044     /* project the dir as well */
1045     intersect_vector_plane(tri[i],n,pd,NULL,i_pt);
1046     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[i]);
1047     VADD(c,tri[i],dir[i]);
1048     intersect_vector_plane(c,n,pd,&t,c);
1049     /* Calculate barycentric coordinates of dir */
1050     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],c[x],c[y],db[i]);
1051     if(t < 0.0)
1052     VSUB(db[i],b[i],db[i]);
1053     else
1054     VSUB(db[i],db[i],b[i]);
1055     }
1056     #ifdef DEBUG_TEST_DRIVER
1057     VCOPY(Pick_v0[Pick_cnt],q0);
1058     VCOPY(Pick_v1[Pick_cnt],q1);
1059     VCOPY(Pick_v2[Pick_cnt],q2);
1060     Pick_cnt++;
1061     #endif
1062     /* trace the ray starting with this node */
1063     nbr = qtVisit_tri_edges(qtptr,b[w],db,wptr,1.0,func,arg1,arg2);
1064     return(nbr);
1065    
1066     }
1067    
1068    
1069    
1070    
1071     /* NOTE: SINCE DIR could be unit: then we could use integer math */
1072     int
1073     qtVisit_tri_edges2(qtptr,b,db0,db1,db2,
1074     db,wptr,t,sign,sfactor,func,arg1,arg2)
1075     QUADTREE *qtptr;
1076     double b[3],db0,db1,db2,db[3][3];
1077     int *wptr;
1078     double t[3];
1079     int sign;
1080     double sfactor;
1081     int (*func)();
1082     int *arg1,arg2;
1083     {
1084     int i,found;
1085     QUADTREE *child;
1086     int nbr,next,w;
1087     double t_l,t_g;
1088     #ifdef DEBUG_TEST_DRIVER
1089     FVECT a1,b1,c1;
1090     int Pick_parent = Pick_cnt-1;
1091     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
1092     Pick_v2[Pick_parent],a1,b1,c1);
1093     #endif
1094     if(QT_IS_TREE(*qtptr))
1095     {
1096     /* Find the appropriate child and reset the coord */
1097     i = bary_child(b);
1098    
1099     QT_SET_FLAG(*qtptr);
1100    
1101     for(;;)
1102     {
1103     w = *wptr;
1104     child = QT_NTH_CHILD_PTR(*qtptr,i);
1105    
1106     if(i != 3)
1107     nbr = qtVisit_tri_edges2(child,b,db0,db1,db2,
1108     db,wptr,t,sign,
1109     sfactor*2.0,func,arg1,arg2);
1110     else
1111     /* If the center cell- must flip direction signs */
1112     nbr = qtVisit_tri_edges2(child,b,-db0,-db1,-db2,
1113     db,wptr,t,1-sign,
1114     sfactor*2.0,func,arg1,arg2);
1115    
1116     if(nbr == QT_DONE)
1117     return(nbr);
1118     if(*wptr != w)
1119     {
1120     w = *wptr;
1121     db0 = db[w][0];db1 = db[w][1];db2 = db[w][2];
1122     if(sign)
1123     { db0 *= -1.0;db1 *= -1.0; db2 *= -1.0;}
1124     }
1125     /* If in same block: traverse */
1126     if(i==3)
1127     next = nbr;
1128     else
1129     if(nbr == i)
1130     next = 3;
1131     else
1132     {
1133     /* reset the barycentric coordinates in the parents*/
1134     bary_parent(b,i);
1135     /* Else pop up to parent and traverse from there */
1136     return(nbr);
1137     }
1138     bary_from_child(b,i,next);
1139     i = next;
1140     }
1141     }
1142     else
1143     {
1144     #ifdef DEBUG_TEST_DRIVER
1145     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
1146     Pick_v2[Pick_parent],a1,b1,c1,i,Pick_v0[Pick_cnt],
1147     Pick_v1[Pick_cnt],Pick_v2[Pick_cnt]);
1148     Pick_cnt++;
1149     #endif
1150    
1151     if(func(qtptr,arg1,arg2) == QT_DONE)
1152     return(QT_DONE);
1153    
1154     /* Advance to next node */
1155     w = *wptr;
1156     while(1)
1157     {
1158     nbr = move_to_nbr(b,db0,db1,db2,&t_l);
1159    
1160     t_g = t_l/sfactor;
1161     #ifdef DEBUG
1162     if(t[w] <= 0.0)
1163     eputs("qtVisit_tri_edges2():negative t\n");
1164     #endif
1165     if(t_g >= t[w])
1166     {
1167     if(w == 2)
1168     return(QT_DONE);
1169    
1170     b[0] += (t[w])*sfactor*db0;
1171     b[1] += (t[w])*sfactor*db1;
1172     b[2] += (t[w])*sfactor*db2;
1173     w++;
1174     db0 = db[w][0];
1175     db1 = db[w][1];
1176     db2 = db[w][2];
1177     if(sign)
1178     { db0 *= -1.0;db1 *= -1.0; db2 *= -1.0;}
1179     }
1180     else
1181     if(nbr != INVALID)
1182     {
1183     b[0] += t_l * db0;
1184     b[1] += t_l * db1;
1185     b[2] += t_l * db2;
1186    
1187     t[w] -= t_g;
1188     *wptr = w;
1189     return(nbr);
1190     }
1191     else
1192     return(INVALID);
1193     }
1194     }
1195    
1196     }
1197    
1198    
1199     int
1200     qtRoot_visit_tri_edges2(qtptr,q0,q1,q2,tri,i_pt,wptr,func,arg1,arg2)
1201     QUADTREE *qtptr;
1202     FVECT q0,q1,q2;
1203     FVECT tri[3],i_pt;
1204     int *wptr;
1205     int (*func)();
1206     int *arg1,arg2;
1207     {
1208     int x,y,z,nbr,w,i,j;
1209     QUADTREE *child;
1210     FVECT n,c,d,v[3];
1211     double pd,b[4][3],db[3][3],et[3],t[3],exit_pt;
1212    
1213     w = *wptr;
1214    
1215     /* Project the origin onto the root node plane */
1216    
1217     /* Find the intersection point of the origin */
1218     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
1219     /* map to 2d by dropping maximum magnitude component of normal */
1220     z = max_index(n);
1221     x = (z+1)%3;
1222     y = (z+2)%3;
1223     /* Calculate barycentric coordinates for current vertex */
1224     if(w != -1)
1225     {
1226     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[3]);
1227     intersect_vector_plane(tri[w],n,pd,&(et[w]),v[w]);
1228     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[w][x],v[w][y],b[w]);
1229     }
1230     else
1231     /* Just starting: b[0] is the origin point: guaranteed to be valid b*/
1232     {
1233     w = 0;
1234     intersect_vector_plane(tri[0],n,pd,&(et[0]),v[0]);
1235     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[0][x],v[0][y],b[0]);
1236     VCOPY(b[3],b[0]);
1237     }
1238    
1239    
1240     j = (w+1)%3;
1241     intersect_vector_plane(tri[j],n,pd,&(et[j]),v[j]);
1242     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[j][x],v[j][y],b[j]);
1243     if(et[j] < 0.0)
1244     {
1245     VSUB(db[w],b[3],b[j]);
1246     t[w] = FHUGE;
1247     }
1248     else
1249     {
1250 gwlarson 3.5 /* NOTE: for stability: do not increment with ipt- use full dir and
1251     calculate t: but for wrap around case: could get same problem?
1252     */
1253 gwlarson 3.4 VSUB(db[w],b[j],b[3]);
1254     t[w] = 1.0;
1255     move_to_nbr(b[3],db[w][0],db[w][1],db[w][2],&exit_pt);
1256     if(exit_pt >= 1.0)
1257     {
1258     for(;j < 3;j++)
1259     {
1260     i = (j+1)%3;
1261     if(i!= w)
1262     {
1263     intersect_vector_plane(tri[i],n,pd,&(et[i]),v[i]);
1264     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[i][x],
1265     v[i][y],b[i]);
1266     }
1267     if(et[i] < 0.0)
1268     {
1269     VSUB(db[j],b[j],b[i]);
1270     t[j] = FHUGE;
1271     break;
1272     }
1273     else
1274     {
1275     VSUB(db[j],b[i],b[j]);
1276     t[j] = 1.0;
1277     }
1278     move_to_nbr(b[j],db[j][0],db[j][1],db[j][2],&exit_pt);
1279     if(exit_pt < 1.0)
1280     break;
1281     }
1282     }
1283     }
1284     *wptr = w;
1285     /* trace the ray starting with this node */
1286     nbr = qtVisit_tri_edges2(qtptr,b[3],db[w][0],db[w][1],db[w][2],
1287     db,wptr,t,0,1.0,func,arg1,arg2);
1288     if(nbr != INVALID && nbr != QT_DONE)
1289     {
1290     i_pt[x] = b[3][0]*q0[x] + b[3][1]*q1[x] + b[3][2]*q2[x];
1291     i_pt[y] = b[3][0]*q0[y] + b[3][1]*q1[y] + b[3][2]*q2[y];
1292     i_pt[z] = (-n[x]*i_pt[x] - n[y]*i_pt[y] -pd)/n[z];
1293     }
1294     return(nbr);
1295    
1296     }
1297    
1298    
1299    
1300    
1301    
1302    
1303 gwlarson 3.3
1304 gwlarson 3.2
1305    
1306    
1307    
1308    
1309    
1310    
1311    
1312    
1313    
1314