ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.5
Committed: Fri Sep 11 11:52:25 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.4: +370 -146 lines
Log Message:
fixed triangle insertion using edge 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.c
9     */
10     #include "standard.h"
11     #include "sm_list.h"
12     #include "sm_geom.h"
13     #include "sm.h"
14    
15    
16     SM *smMesh = NULL;
17     double smDist_sum=0;
18     int smNew_tri_cnt=0;
19    
20 gwlarson 3.5 static int smBase_nbrs[4][3] = { {3,2,1},{3,0,2},{3,1,0},{1,2,0}};
21    
22 gwlarson 3.1 #ifdef TEST_DRIVER
23     VIEW Current_View = {0,{0,0,0},{0,0,-1},{0,1,0},60,60,0};
24     int Pick_cnt =0;
25 gwlarson 3.5 int Pick_tri = -1,Picking = FALSE,Pick_samp=-1;
26 gwlarson 3.1 FVECT Pick_point[500],Pick_origin,Pick_dir;
27     FVECT Pick_v0[500], Pick_v1[500], Pick_v2[500];
28     FVECT P0,P1,P2;
29     FVECT FrustumNear[4],FrustumFar[4];
30     double dev_zmin=.01,dev_zmax=1000;
31     #endif
32    
33     smDir(sm,ps,id)
34     SM *sm;
35     FVECT ps;
36     int id;
37     {
38     FVECT p;
39    
40     VCOPY(p,SM_NTH_WV(sm,id));
41     point_on_sphere(ps,p,SM_VIEW_CENTER(sm));
42     }
43    
44     smClear_mesh(sm)
45     SM *sm;
46     {
47     /* Reset the triangle counters */
48     SM_TRI_CNT(sm) = 0;
49     SM_NUM_TRIS(sm) = 0;
50     SM_FREE_TRIS(sm) = -1;
51     }
52    
53     smClear_flags(sm,which)
54     SM *sm;
55     int which;
56     {
57     int i;
58    
59     if(which== -1)
60     for(i=0; i < T_FLAGS;i++)
61     bzero(SM_NTH_FLAGS(sm,i),T_TOTAL_FLAG_BYTES(SM_MAX_TRIS(sm)));
62     else
63     bzero(SM_NTH_FLAGS(sm,which),T_TOTAL_FLAG_BYTES(SM_MAX_TRIS(sm)));
64     }
65    
66     smClear_locator(sm)
67     SM *sm;
68     {
69     STREE *st;
70    
71     st = SM_LOCATOR(sm);
72    
73     stClear(st);
74     }
75    
76     smInit_locator(sm,center,base)
77     SM *sm;
78     FVECT center,base[4];
79     {
80     STREE *st;
81    
82     st = SM_LOCATOR(sm);
83    
84     stInit(st,center,base);
85    
86     }
87    
88     smClear(sm)
89     SM *sm;
90     {
91     smClear_samples(sm);
92     smClear_mesh(sm);
93     smClear_locator(sm);
94     }
95    
96     int
97     smAlloc_tris(sm,max_verts,max_tris)
98     SM *sm;
99     int max_verts,max_tris;
100     {
101     int i,nbytes,vbytes,fbytes;
102    
103     vbytes = max_verts*sizeof(VERT);
104     fbytes = T_TOTAL_FLAG_BYTES(max_tris);
105     nbytes = vbytes + max_tris*sizeof(TRI) +T_FLAGS*fbytes + 8;
106     for(i = 1024; nbytes > i; i <<= 1)
107     ;
108     /* check if casting works correctly */
109     max_tris = (i-vbytes-8)/(sizeof(TRI) + T_FLAG_BYTES);
110     fbytes = T_TOTAL_FLAG_BYTES(max_tris);
111    
112     SM_BASE(sm)=(char *)malloc(vbytes+max_tris*sizeof(TRI)+T_FLAGS*fbytes);
113    
114     if (SM_BASE(sm) == NULL)
115     return(0);
116    
117     SM_TRIS(sm) = (TRI *)SM_BASE(sm);
118     SM_VERTS(sm) = (VERT *)(SM_TRIS(sm) + max_tris);
119    
120     SM_NTH_FLAGS(sm,0) = (int4 *)(SM_VERTS(sm) + max_verts);
121     for(i=1; i < T_FLAGS; i++)
122     SM_NTH_FLAGS(sm,i) = (int4 *)(SM_NTH_FLAGS(sm,i-1)+fbytes/sizeof(int4));
123    
124     SM_MAX_VERTS(sm) = max_verts;
125     SM_MAX_TRIS(sm) = max_tris;
126    
127     smClear_mesh(sm);
128    
129     return(max_tris);
130     }
131    
132    
133    
134     int
135     smAlloc_locator(sm)
136     SM *sm;
137     {
138     STREE *st;
139    
140     st = SM_LOCATOR(sm);
141    
142     st = stAlloc(st);
143    
144     if(st)
145     return(TRUE);
146     else
147     return(FALSE);
148     }
149    
150     /* Initialize/clear global smL sample list for at least n samples */
151     smAlloc(max_samples)
152     register int max_samples;
153     {
154     unsigned nbytes;
155     register unsigned i;
156     int total_points;
157     int max_tris;
158    
159     /* If this is the first call, allocate sample,vertex and triangle lists */
160     if(!smMesh)
161     {
162     if(!(smMesh = (SM *)malloc(sizeof(SM))))
163     error(SYSTEM,"smAlloc():Unable to allocate memory");
164     bzero(smMesh,sizeof(SM));
165     }
166     else
167     { /* If existing structure: first deallocate */
168     if(SM_BASE(smMesh))
169     free(SM_BASE(smMesh));
170     if(SM_SAMP_BASE(smMesh))
171     free(SM_SAMP_BASE(smMesh));
172     }
173    
174     /* First allocate at least n samples + extra points:at least enough
175     necessary to form the BASE MESH- Default = 4;
176     */
177     max_samples = smAlloc_samples(smMesh, max_samples,SM_EXTRA_POINTS);
178    
179     total_points = max_samples + SM_EXTRA_POINTS;
180     max_tris = total_points*2;
181    
182     /* Now allocate space for mesh vertices and triangles */
183     max_tris = smAlloc_tris(smMesh, total_points, max_tris);
184    
185     /* Initialize the structure for point,triangle location.
186     */
187     smAlloc_locator(smMesh);
188    
189     }
190    
191    
192    
193     smInit_mesh(sm,vp)
194     SM *sm;
195     FVECT vp;
196     {
197    
198     /* NOTE: Should be elsewhere?*/
199     smDist_sum = 0;
200     smNew_tri_cnt = 0;
201    
202     VCOPY(SM_VIEW_CENTER(smMesh),vp);
203     smClear_locator(sm);
204     smInit_locator(sm,vp,0);
205     smClear_aux_samples(sm);
206     smClear_mesh(sm);
207     smCreate_base_mesh(sm,SM_DEFAULT);
208     }
209    
210     /*
211     * int
212     * smInit(n) : Initialize/clear data structures for n entries
213     * int n;
214     *
215     * This routine allocates/initializes the sample, mesh, and point-location
216     * structures for at least n samples.
217     * If n is <= 0, then clear data structures. Returns number samples
218     * actually allocated.
219     */
220    
221     int
222     smInit(n)
223     register int n;
224     {
225     int max_vertices;
226    
227     /* If n <=0, Just clear the existing structures */
228     if(n <= 0)
229     {
230     smClear(smMesh);
231     return(0);
232     }
233    
234     /* Total mesh vertices includes the sample points and the extra vertices
235     to form the base mesh
236     */
237     max_vertices = n + SM_EXTRA_POINTS;
238    
239     /* If the current mesh contains enough room, clear and return */
240     if(smMesh && max_vertices <= SM_MAX_VERTS(smMesh))
241     {
242     smClear(smMesh);
243     return(SM_MAX_SAMP(smMesh));
244     }
245     /* Otherwise- mesh must be allocated with the appropriate number of
246     samples
247     */
248     smAlloc(n);
249    
250     return(SM_MAX_SAMP(smMesh));
251     }
252    
253    
254     int
255     smLocator_apply_func(sm,v0,v1,v2,func,arg)
256     SM *sm;
257     FVECT v0,v1,v2;
258     int (*func)();
259 gwlarson 3.5 int *arg;
260 gwlarson 3.1 {
261     STREE *st;
262 gwlarson 3.5 int found;
263 gwlarson 3.1 FVECT p0,p1,p2;
264    
265     st = SM_LOCATOR(sm);
266    
267 gwlarson 3.5 VSUB(p0,v0,SM_VIEW_CENTER(sm));
268     VSUB(p1,v1,SM_VIEW_CENTER(sm));
269     VSUB(p2,v2,SM_VIEW_CENTER(sm));
270 gwlarson 3.1
271     found = stApply_to_tri_cells(st,p0,p1,p2,func,arg);
272    
273     return(found);
274     }
275    
276    
277     int
278 gwlarson 3.5 add_tri_expand(qtptr,q0,q1,q2,t0,t1,t2,n,arg,t_id)
279     QUADTREE *qtptr;
280     FVECT q0,q1,q2;
281     FVECT t0,t1,t2;
282     int n;
283     int *arg;
284     int t_id;
285     {
286     OBJECT tset[QT_MAXSET+1],*optr;
287     int i,id,found;
288     FVECT v0,v1,v2;
289    
290     #ifdef DEBUG_TEST_DRIVER
291     Pick_tri = t_id;
292     Picking = TRUE;
293     #endif
294    
295     if(QT_IS_EMPTY(*qtptr))
296     {
297     *qtptr = qtaddelem(*qtptr,t_id);
298     return(TRUE);
299     }
300    
301     optr = qtqueryset(*qtptr);
302     if(!inset(optr,t_id))
303     {
304     if(QT_SET_CNT(optr) < QT_MAXSET)
305     *qtptr = qtaddelem(*qtptr,t_id);
306     else
307     {
308     #ifdef DEBUG
309     eputs("add_tri_expand():no room in set\n");
310     #endif
311     return(FALSE);
312     }
313     }
314     optr = qtqueryset(*qtptr);
315     if(QT_SET_CNT(optr) >= QT_SET_THRESHOLD)
316     if (n < QT_MAX_LEVELS)
317     {
318     qtgetset(tset,*qtptr);
319     /* If set size exceeds threshold: subdivide cell and reinsert tris*/
320     qtfreeleaf(*qtptr);
321     qtSubdivide(qtptr);
322    
323     for(optr = QT_SET_PTR(tset),i=QT_SET_CNT(tset); i > 0; i--)
324     {
325     id = QT_SET_NEXT_ELEM(optr);
326     qtTri_from_id(id,NULL,NULL,NULL,v0,v1,v2,NULL,NULL,NULL);
327     found=qtAdd_tri(qtptr,q0,q1,q2,v0,v1,v2,id,n);
328     #ifdef DEBUG
329     if(!found)
330     eputs("add_tri_expand():Reinsert\n");
331     #endif
332     }
333     return(QT_MODIFIED);
334     }
335     else
336     if(QT_SET_CNT(optr) < QT_MAXSET)
337     {
338     #ifdef DEBUG_TEST_DRIVER
339     eputs("add_tri_expand():too many levels:can't expand\n");
340     #endif
341     return(TRUE);
342     }
343     else
344     {
345     #ifdef DEBUG
346     eputs("add_tri_expand():too many tris inset:can't add\n");
347     #endif
348     return(FALSE);
349     }
350     }
351    
352    
353     int
354     add_tri(qtptr,fptr,t_id)
355     QUADTREE *qtptr;
356     int *fptr;
357     int t_id;
358     {
359    
360     OBJECT *optr;
361    
362     #ifdef DEBUG_TEST_DRIVER
363     Pick_tri = t_id;
364     Picking = TRUE;
365     #endif
366     if(QT_IS_EMPTY(*qtptr))
367     {
368     *qtptr = qtaddelem(*qtptr,t_id);
369     if(!QT_FLAG_FILL_TRI(*fptr))
370     (*fptr)++;
371     }
372     else
373     {
374     optr = qtqueryset(*qtptr);
375     if(!inset(optr,t_id))
376     {
377     if(QT_SET_CNT(optr) < QT_MAXSET)
378     {
379     if(QT_SET_CNT(optr) >= QT_SET_THRESHOLD)
380     (*fptr) |= QT_EXPAND;
381     if(!QT_FLAG_FILL_TRI(*fptr))
382     (*fptr)++;
383     *qtptr = qtaddelem(*qtptr,t_id);
384     }
385     else
386     {
387     #ifdef DEBUG_TESTDRIVER
388     eputs("add_tri():exceeded set size\n");
389     #endif
390     return(FALSE);
391     }
392     }
393     }
394     return(TRUE);
395     }
396    
397    
398     int
399     stInsert_tri(st,t_id,t0,t1,t2)
400     STREE *st;
401     int t_id;
402     FVECT t0,t1,t2;
403     {
404     int f;
405     FVECT dir;
406    
407     /* First add all of the leaf cells lying on the triangle perimeter:
408     mark all cells seen on the way
409     */
410     ST_CLEAR_FLAGS(st);
411     f = 0;
412     VSUB(dir,t1,t0);
413     stTrace_edge(st,t0,dir,1.0,add_tri,&f,t_id);
414     VSUB(dir,t2,t1);
415     stTrace_edge(st,t1,dir,1.0,add_tri,&f,t_id);
416     VSUB(dir,t0,t2);
417     stTrace_edge(st,t2,dir,1.0,add_tri,&f,t_id);
418     /* Now visit interior */
419     if(QT_FLAG_FILL_TRI(f) || QT_FLAG_UPDATE(f))
420     stVisit_tri_interior(st,t0,t1,t2,add_tri_expand,&f,t_id);
421     }
422    
423 gwlarson 3.1 smLocator_add_tri(sm,t_id,v0_id,v1_id,v2_id)
424     SM *sm;
425     int t_id;
426     int v0_id,v1_id,v2_id;
427     {
428     STREE *st;
429 gwlarson 3.5 FVECT v0,v1,v2;
430 gwlarson 3.1
431     st = SM_LOCATOR(sm);
432    
433 gwlarson 3.5 VSUB(v0,SM_NTH_WV(sm,v0_id),SM_VIEW_CENTER(sm));
434     VSUB(v1,SM_NTH_WV(sm,v1_id),SM_VIEW_CENTER(sm));
435     VSUB(v2,SM_NTH_WV(sm,v2_id),SM_VIEW_CENTER(sm));
436 gwlarson 3.1
437 gwlarson 3.5 stUpdate_tri(st,t_id,v0,v1,v2,add_tri,add_tri_expand);
438 gwlarson 3.1
439     }
440    
441     /* Add a triangle to the base array with vertices v1-v2-v3 */
442     int
443     smAdd_tri(sm, v0_id,v1_id,v2_id,tptr)
444     SM *sm;
445     int v0_id,v1_id,v2_id;
446     TRI **tptr;
447     {
448     int t_id;
449     TRI *t;
450    
451    
452     if(SM_TRI_CNT(sm)+1 > SM_MAX_TRIS(sm))
453     error(SYSTEM,"smAdd_tri():Too many triangles");
454    
455     /* Get the id for the next available triangle */
456     SM_FREE_TRI_ID(sm,t_id);
457     if(t_id == -1)
458     return(t_id);
459    
460     t = SM_NTH_TRI(sm,t_id);
461     T_CLEAR_NBRS(t);
462    
463     if(SM_BASE_ID(sm,v0_id) || SM_BASE_ID(sm,v1_id) || SM_BASE_ID(sm,v2_id))
464     {
465     smClear_tri_flags(sm,t_id);
466     SM_SET_NTH_T_BASE(sm,t_id);
467     }
468     else
469     {
470     SM_CLEAR_NTH_T_BASE(sm,t_id);
471     SM_SET_NTH_T_ACTIVE(sm,t_id);
472     SM_SET_NTH_T_LRU(sm,t_id);
473     SM_SET_NTH_T_NEW(sm,t_id);
474     SM_NUM_TRIS(sm)++;
475     smNew_tri_cnt++;
476     }
477     /* set the triangle vertex ids */
478     T_NTH_V(t,0) = v0_id;
479     T_NTH_V(t,1) = v1_id;
480     T_NTH_V(t,2) = v2_id;
481    
482     SM_NTH_VERT(sm,v0_id) = t_id;
483     SM_NTH_VERT(sm,v1_id) = t_id;
484     SM_NTH_VERT(sm,v2_id) = t_id;
485    
486     if(t)
487     *tptr = t;
488     /* return initialized triangle */
489     return(t_id);
490     }
491    
492     int
493     smClosest_vertex_in_tri(sm,v0_id,v1_id,v2_id,p,eps)
494     SM *sm;
495     int v0_id,v1_id,v2_id;
496     FVECT p;
497     double eps;
498     {
499     FVECT v;
500     double d,d0,d1,d2;
501     int closest = -1;
502    
503     if(v0_id != -1)
504     {
505     smDir(sm,v,v0_id);
506     d0 = DIST(p,v);
507     if(eps < 0 || d0 < eps)
508     {
509     closest = v0_id;
510     d = d0;
511     }
512     }
513     if(v1_id != -1)
514     {
515     smDir(sm,v,v1_id);
516     d1 = DIST(p,v);
517     if(closest== -1)
518     {
519     if(eps < 0 || d1 < eps)
520     {
521     closest = v1_id;
522     d = d1;
523     }
524     }
525     else
526 gwlarson 3.5 if(d1 < d0)
527 gwlarson 3.1 {
528     if((eps < 0) || d1 < eps)
529     {
530     closest = v1_id;
531     d = d1;
532     }
533     }
534 gwlarson 3.5 }
535 gwlarson 3.1 if(v2_id != -1)
536     {
537     smDir(sm,v,v2_id);
538     d2 = DIST(p,v);
539     if((eps < 0) || d2 < eps)
540 gwlarson 3.5 if(closest == -1 ||(d2 < d))
541 gwlarson 3.1 return(v2_id);
542     }
543     return(closest);
544     }
545    
546    
547     int
548     smClosest_vertex_in_w_tri(sm,v0_id,v1_id,v2_id,p)
549     SM *sm;
550     int v0_id,v1_id,v2_id;
551     FVECT p;
552     {
553     FVECT v;
554     double d,d0,d1,d2;
555     int closest;
556    
557     VCOPY(v,SM_NTH_WV(sm,v0_id));
558     d = d0 = DIST(p,v);
559     closest = v0_id;
560    
561     VCOPY(v,SM_NTH_WV(sm,v1_id));
562     d1 = DIST(p,v);
563 gwlarson 3.5 if(d1 < d0)
564 gwlarson 3.1 {
565     closest = v1_id;
566     d = d1;
567     }
568     VCOPY(v,SM_NTH_WV(sm,v2_id));
569     d2 = DIST(p,v);
570     if(d2 < d)
571     return(v2_id);
572     else
573     return(closest);
574     }
575    
576     void
577 gwlarson 3.3 smTris_swap_edge(sm,t_id,t1_id,e,e1,tn_id,tn1_id,add,del)
578 gwlarson 3.1 SM *sm;
579     int t_id,t1_id;
580     int e,e1;
581 gwlarson 3.5 int *tn_id,*tn1_id;
582 gwlarson 3.3 LIST **add,**del;
583 gwlarson 3.1
584     {
585     TRI *t,*t1;
586     TRI *ta,*tb;
587     int verts[3],enext,eprev,e1next,e1prev;
588     TRI *n;
589     FVECT p1,p2,p3;
590     int ta_id,tb_id;
591     /* swap diagonal (e relative to t, and e1 relative to t1)
592     defined by quadrilateral
593     formed by t,t1- swap for the opposite diagonal
594     */
595     t = SM_NTH_TRI(sm,t_id);
596     t1 = SM_NTH_TRI(sm,t1_id);
597     enext = (e+1)%3;
598     eprev = (e+2)%3;
599     e1next = (e1+1)%3;
600     e1prev = (e1+2)%3;
601     verts[e] = T_NTH_V(t,e);
602     verts[enext] = T_NTH_V(t1,e1prev);
603     verts[eprev] = T_NTH_V(t,eprev);
604     ta_id = smAdd_tri(sm,verts[0],verts[1],verts[2],&ta);
605 gwlarson 3.3 *add = push_data(*add,ta_id);
606 gwlarson 3.1 verts[e1] = T_NTH_V(t1,e1);
607     verts[e1next] = T_NTH_V(t,eprev);
608     verts[e1prev] = T_NTH_V(t1,e1prev);
609     tb_id = smAdd_tri(sm,verts[0],verts[1],verts[2],&tb);
610 gwlarson 3.3 *add = push_data(*add,tb_id);
611    
612 gwlarson 3.1 /* set the neighbors */
613     T_NTH_NBR(ta,e) = T_NTH_NBR(t1,e1next);
614     T_NTH_NBR(tb,e1) = T_NTH_NBR(t,enext);
615     T_NTH_NBR(ta,enext) = tb_id;
616     T_NTH_NBR(tb,e1next) = ta_id;
617     T_NTH_NBR(ta,eprev) = T_NTH_NBR(t,eprev);
618     T_NTH_NBR(tb,e1prev) = T_NTH_NBR(t1,e1prev);
619    
620     /* Reset neighbor pointers of original neighbors */
621     n = SM_NTH_TRI(sm,T_NTH_NBR(t,enext));
622     T_NTH_NBR(n,T_NTH_NBR_PTR(t_id,n)) = tb_id;
623     n = SM_NTH_TRI(sm,T_NTH_NBR(t,eprev));
624     T_NTH_NBR(n,T_NTH_NBR_PTR(t_id,n)) = ta_id;
625    
626     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,e1next));
627     T_NTH_NBR(n,T_NTH_NBR_PTR(t1_id,n)) = ta_id;
628     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,e1prev));
629     T_NTH_NBR(n,T_NTH_NBR_PTR(t1_id,n)) = tb_id;
630    
631     /* Delete two parent triangles */
632 gwlarson 3.5
633 gwlarson 3.3 *del = push_data(*del,t_id);
634     if(SM_IS_NTH_T_NEW(sm,t_id))
635     SM_CLEAR_NTH_T_NEW(sm,t_id);
636     else
637     SM_CLEAR_NTH_T_BASE(sm,t_id);
638     *del = push_data(*del,t1_id);
639     if(SM_IS_NTH_T_NEW(sm,t1_id))
640     SM_CLEAR_NTH_T_NEW(sm,t1_id);
641     else
642     SM_CLEAR_NTH_T_BASE(sm,t1_id);
643 gwlarson 3.1 *tn_id = ta_id;
644     *tn1_id = tb_id;
645     }
646    
647 gwlarson 3.3 smUpdate_locator(sm,add_list,del_list)
648     SM *sm;
649     LIST *add_list,*del_list;
650     {
651     int t_id;
652     TRI *t;
653     while(add_list)
654     {
655     t_id = pop_list(&add_list);
656     if(!SM_IS_NTH_T_NEW(sm,t_id) && !SM_IS_NTH_T_BASE(sm,t_id))
657     {
658     SM_SET_NTH_T_NEW(sm,t_id);
659 gwlarson 3.4 smNew_tri_cnt--;
660 gwlarson 3.3 continue;
661     }
662     t = SM_NTH_TRI(sm,t_id);
663     smLocator_add_tri(sm,t_id,T_NTH_V(t,0),T_NTH_V(t,1),T_NTH_V(t,2));
664     }
665    
666     while(del_list)
667     {
668     t_id = pop_list(&del_list);
669     if(SM_IS_NTH_T_NEW(sm,t_id))
670     {
671     smDelete_tri(sm,t_id);
672     continue;
673     }
674     smLocator_remove_tri(sm,t_id);
675     smDelete_tri(sm,t_id);
676     }
677     }
678 gwlarson 3.1 /* MUST add check for constrained edges */
679 gwlarson 3.3 int
680 gwlarson 3.1 smFix_tris(sm,id,tlist)
681     SM *sm;
682     int id;
683     LIST *tlist;
684     {
685     TRI *t,*t_opp;
686 gwlarson 3.3 FVECT p,p1,p2,p3;
687     int e,e1,swapped = 0;
688 gwlarson 3.1 int t_id,t_opp_id;
689 gwlarson 3.3 LIST *add_list,*del_list;
690    
691    
692     add_list = del_list = NULL;
693     VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
694 gwlarson 3.1 while(tlist)
695     {
696 gwlarson 3.3 t_id = pop_list(&tlist);
697 gwlarson 3.1 t = SM_NTH_TRI(sm,t_id);
698     e = (T_WHICH_V(t,id)+1)%3;
699     t_opp_id = T_NTH_NBR(t,e);
700     t_opp = SM_NTH_TRI(sm,t_opp_id);
701    
702     smDir(sm,p1,T_NTH_V(t_opp,0));
703     smDir(sm,p2,T_NTH_V(t_opp,1));
704     smDir(sm,p3,T_NTH_V(t_opp,2));
705     if(point_in_cone(p,p1,p2,p3))
706     {
707     swapped = 1;
708     e1 = T_NTH_NBR_PTR(t_id,t_opp);
709     /* check list for t_opp and Remove if there */
710     remove_from_list(t_opp_id,&tlist);
711 gwlarson 3.3 smTris_swap_edge(sm,t_id,t_opp_id,e,e1,&t_id,&t_opp_id,
712     &add_list,&del_list);
713 gwlarson 3.1 tlist = push_data(tlist,t_id);
714     tlist = push_data(tlist,t_opp_id);
715     }
716     }
717 gwlarson 3.3 smUpdate_locator(sm,add_list,del_list);
718 gwlarson 3.1 return(swapped);
719     }
720    
721     /* Give the vertex "id" and a triangle "t" that it belongs to- return the
722     next nbr in a counter clockwise order about vertex "id"
723     */
724     int
725     smTri_next_ccw_nbr(sm,t,id)
726     SM *sm;
727     TRI *t;
728     int id;
729     {
730     int t_id;
731     int tri;
732    
733     /* Want the edge for which "id" is the destination */
734     t_id = (T_WHICH_V(t,id)+ 2)% 3;
735     tri = T_NTH_NBR(t,t_id);
736     return(tri);
737     }
738    
739     void
740     smReplace_point(sm,tri,id,nid)
741     SM *sm;
742     TRI *tri;
743     int id,nid;
744     {
745     TRI *t;
746     int t_id;
747    
748     T_NTH_V(tri,T_WHICH_V(tri,id)) = nid;
749    
750 gwlarson 3.5 t_id = smTri_next_ccw_nbr(sm,tri,nid);
751     while((t = SM_NTH_TRI(sm,t_id)) != tri)
752 gwlarson 3.1 {
753     T_NTH_V(t,T_WHICH_V(t,id)) = nid;
754     t_id = smTri_next_ccw_nbr(sm,t,nid);
755     }
756     }
757    
758    
759     smClear_tri_flags(sm,id)
760     SM *sm;
761     int id;
762     {
763     int i;
764    
765     for(i=0; i < T_FLAGS; i++)
766     SM_CLEAR_NTH_T_FLAG(sm,id,i);
767    
768     }
769    
770     /* Locate the point-id in the point location structure: */
771     int
772     smReplace_vertex(sm,c,dir,p,tri_id,snew_id,type,which)
773     SM *sm;
774     COLR c;
775     FVECT dir,p;
776     int tri_id,snew_id;
777 gwlarson 3.5 int type,which;
778 gwlarson 3.1 {
779     int n_id,s_id;
780     TRI *tri;
781    
782     tri = SM_NTH_TRI(sm,tri_id);
783     /* Get the sample that corresponds to the "which" vertex of "tri" */
784     /* NEED: have re-init that sets clock flag */
785     /* If this is a base-sample: create a new sample and replace
786     all references to the base sample with references to the
787     new sample
788     */
789     s_id = T_NTH_V(tri,which);
790     if(SM_BASE_ID(sm,s_id))
791     {
792     if(snew_id != -1)
793     n_id = smAdd_sample_point(sm,c,dir,p);
794     else
795     n_id = snew_id;
796     smReplace_point(sm,tri,s_id,n_id);
797     s_id = n_id;
798     }
799     else /* If the sample exists, reset the values */
800     /* NOTE: This test was based on the SPHERICAL coordinates
801     of the point: If we are doing a multiple-sample-per
802     SPHERICAL pixel: we will want to test for equality-
803     and do other processing: for now: SINGLE SAMPLE PER
804     PIXEL
805     */
806     /* NOTE: snew_id needs to be marked as invalid?*/
807     if(snew_id == -1)
808     smInit_sample(sm,s_id,c,dir,p);
809     else
810     smReset_sample(sm,s_id,snew_id);
811     return(s_id);
812     }
813    
814    
815     /* Locate the point-id in the point location structure: */
816     int
817     smInsert_point_in_tri(sm,c,dir,p,s_id,tri_id)
818     SM *sm;
819     COLR c;
820     FVECT dir,p;
821     int s_id,tri_id;
822     {
823     TRI *tri,*t0,*t1,*t2,*nbr;
824     int v0_id,v1_id,v2_id,n_id;
825     int t0_id,t1_id,t2_id;
826     LIST *tlist;
827     FVECT npt;
828    
829     if(s_id == SM_INVALID)
830     s_id = smAdd_sample_point(sm,c,dir,p);
831    
832     tri = SM_NTH_TRI(sm,tri_id);
833     v0_id = T_NTH_V(tri,0);
834     v1_id = T_NTH_V(tri,1);
835     v2_id = T_NTH_V(tri,2);
836    
837     n_id = -1;
838     if(SM_BASE_ID(sm,v0_id)||SM_BASE_ID(sm,v1_id)||SM_BASE_ID(sm,v2_id))
839     {
840     smDir(sm,npt,s_id);
841     /* Change to an add and delete */
842     t0_id = (SM_BASE_ID(sm,v0_id))?v0_id:-1;
843     t1_id = (SM_BASE_ID(sm,v1_id))?v1_id:-1;
844     t2_id = (SM_BASE_ID(sm,v2_id))?v2_id:-1;
845     n_id = smClosest_vertex_in_tri(sm,t0_id,t1_id,t2_id,npt,P_REPLACE_EPS);
846     }
847     t0_id = smAdd_tri(sm,s_id,v0_id,v1_id,&t0);
848 gwlarson 3.3 /* Add triangle to the locator */
849     smLocator_add_tri(sm,t0_id,s_id,v0_id,v1_id);
850    
851 gwlarson 3.1 t1_id = smAdd_tri(sm,s_id,v1_id,v2_id,&t1);
852 gwlarson 3.3 smLocator_add_tri(sm,t1_id,s_id,v1_id,v2_id);
853 gwlarson 3.1 t2_id = smAdd_tri(sm,s_id,v2_id,v0_id,&t2);
854 gwlarson 3.3 smLocator_add_tri(sm,t2_id,s_id,v2_id,v0_id);
855    
856 gwlarson 3.1 /* Set the neighbor pointers for the new tris */
857     T_NTH_NBR(t0,0) = t2_id;
858     T_NTH_NBR(t0,1) = T_NTH_NBR(tri,0);
859     T_NTH_NBR(t0,2) = t1_id;
860     T_NTH_NBR(t1,0) = t0_id;
861     T_NTH_NBR(t1,1) = T_NTH_NBR(tri,1);
862     T_NTH_NBR(t1,2) = t2_id;
863     T_NTH_NBR(t2,0) = t1_id;
864     T_NTH_NBR(t2,1) = T_NTH_NBR(tri,2);
865     T_NTH_NBR(t2,2) = t0_id;
866    
867     /* Reset the neigbor pointers for the neighbors of the original */
868     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,0));
869     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t0_id;
870     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,1));
871     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t1_id;
872     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,2));
873     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t2_id;
874    
875 gwlarson 3.3 smLocator_remove_tri(sm,tri_id);
876 gwlarson 3.1 smDelete_tri(sm,tri_id);
877    
878     /* Fix up the new triangles*/
879     tlist = push_data(NULL,t0_id);
880     tlist = push_data(tlist,t1_id);
881     tlist = push_data(tlist,t2_id);
882    
883     smFix_tris(sm,s_id,tlist);
884    
885     if(n_id != -1)
886     smDelete_point(sm,n_id);
887    
888     return(s_id);
889     }
890    
891    
892     int
893 gwlarson 3.5 smPointLocate(sm,pt,norm)
894 gwlarson 3.1 SM *sm;
895     FVECT pt;
896 gwlarson 3.5 int norm;
897 gwlarson 3.1 {
898     STREE *st;
899     int tri;
900     FVECT npt;
901    
902     st = SM_LOCATOR(sm);
903     if(norm)
904     {
905 gwlarson 3.5 VSUB(npt,pt,SM_VIEW_CENTER(sm));
906     tri = stPoint_locate(st,npt);
907 gwlarson 3.1 }
908     else
909 gwlarson 3.5 tri = stPoint_locate(st,pt);
910 gwlarson 3.1 return(tri);
911     }
912    
913     QUADTREE
914 gwlarson 3.4 smPointLocateCell(sm,pt,norm,v0,v1,v2)
915 gwlarson 3.1 SM *sm;
916 gwlarson 3.2 FVECT pt;
917 gwlarson 3.5 int norm;
918 gwlarson 3.4 FVECT v0,v1,v2;
919 gwlarson 3.1 {
920     STREE *st;
921 gwlarson 3.4 QUADTREE *qtptr;
922 gwlarson 3.1 FVECT npt;
923    
924     st = SM_LOCATOR(sm);
925     if(norm)
926     {
927 gwlarson 3.5 VSUB(npt,pt,SM_VIEW_CENTER(sm));
928 gwlarson 3.1
929 gwlarson 3.4 qtptr = stPoint_locate_cell(st,npt,v0,v1,v2);
930 gwlarson 3.1 }
931     else
932 gwlarson 3.4 qtptr = stPoint_locate_cell(st,pt,v0,v1,v2);
933 gwlarson 3.1
934 gwlarson 3.4 if(qtptr)
935     return(*qtptr);
936     else
937     return(EMPTY);
938 gwlarson 3.1 }
939    
940     int
941     smAdd_sample_to_mesh(sm,c,dir,pt,s_id)
942     SM *sm;
943     COLR c;
944     FVECT dir,pt;
945     int s_id;
946     {
947     int t_id;
948     double d;
949     FVECT p;
950    
951     /* If new, foreground pt */
952     if(pt)
953     {
954     /* NOTE: This should be elsewhere! */
955     d = DIST(pt,SM_VIEW_CENTER(smMesh));
956     smDist_sum += 1.0/d;
957     /************************************/
958 gwlarson 3.5 t_id = smPointLocate(smMesh,pt,TRUE);
959     if(t_id >= 0)
960 gwlarson 3.1 s_id = smInsert_point_in_tri(smMesh,c,dir,pt,s_id,t_id);
961     #ifdef DEBUG
962     else
963 gwlarson 3.5 {
964     c[0] = 255;c[1]=0;c[2]=0;
965     s_id = smAdd_sample_point(sm,c,dir,pt);
966     eputs("smAdd_sample_to_mesh(): not found fg\n");
967     }
968 gwlarson 3.1 #endif
969     }
970     else if(s_id != -1)
971     {
972     VCOPY(p,SM_NTH_WV(sm,s_id));
973     if(SM_NTH_W_DIR(sm,s_id) != -1)
974     {
975     /* NOTE: This should be elsewhere! */
976     d = DIST(p,SM_VIEW_CENTER(smMesh));
977     smDist_sum += 1.0/d;
978     /************************************/
979     }
980 gwlarson 3.5 t_id = smPointLocate(smMesh,p,TRUE);
981     if(t_id != -1)
982 gwlarson 3.1 s_id = smInsert_point_in_tri(smMesh,c,dir,p,s_id,t_id);
983     #ifdef DEBUG
984     else
985 gwlarson 3.5 eputs("smAdd_sample_to_mesh():not found reinsert\n");
986 gwlarson 3.1 #endif
987     }
988     /* Is a BG(sky point) */
989     else
990     {
991 gwlarson 3.5 t_id = smPointLocate(smMesh,dir,FALSE);
992     if(t_id != -1)
993 gwlarson 3.1 s_id = smInsert_point_in_tri(smMesh,c,dir,NULL,s_id,t_id);
994 gwlarson 3.5
995 gwlarson 3.1 #ifdef DEBUG
996     else
997 gwlarson 3.5 eputs("smAdd_sample_to_mesh(): not found bg\n");
998 gwlarson 3.1 #endif
999     }
1000     return(s_id);
1001     }
1002    
1003     /*
1004     * int
1005     * smNewSamp(c, dir, p) : register new sample point and return index
1006     * COLR c; : pixel color (RGBE)
1007     * FVECT dir; : ray direction vector
1008     * FVECT p; : world intersection point
1009     *
1010     * Add new sample point to data structures, removing old values as necessary.
1011     * New sample representation will be output in next call to smUpdate().
1012     * If the point is a sky point: then v=NULL
1013     */
1014     int
1015     smNewSamp(c,dir,p)
1016     COLR c;
1017     FVECT dir;
1018     FVECT p;
1019    
1020     {
1021     int s_id;
1022 gwlarson 3.5 int debug=0;
1023 gwlarson 3.1
1024     /* First check if this the first sample: if so initialize mesh */
1025     if(SM_NUM_SAMP(smMesh) == 0)
1026     smInit_mesh(smMesh,odev.v.vp);
1027 gwlarson 3.5 if(!debug)
1028     s_id = smAdd_sample_to_mesh(smMesh,c,dir,p,-1);
1029 gwlarson 3.1 return(s_id);
1030    
1031     }
1032     /*
1033     * int
1034     * smFindsamp(orig, dir): intersect ray with 3D rep. and find closest sample
1035     * FVECT orig, dir;
1036     *
1037     * Find the closest sample to the given ray. Return -1 on failure.
1038     */
1039    
1040     /*
1041     * smClean() : display has been wiped clean
1042     *
1043     * Called after display has been effectively cleared, meaning that all
1044     * geometry must be resent down the pipeline in the next call to smUpdate().
1045     */
1046    
1047    
1048     /*
1049     * smUpdate(vp, qua) : update OpenGL output geometry for view vp
1050     * VIEW *vp; : desired view
1051     * int qua; : quality level (percentage on linear time scale)
1052     *
1053     * Draw new geometric representation using OpenGL calls. Assume that the
1054     * view has already been set up and the correct frame buffer has been
1055     * selected for drawing. The quality level is on a linear scale, where 100%
1056     * is full (final) quality. It is not necessary to redraw geometry that has
1057     * been output since the last call to smClean().
1058     */
1059    
1060    
1061     int
1062     smClear_vert(sm,id)
1063     SM *sm;
1064     int id;
1065     {
1066     if(SM_INVALID_POINT_ID(sm,id))
1067     return(FALSE);
1068    
1069     SM_NTH_VERT(sm,id) = SM_INVALID;
1070    
1071     return(TRUE);
1072     }
1073    
1074     int
1075     smAdd_base_vertex(sm,v,d)
1076     SM *sm;
1077     FVECT v,d;
1078     {
1079     int id;
1080    
1081     /* First add coordinate to the sample array */
1082     id = smAdd_aux_point(sm,v,d);
1083     if(id == -1)
1084     return(SM_INVALID);
1085     /* Initialize triangle pointer to -1 */
1086     smClear_vert(sm,id);
1087     return(id);
1088     }
1089    
1090    
1091    
1092     /* Initialize a the point location DAG based on a 6 triangle tesselation
1093     of the unit sphere centered on the view center. The DAG structure
1094     contains 6 roots: one for each initial base triangle
1095     */
1096    
1097     int
1098     smCreate_base_mesh(sm,type)
1099     SM *sm;
1100     int type;
1101     {
1102 gwlarson 3.5 int i,id,tri_id,nbr_id;
1103 gwlarson 3.1 int p[4],ids[4];
1104     int v0_id,v1_id,v2_id;
1105     TRI *tris[4];
1106     FVECT d,pt,cntr;
1107    
1108     /* First insert the base vertices into the sample point array */
1109    
1110     for(i=0; i < 4; i++)
1111     {
1112 gwlarson 3.5 VCOPY(cntr,stDefault_base[i]);
1113     cntr[0] += .01;
1114     cntr[1] += .02;
1115     cntr[2] += .03;
1116     VADD(cntr,cntr,SM_VIEW_CENTER(sm));
1117 gwlarson 3.1 point_on_sphere(d,cntr,SM_VIEW_CENTER(sm));
1118     id = smAdd_base_vertex(sm,cntr,d);
1119     /* test to make sure vertex allocated */
1120     if(id != -1)
1121     p[i] = id;
1122     else
1123     return(0);
1124     }
1125     /* Create the base triangles */
1126     for(i=0;i < 4; i++)
1127     {
1128     v0_id = p[stTri_verts[i][0]];
1129     v1_id = p[stTri_verts[i][1]];
1130     v2_id = p[stTri_verts[i][2]];
1131     if((ids[i] = smAdd_tri(sm, v0_id,v1_id,v2_id,&(tris[i])))== -1)
1132     return(0);
1133 gwlarson 3.3 smLocator_add_tri(sm,ids[i],v0_id,v1_id,v2_id);
1134 gwlarson 3.1 }
1135     /* Set neighbors */
1136    
1137 gwlarson 3.5 for(tri_id=0;tri_id < 4; tri_id++)
1138     for(nbr_id=0; nbr_id < 3; nbr_id++)
1139     T_NTH_NBR(tris[tri_id],nbr_id) = smBase_nbrs[tri_id][nbr_id];
1140 gwlarson 3.1
1141     return(1);
1142    
1143     }
1144    
1145    
1146     int
1147     smNext_tri_flag_set(sm,i,which,b)
1148     SM *sm;
1149     int i,which;
1150 gwlarson 3.5 int b;
1151 gwlarson 3.1 {
1152    
1153     for(; i < SM_TRI_CNT(sm);i++)
1154     {
1155    
1156 gwlarson 3.5 if(!SM_IS_NTH_T_FLAG(sm,i,which))
1157     continue;
1158 gwlarson 3.1 if(!b)
1159     break;
1160     if((b==1) && !SM_BG_TRI(sm,i))
1161     break;
1162     if((b==2) && SM_BG_TRI(sm,i))
1163     break;
1164     }
1165    
1166     return(i);
1167     }
1168    
1169    
1170     int
1171     smNext_valid_tri(sm,i)
1172     SM *sm;
1173     int i;
1174     {
1175    
1176     while( i < SM_TRI_CNT(sm) && !T_IS_VALID(SM_NTH_TRI(sm,i)))
1177     i++;
1178    
1179     return(i);
1180     }
1181    
1182    
1183    
1184 gwlarson 3.5 qtTri_from_id(t_id,v0,v1,v2,n0,n1,n2,v0_idp,v1_idp,v2_idp)
1185 gwlarson 3.1 int t_id;
1186     FVECT v0,v1,v2;
1187 gwlarson 3.5 FVECT n0,n1,n2;
1188     int *v0_idp,*v1_idp,*v2_idp;
1189 gwlarson 3.1 {
1190     TRI *t;
1191     int v0_id,v1_id,v2_id;
1192    
1193     t = SM_NTH_TRI(smMesh,t_id);
1194     v0_id = T_NTH_V(t,0);
1195     v1_id = T_NTH_V(t,1);
1196     v2_id = T_NTH_V(t,2);
1197    
1198 gwlarson 3.5 if(v0)
1199     {
1200     VCOPY(v0,SM_NTH_WV(smMesh,v0_id));
1201     VCOPY(v1,SM_NTH_WV(smMesh,v1_id));
1202     VCOPY(v2,SM_NTH_WV(smMesh,v2_id));
1203     }
1204     if(n0)
1205     {
1206     smDir(smMesh,n0,v0_id);
1207     smDir(smMesh,n1,v1_id);
1208     smDir(smMesh,n2,v2_id);
1209 gwlarson 3.1
1210 gwlarson 3.5 }
1211     if(v0_idp)
1212     {
1213     *v0_idp = v0_id;
1214     *v1_idp = v1_id;
1215     *v2_idp = v2_id;
1216     }
1217 gwlarson 3.1 }
1218    
1219    
1220     /*
1221     * int
1222     * smFindSamp(FVECT orig, FVECT dir)
1223     *
1224     * Find the closest sample to the given ray. Returns sample id, -1 on failure.
1225     * "dir" is assumed to be normalized
1226     */
1227     int
1228     smFindSamp(orig,dir)
1229     FVECT orig,dir;
1230     {
1231     FVECT r,v0,v1,v2,a,b,p;
1232 gwlarson 3.5 OBJECT os[QT_MAXCSET+1],t_set[QT_MAXSET+1],*ts;
1233 gwlarson 3.1 QUADTREE qt;
1234     int s_id;
1235     double d;
1236    
1237     /* r is the normalized vector from the view center to the current
1238     * ray point ( starting with "orig"). Find the cell that r falls in,
1239     * and test the ray against all triangles stored in the cell. If
1240     * the test fails, trace the projection of the ray across to the
1241     * next cell it intersects: iterate until either an intersection
1242     * is found, or the projection ray is // to the direction. The sample
1243     * corresponding to the triangle vertex closest to the intersection
1244     * point is returned.
1245     */
1246    
1247     /* First test if "orig" coincides with the View_center or if "dir" is
1248     parallel to r formed by projecting "orig" on the sphere. In
1249     either case, do a single test against the cell containing the
1250     intersection of "dir" and the sphere
1251     */
1252     point_on_sphere(b,orig,SM_VIEW_CENTER(smMesh));
1253     d = -DOT(b,dir);
1254     if(EQUAL_VEC3(orig,SM_VIEW_CENTER(smMesh)) || EQUAL(fabs(d),1.0))
1255     {
1256 gwlarson 3.4 qt = smPointLocateCell(smMesh,dir,FALSE,NULL,NULL,NULL);
1257 gwlarson 3.1 /* Test triangles in the set for intersection with Ray:returns
1258     first found
1259     */
1260 gwlarson 3.5 ts = qtqueryset(qt);
1261     s_id = intersect_tri_set(ts,orig,dir,p);
1262     #ifdef DEBUG_TEST_DRIVER
1263 gwlarson 3.1 VCOPY(Pick_point[0],p);
1264     #endif
1265     return(s_id);
1266     }
1267     else
1268     {
1269     /* Starting with orig, Walk along projection of ray onto sphere */
1270     point_on_sphere(r,orig,SM_VIEW_CENTER(smMesh));
1271 gwlarson 3.4 qt = smPointLocateCell(smMesh,r,FALSE,v0,v1,v2);
1272 gwlarson 3.5 /* os will contain all triangles seen thus far */
1273 gwlarson 3.1 qtgetset(t_set,qt);
1274     setcopy(os,t_set);
1275    
1276     /* Calculate ray perpendicular to dir: when projection ray is // to dir,
1277     the dot product will become negative.
1278     */
1279     VSUM(a,b,dir,d);
1280     d = DOT(a,b);
1281     while(d > 0)
1282     {
1283 gwlarson 3.5 s_id = intersect_tri_set(t_set,orig,dir,p);
1284     #ifdef DEBUG_TEST_DRIVER
1285 gwlarson 3.1 VCOPY(Pick_point[0],p);
1286     #endif
1287     if(s_id != EMPTY)
1288     return(s_id);
1289     /* Find next cell that projection of ray intersects */
1290 gwlarson 3.4 traceRay(r,dir,v0,v1,v2,r);
1291     qt = smPointLocateCell(smMesh,r,FALSE,v0,v1,v2);
1292 gwlarson 3.1 qtgetset(t_set,qt);
1293     /* Check triangles in set against those seen so far(os):only
1294     check new triangles for intersection (t_set')
1295     */
1296     check_set(t_set,os);
1297 gwlarson 3.4 d = DOT(a,r);
1298 gwlarson 3.1 }
1299     }
1300 gwlarson 3.5 #ifdef DEBUG
1301 gwlarson 3.1 eputs("smFindSamp():Pick Ray did not intersect mesh");
1302     #endif
1303     return(EMPTY);
1304     }
1305    
1306    
1307 gwlarson 3.5 smRebuild_mesh(sm,vp)
1308 gwlarson 3.1 SM *sm;
1309 gwlarson 3.5 FVECT vp;
1310 gwlarson 3.1 {
1311     int i;
1312     FVECT dir;
1313     COLR c;
1314     FVECT p,ov;
1315    
1316     /* Clear the mesh- and rebuild using the current sample array */
1317    
1318 gwlarson 3.5 VSUB(ov,vp,SM_VIEW_CENTER(sm));
1319     smInit_mesh(sm,vp);
1320 gwlarson 3.1
1321     SM_FOR_ALL_SAMPLES(sm,i)
1322     {
1323     if(SM_NTH_W_DIR(sm,i)==-1)
1324     VADD(SM_NTH_WV(sm,i),SM_NTH_WV(sm,i),ov);
1325     smAdd_sample_to_mesh(sm,NULL,NULL,NULL,i);
1326     }
1327     }
1328 gwlarson 3.5
1329     int
1330     intersect_tri_set(t_set,orig,dir,pt)
1331     OBJECT *t_set;
1332     FVECT orig,dir,pt;
1333     {
1334     OBJECT *optr;
1335     int i,t_id,id;
1336     int pid0,pid1,pid2;
1337     FVECT p0,p1,p2,p;
1338     TRI *t;
1339    
1340     optr = QT_SET_PTR(t_set);
1341     for(i = QT_SET_CNT(t_set); i > 0; i--)
1342     {
1343     t_id = QT_SET_NEXT_ELEM(optr);
1344    
1345     t = SM_NTH_TRI(smMesh,t_id);
1346     pid0 = T_NTH_V(t,0);
1347     pid1 = T_NTH_V(t,1);
1348     pid2 = T_NTH_V(t,2);
1349     VCOPY(p0,SM_NTH_WV(smMesh,pid0));
1350     VCOPY(p1,SM_NTH_WV(smMesh,pid1));
1351     VCOPY(p2,SM_NTH_WV(smMesh,pid2));
1352     if(ray_intersect_tri(orig,dir,p0,p1,p2,p))
1353     {
1354     id = closest_point_in_tri(p0,p1,p2,p,pid0,pid1,pid2);
1355    
1356     if(pt)
1357     VCOPY(pt,p);
1358     #ifdef DEBUG_TEST_DRIVER
1359     Pick_tri = t_id;
1360     Pick_samp = id;
1361     VCOPY(Pick_point[0],p);
1362     #endif
1363     return(id);
1364     }
1365     }
1366     return(-1);
1367     }
1368    
1369     int
1370     ray_trace_check_set(qtptr,orig,dir,tptr,os)
1371     QUADTREE *qtptr;
1372     FVECT orig,dir;
1373     int *tptr;
1374     OBJECT *os;
1375     {
1376     OBJECT tset[QT_MAXSET+1];
1377     double dt,t;
1378     int found;
1379     FVECT o;
1380    
1381    
1382     if(!QT_IS_EMPTY(*qtptr))
1383     {
1384     VADD(o,orig,SM_VIEW_CENTER(smMesh));
1385     qtgetset(tset,*qtptr);
1386     /* Check triangles in set against those seen so far(os):only
1387     check new triangles for intersection (t_set')
1388     */
1389     check_set(tset,os);
1390     if((found = intersect_tri_set(tset,o,dir,NULL))!= -1)
1391     {
1392     *tptr = found;
1393     return(QT_DONE);
1394     }
1395     }
1396     return(FALSE);
1397     }
1398    
1399     int
1400     smFindSamp_opt(orig,dir)
1401     FVECT orig,dir;
1402     {
1403     FVECT b,p,o;
1404     OBJECT *ts;
1405     QUADTREE qt;
1406     int s_id;
1407     double d;
1408    
1409     /* r is the normalized vector from the view center to the current
1410     * ray point ( starting with "orig"). Find the cell that r falls in,
1411     * and test the ray against all triangles stored in the cell. If
1412     * the test fails, trace the projection of the ray across to the
1413     * next cell it intersects: iterate until either an intersection
1414     * is found, or the projection ray is // to the direction. The sample
1415     * corresponding to the triangle vertex closest to the intersection
1416     * point is returned.
1417     */
1418    
1419     /* First test if "orig" coincides with the View_center or if "dir" is
1420     parallel to r formed by projecting "orig" on the sphere. In
1421     either case, do a single test against the cell containing the
1422     intersection of "dir" and the sphere
1423     */
1424     /* orig will be updated-so preserve original value */
1425     if(!smMesh)
1426     return;
1427     point_on_sphere(b,orig,SM_VIEW_CENTER(smMesh));
1428     d = -DOT(b,dir);
1429     if(EQUAL_VEC3(orig,SM_VIEW_CENTER(smMesh)) || EQUAL(fabs(d),1.0))
1430     {
1431     qt = smPointLocateCell(smMesh,dir,FALSE,NULL,NULL,NULL);
1432     /* Test triangles in the set for intersection with Ray:returns
1433     first found
1434     */
1435     ts = qtqueryset(qt);
1436     s_id = intersect_tri_set(ts,orig,dir,p);
1437     #ifdef DEBUG_TEST_DRIVER
1438     VCOPY(Pick_point[0],p);
1439     #endif
1440     }
1441     else
1442     {
1443     OBJECT t_set[QT_MAXCSET+1];
1444     /* Test each of the root triangles against point id */
1445     QT_CLEAR_SET(t_set);
1446     VSUB(o,orig,SM_VIEW_CENTER(smMesh));
1447     ST_CLEAR_FLAGS(SM_LOCATOR(smMesh));
1448     s_id=stTrace_ray(SM_LOCATOR(smMesh),o,dir,ray_trace_check_set,&s_id,t_set);
1449     }
1450     return(s_id);
1451     }
1452    
1453    
1454    
1455    
1456    
1457    
1458    
1459    
1460    
1461    
1462 gwlarson 3.1
1463