ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_qtree.c
Revision: 3.6
Committed: Wed Sep 16 18:16:29 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.5: +273 -323 lines
Log Message:
implemented integer triangle tracing

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 gwlarson 3.6 i = max_index(n,NULL);
178 gwlarson 3.2 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 gwlarson 3.6 qtTri_from_id(id,r0,r1,r2,NULL,NULL,NULL,NULL,NULL,NULL);
378 gwlarson 3.4 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_ray(qtptr,b,db0,db1,db2,orig,dir,func,arg1,arg2)
531     QUADTREE *qtptr;
532     double b[3],db0,db1,db2;
533     FVECT orig,dir;
534     int (*func)();
535     int *arg1,arg2;
536     {
537    
538     int i,found;
539     QUADTREE *child;
540     int nbr,next;
541     double t;
542     #ifdef DEBUG_TEST_DRIVER
543    
544     FVECT a1,b1,c1;
545     int Pick_parent = Pick_cnt-1;
546     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
547     Pick_v2[Pick_parent],a1,b1,c1);
548    
549     #endif
550     if(QT_IS_TREE(*qtptr))
551     {
552     /* Find the appropriate child and reset the coord */
553     i = bary_child(b);
554    
555     QT_SET_FLAG(*qtptr);
556    
557     for(;;)
558     {
559     child = QT_NTH_CHILD_PTR(*qtptr,i);
560    
561     if(i != 3)
562     nbr = qtTrace_ray(child,b,db0,db1,db2,orig,dir,func,arg1,arg2);
563     else
564     /* If the center cell- must flip direction signs */
565     nbr =qtTrace_ray(child,b,-db0,-db1,-db2,orig,dir,func,arg1,arg2);
566     if(nbr == QT_DONE)
567     return(nbr);
568    
569     /* If in same block: traverse */
570     if(i==3)
571     next = nbr;
572     else
573     if(nbr == i)
574     next = 3;
575     else
576     {
577     /* reset the barycentric coordinates in the parents*/
578     bary_parent(b,i);
579     /* Else pop up to parent and traverse from there */
580     return(nbr);
581     }
582     bary_from_child(b,i,next);
583     i = next;
584     }
585     }
586     else
587     {
588     #ifdef DEBUG_TEST_DRIVER
589     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
590     Pick_v2[Pick_parent],a1,b1,c1,i,
591     Pick_v0[Pick_cnt],Pick_v1[Pick_cnt],
592     Pick_v2[Pick_cnt]);
593     Pick_cnt++;
594     #endif
595    
596     if(func(qtptr,orig,dir,arg1,arg2) == QT_DONE)
597     return(QT_DONE);
598    
599     /* Advance to next node */
600     /* NOTE: Optimize: should only have to check 1/2 */
601     nbr = move_to_nbr(b,db0,db1,db2,&t);
602    
603     if(nbr != -1)
604     {
605     b[0] += t * db0;
606     b[1] += t * db1;
607     b[2] += t * db2;
608     }
609     return(nbr);
610     }
611    
612     }
613    
614     int
615     qtRoot_trace_ray(qtptr,q0,q1,q2,orig,dir,func,arg1,arg2)
616     QUADTREE *qtptr;
617     FVECT q0,q1,q2;
618     FVECT orig,dir;
619     int (*func)();
620     int *arg1,arg2;
621     {
622     int i,x,y,nbr;
623     QUADTREE *child;
624     FVECT n,c,i_pt,d;
625     double pd,b[3],db[3],t;
626     /* Determine if point lies within pyramid (and therefore
627     inside a spherical quadtree cell):GT_INTERIOR, on one of the
628     pyramid sides (and on cell edge):GT_EDGE(1,2 or 3),
629     or on pyramid vertex (and on cell vertex):GT_VERTEX(1,2, or 3).
630     For each triangle edge: compare the
631     point against the plane formed by the edge and the view center
632     */
633     i = point_in_stri(q0,q1,q2,orig);
634    
635     /* Not in this triangle */
636     if(!i)
637     return(INVALID);
638     /* Project the origin onto the root node plane */
639    
640     /* Find the intersection point of the origin */
641     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
642     intersect_vector_plane(orig,n,pd,NULL,i_pt);
643     /* project the dir as well */
644     VADD(c,orig,dir);
645     intersect_vector_plane(c,n,pd,&t,c);
646    
647     /* map to 2d by dropping maximum magnitude component of normal */
648 gwlarson 3.6 i = max_index(n,NULL);
649 gwlarson 3.4 x = (i+1)%3;
650     y = (i+2)%3;
651     /* Calculate barycentric coordinates of orig */
652     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b);
653     /* Calculate barycentric coordinates of dir */
654     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],c[x],c[y],db);
655     if(t < 0.0)
656     VSUB(db,b,db);
657     else
658     VSUB(db,db,b);
659    
660    
661     #ifdef DEBUG_TEST_DRIVER
662     VCOPY(Pick_v0[Pick_cnt],q0);
663     VCOPY(Pick_v1[Pick_cnt],q1);
664     VCOPY(Pick_v2[Pick_cnt],q2);
665     Pick_cnt++;
666     #endif
667    
668     /* trace the ray starting with this node */
669     nbr = qtTrace_ray(qtptr,b,db[0],db[1],db[2],orig,dir,func,arg1,arg2);
670     return(nbr);
671    
672     }
673    
674 gwlarson 3.6 qtVisit_tri_interior(qtptr,q0,q1,q2,t0,t1,t2,n,func,arg1,arg2,arg3)
675 gwlarson 3.4 QUADTREE *qtptr;
676     FVECT q0,q1,q2;
677     FVECT t0,t1,t2;
678     int n;
679     int (*func)();
680 gwlarson 3.6 int *arg1,arg2,*arg3;
681 gwlarson 3.4 {
682     int i,found,test;
683     QUADTREE *child;
684     FVECT c0,c1,c2,a,b,c;
685     OBJECT os[QT_MAXSET+1],*optr;
686     int w;
687    
688     /* If qt Flag set, or qt vertices interior to t0t1t2-descend */
689     tree_modified:
690    
691     if(QT_IS_TREE(*qtptr))
692     {
693     if(QT_IS_FLAG(*qtptr) || point_in_stri(t0,t1,t2,q0))
694     {
695     QT_SET_FLAG(*qtptr);
696     qtSubdivide_tri(q0,q1,q2,a,b,c);
697     /* descend to children */
698     for(i=0;i < 4; i++)
699     {
700     child = QT_NTH_CHILD_PTR(*qtptr,i);
701     qtNth_child_tri(q0,q1,q2,a,b,c,i,c0,c1,c2);
702     qtVisit_tri_interior(child,c0,c1,c2,t0,t1,t2,n+1,
703 gwlarson 3.6 func,arg1,arg2,arg3);
704 gwlarson 3.4 }
705     }
706     }
707     else
708     {
709     /* NOTE THIS IN TRI TEST Could be replaced by a flag */
710     if(!QT_IS_EMPTY(*qtptr))
711     {
712     if(qtinset(*qtptr,arg2))
713 gwlarson 3.6 if(func(qtptr,q0,q1,q2,t0,t1,t2,n,arg1,arg2,arg3)==QT_MODIFIED)
714 gwlarson 3.4 goto tree_modified;
715     else
716     return;
717     }
718     if(point_in_stri(t0,t1,t2,q0) )
719 gwlarson 3.6 if(func(qtptr,q0,q1,q2,t0,t1,t2,n,arg1,arg2,arg3)==QT_MODIFIED)
720 gwlarson 3.4 goto tree_modified;
721     }
722     }
723    
724    
725    
726    
727    
728    
729 gwlarson 3.6 /* NOTE: SINCE DIR could be unit: then we could use integer math */
730 gwlarson 3.4 int
731 gwlarson 3.6 qtVisit_tri_edges(qtptr,b,db0,db1,db2,
732     db,wptr,t,sign,sfactor,func,arg1,arg2,arg3)
733 gwlarson 3.4 QUADTREE *qtptr;
734 gwlarson 3.6 double b[3],db0,db1,db2,db[3][3];
735 gwlarson 3.4 int *wptr;
736 gwlarson 3.6 double t[3];
737     int sign;
738 gwlarson 3.4 double sfactor;
739     int (*func)();
740 gwlarson 3.6 int *arg1,arg2,*arg3;
741 gwlarson 3.4 {
742     int i,found;
743     QUADTREE *child;
744     int nbr,next,w;
745 gwlarson 3.6 double t_l,t_g;
746 gwlarson 3.4 #ifdef DEBUG_TEST_DRIVER
747     FVECT a1,b1,c1;
748     int Pick_parent = Pick_cnt-1;
749     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
750     Pick_v2[Pick_parent],a1,b1,c1);
751     #endif
752     if(QT_IS_TREE(*qtptr))
753     {
754     /* Find the appropriate child and reset the coord */
755     i = bary_child(b);
756    
757     QT_SET_FLAG(*qtptr);
758    
759     for(;;)
760     {
761     w = *wptr;
762     child = QT_NTH_CHILD_PTR(*qtptr,i);
763    
764     if(i != 3)
765 gwlarson 3.6 nbr = qtVisit_tri_edges(child,b,db0,db1,db2,
766     db,wptr,t,sign,
767     sfactor*2.0,func,arg1,arg2,arg3);
768     else
769     /* If the center cell- must flip direction signs */
770     nbr = qtVisit_tri_edges(child,b,-db0,-db1,-db2,
771     db,wptr,t,1-sign,
772     sfactor*2.0,func,arg1,arg2,arg3);
773 gwlarson 3.4
774     if(nbr == QT_DONE)
775 gwlarson 3.6 return(nbr);
776     if(*wptr != w)
777     {
778     w = *wptr;
779     db0 = db[w][0];db1 = db[w][1];db2 = db[w][2];
780     if(sign)
781     { db0 *= -1.0;db1 *= -1.0; db2 *= -1.0;}
782     }
783 gwlarson 3.4 /* If in same block: traverse */
784     if(i==3)
785     next = nbr;
786     else
787     if(nbr == i)
788     next = 3;
789     else
790     {
791     /* reset the barycentric coordinates in the parents*/
792     bary_parent(b,i);
793     /* Else pop up to parent and traverse from there */
794     return(nbr);
795     }
796 gwlarson 3.6 bary_from_child(b,i,next);
797     i = next;
798     }
799 gwlarson 3.4 }
800     else
801     {
802     #ifdef DEBUG_TEST_DRIVER
803     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
804     Pick_v2[Pick_parent],a1,b1,c1,i,Pick_v0[Pick_cnt],
805     Pick_v1[Pick_cnt],Pick_v2[Pick_cnt]);
806     Pick_cnt++;
807     #endif
808    
809 gwlarson 3.6 if(func(qtptr,arg1,arg2,arg3) == QT_DONE)
810 gwlarson 3.4 return(QT_DONE);
811    
812     /* Advance to next node */
813     w = *wptr;
814     while(1)
815     {
816 gwlarson 3.6 nbr = move_to_nbr(b,db0,db1,db2,&t_l);
817 gwlarson 3.4
818 gwlarson 3.6 t_g = t_l/sfactor;
819     #ifdef DEBUG
820     if(t[w] <= 0.0)
821     eputs("qtVisit_tri_edges():negative t\n");
822     #endif
823     if(t_g >= t[w])
824     {
825 gwlarson 3.4 if(w == 2)
826     return(QT_DONE);
827 gwlarson 3.6
828     b[0] += (t[w])*sfactor*db0;
829     b[1] += (t[w])*sfactor*db1;
830     b[2] += (t[w])*sfactor*db2;
831 gwlarson 3.4 w++;
832 gwlarson 3.6 db0 = db[w][0];
833     db1 = db[w][1];
834     db2 = db[w][2];
835     if(sign)
836     { db0 *= -1.0;db1 *= -1.0; db2 *= -1.0;}
837 gwlarson 3.4 }
838     else
839     if(nbr != INVALID)
840     {
841 gwlarson 3.6 b[0] += t_l * db0;
842     b[1] += t_l * db1;
843     b[2] += t_l * db2;
844    
845     t[w] -= t_g;
846 gwlarson 3.4 *wptr = w;
847     return(nbr);
848     }
849     else
850     return(INVALID);
851     }
852     }
853    
854     }
855    
856    
857     int
858 gwlarson 3.6 qtRoot_visit_tri_edges(qtptr,q0,q1,q2,tri,i_pt,wptr,func,arg1,arg2,arg3)
859 gwlarson 3.4 QUADTREE *qtptr;
860     FVECT q0,q1,q2;
861 gwlarson 3.6 FVECT tri[3],i_pt;
862 gwlarson 3.4 int *wptr;
863     int (*func)();
864 gwlarson 3.6 int *arg1,arg2,*arg3;
865 gwlarson 3.4 {
866 gwlarson 3.6 int x,y,z,nbr,w,i,j;
867 gwlarson 3.4 QUADTREE *child;
868 gwlarson 3.6 FVECT n,c,d,v[3];
869     double pd,b[4][3],db[3][3],et[3],t[3],exit_pt;
870 gwlarson 3.4
871     w = *wptr;
872    
873     /* Project the origin onto the root node plane */
874    
875     /* Find the intersection point of the origin */
876     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
877     /* map to 2d by dropping maximum magnitude component of normal */
878 gwlarson 3.6 z = max_index(n,NULL);
879     x = (z+1)%3;
880     y = (z+2)%3;
881 gwlarson 3.4 /* Calculate barycentric coordinates for current vertex */
882 gwlarson 3.6 if(w != -1)
883 gwlarson 3.4 {
884 gwlarson 3.6 bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[3]);
885     intersect_vector_plane(tri[w],n,pd,&(et[w]),v[w]);
886     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[w][x],v[w][y],b[w]);
887 gwlarson 3.4 }
888 gwlarson 3.6 else
889     /* Just starting: b[0] is the origin point: guaranteed to be valid b*/
890     {
891     w = 0;
892     intersect_vector_plane(tri[0],n,pd,&(et[0]),v[0]);
893     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[0][x],v[0][y],b[0]);
894     VCOPY(b[3],b[0]);
895     }
896    
897    
898     j = (w+1)%3;
899     intersect_vector_plane(tri[j],n,pd,&(et[j]),v[j]);
900     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[j][x],v[j][y],b[j]);
901     if(et[j] < 0.0)
902     {
903     VSUB(db[w],b[3],b[j]);
904     t[w] = FHUGE;
905     }
906     else
907     {
908     /* NOTE: for stability: do not increment with ipt- use full dir and
909     calculate t: but for wrap around case: could get same problem?
910     */
911     VSUB(db[w],b[j],b[3]);
912     t[w] = 1.0;
913     move_to_nbr(b[3],db[w][0],db[w][1],db[w][2],&exit_pt);
914     if(exit_pt >= 1.0)
915     {
916     for(;j < 3;j++)
917     {
918     i = (j+1)%3;
919     if(i!= w)
920     {
921     intersect_vector_plane(tri[i],n,pd,&(et[i]),v[i]);
922     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[i][x],
923     v[i][y],b[i]);
924     }
925     if(et[i] < 0.0)
926     {
927     VSUB(db[j],b[j],b[i]);
928     t[j] = FHUGE;
929     break;
930     }
931     else
932     {
933     VSUB(db[j],b[i],b[j]);
934     t[j] = 1.0;
935     }
936     move_to_nbr(b[j],db[j][0],db[j][1],db[j][2],&exit_pt);
937     if(exit_pt < 1.0)
938     break;
939     }
940     }
941     }
942     *wptr = w;
943     /* trace the ray starting with this node */
944     nbr = qtVisit_tri_edges(qtptr,b[3],db[w][0],db[w][1],db[w][2],
945     db,wptr,t,0,1.0,func,arg1,arg2,arg3);
946     if(nbr != INVALID && nbr != QT_DONE)
947     {
948     i_pt[x] = b[3][0]*q0[x] + b[3][1]*q1[x] + b[3][2]*q2[x];
949     i_pt[y] = b[3][0]*q0[y] + b[3][1]*q1[y] + b[3][2]*q2[y];
950     i_pt[z] = (-n[x]*i_pt[x] - n[y]*i_pt[y] -pd)/n[z];
951     }
952 gwlarson 3.4 return(nbr);
953    
954     }
955    
956 gwlarson 3.6 int
957     move_to_nbri(b,db0,db1,db2,tptr)
958     BCOORD b[3];
959     BDIR db0,db1,db2;
960     TINT *tptr;
961     {
962     TINT t,dt;
963     BCOORD bc;
964     int nbr;
965    
966     nbr = -1;
967     /* Advance to next node */
968     if(db0 < 0)
969     {
970     bc = MAXBCOORD*b[0];
971     t = bc/-db0;
972     nbr = 0;
973     }
974     else
975     t = HUGET;
976     if(db1 < 0)
977     {
978     bc = MAXBCOORD*b[1];
979     dt = bc/-db1;
980     if( dt < t)
981     {
982     t = dt;
983     nbr = 1;
984     }
985     }
986     if(db2 < 0)
987     {
988     bc = MAXBCOORD*b[2];
989     dt = bc/-db2;
990     if( dt < t)
991     {
992     t = dt;
993     nbr = 2;
994     }
995     }
996     *tptr = t;
997     return(nbr);
998     }
999 gwlarson 3.4 /* NOTE: SINCE DIR could be unit: then we could use integer math */
1000     int
1001 gwlarson 3.6 qtVisit_tri_edgesi(qtptr,b,db0,db1,db2,
1002     db,wptr,t,sign,sfactor,func,arg1,arg2,arg3)
1003 gwlarson 3.4 QUADTREE *qtptr;
1004 gwlarson 3.6 BCOORD b[3];
1005     BDIR db0,db1,db2,db[3][3];
1006 gwlarson 3.4 int *wptr;
1007 gwlarson 3.6 TINT t[3];
1008 gwlarson 3.4 int sign;
1009 gwlarson 3.6 int sfactor;
1010 gwlarson 3.4 int (*func)();
1011 gwlarson 3.6 int *arg1,arg2,*arg3;
1012 gwlarson 3.4 {
1013     int i,found;
1014     QUADTREE *child;
1015     int nbr,next,w;
1016 gwlarson 3.6 TINT t_g,t_l,t_i;
1017 gwlarson 3.4 #ifdef DEBUG_TEST_DRIVER
1018     FVECT a1,b1,c1;
1019     int Pick_parent = Pick_cnt-1;
1020     qtSubdivide_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
1021     Pick_v2[Pick_parent],a1,b1,c1);
1022     #endif
1023     if(QT_IS_TREE(*qtptr))
1024     {
1025     /* Find the appropriate child and reset the coord */
1026 gwlarson 3.6 i = baryi_child(b);
1027 gwlarson 3.4
1028     QT_SET_FLAG(*qtptr);
1029    
1030     for(;;)
1031     {
1032     w = *wptr;
1033     child = QT_NTH_CHILD_PTR(*qtptr,i);
1034    
1035     if(i != 3)
1036 gwlarson 3.6 nbr = qtVisit_tri_edgesi(child,b,db0,db1,db2,
1037 gwlarson 3.4 db,wptr,t,sign,
1038 gwlarson 3.6 sfactor+1,func,arg1,arg2,arg3);
1039 gwlarson 3.4 else
1040     /* If the center cell- must flip direction signs */
1041 gwlarson 3.6 nbr = qtVisit_tri_edgesi(child,b,-db0,-db1,-db2,
1042 gwlarson 3.4 db,wptr,t,1-sign,
1043 gwlarson 3.6 sfactor+1,func,arg1,arg2,arg3);
1044 gwlarson 3.4
1045     if(nbr == QT_DONE)
1046     return(nbr);
1047     if(*wptr != w)
1048     {
1049     w = *wptr;
1050     db0 = db[w][0];db1 = db[w][1];db2 = db[w][2];
1051     if(sign)
1052 gwlarson 3.6 { db0 *= -1;db1 *= -1; db2 *= -1;}
1053 gwlarson 3.4 }
1054     /* If in same block: traverse */
1055     if(i==3)
1056     next = nbr;
1057     else
1058     if(nbr == i)
1059     next = 3;
1060     else
1061     {
1062     /* reset the barycentric coordinates in the parents*/
1063 gwlarson 3.6 baryi_parent(b,i);
1064 gwlarson 3.4 /* Else pop up to parent and traverse from there */
1065     return(nbr);
1066     }
1067 gwlarson 3.6 baryi_from_child(b,i,next);
1068 gwlarson 3.4 i = next;
1069     }
1070     }
1071     else
1072     {
1073     #ifdef DEBUG_TEST_DRIVER
1074     qtNth_child_tri(Pick_v0[Pick_parent],Pick_v1[Pick_parent],
1075     Pick_v2[Pick_parent],a1,b1,c1,i,Pick_v0[Pick_cnt],
1076     Pick_v1[Pick_cnt],Pick_v2[Pick_cnt]);
1077     Pick_cnt++;
1078     #endif
1079    
1080 gwlarson 3.6 if(func(qtptr,arg1,arg2,arg3) == QT_DONE)
1081 gwlarson 3.4 return(QT_DONE);
1082    
1083     /* Advance to next node */
1084     w = *wptr;
1085     while(1)
1086     {
1087 gwlarson 3.6 nbr = move_to_nbri(b,db0,db1,db2,&t_i);
1088 gwlarson 3.4
1089 gwlarson 3.6 t_g = t_i >> sfactor;
1090    
1091 gwlarson 3.4 if(t_g >= t[w])
1092     {
1093     if(w == 2)
1094     return(QT_DONE);
1095    
1096 gwlarson 3.6 /* The edge fits in the cell- therefore the result of shifting db by
1097     sfactor is guaranteed to be less than MAXBCOORD
1098     */
1099     /* Caution: (t[w]*db) must occur before divide by MAXBCOORD
1100     since t[w] will always be < MAXBCOORD
1101     */
1102     b[0] = b[0] + (t[w]*db0*(1 << sfactor))/MAXBCOORD;
1103     b[1] = b[1] + (t[w]*db1*(1 << sfactor))/MAXBCOORD;
1104     b[2] = b[2] + (t[w]*db2*(1 << sfactor))/MAXBCOORD;
1105 gwlarson 3.4 w++;
1106 gwlarson 3.6 db0 = db[w][0]; db1 = db[w][1]; db2 = db[w][2];
1107 gwlarson 3.4 if(sign)
1108 gwlarson 3.6 { db0 *= -1;db1 *= -1; db2 *= -1;}
1109 gwlarson 3.4 }
1110     else
1111     if(nbr != INVALID)
1112     {
1113 gwlarson 3.6 /* Caution: (t_i*db) must occur before divide by MAXBCOORD
1114     since t_i will always be < MAXBCOORD
1115     */
1116     b[0] = b[0] + (t_i *db0) / MAXBCOORD;
1117     b[1] = b[1] + (t_i *db1) / MAXBCOORD;
1118     b[2] = b[2] + (t_i *db2) / MAXBCOORD;
1119 gwlarson 3.4
1120     t[w] -= t_g;
1121     *wptr = w;
1122     return(nbr);
1123     }
1124     else
1125     return(INVALID);
1126     }
1127 gwlarson 3.6 }
1128 gwlarson 3.4 }
1129    
1130    
1131     int
1132 gwlarson 3.6 qtRoot_visit_tri_edgesi(qtptr,q0,q1,q2,tri,i_pt,wptr,func,arg1,arg2,arg3)
1133 gwlarson 3.4 QUADTREE *qtptr;
1134     FVECT q0,q1,q2;
1135     FVECT tri[3],i_pt;
1136     int *wptr;
1137     int (*func)();
1138 gwlarson 3.6 int *arg1,arg2,*arg3;
1139 gwlarson 3.4 {
1140     int x,y,z,nbr,w,i,j;
1141     QUADTREE *child;
1142     FVECT n,c,d,v[3];
1143 gwlarson 3.6 double pd,b[4][3],db[3][3],et[3],exit_pt;
1144     BCOORD bi[3];
1145     TINT t[3];
1146     BDIR dbi[3][3];
1147 gwlarson 3.4 w = *wptr;
1148    
1149     /* Project the origin onto the root node plane */
1150    
1151 gwlarson 3.6 t[0] = t[1] = t[2] = 0;
1152 gwlarson 3.4 /* Find the intersection point of the origin */
1153     tri_plane_equation(q0,q1,q2,n,&pd,FALSE);
1154     /* map to 2d by dropping maximum magnitude component of normal */
1155 gwlarson 3.6 z = max_index(n,NULL);
1156 gwlarson 3.4 x = (z+1)%3;
1157     y = (z+2)%3;
1158     /* Calculate barycentric coordinates for current vertex */
1159     if(w != -1)
1160     {
1161     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],i_pt[x],i_pt[y],b[3]);
1162     intersect_vector_plane(tri[w],n,pd,&(et[w]),v[w]);
1163     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[w][x],v[w][y],b[w]);
1164     }
1165     else
1166     /* Just starting: b[0] is the origin point: guaranteed to be valid b*/
1167     {
1168     w = 0;
1169     intersect_vector_plane(tri[0],n,pd,&(et[0]),v[0]);
1170     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[0][x],v[0][y],b[0]);
1171     VCOPY(b[3],b[0]);
1172     }
1173    
1174    
1175     j = (w+1)%3;
1176     intersect_vector_plane(tri[j],n,pd,&(et[j]),v[j]);
1177     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[j][x],v[j][y],b[j]);
1178     if(et[j] < 0.0)
1179     {
1180     VSUB(db[w],b[3],b[j]);
1181 gwlarson 3.6 t[w] = HUGET;
1182 gwlarson 3.4 }
1183     else
1184     {
1185 gwlarson 3.5 /* NOTE: for stability: do not increment with ipt- use full dir and
1186     calculate t: but for wrap around case: could get same problem?
1187     */
1188 gwlarson 3.4 VSUB(db[w],b[j],b[3]);
1189 gwlarson 3.6 /* Check if the point is out side of the triangle: if so t[w] =HUGET */
1190     if((fabs(b[j][0])>(FTINY+1.0)) ||(fabs(b[j][1])>(FTINY+1.0)) ||
1191     (fabs(b[j][2])>(FTINY+1.0)))
1192     t[w] = HUGET;
1193     else
1194 gwlarson 3.4 {
1195 gwlarson 3.6 /* The next point is in the triangle- so db values will be in valid
1196     range and t[w]= MAXT
1197     */
1198     t[w] = MAXT;
1199     if(j != 0)
1200     for(;j < 3;j++)
1201 gwlarson 3.4 {
1202 gwlarson 3.6 i = (j+1)%3;
1203     if(i!= w)
1204     {
1205     intersect_vector_plane(tri[i],n,pd,&(et[i]),v[i]);
1206     bary2d(q0[x],q0[y],q1[x],q1[y],q2[x],q2[y],v[i][x],
1207     v[i][y],b[i]);
1208     }
1209     if(et[i] < 0.0)
1210     {
1211     VSUB(db[j],b[j],b[i]);
1212     t[j] = HUGET;
1213     break;
1214     }
1215     else
1216     {
1217     VSUB(db[j],b[i],b[j]);
1218     if((fabs(b[j][0])>(FTINY+1.0)) ||
1219     (fabs(b[j][1])>(FTINY+1.0)) ||
1220     (fabs(b[j][2])>(FTINY+1.0)))
1221     {
1222     t[j] = HUGET;
1223     break;
1224     }
1225     else
1226     t[j] = MAXT;
1227     }
1228 gwlarson 3.4 }
1229     }
1230 gwlarson 3.6 }
1231 gwlarson 3.4 *wptr = w;
1232 gwlarson 3.6 bary_dtol(b[3],db,bi,dbi,t);
1233    
1234 gwlarson 3.4 /* trace the ray starting with this node */
1235 gwlarson 3.6 nbr = qtVisit_tri_edgesi(qtptr,bi,dbi[w][0],dbi[w][1],dbi[w][2],
1236     dbi,wptr,t,0,0,func,arg1,arg2,arg3);
1237 gwlarson 3.4 if(nbr != INVALID && nbr != QT_DONE)
1238     {
1239 gwlarson 3.6 b[3][0] = (double)bi[0]/(double)MAXBCOORD;
1240     b[3][1] = (double)bi[1]/(double)MAXBCOORD;
1241     b[3][2] = (double)bi[2]/(double)MAXBCOORD;
1242     i_pt[x] = b[3][0]*q0[x] + b[3][1]*q1[x] + b[3][2]*q2[x];
1243     i_pt[y] = b[3][0]*q0[y] + b[3][1]*q1[y] + b[3][2]*q2[y];
1244     i_pt[z] = (-n[x]*i_pt[x] - n[y]*i_pt[y] -pd)/n[z];
1245 gwlarson 3.4 }
1246     return(nbr);
1247    
1248     }
1249    
1250    
1251    
1252    
1253 gwlarson 3.3
1254 gwlarson 3.2
1255    
1256    
1257    
1258    
1259    
1260    
1261    
1262    
1263    
1264