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

# 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 gwlarson 3.7 #include "sm_flag.h"
18 gwlarson 3.1 #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 gwlarson 3.7
31    
32 gwlarson 3.4 #endif
33 gwlarson 3.7 int Incnt=0;
34 gwlarson 3.4
35 gwlarson 3.1 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 gwlarson 3.3 QT_BLOCK_SIZE*4*sizeof(QUADTREE))) == NULL)
52 gwlarson 3.7 error(SYSTEM,"qtAlloc(): Unable to allocate memory\n");
53 gwlarson 3.4
54 gwlarson 3.7 /* Realloc the per/node flags */
55 gwlarson 3.3 quad_flag = (int4 *)realloc((char *)quad_flag,
56 gwlarson 3.7 (QT_BLOCK(freet)+1)*((QT_BLOCK_SIZE+7)>>3));
57 gwlarson 3.3 if (quad_flag == NULL)
58 gwlarson 3.7 error(SYSTEM,"qtAlloc(): Unable to allocate memory\n");
59 gwlarson 3.1 }
60     treetop += 4;
61     return(freet);
62     }
63    
64    
65 gwlarson 3.3 qtClearAllFlags() /* clear all quadtree branch flags */
66     {
67 gwlarson 3.7 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 gwlarson 3.3 }
75    
76 gwlarson 3.1 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 gwlarson 3.7
97 gwlarson 3.4 qtfreeleaves();
98 gwlarson 3.1 for (i = 0; i < QT_MAX_BLK; i++)
99     {
100 gwlarson 3.3 if (quad_block[i] == NULL)
101     break;
102     free((char *)quad_block[i]);
103 gwlarson 3.1 quad_block[i] = NULL;
104     }
105 gwlarson 3.7 /* Free the flags */
106 gwlarson 3.3 if (i) free((char *)quad_flag);
107     quad_flag = NULL;
108 gwlarson 3.1 quad_free_list = EMPTY;
109     treetop = 0;
110     }
111    
112     QUADTREE
113 gwlarson 3.7 qtLocate_leaf(qt,bcoord)
114     QUADTREE qt;
115     BCOORD bcoord[3];
116 gwlarson 3.2 {
117     int i;
118    
119 gwlarson 3.7 if(QT_IS_TREE(qt))
120     {
121     i = baryi_child(bcoord);
122 gwlarson 3.4
123 gwlarson 3.7 return(qtLocate_leaf(QT_NTH_CHILD(qt,i),bcoord));
124     }
125     else
126     return(qt);
127 gwlarson 3.2 }
128    
129 gwlarson 3.7 /*
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 gwlarson 3.2 QUADTREE
134 gwlarson 3.7 qtRoot_point_locate(qt,q0,q1,q2,peq,pt)
135     QUADTREE qt;
136     FVECT q0,q1,q2;
137     FPEQ peq;
138 gwlarson 3.1 FVECT pt;
139     {
140 gwlarson 3.2 int i,x,y;
141 gwlarson 3.7 FVECT i_pt;
142     double bcoord[3];
143     BCOORD bcoordi[3];
144 gwlarson 3.1
145 gwlarson 3.7 /* Will return lowest level triangle containing point: It the
146 gwlarson 3.1 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 gwlarson 3.7 if(QT_IS_TREE(qt))
151 gwlarson 3.1 {
152 gwlarson 3.2 /* Find the intersection point */
153 gwlarson 3.7 intersect_vector_plane(pt,peq,NULL,i_pt);
154 gwlarson 3.2
155 gwlarson 3.7 x = FP_X(peq);
156     y = FP_Y(peq);
157 gwlarson 3.2 /* Calculate barycentric coordinates of i_pt */
158 gwlarson 3.7 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 gwlarson 3.2
163 gwlarson 3.7 i = baryi_child(bcoordi);
164    
165     return(qtLocate_leaf(QT_NTH_CHILD(qt,i),bcoordi));
166 gwlarson 3.1 }
167     else
168 gwlarson 3.7 return(qt);
169 gwlarson 3.1 }
170    
171 gwlarson 3.4
172 gwlarson 3.1
173    
174 gwlarson 3.2 /* for triangle v0-v1-v2- returns a,b,c: children are:
175 gwlarson 3.1
176 gwlarson 3.2 v2 0: v0,a,c
177     /\ 1: a,v1,b
178     /2 \ 2: c,b,v2
179     c/____\b 3: b,c,a
180 gwlarson 3.1 /\ /\
181 gwlarson 3.2 /0 \3 /1 \
182     v0____\/____\v1
183 gwlarson 3.1 a
184     */
185    
186    
187 gwlarson 3.2 qtNth_child_tri(v0,v1,v2,a,b,c,i,r0,r1,r2)
188     FVECT v0,v1,v2;
189 gwlarson 3.1 FVECT a,b,c;
190     int i;
191 gwlarson 3.2 FVECT r0,r1,r2;
192 gwlarson 3.1 {
193 gwlarson 3.4
194 gwlarson 3.7 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 gwlarson 3.1 }
220 gwlarson 3.7 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 gwlarson 3.1 }
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 gwlarson 3.7 QUADTREE
248     qtRoot_add_tri(qt,q0,q1,q2,t0,t1,t2,id,n)
249     QUADTREE qt;
250 gwlarson 3.4 FVECT q0,q1,q2;
251     FVECT t0,t1,t2;
252 gwlarson 3.7 int id,n;
253 gwlarson 3.3 {
254 gwlarson 3.7 if(stri_intersect(q0,q1,q2,t0,t1,t2))
255     qt = qtAdd_tri(qt,q0,q1,q2,t0,t1,t2,id,n);
256 gwlarson 3.3
257 gwlarson 3.7 return(qt);
258 gwlarson 3.3 }
259    
260 gwlarson 3.7 QUADTREE
261     qtRoot_remove_tri(qt,q0,q1,q2,t0,t1,t2,id,n)
262     QUADTREE qt;
263 gwlarson 3.4 FVECT q0,q1,q2;
264 gwlarson 3.3 FVECT t0,t1,t2;
265 gwlarson 3.7 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 gwlarson 3.1 int id;
280     int n;
281     {
282     FVECT a,b,c;
283 gwlarson 3.7 OBJECT tset[QT_MAXSET+1],*optr,*tptr;
284 gwlarson 3.2 FVECT r0,r1,r2;
285 gwlarson 3.7 int i;
286 gwlarson 3.1
287     /* if this is tree: recurse */
288 gwlarson 3.7 if(QT_IS_TREE(qt))
289 gwlarson 3.1 {
290 gwlarson 3.7 QT_SET_FLAG(qt);
291 gwlarson 3.1 n++;
292 gwlarson 3.4 qtSubdivide_tri(q0,q1,q2,a,b,c);
293 gwlarson 3.7
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 gwlarson 3.1 }
304     else
305     {
306     /* If this leave node emptry- create a new set */
307 gwlarson 3.7 if(QT_IS_EMPTY(qt))
308     qt = qtaddelem(qt,id);
309 gwlarson 3.1 else
310     {
311     /* If the set is too large: subdivide */
312 gwlarson 3.7 optr = qtqueryset(qt);
313 gwlarson 3.4
314     if(QT_SET_CNT(optr) < QT_SET_THRESHOLD)
315 gwlarson 3.7 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 gwlarson 3.4
336 gwlarson 3.7 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 gwlarson 3.4
342 gwlarson 3.7 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 gwlarson 3.4 }
352 gwlarson 3.1 else
353 gwlarson 3.7 qt = qtaddelem(qt,id);
354     }
355 gwlarson 3.1 }
356     }
357 gwlarson 3.7 return(qt);
358     memerr:
359     error(SYSTEM,"qtAdd_tri():Unable to allocate memory");
360 gwlarson 3.1 }
361    
362    
363 gwlarson 3.7 QUADTREE
364     qtRemove_tri(qt,id,q0,q1,q2,t0,t1,t2)
365     QUADTREE qt;
366 gwlarson 3.1 int id;
367 gwlarson 3.7 FVECT q0,q1,q2;
368 gwlarson 3.2 FVECT t0,t1,t2;
369 gwlarson 3.1 {
370     FVECT a,b,c;
371    
372 gwlarson 3.2 /* test if triangle (t0,t1,t2) overlaps cell triangle (v0,v1,v2) */
373 gwlarson 3.7 if(!stri_intersect(t0,t1,t2,q0,q1,q2))
374     return(qt);
375 gwlarson 3.1
376     /* if this is tree: recurse */
377 gwlarson 3.7 if(QT_IS_TREE(qt))
378 gwlarson 3.1 {
379 gwlarson 3.7 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 gwlarson 3.1 }
386     else
387     {
388 gwlarson 3.7 if(QT_IS_EMPTY(qt))
389 gwlarson 3.1 {
390     #ifdef DEBUG
391     eputs("qtRemove_tri(): triangle not found\n");
392     #endif
393     }
394     /* remove id from set */
395     else
396     {
397 gwlarson 3.7 if(!qtinset(qt,id))
398 gwlarson 3.1 {
399     #ifdef DEBUG
400     eputs("qtRemove_tri(): tri not in set\n");
401     #endif
402     }
403     else
404 gwlarson 3.7 qt = qtdelelem(qt,id);
405 gwlarson 3.1 }
406     }
407 gwlarson 3.7 return(qt);
408 gwlarson 3.1 }
409 gwlarson 3.4
410    
411 gwlarson 3.7 QUADTREE
412     qtVisit_tri_interior(qt,q0,q1,q2,t0,t1,t2,n0,n1,n2,n,func,f,argptr)
413     QUADTREE qt;
414 gwlarson 3.4 FVECT q0,q1,q2;
415     FVECT t0,t1,t2;
416 gwlarson 3.7 FVECT n0,n1,n2;
417 gwlarson 3.4 int n;
418 gwlarson 3.7 int (*func)(),*f;
419     int *argptr;
420 gwlarson 3.4 {
421 gwlarson 3.7 FVECT a,b,c;
422 gwlarson 3.4
423     /* If qt Flag set, or qt vertices interior to t0t1t2-descend */
424     tree_modified:
425    
426 gwlarson 3.7 if(QT_IS_TREE(qt))
427 gwlarson 3.4 {
428 gwlarson 3.7 if(QT_IS_FLAG(qt) || point_in_stri_n(n0,n1,n2,q0))
429 gwlarson 3.4 {
430 gwlarson 3.7 QT_SET_FLAG(qt);
431 gwlarson 3.4 qtSubdivide_tri(q0,q1,q2,a,b,c);
432     /* descend to children */
433 gwlarson 3.7 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 gwlarson 3.4 }
442     }
443     else
444 gwlarson 3.7 if((!QT_IS_EMPTY(qt) && QT_LEAF_IS_FLAG(qt)) ||
445     point_in_stri_n(n0,n1,n2,q0))
446 gwlarson 3.4 {
447 gwlarson 3.7 func(&qt,f,argptr,q0,q1,q2,t0,t1,t2,n);
448     if(QT_FLAG_IS_MODIFIED(*f))
449 gwlarson 3.4 {
450 gwlarson 3.7 QT_SET_FLAG(qt);
451     goto tree_modified;
452 gwlarson 3.4 }
453 gwlarson 3.7 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 gwlarson 3.4 }
461    
462    
463    
464 gwlarson 3.6 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 gwlarson 3.7 *tptr = 0;
476 gwlarson 3.6 /* Advance to next node */
477 gwlarson 3.7 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 gwlarson 3.6 if(db0 < 0)
485     {
486 gwlarson 3.7 bc = b[0]<<SHIFT_MAXBCOORD;
487 gwlarson 3.6 t = bc/-db0;
488     nbr = 0;
489     }
490     else
491     t = HUGET;
492     if(db1 < 0)
493     {
494 gwlarson 3.7 bc = b[1] <<SHIFT_MAXBCOORD;
495 gwlarson 3.6 dt = bc/-db1;
496     if( dt < t)
497     {
498     t = dt;
499     nbr = 1;
500     }
501     }
502     if(db2 < 0)
503     {
504 gwlarson 3.7 bc = b[2] << SHIFT_MAXBCOORD;
505 gwlarson 3.6 dt = bc/-db2;
506     if( dt < t)
507     {
508     t = dt;
509     nbr = 2;
510     }
511     }
512     *tptr = t;
513     return(nbr);
514     }
515 gwlarson 3.7
516     QUADTREE
517     qtVisit_tri_edges(qt,b,db0,db1,db2,db,wptr,nextptr,t,sign,sfactor,func,f,argptr)
518     QUADTREE qt;
519 gwlarson 3.6 BCOORD b[3];
520     BDIR db0,db1,db2,db[3][3];
521 gwlarson 3.7 int *wptr,*nextptr;
522 gwlarson 3.6 TINT t[3];
523 gwlarson 3.7 int sign,sfactor;
524 gwlarson 3.4 int (*func)();
525 gwlarson 3.7 int *f,*argptr;
526 gwlarson 3.4 {
527     int i,found;
528 gwlarson 3.7 QUADTREE child;
529 gwlarson 3.4 int nbr,next,w;
530 gwlarson 3.7 TINT t_g,t_l,t_i,l;
531    
532     if(QT_IS_TREE(qt))
533 gwlarson 3.4 {
534 gwlarson 3.7 /* Find the appropriate child and reset the coord */
535     i = baryi_child(b);
536 gwlarson 3.4
537 gwlarson 3.7 QT_SET_FLAG(qt);
538 gwlarson 3.4
539 gwlarson 3.7 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 gwlarson 3.4 w = *wptr;
558 gwlarson 3.7 db0 = db[w][0];db1 = db[w][1];db2 = db[w][2];
559     if(sign)
560     { db0 *= -1;db1 *= -1; db2 *= -1;}
561 gwlarson 3.4 }
562 gwlarson 3.7 /* 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 gwlarson 3.4 }
579     else
580     {
581 gwlarson 3.7 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 gwlarson 3.4 {
595 gwlarson 3.7 nbr = move_to_nbri(b,db0,db1,db2,&t_i);
596    
597 gwlarson 3.6 t_g = t_i >> sfactor;
598    
599 gwlarson 3.4 if(t_g >= t[w])
600     {
601     if(w == 2)
602 gwlarson 3.7 {
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 gwlarson 3.6 /* Caution: (t[w]*db) must occur before divide by MAXBCOORD
610     since t[w] will always be < MAXBCOORD
611 gwlarson 3.7 */
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 gwlarson 3.4 w++;
618 gwlarson 3.6 db0 = db[w][0]; db1 = db[w][1]; db2 = db[w][2];
619 gwlarson 3.4 if(sign)
620 gwlarson 3.7 { db0 *= -1;db1 *= -1; db2 *= -1;}
621 gwlarson 3.4 }
622 gwlarson 3.7 else
623     {
624 gwlarson 3.6 /* Caution: (t_i*db) must occur before divide by MAXBCOORD
625 gwlarson 3.7 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 gwlarson 3.4 t[w] -= t_g;
632     *wptr = w;
633 gwlarson 3.7 *nextptr = nbr;
634     return(qt);
635 gwlarson 3.4 }
636     }
637 gwlarson 3.6 }
638 gwlarson 3.4 }
639    
640    
641 gwlarson 3.7 QUADTREE
642     qtRoot_visit_tri_edges(qt,q0,q1,q2,peq,tri,i_pt,wptr,nextptr,func,f,argptr)
643     QUADTREE qt;
644 gwlarson 3.4 FVECT q0,q1,q2;
645 gwlarson 3.7 FPEQ peq;
646 gwlarson 3.4 FVECT tri[3],i_pt;
647 gwlarson 3.7 int *wptr,*nextptr;
648 gwlarson 3.4 int (*func)();
649 gwlarson 3.7 int *f,*argptr;
650 gwlarson 3.4 {
651 gwlarson 3.7 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 gwlarson 3.6 BCOORD bi[3];
656     TINT t[3];
657     BDIR dbi[3][3];
658 gwlarson 3.7
659     first =0;
660 gwlarson 3.4 w = *wptr;
661 gwlarson 3.7 if(w==-1)
662     {
663     first = 1;
664     *wptr = w = 0;
665     }
666 gwlarson 3.4 /* Project the origin onto the root node plane */
667    
668 gwlarson 3.6 t[0] = t[1] = t[2] = 0;
669 gwlarson 3.4 /* Find the intersection point of the origin */
670     /* map to 2d by dropping maximum magnitude component of normal */
671 gwlarson 3.7
672     x = FP_X(peq);
673     y = FP_Y(peq);
674     z = FP_Z(peq);
675 gwlarson 3.4 /* Calculate barycentric coordinates for current vertex */
676 gwlarson 3.7 if(!first)
677 gwlarson 3.4 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 gwlarson 3.7 intersect_vector_plane(tri[0],peq,&(et[0]),v[0]);
682 gwlarson 3.4 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 gwlarson 3.7 intersect_vector_plane(tri[j],peq,&(et[j]),v[j]);
688 gwlarson 3.4 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 gwlarson 3.6 t[w] = HUGET;
693 gwlarson 3.4 }
694     else
695     {
696 gwlarson 3.5 /* 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 gwlarson 3.4 VSUB(db[w],b[j],b[3]);
700 gwlarson 3.6 /* 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 gwlarson 3.7 (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 gwlarson 3.6 else
706 gwlarson 3.4 {
707 gwlarson 3.6 /* 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 gwlarson 3.7 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 gwlarson 3.4 }
742 gwlarson 3.7 }
743     bary_dtol(b[3],db,bi,dbi,t,w);
744    
745 gwlarson 3.4 /* trace the ray starting with this node */
746 gwlarson 3.7 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 gwlarson 3.4
759     }
760    
761    
762 gwlarson 3.7 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 gwlarson 3.4
783 gwlarson 3.7 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 gwlarson 3.4
831 gwlarson 3.3
832 gwlarson 3.2
833    
834    
835    
836    
837    
838    
839    
840    
841    
842