1 |
– |
/* Copyright (c) 1998 Silicon Graphics, Inc. */ |
2 |
– |
|
1 |
|
#ifndef lint |
2 |
< |
static char SCCSid[] = "$SunId$ SGI"; |
2 |
> |
static const char RCSid[] = "$Id$"; |
3 |
|
#endif |
6 |
– |
|
4 |
|
/* |
5 |
|
* sm.c |
6 |
|
*/ |
10 |
|
#include "sm_geom.h" |
11 |
|
#include "sm.h" |
12 |
|
|
16 |
– |
|
17 |
– |
|
13 |
|
SM *smMesh = NULL; |
14 |
|
double smDist_sum=0; |
15 |
|
|
238 |
|
unsigned len; |
239 |
|
int resize; |
240 |
|
{ |
246 |
– |
extern char *malloc(), *realloc(); |
241 |
|
static char *tempbuf = NULL; |
242 |
|
static unsigned tempbuflen = 0; |
243 |
|
|
271 |
|
smDir(sm,ps,id) |
272 |
|
SM *sm; |
273 |
|
FVECT ps; |
274 |
< |
int id; |
274 |
> |
S_ID id; |
275 |
|
{ |
276 |
|
VSUB(ps,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm)); |
277 |
|
normalize(ps); |
341 |
|
} |
342 |
|
|
343 |
|
|
344 |
+ |
/* |
345 |
+ |
* smAlloc_tri(sm) : Allocate a new mesh triangle |
346 |
+ |
* SM *sm; : mesh |
347 |
+ |
* |
348 |
+ |
* Returns ptr to next available tri |
349 |
+ |
*/ |
350 |
|
int |
351 |
|
smAlloc_tri(sm) |
352 |
|
SM *sm; |
367 |
|
return(INVALID); |
368 |
|
} |
369 |
|
|
370 |
+ |
|
371 |
|
smFree_mesh(sm) |
372 |
|
SM *sm; |
373 |
|
{ |
380 |
|
free(SM_NTH_FLAGS(sm,i)); |
381 |
|
} |
382 |
|
|
383 |
< |
|
384 |
< |
/* Initialize/clear global smL sample list for at least n samples */ |
383 |
> |
|
384 |
> |
/* |
385 |
> |
* smAlloc(max_samples) : Initialize/clear global sample list for at least |
386 |
> |
* max_samples |
387 |
> |
* int max_samples; |
388 |
> |
* |
389 |
> |
*/ |
390 |
|
smAlloc(max_samples) |
391 |
|
register int max_samples; |
392 |
|
{ |
435 |
|
SM *sm; |
436 |
|
FVECT vp; |
437 |
|
{ |
432 |
– |
|
438 |
|
VCOPY(SM_VIEW_CENTER(sm),vp); |
439 |
|
smClear(sm); |
440 |
|
smCreate_base_mesh(sm,SM_DEFAULT); |
450 |
|
* If n is <= 0, then clear data structures. Returns number samples |
451 |
|
* actually allocated. |
452 |
|
*/ |
448 |
– |
|
453 |
|
int |
454 |
|
smInit(n) |
455 |
|
register int n; |
456 |
|
{ |
457 |
|
int max_vertices; |
458 |
< |
|
458 |
> |
sleep(5); |
459 |
|
/* If n <=0, Just clear the existing structures */ |
460 |
|
if(n <= 0) |
461 |
|
{ |
509 |
|
|
510 |
|
} |
511 |
|
|
512 |
+ |
/* |
513 |
+ |
* QUADTREE |
514 |
+ |
* insert_samp(argptr,root,qt,parent,q0,q1,q2,bc,scale,rev,f,n,doneptr) |
515 |
+ |
* Callback function called from quadtree traversal when leaf is reached |
516 |
+ |
* int *argptr; :ptr to sample id number |
517 |
+ |
* int root; :quadtree root from which traversal started |
518 |
+ |
* QUADTREE qt,parent; :current quadtree node and its parent |
519 |
+ |
* BCOORD q0[3],q1[3],q2[3],bc[3]; :barycentric coordinates of the current |
520 |
+ |
* quadtree node (q0,q1,q2) and sample (bc) |
521 |
+ |
* unsigned int scale,rev; :scale factor relative to which level at in |
522 |
+ |
* tree, rev indicates if traversed of child 3 |
523 |
+ |
* FUNC f; :function structure so can recurse |
524 |
+ |
* int n,*doneptr; :n indicates which level at in quadtree, and |
525 |
+ |
* doneptr can be set to indicate whether nbr |
526 |
+ |
* sample has been found |
527 |
+ |
*/ |
528 |
|
QUADTREE |
529 |
|
insert_samp(argptr,root,qt,parent,q0,q1,q2,bc,scale,rev,f,n,doneptr) |
530 |
|
int *argptr; |
535 |
|
FUNC f; |
536 |
|
int n,*doneptr; |
537 |
|
{ |
538 |
< |
OBJECT *optr,*sptr,s_set[QT_MAXSET+1]; |
539 |
< |
int i,s_id; |
520 |
< |
FVECT p; |
521 |
< |
BCOORD bp[3]; |
522 |
< |
FUNC sfunc; |
523 |
< |
S_ARGS args; |
538 |
> |
S_ID s_id; |
539 |
> |
S_ID *optr; |
540 |
|
|
541 |
|
s_id = ((S_ARGS *)argptr)->s_id; |
542 |
|
/* If the set is empty - just add */ |
573 |
|
/* otherwise: expand node- and insert sample, and reinsert existing samples |
574 |
|
in set to children of new node |
575 |
|
*/ |
560 |
– |
if(QT_SET_CNT(optr) > QT_MAXSET) |
561 |
– |
{ |
562 |
– |
if(!(sptr = (OBJECT *)malloc((QT_SET_CNT(optr)+1)*sizeof(OBJECT)))) |
563 |
– |
goto memerr; |
564 |
– |
} |
565 |
– |
else |
566 |
– |
sptr = s_set; |
567 |
– |
qtgetset(sptr,qt); |
568 |
– |
|
569 |
– |
/* subdivide node */ |
570 |
– |
qtfreeleaf(qt); |
571 |
– |
qtSubdivide(qt); |
572 |
– |
|
573 |
– |
/* Now add in all of the rest; */ |
574 |
– |
F_FUNC(sfunc) = F_FUNC(f); |
575 |
– |
F_ARGS(sfunc) = (int *) (&args); |
576 |
– |
args.n_id = 0; |
577 |
– |
for(optr = sptr,i=QT_SET_CNT(sptr); i > 0; i--) |
576 |
|
{ |
577 |
< |
s_id = QT_SET_NEXT_ELEM(optr); |
578 |
< |
args.s_id = s_id; |
579 |
< |
VSUB(p,SM_NTH_WV(smMesh,s_id),SM_VIEW_CENTER(smMesh)); |
580 |
< |
normalize(p); |
581 |
< |
vert_to_qt_frame(i,p,bp); |
582 |
< |
if(rev) |
583 |
< |
qt= qtInsert_point_rev(root,qt,parent,q0,q1,q2,bp,scale,sfunc,n,doneptr); |
584 |
< |
else |
585 |
< |
qt= qtInsert_point(root,qt,parent,q0,q1,q2,bp,scale,sfunc,n,doneptr); |
586 |
< |
} |
587 |
< |
/* Add current sample: have all of the information */ |
588 |
< |
if(rev) |
589 |
< |
qt =qtInsert_point_rev(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr); |
590 |
< |
else |
593 |
< |
qt = qtInsert_point(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr); |
594 |
< |
|
595 |
< |
/* If we allocated memory: free it */ |
577 |
> |
OBJECT *sptr,s_set[QT_MAXSET+1]; |
578 |
> |
FUNC sfunc; |
579 |
> |
S_ARGS args; |
580 |
> |
FVECT p; |
581 |
> |
BCOORD bp[3]; |
582 |
> |
int i; |
583 |
> |
|
584 |
> |
if(QT_SET_CNT(optr) > QT_MAXSET) |
585 |
> |
{ |
586 |
> |
if(!(sptr = (OBJECT *)malloc((QT_SET_CNT(optr)+1)*sizeof(OBJECT)))) |
587 |
> |
goto memerr; |
588 |
> |
} |
589 |
> |
else |
590 |
> |
sptr = s_set; |
591 |
|
|
592 |
< |
if( sptr != s_set) |
593 |
< |
free(sptr); |
592 |
> |
qtgetset(sptr,qt); |
593 |
> |
|
594 |
> |
/* subdivide node */ |
595 |
> |
qtfreeleaf(qt); |
596 |
> |
qtSubdivide(qt); |
597 |
> |
|
598 |
> |
/* Now add in all of the rest; */ |
599 |
> |
F_FUNC(sfunc) = F_FUNC(f); |
600 |
> |
F_ARGS(sfunc) = (int *) (&args); |
601 |
> |
args.n_id = 0; |
602 |
> |
for(optr = sptr,i=QT_SET_CNT(sptr); i > 0; i--) |
603 |
> |
{ |
604 |
> |
s_id = QT_SET_NEXT_ELEM(optr); |
605 |
> |
args.s_id = s_id; |
606 |
> |
VSUB(p,SM_NTH_WV(smMesh,s_id),SM_VIEW_CENTER(smMesh)); |
607 |
> |
normalize(p); |
608 |
> |
vert_to_qt_frame(i,p,bp); |
609 |
> |
if(rev) |
610 |
> |
qt= qtInsert_point_rev(root,qt,parent,q0,q1,q2,bp, |
611 |
> |
scale,sfunc,n,doneptr); |
612 |
> |
else |
613 |
> |
qt= qtInsert_point(root,qt,parent,q0,q1,q2,bp, |
614 |
> |
scale,sfunc,n,doneptr); |
615 |
> |
} |
616 |
> |
/* Add current sample: have all of the information */ |
617 |
> |
if(rev) |
618 |
> |
qt =qtInsert_point_rev(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr); |
619 |
> |
else |
620 |
> |
qt = qtInsert_point(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr); |
621 |
> |
|
622 |
> |
/* If we allocated memory: free it */ |
623 |
|
|
624 |
< |
return(qt); |
624 |
> |
if( sptr != s_set) |
625 |
> |
free(sptr); |
626 |
> |
|
627 |
> |
return(qt); |
628 |
> |
} |
629 |
|
memerr: |
630 |
|
error(SYSTEM,"expand_node():Unable to allocate memory"); |
631 |
|
|
632 |
|
} |
633 |
|
|
634 |
|
|
635 |
< |
double |
636 |
< |
triangle_normal(n,a,b,c) |
637 |
< |
double n[3]; |
638 |
< |
double a[3],b[3],c[3]; |
639 |
< |
{ |
640 |
< |
double ab[3],ac[3]; |
641 |
< |
|
642 |
< |
VSUB(ab,b,a); |
643 |
< |
normalize(ab); |
644 |
< |
VSUB(ac,c,a); |
645 |
< |
normalize(ac); |
618 |
< |
VCROSS(n,ab,ac); |
619 |
< |
return(normalize(n)); |
620 |
< |
} |
621 |
< |
double on0,on1,on2; |
622 |
< |
/* Add a triangle to the base array with vertices v1-v2-v3 */ |
635 |
> |
/* |
636 |
> |
* int |
637 |
> |
* smAdd_tri(sm,v0_id,v1_id,v2_id,tptr) |
638 |
> |
* : Add a triangle to the base array with vertices v0-v1-v2, |
639 |
> |
* returns ptr to triangle in tptr |
640 |
> |
* SM *sm; : mesh |
641 |
> |
* S_ID v0_id,v1_id,v2_id; : sample ids of triangle vertices |
642 |
> |
* TRI **tptr; : ptr to set to triangle |
643 |
> |
* |
644 |
> |
* Allocates and initializes mesh triangle with vertices specified. |
645 |
> |
*/ |
646 |
|
int |
647 |
|
smAdd_tri(sm, v0_id,v1_id,v2_id,tptr) |
648 |
|
SM *sm; |
649 |
< |
int v0_id,v1_id,v2_id; |
649 |
> |
S_ID v0_id,v1_id,v2_id; |
650 |
|
TRI **tptr; |
651 |
|
{ |
652 |
|
int t_id; |
653 |
|
TRI *t; |
654 |
+ |
|
655 |
|
#ifdef DEBUG |
656 |
|
if(v0_id==v1_id || v0_id==v2_id || v1_id==v2_id) |
657 |
|
error(CONSISTENCY,"smAdd_tri: invalid vertex ids\n"); |
663 |
|
{ |
664 |
|
double v0[3],v1[3],v2[3],n[3]; |
665 |
|
double area,dp; |
666 |
< |
|
666 |
> |
double ab[3],ac[3]; |
667 |
|
VSUB(v0,SM_NTH_WV(sm,v0_id),SM_VIEW_CENTER(sm)); |
668 |
|
VSUB(v1,SM_NTH_WV(sm,v1_id),SM_VIEW_CENTER(sm)); |
669 |
|
VSUB(v2,SM_NTH_WV(sm,v2_id),SM_VIEW_CENTER(sm)); |
670 |
|
normalize(v0); |
671 |
|
normalize(v1); |
672 |
|
normalize(v2); |
673 |
< |
area = triangle_normal(n,v2,v1,v0); |
673 |
> |
|
674 |
> |
VSUB(ab,v1,v2); |
675 |
> |
normalize(ab); |
676 |
> |
VSUB(ac,v0,v2); |
677 |
> |
normalize(ac); |
678 |
> |
VCROSS(n,ab,ac); |
679 |
> |
area = normalize(n); |
680 |
|
if((dp=DOT(v0,n)) < 0.0) |
681 |
|
{ |
652 |
– |
fprintf(stderr,"dp = %.10f on0=%.10f on1=%.10f on2=%.10f\n", dp, |
653 |
– |
on0,on1,on2); |
682 |
|
eputs("backwards tri\n"); |
683 |
|
} |
684 |
|
} |
685 |
|
#endif |
686 |
|
#endif |
687 |
|
|
660 |
– |
|
688 |
|
t = SM_NTH_TRI(sm,t_id); |
689 |
< |
|
689 |
> |
#ifdef DEBUG |
690 |
|
T_CLEAR_NBRS(t); |
691 |
+ |
#endif |
692 |
|
/* set the triangle vertex ids */ |
693 |
|
T_NTH_V(t,0) = v0_id; |
694 |
|
T_NTH_V(t,1) = v1_id; |
713 |
|
SM_SET_NTH_T_ACTIVE(sm,t_id); |
714 |
|
SM_SET_NTH_T_NEW(sm,t_id); |
715 |
|
|
688 |
– |
|
716 |
|
*tptr = t; |
717 |
|
/* return initialized triangle */ |
718 |
|
return(t_id); |
719 |
|
} |
720 |
|
|
721 |
|
|
695 |
– |
/* pt_in_cone: assumed apex at origin, a,b,c are unit vectors defining the |
696 |
– |
triangle which the cone circumscribes. Assumed p is not normalized |
697 |
– |
*/ |
698 |
– |
int |
699 |
– |
pt_in_cone(p,a,b,c) |
700 |
– |
double p[3],a[3],b[3],c[3]; |
701 |
– |
{ |
702 |
– |
double r[3]; |
703 |
– |
double pr,ar; |
704 |
– |
double ab[3],ac[3]; |
705 |
– |
/* r = (B-A)X(C-A) */ |
706 |
– |
/* in = (p.r) > (a.r) */ |
722 |
|
|
708 |
– |
#ifdef DEBUG |
709 |
– |
#if DEBUG > 1 |
710 |
– |
{ |
711 |
– |
double l; |
712 |
– |
l = triangle_normal(r,a,b,c); |
713 |
– |
/* l = sin@ between ab,ac - if 0 vectors are colinear */ |
714 |
– |
if( l <= COLINEAR_EPS) |
715 |
– |
{ |
716 |
– |
eputs("pt in cone: null triangle:returning FALSE\n"); |
717 |
– |
return(FALSE); |
718 |
– |
} |
719 |
– |
} |
720 |
– |
#endif |
721 |
– |
#endif |
722 |
– |
|
723 |
– |
VSUB(ab,b,a); |
724 |
– |
VSUB(ac,c,a); |
725 |
– |
VCROSS(r,ab,ac); |
726 |
– |
|
727 |
– |
pr = DOT(p,r); |
728 |
– |
ar = DOT(a,r); |
729 |
– |
/* Need to check for equality for degeneracy of 4 points on circle */ |
730 |
– |
if( pr > ar *( 1.0 + EQUALITY_EPS)) |
731 |
– |
return(TRUE); |
732 |
– |
else |
733 |
– |
return(FALSE); |
734 |
– |
} |
735 |
– |
|
723 |
|
smRestore_Delaunay(sm,a,b,c,t,t_id,a_id,b_id,c_id) |
724 |
|
SM *sm; |
725 |
|
FVECT a,b,c; |
726 |
|
TRI *t; |
727 |
|
int t_id,a_id,b_id,c_id; |
728 |
|
{ |
729 |
< |
int e1,topp_id,p_id; |
729 |
> |
int e1,topp_id; |
730 |
> |
S_ID p_id; |
731 |
|
TRI *topp; |
732 |
|
FVECT p; |
733 |
|
|
871 |
|
smTri_next_ccw_nbr(sm,t,id) |
872 |
|
SM *sm; |
873 |
|
TRI *t; |
874 |
< |
int id; |
874 |
> |
S_ID id; |
875 |
|
{ |
876 |
|
int which; |
877 |
|
int nbr_id; |
900 |
|
int |
901 |
|
smInsert_samp_mesh(sm,s_id,tri_id,a,b,c,d,on,which) |
902 |
|
SM *sm; |
903 |
< |
int s_id,tri_id; |
903 |
> |
S_ID s_id; |
904 |
> |
int tri_id; |
905 |
|
FVECT a,b,c,d; |
906 |
|
int on,which; |
907 |
|
{ |
908 |
< |
int v_id[3],topp_id,i; |
908 |
> |
S_ID v_id[3],opp_id; |
909 |
> |
int topp_id,i; |
910 |
|
int t0_id,t1_id,t2_id,t3_id; |
911 |
< |
int e0,e1,e2,opp_id,opp0,opp1,opp2; |
911 |
> |
int e0,e1,e2,opp0,opp1,opp2; |
912 |
|
TRI *tri,*nbr,*topp,*t0,*t1,*t2,*t3; |
913 |
|
FVECT e; |
914 |
|
|
1321 |
|
{ |
1322 |
|
FVECT n,v0,v1,v2; |
1323 |
|
TRI *tn; |
1324 |
< |
|
1324 |
> |
double on0,on1,on2; |
1325 |
|
int tn_id; |
1326 |
|
|
1327 |
|
#ifdef DEBUG |
1702 |
|
if(EQUAL_VEC3(v2,p)){ *o = ON_V; *w = 2; return(t_id);} |
1703 |
|
|
1704 |
|
|
1705 |
< |
int |
1705 |
> |
|
1706 |
|
find_neighbor(argptr,qt,f,doneptr) |
1707 |
|
int *argptr; |
1708 |
|
QUADTREE qt; |
1709 |
|
FUNC f; |
1710 |
|
int *doneptr; |
1711 |
|
{ |
1712 |
< |
int s_id,i; |
1713 |
< |
OBJECT *optr; |
1712 |
> |
S_ID s_id; |
1713 |
> |
int i; |
1714 |
> |
S_ID *optr; |
1715 |
|
|
1716 |
|
if(QT_IS_EMPTY(qt)) |
1717 |
|
return; |
1743 |
|
|
1744 |
|
smInsert_samp(sm,s_id,p,nptr) |
1745 |
|
SM *sm; |
1746 |
< |
int s_id; |
1746 |
> |
S_ID s_id; |
1747 |
|
FVECT p; |
1748 |
< |
int *nptr; |
1748 |
> |
S_ID *nptr; |
1749 |
|
{ |
1750 |
|
FVECT tpt; |
1751 |
|
FUNC f; |
1772 |
|
smSample_locate_tri(sm,p,s_id,onptr,whichptr,nptr) |
1773 |
|
SM *sm; |
1774 |
|
FVECT p; |
1775 |
< |
int s_id; |
1776 |
< |
int *onptr,*whichptr,*nptr; |
1775 |
> |
S_ID s_id; |
1776 |
> |
int *onptr,*whichptr; |
1777 |
> |
S_ID *nptr; |
1778 |
|
{ |
1779 |
|
int tri_id; |
1780 |
|
FVECT tpt; |
1845 |
|
SM *sm; |
1846 |
|
int tri_id; |
1847 |
|
FVECT dir,p; |
1848 |
< |
int *rptr; |
1848 |
> |
S_ID *rptr; |
1849 |
|
FVECT ns,n0,n1,n2; |
1850 |
|
double ds,d0; |
1851 |
|
int on,which; |
1853 |
|
TRI *tri; |
1854 |
|
double d,d2,dnear,dspt,d01,d12,d20,s0,s1,s2; |
1855 |
|
double dp,dp1; |
1856 |
< |
int vid[3],i,nearid,norm,dcnt,bcnt; |
1856 |
> |
S_ID vid[3]; |
1857 |
> |
int i,norm,dcnt,bcnt; |
1858 |
|
FVECT diff[3],spt,npt,n; |
1859 |
|
FVECT nearpt; |
1860 |
|
|
1873 |
|
if(SM_DIR_ID(sm,vid[i])) |
1874 |
|
dcnt++; |
1875 |
|
} |
1883 |
– |
if( on == IN_T) |
1884 |
– |
{ |
1885 |
– |
d = DIST_SQ(n0,ns); |
1886 |
– |
dnear = d; |
1887 |
– |
nearid = 0; |
1888 |
– |
d = DIST_SQ(n1,ns); |
1889 |
– |
if(d < dnear) |
1890 |
– |
{ |
1891 |
– |
dnear = d; nearid = 1; |
1892 |
– |
} |
1893 |
– |
d = DIST_SQ(n2,ns); |
1894 |
– |
if(d < dnear) |
1895 |
– |
{ |
1896 |
– |
dnear = d; nearid = 2; |
1897 |
– |
} |
1898 |
– |
} |
1876 |
|
if(on == ON_P) |
1900 |
– |
nearid = which; |
1901 |
– |
if(on == ON_P || dnear < VERT_EPS*VERT_EPS) |
1877 |
|
{ |
1878 |
|
FVECT edir; |
1879 |
< |
/* Pick the point with dir closest to that of the canonical view |
1880 |
< |
if it is the new sample: mark existing point for deletion |
1881 |
< |
*/ |
1907 |
< |
if(SM_BASE_ID(sm,vid[nearid])) |
1908 |
< |
return(FALSE); |
1879 |
> |
/* Pick the point with dir closest to that of the canonical view |
1880 |
> |
if it is the new sample: mark existing point for deletion |
1881 |
> |
*/ |
1882 |
|
if(!dir) |
1883 |
< |
return(FALSE); |
1884 |
< |
if(SM_DIR_ID(sm,vid[nearid])) |
1883 |
> |
return(FALSE); |
1884 |
> |
if(SM_BASE_ID(sm,vid[which])) |
1885 |
> |
return(FALSE); |
1886 |
> |
if(SM_DIR_ID(sm,vid[which])) |
1887 |
|
{ |
1888 |
< |
*rptr = vid[nearid]; |
1889 |
< |
return(TRUE); |
1888 |
> |
*rptr = vid[which]; |
1889 |
> |
return(TRUE); |
1890 |
|
} |
1891 |
< |
decodedir(edir,SM_NTH_W_DIR(sm,vid[nearid])); |
1892 |
< |
if(nearid == 0) |
1891 |
> |
decodedir(edir,SM_NTH_W_DIR(sm,vid[which])); |
1892 |
> |
if(which == 0) |
1893 |
|
d = DOT(edir,n0); |
1894 |
|
else |
1895 |
< |
if(nearid == 1) |
1895 |
> |
if(which == 1) |
1896 |
|
d = DOT(edir,n1); |
1897 |
|
else |
1898 |
|
d = DOT(edir,n2); |
1903 |
|
else |
1904 |
|
{ |
1905 |
|
/* The new sample is better: mark existing one for deletion*/ |
1906 |
< |
*rptr = vid[nearid]; |
1906 |
> |
*rptr = vid[which]; |
1907 |
|
return(TRUE); |
1908 |
|
} |
1909 |
|
} |
2001 |
|
|
2002 |
|
return(FALSE); |
2003 |
|
} |
2004 |
< |
int |
2004 |
> |
S_ID |
2005 |
|
smReplace_samp(sm,c,dir,p,np,s_id,t_id,o_id,on,which) |
2006 |
|
SM *sm; |
2007 |
|
COLR c; |
2008 |
|
FVECT dir,p,np; |
2009 |
< |
int s_id,t_id,o_id,on,which; |
2009 |
> |
S_ID s_id; |
2010 |
> |
int t_id; |
2011 |
> |
S_ID o_id; |
2012 |
> |
int on,which; |
2013 |
|
{ |
2014 |
< |
int v_id,tri_id; |
2014 |
> |
S_ID v_id; |
2015 |
> |
int tri_id; |
2016 |
|
TRI *t,*tri; |
2017 |
|
|
2018 |
|
tri = SM_NTH_TRI(sm,t_id); |
2061 |
|
|
2062 |
|
} |
2063 |
|
|
2064 |
< |
int |
2064 |
> |
S_ID |
2065 |
|
smAlloc_samp(sm) |
2066 |
|
SM *sm; |
2067 |
|
{ |
2068 |
< |
int s_id,replaced,cnt; |
2068 |
> |
S_ID s_id; |
2069 |
> |
int replaced,cnt; |
2070 |
|
SAMP *s; |
2071 |
|
FVECT p; |
2072 |
|
|
2094 |
|
b) coincide with existing edge |
2095 |
|
c) Fall in existing triangle |
2096 |
|
*/ |
2097 |
< |
int |
2097 |
> |
S_ID |
2098 |
|
smAdd_samp(sm,c,dir,p,o_id) |
2099 |
|
SM *sm; |
2100 |
|
COLR c; |
2101 |
|
FVECT dir,p; |
2102 |
< |
int o_id; |
2102 |
> |
S_ID o_id; |
2103 |
|
{ |
2104 |
< |
int t_id,s_id,r_id,on,which,n_id,nbr_id; |
2104 |
> |
int t_id,on,which,n_id; |
2105 |
> |
S_ID s_id,r_id,nbr_id; |
2106 |
|
double ds,d0; |
2107 |
|
FVECT wpt,ns,n0,n1,n2; |
2108 |
|
QUADTREE qt,parent; |
2112 |
|
nbr_id = INVALID; |
2113 |
|
/* Must do this first-as may change mesh */ |
2114 |
|
s_id = smAlloc_samp(sm); |
2134 |
– |
|
2115 |
|
SM_S_NTH_QT(sm,s_id)= EMPTY; |
2116 |
|
/* If sample is a world space point */ |
2117 |
|
if(p) |
2176 |
|
/* If sample is being added in the middle of the sample array: tone |
2177 |
|
map individually |
2178 |
|
*/ |
2199 |
– |
/* Initialize sample */ |
2200 |
– |
sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id); |
2179 |
|
/* If not base or sky point, add distance from center to average*/ |
2180 |
|
smDist_sum += 1.0/ds; |
2181 |
+ |
/* Initialize sample */ |
2182 |
+ |
sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id); |
2183 |
|
smInsert_samp_mesh(sm,s_id,t_id,ns,n0,n1,n2,on,which); |
2184 |
|
} |
2185 |
|
/* If sample is a direction vector */ |
2186 |
|
else |
2187 |
|
{ |
2188 |
|
VADD(wpt,dir,SM_VIEW_CENTER(sm)); |
2189 |
+ |
/* Allocate space for a sample and initialize */ |
2190 |
|
while(1) |
2191 |
|
{ |
2192 |
|
t_id = smSample_locate_tri(sm,dir,s_id,&on,&which,&nbr_id); |
2231 |
|
else |
2232 |
|
break; |
2233 |
|
} |
2253 |
– |
/* Allocate space for a sample and initialize */ |
2234 |
|
sInit_samp(SM_SAMP(sm),s_id,c,NULL,wpt,o_id); |
2235 |
|
smInsert_samp_mesh(sm,s_id,t_id,dir,n0,n1,n2,on,which); |
2236 |
|
} |
2248 |
|
* New sample representation will be output in next call to smUpdate(). |
2249 |
|
* If the point is a sky point: then v=NULL |
2250 |
|
*/ |
2251 |
+ |
#define FVECT_TO_SFLOAT(p) \ |
2252 |
+ |
(p[0]=(SFLOAT)p[0],p[1]=(SFLOAT)p[1],p[2]=(SFLOAT)p[2]) |
2253 |
|
int |
2254 |
|
smNewSamp(c,dir,p) |
2255 |
|
COLR c; |
2256 |
|
FVECT dir; |
2257 |
|
FVECT p; |
2258 |
|
{ |
2259 |
< |
int s_id; |
2259 |
> |
S_ID s_id; |
2260 |
> |
|
2261 |
|
/* First check if this the first sample: if so initialize mesh */ |
2262 |
|
if(SM_NUM_SAMP(smMesh) == 0) |
2263 |
|
{ |
2264 |
|
smInit_sm(smMesh,odev.v.vp); |
2265 |
|
sClear_all_flags(SM_SAMP(smMesh)); |
2266 |
|
} |
2267 |
+ |
FVECT_TO_SFLOAT(p); |
2268 |
+ |
FVECT_TO_SFLOAT(dir); |
2269 |
|
/* Add the sample to the mesh */ |
2270 |
|
s_id = smAdd_samp(smMesh,c,dir,p,INVALID); |
2271 |
|
|
2272 |
< |
#if 0 |
2288 |
< |
{ |
2289 |
< |
int i; |
2290 |
< |
FILE *fp; |
2291 |
< |
if(s_id == 10000) |
2292 |
< |
{ |
2293 |
< |
fp = fopen("test.xyz","w"); |
2294 |
< |
for(i=0; i < s_id; i++) |
2295 |
< |
if(!SM_DIR_ID(smMesh,i)) |
2296 |
< |
fprintf(fp,"%f %f %f %d %d %d \n",SM_NTH_WV(smMesh,i)[0], |
2297 |
< |
SM_NTH_WV(smMesh,i)[1],SM_NTH_WV(smMesh,i)[2], |
2298 |
< |
SM_NTH_RGB(smMesh,i)[0],SM_NTH_RGB(smMesh,i)[1], |
2299 |
< |
SM_NTH_RGB(smMesh,i)[2]); |
2300 |
< |
fclose(fp); |
2301 |
< |
} |
2302 |
< |
} |
2303 |
< |
#endif |
2304 |
< |
return(s_id); |
2272 |
> |
return((int)s_id); |
2273 |
|
|
2274 |
|
} |
2275 |
< |
int |
2275 |
> |
S_ID |
2276 |
|
smAdd_base_vertex(sm,v) |
2277 |
|
SM *sm; |
2278 |
|
FVECT v; |
2279 |
|
{ |
2280 |
< |
int id; |
2280 |
> |
S_ID id; |
2281 |
|
|
2282 |
|
/* First add coordinate to the sample array */ |
2283 |
|
id = sAdd_base_point(SM_SAMP(sm),v); |
2301 |
|
int type; |
2302 |
|
{ |
2303 |
|
int i,s_id,tri_id,nbr_id; |
2304 |
< |
int p[SM_BASE_POINTS],ids[SM_BASE_TRIS]; |
2305 |
< |
int v0_id,v1_id,v2_id; |
2304 |
> |
S_ID p[SM_BASE_POINTS]; |
2305 |
> |
int ids[SM_BASE_TRIS]; |
2306 |
> |
S_ID v0_id,v1_id,v2_id; |
2307 |
|
FVECT d,pt,cntr,v0,v1,v2; |
2308 |
|
TRI *t; |
2309 |
|
|
2310 |
|
/* First insert the base vertices into the sample point array */ |
2342 |
– |
|
2311 |
|
for(i=0; i < SM_BASE_POINTS; i++) |
2312 |
|
{ |
2313 |
|
VADD(cntr,icosa_verts[i],SM_VIEW_CENTER(sm)); |
2334 |
|
SM *sm; |
2335 |
|
VIEW *v; |
2336 |
|
{ |
2337 |
< |
int i,j,cnt; |
2337 |
> |
S_ID s_id; |
2338 |
> |
int j,cnt; |
2339 |
|
FVECT p,ov,dir; |
2340 |
|
double d; |
2341 |
|
|
2355 |
|
/* Go through all samples and add in if in the new view frustum, and |
2356 |
|
the dir is <= 30 degrees from new view |
2357 |
|
*/ |
2358 |
< |
for(i=0; i < cnt; i++) |
2358 |
> |
for(s_id=0; s_id < cnt; s_id++) |
2359 |
|
{ |
2360 |
|
/* First check if sample visible(conservative approx: if one of tris |
2361 |
|
attached to sample is in frustum) */ |
2362 |
< |
if(!S_IS_FLAG(i)) |
2362 |
> |
if(!S_IS_FLAG(s_id)) |
2363 |
|
continue; |
2364 |
|
|
2365 |
|
/* Next test if direction > 30 degrees from current direction */ |
2366 |
< |
if(SM_NTH_W_DIR(sm,i)!=-1) |
2366 |
> |
if(SM_NTH_W_DIR(sm,s_id)!=-1) |
2367 |
|
{ |
2368 |
< |
VSUB(p,SM_NTH_WV(sm,i),v->vp); |
2369 |
< |
decodedir(dir,SM_NTH_W_DIR(sm,i)); |
2368 |
> |
VSUB(p,SM_NTH_WV(sm,s_id),v->vp); |
2369 |
> |
decodedir(dir,SM_NTH_W_DIR(sm,s_id)); |
2370 |
|
d = DOT(dir,p); |
2371 |
|
if (d*d < MAXDIFF2*DOT(p,p)) |
2372 |
|
continue; |
2373 |
< |
VCOPY(p,SM_NTH_WV(sm,i)); |
2374 |
< |
smAdd_samp(sm,NULL,dir,p,i); |
2373 |
> |
VCOPY(p,SM_NTH_WV(sm,s_id)); |
2374 |
> |
smAdd_samp(sm,NULL,dir,p,s_id); |
2375 |
|
} |
2376 |
|
else |
2377 |
|
{ |
2378 |
|
/* If the direction is > 45 degrees from current view direction: |
2379 |
|
throw out |
2380 |
|
*/ |
2381 |
< |
VSUB(dir,SM_NTH_WV(sm,i),ov); |
2381 |
> |
VSUB(dir,SM_NTH_WV(sm,s_id),ov); |
2382 |
|
if(DOT(dir,v->vdir) < MAXDIR) |
2383 |
|
continue; |
2384 |
|
|
2385 |
< |
VADD(SM_NTH_WV(sm,i),dir,SM_VIEW_CENTER(sm)); |
2386 |
< |
smAdd_samp(sm,NULL,dir,NULL,i); |
2385 |
> |
VADD(SM_NTH_WV(sm,s_id),dir,SM_VIEW_CENTER(sm)); |
2386 |
> |
smAdd_samp(sm,NULL,dir,NULL,s_id); |
2387 |
|
} |
2388 |
|
|
2389 |
|
} |
2392 |
|
#endif |
2393 |
|
} |
2394 |
|
|
2426 |
– |
int |
2427 |
– |
intersect_tri_set(t_set,orig,dir,pt) |
2428 |
– |
OBJECT *t_set; |
2429 |
– |
FVECT orig,dir,pt; |
2430 |
– |
{ |
2431 |
– |
OBJECT *optr; |
2432 |
– |
int i,t_id,id,base; |
2433 |
– |
int pid0,pid1,pid2; |
2434 |
– |
FVECT p0,p1,p2,p; |
2435 |
– |
TRI *t; |
2436 |
– |
double d,d1; |
2437 |
– |
|
2438 |
– |
optr = t_set; |
2439 |
– |
for(i = QT_SET_CNT(t_set); i > 0; i--) |
2440 |
– |
{ |
2441 |
– |
t_id = QT_SET_NEXT_ELEM(optr); |
2442 |
– |
t = SM_NTH_TRI(smMesh,t_id); |
2443 |
– |
if(!T_IS_VALID(t) || SM_IS_NTH_T_BASE(smMesh,t_id)|| |
2444 |
– |
SM_IS_NTH_T_BG(smMesh,t_id)) |
2445 |
– |
continue; |
2446 |
– |
pid0 = T_NTH_V(t,0); |
2447 |
– |
pid1 = T_NTH_V(t,1); |
2448 |
– |
pid2 = T_NTH_V(t,2); |
2449 |
– |
VCOPY(p0,SM_NTH_WV(smMesh,pid0)); |
2450 |
– |
VCOPY(p1,SM_NTH_WV(smMesh,pid1)); |
2451 |
– |
VCOPY(p2,SM_NTH_WV(smMesh,pid2)); |
2452 |
– |
if(ray_intersect_tri(orig,dir,p0,p1,p2,p)) |
2453 |
– |
{ |
2454 |
– |
d = DIST_SQ(p,p0); |
2455 |
– |
d1 = DIST_SQ(p,p1); |
2456 |
– |
if(d < d1) |
2457 |
– |
{ |
2458 |
– |
d1 = DIST_SQ(p,p2); |
2459 |
– |
id = (d1 < d)?pid2:pid0; |
2460 |
– |
} |
2461 |
– |
else |
2462 |
– |
{ |
2463 |
– |
d = DIST_SQ(p,p2); |
2464 |
– |
id = (d < d1)? pid2:pid1; |
2465 |
– |
} |
2466 |
– |
if(pt) |
2467 |
– |
VCOPY(pt,p); |
2468 |
– |
#ifdef TEST_DRIVER |
2469 |
– |
Pick_tri = t_id; |
2470 |
– |
Pick_samp = id; |
2471 |
– |
VCOPY(Pick_point[0],p); |
2472 |
– |
#endif |
2473 |
– |
return(id); |
2474 |
– |
} |
2475 |
– |
} |
2476 |
– |
return(-1); |
2477 |
– |
} |
2478 |
– |
|
2395 |
|
/* OS is constrained to be <= QT_MAXCSET : if the set exceeds this, the |
2396 |
|
results of check_set are conservative |
2397 |
|
*/ |
2398 |
|
int |
2399 |
|
compare_ids(id1,id2) |
2400 |
< |
OBJECT *id1,*id2; |
2400 |
> |
S_ID *id1,*id2; |
2401 |
|
{ |
2402 |
|
int d; |
2403 |
|
|
2411 |
|
return(0); |
2412 |
|
} |
2413 |
|
|
2498 |
– |
ray_trace_check_set(qt,argptr,fptr) |
2499 |
– |
QUADTREE qt; |
2500 |
– |
RT_ARGS *argptr; |
2501 |
– |
int *fptr; |
2502 |
– |
{ |
2503 |
– |
OBJECT tset[QT_MAXSET+1],*tptr; |
2504 |
– |
double dt,t; |
2505 |
– |
int found; |
2506 |
– |
if(QT_IS_EMPTY(qt)) |
2507 |
– |
return; |
2508 |
– |
if(QT_LEAF_IS_FLAG(qt)) |
2509 |
– |
{ |
2510 |
– |
QT_FLAG_SET_DONE(*fptr); |
2511 |
– |
#if DEBUG |
2512 |
– |
eputs("ray_trace_check_set():Already visited this node:aborting\n"); |
2513 |
– |
#endif |
2514 |
– |
return; |
2515 |
– |
} |
2516 |
– |
else |
2517 |
– |
QT_LEAF_SET_FLAG(qt); |
2414 |
|
|
2519 |
– |
tptr = qtqueryset(qt); |
2520 |
– |
if(QT_SET_CNT(tptr) > QT_MAXSET) |
2521 |
– |
tptr = (OBJECT *)malloc((QT_SET_CNT(tptr)+1)*sizeof(OBJECT)); |
2522 |
– |
else |
2523 |
– |
tptr = tset; |
2524 |
– |
if(!tptr) |
2525 |
– |
goto memerr; |
2526 |
– |
|
2527 |
– |
qtgetset(tptr,qt); |
2528 |
– |
/* Must sort */ |
2529 |
– |
qsort((void *)(&(tptr[1])),tptr[0],sizeof(OBJECT),compare_ids); |
2530 |
– |
/* Check triangles in set against those seen so far(os):only |
2531 |
– |
check new triangles for intersection (t_set') |
2532 |
– |
*/ |
2533 |
– |
check_set_large(tptr,argptr->os); |
2534 |
– |
|
2535 |
– |
if(!QT_SET_CNT(tptr)) |
2536 |
– |
return; |
2537 |
– |
found = intersect_tri_set(tptr,argptr->orig,argptr->dir,NULL); |
2538 |
– |
if(tptr != tset) |
2539 |
– |
free(tptr); |
2540 |
– |
if(found != INVALID) |
2541 |
– |
{ |
2542 |
– |
argptr->t_id = found; |
2543 |
– |
QT_FLAG_SET_DONE(*fptr); |
2544 |
– |
} |
2545 |
– |
return; |
2546 |
– |
memerr: |
2547 |
– |
error(SYSTEM,"ray_trace_check_set():Unable to allocate memory"); |
2548 |
– |
} |
2549 |
– |
|
2550 |
– |
|
2551 |
– |
/* |
2552 |
– |
* int |
2553 |
– |
* smFindSamp(FVECT orig, FVECT dir) |
2554 |
– |
* |
2555 |
– |
* Find the closest sample to the given ray. Returns sample id, -1 on failure. |
2556 |
– |
* "dir" is assumed to be normalized |
2557 |
– |
*/ |
2558 |
– |
|
2559 |
– |
int |
2560 |
– |
smFindSamp(orig,dir) |
2561 |
– |
FVECT orig,dir; |
2562 |
– |
{ |
2563 |
– |
FVECT b,p,o; |
2564 |
– |
OBJECT *ts; |
2565 |
– |
QUADTREE qt; |
2566 |
– |
int s_id,test; |
2567 |
– |
double d; |
2568 |
– |
|
2569 |
– |
/* r is the normalized vector from the view center to the current |
2570 |
– |
* ray point ( starting with "orig"). Find the cell that r falls in, |
2571 |
– |
* and test the ray against all triangles stored in the cell. If |
2572 |
– |
* the test fails, trace the projection of the ray across to the |
2573 |
– |
* next cell it intersects: iterate until either an intersection |
2574 |
– |
* is found, or the projection ray is // to the direction. The sample |
2575 |
– |
* corresponding to the triangle vertex closest to the intersection |
2576 |
– |
* point is returned. |
2577 |
– |
*/ |
2578 |
– |
|
2579 |
– |
/* First test if "orig" coincides with the View_center or if "dir" is |
2580 |
– |
parallel to r formed by projecting "orig" on the sphere. In |
2581 |
– |
either case, do a single test against the cell containing the |
2582 |
– |
intersection of "dir" and the sphere |
2583 |
– |
*/ |
2584 |
– |
/* orig will be updated-so preserve original value */ |
2585 |
– |
if(!smMesh) |
2586 |
– |
return; |
2587 |
– |
|
2588 |
– |
if(EQUAL_VEC3(orig,SM_VIEW_CENTER(smMesh))) |
2589 |
– |
{ |
2590 |
– |
qt = smPoint_locate_cell(smMesh,dir); |
2591 |
– |
if(QT_IS_EMPTY(qt)) |
2592 |
– |
goto Lerror; |
2593 |
– |
ts = qtqueryset(qt); |
2594 |
– |
s_id = intersect_tri_set(ts,orig,dir,p); |
2595 |
– |
return(s_id); |
2596 |
– |
} |
2597 |
– |
d = point_on_sphere(b,orig,SM_VIEW_CENTER(smMesh)); |
2598 |
– |
if(EQUAL_VEC3(b,dir)) |
2599 |
– |
{ |
2600 |
– |
qt = smPoint_locate_cell(smMesh,dir); |
2601 |
– |
if(QT_IS_EMPTY(qt)) |
2602 |
– |
goto Lerror; |
2603 |
– |
ts = qtqueryset(qt); |
2604 |
– |
s_id = intersect_tri_set(ts,orig,dir,p); |
2605 |
– |
return(s_id); |
2606 |
– |
} |
2607 |
– |
if(OPP_EQUAL_VEC3(b,dir)) |
2608 |
– |
{ |
2609 |
– |
qt = smPoint_locate_cell(smMesh,orig); |
2610 |
– |
if(QT_IS_EMPTY(qt)) |
2611 |
– |
goto Lerror; |
2612 |
– |
ts = qtqueryset(qt); |
2613 |
– |
s_id = intersect_tri_set(ts,orig,dir,p); |
2614 |
– |
if(s_id != INVALID) |
2615 |
– |
{ |
2616 |
– |
#ifdef DEBUG |
2617 |
– |
fprintf(stderr,"Front pick returning %d\n",s_id); |
2618 |
– |
#endif |
2619 |
– |
return(s_id); |
2620 |
– |
} |
2621 |
– |
qt = smPoint_locate_cell(smMesh,dir); |
2622 |
– |
if(QT_IS_EMPTY(qt)) |
2623 |
– |
goto Lerror; |
2624 |
– |
ts = qtqueryset(qt); |
2625 |
– |
s_id = intersect_tri_set(ts,orig,dir,p); |
2626 |
– |
#ifdef DEBUG |
2627 |
– |
fprintf(stderr,"Back pick returning %d\n",s_id); |
2628 |
– |
#endif |
2629 |
– |
return(s_id); |
2630 |
– |
} |
2631 |
– |
{ |
2632 |
– |
OBJECT t_set[QT_MAXCSET + 1]; |
2633 |
– |
RT_ARGS rt; |
2634 |
– |
FUNC func; |
2635 |
– |
|
2636 |
– |
/* Test each of the root triangles against point id */ |
2637 |
– |
QT_CLEAR_SET(t_set); |
2638 |
– |
VSUB(o,orig,SM_VIEW_CENTER(smMesh)); |
2639 |
– |
ST_CLEAR_FLAGS(SM_LOCATOR(smMesh)); |
2640 |
– |
rt.t_id = -1; |
2641 |
– |
rt.os = t_set; |
2642 |
– |
VCOPY(rt.orig,orig); |
2643 |
– |
VCOPY(rt.dir,dir); |
2644 |
– |
F_FUNC(func) = ray_trace_check_set; |
2645 |
– |
F_ARGS(func) = (int *)(&rt); |
2646 |
– |
stTrace_ray(SM_LOCATOR(smMesh),o,dir,func); |
2647 |
– |
s_id = rt.t_id; |
2648 |
– |
|
2649 |
– |
} |
2650 |
– |
return(s_id); |
2651 |
– |
|
2652 |
– |
Lerror: |
2653 |
– |
#ifdef DEBUG |
2654 |
– |
eputs("smFindSamp(): point not found"); |
2655 |
– |
#endif |
2656 |
– |
return(INVALID); |
2657 |
– |
|
2658 |
– |
} |
2659 |
– |
|
2415 |
|
null_func(argptr,root,qt,n) |
2416 |
|
int *argptr; |
2417 |
|
int root; |
2427 |
|
QUADTREE qt; |
2428 |
|
int n; |
2429 |
|
{ |
2430 |
< |
OBJECT *os; |
2431 |
< |
register int i,s_id,t_id,tri_id; |
2430 |
> |
S_ID *os,s_id; |
2431 |
> |
register int i,t_id,tri_id; |
2432 |
|
TRI *tri; |
2433 |
|
|
2434 |
|
if(QT_IS_EMPTY(qt) || QT_LEAF_IS_FLAG(qt)) |