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

# Content
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 static int smBase_nbrs[4][3] = { {3,2,1},{3,0,2},{3,1,0},{1,2,0}};
21
22 #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 int Pick_tri = -1,Picking = FALSE,Pick_samp=-1;
26 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 int *arg;
260 {
261 STREE *st;
262 int found;
263 FVECT p0,p1,p2;
264
265 st = SM_LOCATOR(sm);
266
267 VSUB(p0,v0,SM_VIEW_CENTER(sm));
268 VSUB(p1,v1,SM_VIEW_CENTER(sm));
269 VSUB(p2,v2,SM_VIEW_CENTER(sm));
270
271 found = stApply_to_tri_cells(st,p0,p1,p2,func,arg);
272
273 return(found);
274 }
275
276
277 int
278 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 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 FVECT v0,v1,v2;
430
431 st = SM_LOCATOR(sm);
432
433 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
437 stUpdate_tri(st,t_id,v0,v1,v2,add_tri,add_tri_expand);
438
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 if(d1 < d0)
527 {
528 if((eps < 0) || d1 < eps)
529 {
530 closest = v1_id;
531 d = d1;
532 }
533 }
534 }
535 if(v2_id != -1)
536 {
537 smDir(sm,v,v2_id);
538 d2 = DIST(p,v);
539 if((eps < 0) || d2 < eps)
540 if(closest == -1 ||(d2 < d))
541 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 if(d1 < d0)
564 {
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 smTris_swap_edge(sm,t_id,t1_id,e,e1,tn_id,tn1_id,add,del)
578 SM *sm;
579 int t_id,t1_id;
580 int e,e1;
581 int *tn_id,*tn1_id;
582 LIST **add,**del;
583
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 *add = push_data(*add,ta_id);
606 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 *add = push_data(*add,tb_id);
611
612 /* 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
633 *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 *tn_id = ta_id;
644 *tn1_id = tb_id;
645 }
646
647 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 smNew_tri_cnt--;
660 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 /* MUST add check for constrained edges */
679 int
680 smFix_tris(sm,id,tlist)
681 SM *sm;
682 int id;
683 LIST *tlist;
684 {
685 TRI *t,*t_opp;
686 FVECT p,p1,p2,p3;
687 int e,e1,swapped = 0;
688 int t_id,t_opp_id;
689 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 while(tlist)
695 {
696 t_id = pop_list(&tlist);
697 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 smTris_swap_edge(sm,t_id,t_opp_id,e,e1,&t_id,&t_opp_id,
712 &add_list,&del_list);
713 tlist = push_data(tlist,t_id);
714 tlist = push_data(tlist,t_opp_id);
715 }
716 }
717 smUpdate_locator(sm,add_list,del_list);
718 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 t_id = smTri_next_ccw_nbr(sm,tri,nid);
751 while((t = SM_NTH_TRI(sm,t_id)) != tri)
752 {
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 int type,which;
778 {
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 /* Add triangle to the locator */
849 smLocator_add_tri(sm,t0_id,s_id,v0_id,v1_id);
850
851 t1_id = smAdd_tri(sm,s_id,v1_id,v2_id,&t1);
852 smLocator_add_tri(sm,t1_id,s_id,v1_id,v2_id);
853 t2_id = smAdd_tri(sm,s_id,v2_id,v0_id,&t2);
854 smLocator_add_tri(sm,t2_id,s_id,v2_id,v0_id);
855
856 /* 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 smLocator_remove_tri(sm,tri_id);
876 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 smPointLocate(sm,pt,norm)
894 SM *sm;
895 FVECT pt;
896 int norm;
897 {
898 STREE *st;
899 int tri;
900 FVECT npt;
901
902 st = SM_LOCATOR(sm);
903 if(norm)
904 {
905 VSUB(npt,pt,SM_VIEW_CENTER(sm));
906 tri = stPoint_locate(st,npt);
907 }
908 else
909 tri = stPoint_locate(st,pt);
910 return(tri);
911 }
912
913 QUADTREE
914 smPointLocateCell(sm,pt,norm,v0,v1,v2)
915 SM *sm;
916 FVECT pt;
917 int norm;
918 FVECT v0,v1,v2;
919 {
920 STREE *st;
921 QUADTREE *qtptr;
922 FVECT npt;
923
924 st = SM_LOCATOR(sm);
925 if(norm)
926 {
927 VSUB(npt,pt,SM_VIEW_CENTER(sm));
928
929 qtptr = stPoint_locate_cell(st,npt,v0,v1,v2);
930 }
931 else
932 qtptr = stPoint_locate_cell(st,pt,v0,v1,v2);
933
934 if(qtptr)
935 return(*qtptr);
936 else
937 return(EMPTY);
938 }
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 t_id = smPointLocate(smMesh,pt,TRUE);
959 if(t_id >= 0)
960 s_id = smInsert_point_in_tri(smMesh,c,dir,pt,s_id,t_id);
961 #ifdef DEBUG
962 else
963 {
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 #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 t_id = smPointLocate(smMesh,p,TRUE);
981 if(t_id != -1)
982 s_id = smInsert_point_in_tri(smMesh,c,dir,p,s_id,t_id);
983 #ifdef DEBUG
984 else
985 eputs("smAdd_sample_to_mesh():not found reinsert\n");
986 #endif
987 }
988 /* Is a BG(sky point) */
989 else
990 {
991 t_id = smPointLocate(smMesh,dir,FALSE);
992 if(t_id != -1)
993 s_id = smInsert_point_in_tri(smMesh,c,dir,NULL,s_id,t_id);
994
995 #ifdef DEBUG
996 else
997 eputs("smAdd_sample_to_mesh(): not found bg\n");
998 #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 int debug=0;
1023
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 if(!debug)
1028 s_id = smAdd_sample_to_mesh(smMesh,c,dir,p,-1);
1029 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 int i,id,tri_id,nbr_id;
1103 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 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 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 smLocator_add_tri(sm,ids[i],v0_id,v1_id,v2_id);
1134 }
1135 /* Set neighbors */
1136
1137 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
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 int b;
1151 {
1152
1153 for(; i < SM_TRI_CNT(sm);i++)
1154 {
1155
1156 if(!SM_IS_NTH_T_FLAG(sm,i,which))
1157 continue;
1158 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 qtTri_from_id(t_id,v0,v1,v2,n0,n1,n2,v0_idp,v1_idp,v2_idp)
1185 int t_id;
1186 FVECT v0,v1,v2;
1187 FVECT n0,n1,n2;
1188 int *v0_idp,*v1_idp,*v2_idp;
1189 {
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 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
1210 }
1211 if(v0_idp)
1212 {
1213 *v0_idp = v0_id;
1214 *v1_idp = v1_id;
1215 *v2_idp = v2_id;
1216 }
1217 }
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 OBJECT os[QT_MAXCSET+1],t_set[QT_MAXSET+1],*ts;
1233 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 qt = smPointLocateCell(smMesh,dir,FALSE,NULL,NULL,NULL);
1257 /* Test triangles in the set for intersection with Ray:returns
1258 first found
1259 */
1260 ts = qtqueryset(qt);
1261 s_id = intersect_tri_set(ts,orig,dir,p);
1262 #ifdef DEBUG_TEST_DRIVER
1263 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 qt = smPointLocateCell(smMesh,r,FALSE,v0,v1,v2);
1272 /* os will contain all triangles seen thus far */
1273 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 s_id = intersect_tri_set(t_set,orig,dir,p);
1284 #ifdef DEBUG_TEST_DRIVER
1285 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 traceRay(r,dir,v0,v1,v2,r);
1291 qt = smPointLocateCell(smMesh,r,FALSE,v0,v1,v2);
1292 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 d = DOT(a,r);
1298 }
1299 }
1300 #ifdef DEBUG
1301 eputs("smFindSamp():Pick Ray did not intersect mesh");
1302 #endif
1303 return(EMPTY);
1304 }
1305
1306
1307 smRebuild_mesh(sm,vp)
1308 SM *sm;
1309 FVECT vp;
1310 {
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 VSUB(ov,vp,SM_VIEW_CENTER(sm));
1319 smInit_mesh(sm,vp);
1320
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
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
1463