ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.15
Committed: Thu Jun 10 15:22:21 1999 UTC (24 years, 10 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.14: +1471 -928 lines
Log Message:
Implemented sample quadtree in place of triangle quadtree
Made geometric predicates more robust
Added #define LORES which utilizes a single precision floating point
  sample array, the default is a double sample array
Added topology DEBUG commands (for DEBUG > 1)
Made code optimizations

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 gwlarson 3.8 #include "sm_flag.h"
12 gwlarson 3.1 #include "sm_list.h"
13     #include "sm_geom.h"
14     #include "sm.h"
15    
16    
17 gwlarson 3.15
18 gwlarson 3.1 SM *smMesh = NULL;
19     double smDist_sum=0;
20    
21 gwlarson 3.15 #ifdef DEBUG
22     int Tcnt=0,Wcnt=0;
23     #endif
24     /* Each edge extends .372 radians */
25 gwlarson 3.10 static FVECT icosa_verts[162] =
26     {{-0.018096,0.495400,0.868477},{0.018614,-0.554780,0.831789},
27     {0.850436,0.011329,0.525956},{0.850116,0.048016,-0.524402},
28     {-0.850116,-0.048016,0.524402},{-0.850436,-0.011329,-0.525956},
29     {0.495955,0.867825,0.030147},{-0.555329,0.831118,0.029186},
30     {0.555329,-0.831118,-0.029186},{-0.495955,-0.867825,-0.030147},
31     {-0.018614,0.554780,-0.831789},{0.018096,-0.495400,-0.868477},
32     {0.000305,-0.034906,0.999391},{0.489330,0.297837,0.819664},
33     {0.510900,-0.319418,0.798094},{-0.488835,-0.354308,0.797186},
34     {-0.510409,0.262947,0.818744},{0.999391,0.034875,0.000914},
35     {0.791335,0.516672,0.326862},{0.791142,0.538234,-0.290513},
36     {0.826031,-0.460219,-0.325378},{0.826216,-0.481780,0.291985},
37     {-0.999391,-0.034875,-0.000914},{-0.826216,0.481780,-0.291985},
38     {-0.826031,0.460219,0.325378},{-0.791142,-0.538234,0.290513},
39     {-0.791335,-0.516672,-0.326862},{-0.034911,0.998782,0.034881},
40     {0.280899,0.801316,0.528194},{-0.337075,0.779739,0.527624},
41     {-0.337377,0.814637,-0.471746},{0.280592,0.836213,-0.471186},
42     {0.034911,-0.998782,-0.034881},{-0.280592,-0.836213,0.471186},
43     {0.337377,-0.814637,0.471746},{0.337075,-0.779739,-0.527624},
44     {-0.280899,-0.801316,-0.528194},{-0.000305,0.034906,-0.999391},
45     {0.510409,-0.262947,-0.818744},{0.488835,0.354308,-0.797186},
46     {-0.510900,0.319418,-0.798094},{-0.489330,-0.297837,-0.819664},
47     {0.009834,-0.306509,0.951817},{0.268764,-0.186284,0.945021},
48     {0.275239,-0.454405,0.847207},{-0.009247,0.239357,0.970888},
49     {0.244947,0.412323,0.877491},{0.257423,0.138235,0.956360},
50     {0.525850,-0.011345,0.850502},{0.696394,0.160701,0.699436},
51     {0.707604,-0.160141,0.688223},{-0.268186,0.119892,0.955878},
52     {-0.274715,0.394186,0.877011},{-0.244420,-0.472542,0.846737},
53     {-0.256843,-0.204627,0.944542},{-0.525332,-0.048031,0.849541},
54     {-0.695970,-0.209123,0.686945},{-0.707182,0.111718,0.698149},
55     {0.961307,0.043084,-0.272090},{0.941300,0.301289,-0.152245},
56     {0.853076,0.304715,-0.423568},{0.961473,0.024015,0.273848},
57     {0.853344,0.274439,0.443269},{0.941400,0.289953,0.172315},
58     {0.831918,0.554570,0.019109},{0.669103,0.719629,0.185565},
59     {0.669003,0.730836,-0.135332},{0.959736,-0.234941,0.153979},
60     {0.871472,-0.244526,0.425140},{0.871210,-0.214250,-0.441690},
61     {0.959638,-0.223606,-0.170573},{0.868594,-0.495213,-0.017555},
62     {0.717997,-0.671205,-0.184294},{0.718092,-0.682411,0.136596},
63     {-0.961307,-0.043084,0.272090},{-0.959638,0.223606,0.170573},
64     {-0.871210,0.214250,0.441690},{-0.961473,-0.024015,-0.273848},
65     {-0.871472,0.244526,-0.425140},{-0.959736,0.234941,-0.153979},
66     {-0.868594,0.495213,0.017555},{-0.718092,0.682411,-0.136596},
67     {-0.717997,0.671205,0.184294},{-0.941400,-0.289953,-0.172315},
68     {-0.853344,-0.274439,-0.443269},{-0.853076,-0.304715,0.423568},
69     {-0.941300,-0.301289,0.152245},{-0.831918,-0.554570,-0.019109},
70     {-0.669003,-0.730836,0.135332},{-0.669103,-0.719629,-0.185565},
71     {-0.306809,0.951188,0.033302},{-0.195568,0.935038,0.295731},
72     {-0.463858,0.837300,0.289421},{0.239653,0.970270,0.033802},
73     {0.403798,0.867595,0.290218},{0.129326,0.946383,0.296031},
74     {-0.029535,0.831255,0.555106},{0.136603,0.674019,0.725974},
75     {-0.184614,0.662804,0.725678},{0.129164,0.964728,-0.229382},
76     {0.403637,0.885733,-0.229245},{-0.464015,0.855438,-0.230036},
77     {-0.195726,0.953383,-0.229677},{-0.029855,0.867949,-0.495755},
78     {-0.185040,0.711807,-0.677562},{0.136173,0.723022,-0.677271},
79     {0.306809,-0.951188,-0.033302},{0.195726,-0.953383,0.229677},
80     {0.464015,-0.855438,0.230036},{-0.239653,-0.970270,-0.033802},
81     {-0.403637,-0.885733,0.229245},{-0.129164,-0.964728,0.229382},
82     {0.029855,-0.867949,0.495755},{-0.136173,-0.723022,0.677271},
83     {0.185040,-0.711807,0.677562},{-0.129326,-0.946383,-0.296031},
84     {-0.403798,-0.867595,-0.290218},{0.463858,-0.837300,-0.289421}
85     ,{0.195568,-0.935038,-0.295731},{0.029535,-0.831255,-0.555106},
86     {0.184614,-0.662804,-0.725678},{-0.136603,-0.674019,-0.725974},
87     {-0.009834,0.306509,-0.951817},{0.256843,0.204627,-0.944542},
88     {0.244420,0.472542,-0.846737},{0.009247,-0.239357,-0.970888},
89     {0.274715,-0.394186,-0.877011},{0.268186,-0.119892,-0.955878},
90     {0.525332,0.048031,-0.849541},{0.707182,-0.111718,-0.698149},
91     {0.695970,0.209123,-0.686945},{-0.257423,-0.138235,-0.956360},
92     {-0.244947,-0.412323,-0.877491},{-0.275239,0.454405,-0.847207},
93     {-0.268764,0.186284,-0.945021},{-0.525850,0.011345,-0.850502},
94     {-0.707604,0.160141,-0.688223},{-0.696394,-0.160701,-0.699436},
95     {0.563717,0.692920,0.449538},{0.673284,0.428212,0.602763},
96     {0.404929,0.577853,0.708603},{0.445959,-0.596198,0.667584},
97     {0.702960,-0.421213,0.573086},{0.611746,-0.681577,0.401523},
98     {-0.445543,0.548166,0.707818},{-0.702606,0.380190,0.601498},
99     {-0.611490,0.651895,0.448456},{-0.563454,-0.722602,0.400456},
100     {-0.672921,-0.469235,0.571835},{-0.404507,-0.625886,0.666814},
101     {0.404507,0.625886,-0.666814},{0.672921,0.469235,-0.571835},
102     {0.563454,0.722602,-0.400456},{0.611490,-0.651895,-0.448456},
103     {0.702606,-0.380190,-0.601498},{0.445543,-0.548166,-0.707818},
104     {-0.611746,0.681577,-0.401523},{-0.702960,0.421213,-0.573086},
105     {-0.445959,0.596198,-0.667584},{-0.404929,-0.577853,-0.708603},
106     {-0.673284,-0.428212,-0.602763},{-0.563717,-0.692920,-0.449538}};
107     static int icosa_tris[320][3] =
108     { {1,42,44},{42,12,43},{44,43,14},{42,43,44},{12,45,47},{45,0,46},{47,46,13},
109     {45,46,47},{14,48,50},{48,13,49},{50,49,2},{48,49,50},{12,47,43},{47,13,48},
110     {43,48,14},{47,48,43},{0,45,52},{45,12,51},{52,51,16},{45,51,52},{12,42,54},
111     {42,1,53},{54,53,15},{42,53,54},{16,55,57},{55,15,56},{57,56,4},{55,56,57},
112     {12,54,51},{54,15,55},{51,55,16},{54,55,51},{3,58,60},{58,17,59},{60,59,19},
113     {58,59,60},{17,61,63},{61,2,62},{63,62,18},{61,62,63},{19,64,66},{64,18,65},
114     {66,65,6},{64,65,66},{17,63,59},{63,18,64},{59,64,19},{63,64,59},{2,61,68},
115     {61,17,67},{68,67,21},{61,67,68},{17,58,70},{58,3,69},{70,69,20},{58,69,70},
116     {21,71,73},{71,20,72},{73,72,8},{71,72,73},{17,70,67},{70,20,71},{67,71,21},
117     {70,71,67},{4,74,76},{74,22,75},{76,75,24},{74,75,76},{22,77,79},{77,5,78},
118     {79,78,23},{77,78,79},{24,80,82},{80,23,81},{82,81,7},{80,81,82},{22,79,75},
119     {79,23,80},{75,80,24},{79,80,75},{5,77,84},{77,22,83},{84,83,26},{77,83,84},
120     {22,74,86},{74,4,85},{86,85,25},{74,85,86},{26,87,89},{87,25,88},{89,88,9},
121     {87,88,89},{22,86,83},{86,25,87},{83,87,26},{86,87,83},{7,90,92},{90,27,91},
122     {92,91,29},{90,91,92},{27,93,95},{93,6,94},{95,94,28},{93,94,95},{29,96,98},
123     {96,28,97},{98,97,0},{96,97,98},{27,95,91},{95,28,96},{91,96,29},{95,96,91},
124     {6,93,100},{93,27,99},{100,99,31},{93,99,100},{27,90,102},{90,7,101},
125     {102,101,30},{90,101,102},{31,103,105},{103,30,104},{105,104,10},{103,104,105},
126     {27,102,99},{102,30,103},{99,103,31},{102,103,99},{8,106,108},{106,32,107},
127     {108,107,34},{106,107,108},{32,109,111},{109,9,110},{111,110,33},{109,110,111},
128     {34,112,114},{112,33,113},{114,113,1},{112,113,114},{32,111,107},{111,33,112},
129     {107,112,34},{111,112,107},{9,109,116},{109,32,115},{116,115,36},{109,115,116},
130     {32,106,118},{106,8,117},{118,117,35},{106,117,118},{36,119,121},{119,35,120},
131 gwlarson 3.15 {121,120,11},{119,120,121},{32,118,115},{118,35,119},{115,119,36},
132     {118,119,115},{10,122,124},{122,37,123},{124,123,39},{122,123,124},
133     {37,125,127},{125,11,126},{127,126,38},{125,126,127},{39,128,130},
134     {128,38,129},{130,129,3},{128,129,130},
135 gwlarson 3.10 {37,127,123},{127,38,128},{123,128,39},{127,128,123},{11,125,132},{125,37,131},
136 gwlarson 3.15 {132,131,41},{125,131,132},{37,122,134},{122,10,133},{134,133,40},
137     {122,133,134},{41,135,137},{135,40,136},{137,136,5},{135,136,137},
138     {37,134,131},{134,40,135},
139 gwlarson 3.10 {131,135,41},{134,135,131},{6,65,94},{65,18,138},{94,138,28},{65,138,94},
140 gwlarson 3.15 {18,62,139},{62,2,49},{139,49,13},{62,49,139},{28,140,97},{140,13,46},
141     {97,46,0},{140,46,97},{18,139,138},{139,13,140},{138,140,28},{139,140,138},
142     {1,44,114},
143 gwlarson 3.10 {44,14,141},{114,141,34},{44,141,114},{14,50,142},{50,2,68},{142,68,21},
144     {50,68,142},{34,143,108},{143,21,73},{108,73,8},{143,73,108},{14,142,141},
145     {142,21,143},{141,143,34},{142,143,141},{0,52,98},{52,16,144},{98,144,29},
146     {52,144,98},{16,57,145},{57,4,76},{145,76,24},{57,76,145},{29,146,92},
147     {146,24,82},{92,82,7},{146,82,92},{16,145,144},{145,24,146},{144,146,29},
148     {145,146,144},{9,88,110},{88,25,147},{110,147,33},{88,147,110},{25,85,148},
149     {85,4,56},{148,56,15},{85,56,148},{33,149,113},{149,15,53},{113,53,1},
150     {149,53,113},{25,148,147},{148,15,149},{147,149,33},{148,149,147},{10,124,105},
151     {124,39,150},{105,150,31},{124,150,105},{39,130,151},{130,3,60},{151,60,19},
152     {130,60,151},{31,152,100},{152,19,66},{100,66,6},{152,66,100},{39,151,150},
153     {151,19,152},{150,152,31},{151,152,150},{8,72,117},{72,20,153},{117,153,35},
154     {72,153,117},{20,69,154},{69,3,129},{154,129,38},{69,129,154},{35,155,120},
155     {155,38,126},{120,126,11},{155,126,120},{20,154,153},{154,38,155},{153,155,35},
156     {154,155,153},{7,81,101},{81,23,156},{101,156,30},{81,156,101},{23,78,157},
157     {78,5,136},{157,136,40},{78,136,157},{30,158,104},{158,40,133},{104,133,10},
158 gwlarson 3.15 {158,133,104},{23,157,156},{157,40,158},{156,158,30},{157,158,156},{
159     11,132,121},
160 gwlarson 3.10 {132,41,159},{121,159,36},{132,159,121},{41,137,160},{137,5,84},{160,84,26},
161     {137,84,160},{36,161,116},{161,26,89},{116,89,9},{161,89,116},{41,160,159},
162     {160,26,161},{159,161,36},{160,161,159}};
163     static int icosa_nbrs[320][3] =
164     {{3,208,21},{12,3,20},{14,209,3},{2,0,1},{7,12,17},{202,7,16},{201,13,7},
165     {6,4,5},{11,212,14},{198,11,13},{197,213,11},{10,8,9},{15,1,4},{9,15,6},
166     {8,2,15},{14,12,13},{19,224,5},{28,19,4},{30,225,19},{18,16,17},{23,28,1},
167     {250,23,0},{249,29,23},{22,20,21},{27,228,30},{246,27,29},{245,229,27},
168     {26,24,25},{31,17,20},{25,31,22},{24,18,31},{30,28,29},{35,261,53},{44,35,52},
169     {46,262,35},{34,32,33},{39,44,49},{197,39,48},{196,45,39},{38,36,37},
170     {43,265,46},{193,43,45},{192,266,43},{42,40,41},{47,33,36},{41,47,38},
171     {40,34,47},{46,44,45},{51,213,37},{60,51,36},{62,214,51},{50,48,49},{55,60,33},
172     {277,55,32},{276,61,55},{54,52,53},{59,217,62},{273,59,61},{272,218,59},
173     {58,56,57},{63,49,52},{57,63,54},{56,50,63},{62,60,61},{67,229,85},{76,67,84},
174     {78,230,67},{66,64,65},{71,76,81},{293,71,80},{292,77,71},{70,68,69},
175     {75,233,78},{289,75,77},{288,234,75},{74,72,73},{79,65,68},{73,79,70},
176     {72,66,79},{78,76,77},{83,309,69},{92,83,68},{94,310,83},{82,80,81},{87,92,65},
177     {245,87,64},{244,93,87},{86,84,85},{91,313,94},{241,91,93},{240,314,91},
178     {90,88,89},{95,81,84},{89,95,86},{88,82,95},{94,92,93},{99,234,117},
179     {108,99,116},{110,232,99},{98,96,97},{103,108,113},{192,103,112},{194,109,103},
180     {102,100,101},{107,226,110},{200,107,109},{202,224,107},{106,104,105},
181     {111,97,100},{105,111,102},{104,98,111},{110,108,109},{115,266,101},
182     {124,115,100},{126,264,115},{114,112,113},{119,124,97},{288,119,96},
183     {290,125,119},{118,116,117},{123,258,126},{296,123,125},{298,256,123},
184     {122,120,121},{127,113,116},{121,127,118},{120,114,127},{126,124,125},
185     {131,218,149},{140,131,148},{142,216,131},{130,128,129},{135,140,145},
186     {240,135,144},{242,141,135},{134,132,133},{139,210,142},{248,139,141},
187     {250,208,139},{138,136,137},{143,129,132},{137,143,134},{136,130,143},
188     {142,140,141},{147,314,133},{156,147,132},{158,312,147},{146,144,145},
189     {151,156,129},{272,151,128},{274,157,151},{150,148,149},{155,306,158},
190     {280,155,157},{282,304,155},{154,152,153},{159,145,148},{153,159,150},
191     {152,146,159},{158,156,157},{163,256,181},{172,163,180},{174,257,163},
192     {162,160,161},{167,172,177},{282,167,176},{281,173,167},{166,164,165},
193     {171,260,174},{278,171,173},{277,261,171},{170,168,169},{175,161,164},
194     {169,175,166},{168,162,175},{174,172,173},{179,304,165},{188,179,164},
195     {190,305,179},{178,176,177},{183,188,161},{298,183,160},{297,189,183},
196     {182,180,181},{187,308,190},{294,187,189},{293,309,187},{186,184,185},
197     {191,177,180},{185,191,182},{184,178,191},{190,188,189},{195,101,42},
198     {204,195,41},{206,102,195},{194,192,193},{199,204,38},{10,199,37},{9,205,199},
199 gwlarson 3.15 {198,196,197},{203,105,206},{6,203,205},{5,106,203},{202,200,201},
200     {207,193,196},{201,207,198},{200,194,207},{206,204,205},{211,138,0},
201     {220,211,2}, {222,136,211},{210,208,209},{215,220,8},{48,215,10},{50,221,215},
202     {214,212,213},{219,130,222},
203 gwlarson 3.10 {56,219,221},{58,128,219},{218,216,217},{223,209,212},{217,223,214},
204     {216,210,223},{222,220,221},{227,106,16},{236,227,18},{238,104,227},
205 gwlarson 3.15 {226,224,225},{231,236,24},{64,231,26},{66,237,231},{230,228,229},
206     {235,98,238},
207 gwlarson 3.10 {72,235,237},{74,96,235},{234,232,233},{239,225,228},{233,239,230},
208     {232,226,239},{238,236,237},{243,133,90},{252,243,89},{254,134,243},
209 gwlarson 3.15 {242,240,241},{247,252,86},{26,247,85},{25,253,247},{246,244,245},
210     {251,137,254},
211 gwlarson 3.10 {22,251,253},{21,138,251},{250,248,249},{255,241,244},{249,255,246},
212     {248,242,255},{254,252,253},{259,122,160},{268,259,162},{270,120,259},
213     {258,256,257},{263,268,168},{32,263,170},{34,269,263},{262,260,261},
214     {267,114,270},{40,267,269},{42,112,267},{266,264,265},{271,257,260},
215     {265,271,262},{264,258,271},{270,268,269},{275,149,58},{284,275,57},
216     {286,150,275},{274,272,273},{279,284,54},{170,279,53},{169,285,279},
217     {278,276,277},{283,153,286},{166,283,285},{165,154,283},{282,280,281},
218     {287,273,276},{281,287,278},{280,274,287},{286,284,285},{291,117,74},
219     {300,291,73},{302,118,291},{290,288,289},{295,300,70},{186,295,69},
220     {185,301,295},{294,292,293},{299,121,302},{182,299,301},{181,122,299},
221     {298,296,297},{303,289,292},{297,303,294},{296,290,303},{302,300,301},
222     {307,154,176},{316,307,178},{318,152,307},{306,304,305},{311,316,184},
223     {80,311,186},{82,317,311},{310,308,309},{315,146,318},{88,315,317},
224     {90,144,315},{314,312,313},{319,305,308},{313,319,310},{312,306,319},
225     {318,316,317}};
226 gwlarson 3.8
227 gwlarson 3.5
228 gwlarson 3.1 #ifdef TEST_DRIVER
229     VIEW Current_View = {0,{0,0,0},{0,0,-1},{0,1,0},60,60,0};
230     int Pick_cnt =0;
231 gwlarson 3.5 int Pick_tri = -1,Picking = FALSE,Pick_samp=-1;
232 gwlarson 3.1 FVECT Pick_point[500],Pick_origin,Pick_dir;
233     FVECT Pick_v0[500], Pick_v1[500], Pick_v2[500];
234 gwlarson 3.9 int Pick_q[500];
235 gwlarson 3.1 FVECT P0,P1,P2;
236     FVECT FrustumNear[4],FrustumFar[4];
237     double dev_zmin=.01,dev_zmax=1000;
238     #endif
239    
240 gwlarson 3.15
241     char *
242     tempbuf(len,resize) /* get a temporary buffer */
243     unsigned len;
244     int resize;
245     {
246     extern char *malloc(), *realloc();
247     static char *tempbuf = NULL;
248     static unsigned tempbuflen = 0;
249    
250     #ifdef DEBUG
251     static int in_use=FALSE;
252    
253     if(len == -1)
254     {
255     in_use = FALSE;
256     return(NULL);
257     }
258     if(!resize && in_use)
259     {
260     eputs("Buffer in use:cannot allocate:tempbuf()\n");
261     return(NULL);
262     }
263     #endif
264     if (len > tempbuflen) {
265     if (tempbuflen > 0)
266     tempbuf = realloc(tempbuf, len);
267     else
268     tempbuf = malloc(len);
269     tempbuflen = tempbuf==NULL ? 0 : len;
270     }
271     #ifdef DEBUG
272     in_use = TRUE;
273     #endif
274     return(tempbuf);
275     }
276    
277 gwlarson 3.1 smDir(sm,ps,id)
278     SM *sm;
279     FVECT ps;
280     int id;
281     {
282 gwlarson 3.8 VSUB(ps,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
283     normalize(ps);
284 gwlarson 3.1 }
285 gwlarson 3.8
286 gwlarson 3.1 smClear_flags(sm,which)
287     SM *sm;
288     int which;
289     {
290     int i;
291    
292     if(which== -1)
293     for(i=0; i < T_FLAGS;i++)
294 gwlarson 3.8 bzero(SM_NTH_FLAGS(sm,i),FLAG_BYTES(SM_MAX_TRIS(sm)));
295 gwlarson 3.1 else
296 gwlarson 3.8 bzero(SM_NTH_FLAGS(sm,which),FLAG_BYTES(SM_MAX_TRIS(sm)));
297 gwlarson 3.1 }
298    
299 gwlarson 3.8 /* Given an allocated mesh- initialize */
300     smInit_mesh(sm)
301     SM *sm;
302 gwlarson 3.1 {
303 gwlarson 3.8 /* Reset the triangle counters */
304     SM_NUM_TRI(sm) = 0;
305     SM_FREE_TRIS(sm) = -1;
306     smClear_flags(sm,-1);
307 gwlarson 3.1 }
308    
309    
310 gwlarson 3.8 /* Clear the SM for reuse: free any extra allocated memory:does initialization
311     as well
312     */
313 gwlarson 3.1 smClear(sm)
314     SM *sm;
315     {
316 gwlarson 3.15 smDist_sum = 0;
317     smInit_samples(sm);
318     smInit_locator(sm);
319 gwlarson 3.8 smInit_mesh(sm);
320 gwlarson 3.1 }
321    
322 gwlarson 3.8 /* Allocate and initialize a new mesh with max_verts and max_tris */
323     int
324     smAlloc_mesh(sm,max_verts,max_tris)
325     SM *sm;
326 gwlarson 3.1 int max_verts,max_tris;
327     {
328 gwlarson 3.8 int fbytes,i;
329 gwlarson 3.1
330 gwlarson 3.8 fbytes = FLAG_BYTES(max_tris);
331 gwlarson 3.1
332 gwlarson 3.15 if(!(SM_TRIS(sm) = (TRI *)malloc(max_tris*sizeof(TRI))))
333 gwlarson 3.8 goto memerr;
334 gwlarson 3.1
335 gwlarson 3.8 for(i=0; i< T_FLAGS; i++)
336 gwlarson 3.15 if(!(SM_NTH_FLAGS(sm,i)=(int4 *)malloc(fbytes)))
337 gwlarson 3.8 goto memerr;
338    
339 gwlarson 3.1 SM_MAX_VERTS(sm) = max_verts;
340     SM_MAX_TRIS(sm) = max_tris;
341    
342 gwlarson 3.8 smInit_mesh(sm);
343    
344 gwlarson 3.1 return(max_tris);
345 gwlarson 3.8 memerr:
346     error(SYSTEM, "out of memory in smAlloc_mesh()");
347 gwlarson 3.1 }
348    
349    
350     int
351 gwlarson 3.8 smAlloc_tri(sm)
352 gwlarson 3.1 SM *sm;
353     {
354 gwlarson 3.8 int id;
355    
356     /* First check if there are any tris on the free list */
357     /* Otherwise, have we reached the end of the list yet?*/
358     if(SM_NUM_TRI(sm) < SM_MAX_TRIS(sm))
359     return(SM_NUM_TRI(sm)++);
360     if((id = SM_FREE_TRIS(sm)) != -1)
361     {
362 gwlarson 3.15 SM_FREE_TRIS(sm) = T_NEXT_FREE(SM_NTH_TRI(sm,id));
363 gwlarson 3.8 return(id);
364     }
365 gwlarson 3.15
366     error(CONSISTENCY,"smAlloc_tri: no more available triangles\n");
367     return(INVALID);
368 gwlarson 3.1 }
369    
370 gwlarson 3.8 smFree_mesh(sm)
371     SM *sm;
372     {
373     int i;
374    
375     if(SM_TRIS(sm))
376     free(SM_TRIS(sm));
377     for(i=0; i< T_FLAGS; i++)
378     if(SM_NTH_FLAGS(sm,i))
379     free(SM_NTH_FLAGS(sm,i));
380     }
381    
382    
383 gwlarson 3.1 /* Initialize/clear global smL sample list for at least n samples */
384     smAlloc(max_samples)
385     register int max_samples;
386     {
387     unsigned nbytes;
388     register unsigned i;
389     int total_points;
390 gwlarson 3.8 int max_tris,n;
391 gwlarson 3.1
392 gwlarson 3.8 n = max_samples;
393 gwlarson 3.1 /* If this is the first call, allocate sample,vertex and triangle lists */
394     if(!smMesh)
395     {
396     if(!(smMesh = (SM *)malloc(sizeof(SM))))
397 gwlarson 3.8 error(SYSTEM,"smAlloc():Unable to allocate memory\n");
398 gwlarson 3.1 bzero(smMesh,sizeof(SM));
399     }
400     else
401     { /* If existing structure: first deallocate */
402 gwlarson 3.8 smFree_mesh(smMesh);
403     smFree_samples(smMesh);
404     smFree_locator(smMesh);
405     }
406 gwlarson 3.1
407     /* First allocate at least n samples + extra points:at least enough
408     necessary to form the BASE MESH- Default = 4;
409     */
410 gwlarson 3.15 SM_SAMP(smMesh) = sAlloc(&n,SM_BASE_POINTS);
411 gwlarson 3.1
412 gwlarson 3.15 total_points = n + SM_BASE_POINTS;
413 gwlarson 3.1
414 gwlarson 3.15 /* Need enough tris for base mesh, + 2 for each sample, plus extra
415     since triangles are not deleted until added and edge flips (max 4)
416     */
417     max_tris = n*2 + SM_BASE_TRIS + 10;
418 gwlarson 3.1 /* Now allocate space for mesh vertices and triangles */
419 gwlarson 3.8 max_tris = smAlloc_mesh(smMesh, total_points, max_tris);
420 gwlarson 3.1
421     /* Initialize the structure for point,triangle location.
422     */
423     smAlloc_locator(smMesh);
424     }
425    
426    
427    
428 gwlarson 3.8 smInit_sm(sm,vp)
429 gwlarson 3.1 SM *sm;
430     FVECT vp;
431     {
432    
433 gwlarson 3.8 VCOPY(SM_VIEW_CENTER(sm),vp);
434 gwlarson 3.15 smClear(sm);
435 gwlarson 3.1 smCreate_base_mesh(sm,SM_DEFAULT);
436     }
437    
438     /*
439     * int
440     * smInit(n) : Initialize/clear data structures for n entries
441     * int n;
442     *
443     * This routine allocates/initializes the sample, mesh, and point-location
444     * structures for at least n samples.
445     * If n is <= 0, then clear data structures. Returns number samples
446     * actually allocated.
447     */
448    
449     int
450     smInit(n)
451     register int n;
452     {
453     int max_vertices;
454    
455     /* If n <=0, Just clear the existing structures */
456     if(n <= 0)
457     {
458 gwlarson 3.15 #ifdef DEBUG
459     fprintf(stderr,"Tcnt=%d Wcnt = %d, avg = %f\n",Tcnt,Wcnt,(float)Wcnt/Tcnt);
460     #endif
461 gwlarson 3.1 smClear(smMesh);
462     return(0);
463     }
464    
465     /* Total mesh vertices includes the sample points and the extra vertices
466     to form the base mesh
467     */
468 gwlarson 3.15 max_vertices = n + SM_BASE_POINTS;
469 gwlarson 3.1
470     /* If the current mesh contains enough room, clear and return */
471 gwlarson 3.8 if(smMesh && (max_vertices <= SM_MAX_VERTS(smMesh)) && SM_MAX_SAMP(smMesh) <=
472     n && SM_MAX_POINTS(smMesh) <= max_vertices)
473 gwlarson 3.1 {
474     smClear(smMesh);
475     return(SM_MAX_SAMP(smMesh));
476     }
477     /* Otherwise- mesh must be allocated with the appropriate number of
478     samples
479     */
480     smAlloc(n);
481    
482 gwlarson 3.15 #ifdef DEBUG
483     fprintf(stderr,"smInit: allocating room for %d samples\n",
484     SM_MAX_SAMP(smMesh));
485     #endif
486 gwlarson 3.1 return(SM_MAX_SAMP(smMesh));
487     }
488    
489    
490 gwlarson 3.14 smLocator_apply(sm,v0,v1,v2,func,n)
491 gwlarson 3.7 SM *sm;
492     FVECT v0,v1,v2;
493 gwlarson 3.10 FUNC func;
494 gwlarson 3.14 int n;
495 gwlarson 3.1 {
496     STREE *st;
497 gwlarson 3.10 FVECT tri[3];
498 gwlarson 3.1
499     st = SM_LOCATOR(sm);
500    
501 gwlarson 3.10 VSUB(tri[0],v0,SM_VIEW_CENTER(sm));
502     VSUB(tri[1],v1,SM_VIEW_CENTER(sm));
503     VSUB(tri[2],v2,SM_VIEW_CENTER(sm));
504 gwlarson 3.14 stVisit(st,tri,func,n);
505 gwlarson 3.1
506     }
507    
508 gwlarson 3.8 QUADTREE
509 gwlarson 3.15 insert_samp(argptr,root,qt,parent,q0,q1,q2,bc,scale,rev,f,n,doneptr)
510 gwlarson 3.10 int *argptr;
511     int root;
512 gwlarson 3.15 QUADTREE qt,parent;
513     BCOORD q0[3],q1[3],q2[3],bc[3];
514     unsigned int scale,rev;
515 gwlarson 3.10 FUNC f;
516 gwlarson 3.15 int n,*doneptr;
517 gwlarson 3.8 {
518 gwlarson 3.15 OBJECT *optr,*sptr,s_set[QT_MAXSET+1];
519     int i,s_id;
520     FVECT p;
521     BCOORD bp[3];
522     FUNC sfunc;
523     S_ARGS args;
524 gwlarson 3.8
525 gwlarson 3.15 s_id = ((S_ARGS *)argptr)->s_id;
526 gwlarson 3.10 /* If the set is empty - just add */
527     if(QT_IS_EMPTY(qt))
528 gwlarson 3.15 {
529     qt = qtadduelem(qt,s_id);
530     SM_S_NTH_QT(smMesh,s_id) = qt;
531     if(((S_ARGS *)argptr)->n_id)
532     *doneptr = FALSE;
533     else
534     *doneptr = TRUE;
535     return(qt);
536     }
537 gwlarson 3.10 /* If the set size is below expansion threshold,or at maximum
538     number of quadtree levels : just add */
539     optr = qtqueryset(qt);
540 gwlarson 3.11 if(QT_SET_CNT(optr) < QT_SET_THRESHOLD || (n > (QT_MAX_LEVELS-2)))
541 gwlarson 3.15 {
542     qt = qtadduelem(qt,s_id);
543    
544     SM_S_NTH_QT(smMesh,s_id) = qt;
545     if(((S_ARGS *)argptr)->n_id)
546     if(QT_SET_CNT(qtqueryset(qt)) > 1)
547     {
548     ((S_ARGS *)argptr)->n_id = qtqueryset(qt)[1];
549     *doneptr = TRUE;
550     }
551     else
552     *doneptr = FALSE;
553     else
554     *doneptr = TRUE;
555     return(qt);
556     }
557     /* otherwise: expand node- and insert sample, and reinsert existing samples
558 gwlarson 3.10 in set to children of new node
559     */
560 gwlarson 3.15 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 gwlarson 3.10
569     /* subdivide node */
570 gwlarson 3.8 qtfreeleaf(qt);
571     qtSubdivide(qt);
572    
573 gwlarson 3.10 /* Now add in all of the rest; */
574 gwlarson 3.15 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--)
578 gwlarson 3.8 {
579 gwlarson 3.15 s_id = QT_SET_NEXT_ELEM(optr);
580     args.s_id = s_id;
581     VSUB(p,SM_NTH_WV(smMesh,s_id),SM_VIEW_CENTER(smMesh));
582     normalize(p);
583     vert_to_qt_frame(i,p,bp);
584 gwlarson 3.10 if(rev)
585 gwlarson 3.15 qt= qtInsert_point_rev(root,qt,parent,q0,q1,q2,bp,scale,sfunc,n,doneptr);
586 gwlarson 3.10 else
587 gwlarson 3.15 qt= qtInsert_point(root,qt,parent,q0,q1,q2,bp,scale,sfunc,n,doneptr);
588 gwlarson 3.8 }
589 gwlarson 3.15 /* Add current sample: have all of the information */
590     if(rev)
591     qt =qtInsert_point_rev(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr);
592     else
593     qt = qtInsert_point(root,qt,parent,q0,q1,q2,bc,scale,f,n,doneptr);
594    
595 gwlarson 3.8 /* If we allocated memory: free it */
596    
597 gwlarson 3.15 if( sptr != s_set)
598     free(sptr);
599    
600 gwlarson 3.8 return(qt);
601     memerr:
602     error(SYSTEM,"expand_node():Unable to allocate memory");
603    
604 gwlarson 3.5 }
605    
606    
607 gwlarson 3.15 double
608     triangle_normal(n,a,b,c)
609     double n[3];
610     double a[3],b[3],c[3];
611 gwlarson 3.1 {
612 gwlarson 3.15 double ab[3],ac[3];
613 gwlarson 3.8
614 gwlarson 3.15 VSUB(ab,b,a);
615     normalize(ab);
616     VSUB(ac,c,a);
617     normalize(ac);
618     VCROSS(n,ab,ac);
619     return(normalize(n));
620 gwlarson 3.1 }
621 gwlarson 3.15 double on0,on1,on2;
622 gwlarson 3.1 /* Add a triangle to the base array with vertices v1-v2-v3 */
623     int
624 gwlarson 3.15 smAdd_tri(sm, v0_id,v1_id,v2_id,tptr)
625 gwlarson 3.1 SM *sm;
626     int v0_id,v1_id,v2_id;
627 gwlarson 3.15 TRI **tptr;
628 gwlarson 3.1 {
629     int t_id;
630     TRI *t;
631 gwlarson 3.9 #ifdef DEBUG
632     if(v0_id==v1_id || v0_id==v2_id || v1_id==v2_id)
633 gwlarson 3.10 error(CONSISTENCY,"smAdd_tri: invalid vertex ids\n");
634 gwlarson 3.1
635 gwlarson 3.15 #endif
636     t_id = smAlloc_tri(sm);
637     #ifdef DEBUG
638     #if DEBUG > 1
639     {
640     double v0[3],v1[3],v2[3],n[3];
641     double area,dp;
642 gwlarson 3.1
643 gwlarson 3.15 VSUB(v0,SM_NTH_WV(sm,v0_id),SM_VIEW_CENTER(sm));
644     VSUB(v1,SM_NTH_WV(sm,v1_id),SM_VIEW_CENTER(sm));
645     VSUB(v2,SM_NTH_WV(sm,v2_id),SM_VIEW_CENTER(sm));
646     normalize(v0);
647     normalize(v1);
648     normalize(v2);
649     area = triangle_normal(n,v2,v1,v0);
650     if((dp=DOT(v0,n)) < 0.0)
651     {
652     fprintf(stderr,"dp = %.10f on0=%.10f on1=%.10f on2=%.10f\n", dp,
653     on0,on1,on2);
654     eputs("backwards tri\n");
655     }
656     }
657     #endif
658     #endif
659    
660    
661 gwlarson 3.1 t = SM_NTH_TRI(sm,t_id);
662 gwlarson 3.8
663 gwlarson 3.1 T_CLEAR_NBRS(t);
664 gwlarson 3.8 /* set the triangle vertex ids */
665     T_NTH_V(t,0) = v0_id;
666     T_NTH_V(t,1) = v1_id;
667     T_NTH_V(t,2) = v2_id;
668 gwlarson 3.1
669 gwlarson 3.8 SM_NTH_VERT(sm,v0_id) = t_id;
670     SM_NTH_VERT(sm,v1_id) = t_id;
671     SM_NTH_VERT(sm,v2_id) = t_id;
672    
673 gwlarson 3.1 if(SM_BASE_ID(sm,v0_id) || SM_BASE_ID(sm,v1_id) || SM_BASE_ID(sm,v2_id))
674     SM_SET_NTH_T_BASE(sm,t_id);
675 gwlarson 3.15 else
676     SM_CLR_NTH_T_BASE(sm,t_id);
677 gwlarson 3.14 if(SM_DIR_ID(sm,v0_id) || SM_DIR_ID(sm,v1_id) || SM_DIR_ID(sm,v2_id))
678 gwlarson 3.13 SM_SET_NTH_T_BG(sm,t_id);
679 gwlarson 3.15 else
680     SM_CLR_NTH_T_BG(sm,t_id);
681 gwlarson 3.13 S_SET_FLAG(T_NTH_V(t,0));
682     S_SET_FLAG(T_NTH_V(t,1));
683     S_SET_FLAG(T_NTH_V(t,2));
684    
685 gwlarson 3.12 SM_SET_NTH_T_ACTIVE(sm,t_id);
686 gwlarson 3.13 SM_SET_NTH_T_NEW(sm,t_id);
687 gwlarson 3.1
688 gwlarson 3.12
689 gwlarson 3.15 *tptr = t;
690 gwlarson 3.1 /* return initialized triangle */
691     return(t_id);
692     }
693    
694    
695 gwlarson 3.15 /* 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 gwlarson 3.1 {
702 gwlarson 3.15 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) */
707 gwlarson 3.10
708     #ifdef DEBUG
709 gwlarson 3.15 #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 gwlarson 3.10 #endif
721     #endif
722 gwlarson 3.1
723 gwlarson 3.15 VSUB(ab,b,a);
724     VSUB(ac,c,a);
725     VCROSS(r,ab,ac);
726 gwlarson 3.1
727 gwlarson 3.15 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 gwlarson 3.5
736 gwlarson 3.15 smRestore_Delaunay(sm,a,b,c,t,t_id,a_id,b_id,c_id)
737     SM *sm;
738     FVECT a,b,c;
739     TRI *t;
740     int t_id,a_id,b_id,c_id;
741     {
742     int e1,topp_id,p_id;
743     TRI *topp;
744     FVECT p;
745 gwlarson 3.12
746 gwlarson 3.15 topp_id = T_NTH_NBR(t,0);
747 gwlarson 3.10 #ifdef DEBUG
748 gwlarson 3.15 if(topp_id==INVALID)
749     {
750     eputs("Invalid tri id smRestore_delaunay()\n");
751     return;
752     }
753 gwlarson 3.10 #endif
754 gwlarson 3.15 topp = SM_NTH_TRI(sm,topp_id);
755     #ifdef DEBUG
756     if(!T_IS_VALID(topp))
757     {
758     eputs("Invalid tri smRestore_delaunay()\n");
759 gwlarson 3.10 return;
760 gwlarson 3.15 }
761     #endif
762     e1 = T_NTH_NBR_PTR(t_id,topp);
763     p_id = T_NTH_V(topp,e1);
764 gwlarson 3.1
765 gwlarson 3.15 VSUB(p,SM_NTH_WV(sm,p_id),SM_VIEW_CENTER(sm));
766     normalize(p);
767     if(pt_in_cone(p,c,b,a))
768 gwlarson 3.3 {
769 gwlarson 3.15 int e1next,e1prev;
770     int ta_id,tb_id;
771     TRI *ta,*tb,*n;
772     e1next = (e1 + 1)%3;
773     e1prev = (e1 + 2)%3;
774     ta_id = smAdd_tri(sm,a_id,b_id,p_id,&ta);
775     tb_id = smAdd_tri(sm,a_id,p_id,c_id,&tb);
776 gwlarson 3.7
777 gwlarson 3.15 T_NTH_NBR(ta,0) = T_NTH_NBR(topp,e1next);
778     T_NTH_NBR(ta,1) = tb_id;
779     T_NTH_NBR(ta,2) = T_NTH_NBR(t,2);
780    
781     T_NTH_NBR(tb,0) = T_NTH_NBR(topp,e1prev);
782     T_NTH_NBR(tb,1) = T_NTH_NBR(t,1);
783     T_NTH_NBR(tb,2) = ta_id;
784    
785     n = SM_NTH_TRI(sm,T_NTH_NBR(t,1));
786     T_NTH_NBR(n,T_NTH_NBR_PTR(t_id,n)) = tb_id;
787     n = SM_NTH_TRI(sm,T_NTH_NBR(t,2));
788     T_NTH_NBR(n,T_NTH_NBR_PTR(t_id,n)) = ta_id;
789     n = SM_NTH_TRI(sm,T_NTH_NBR(topp,e1next));
790     T_NTH_NBR(n,T_NTH_NBR_PTR(topp_id,n)) = ta_id;
791     n = SM_NTH_TRI(sm,T_NTH_NBR(topp,e1prev));
792     T_NTH_NBR(n,T_NTH_NBR_PTR(topp_id,n)) = tb_id;
793    
794     smDelete_tri(sm,t_id,t);
795     smDelete_tri(sm,topp_id,topp);
796 gwlarson 3.3
797 gwlarson 3.9 #ifdef DEBUG
798 gwlarson 3.15 #if DEBUG > 1
799     if(T_NTH_NBR(ta,0) == T_NTH_NBR(ta,1) ||
800     T_NTH_NBR(ta,1) == T_NTH_NBR(ta,2) ||
801     T_NTH_NBR(ta,0) == T_NTH_NBR(ta,2))
802     error(CONSISTENCY,"Invalid topology\n");
803     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(ta,0))) ||
804     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(ta,1))) ||
805     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(ta,2))))
806     error(CONSISTENCY,"Invalid topology\n");
807     n = SM_NTH_TRI(sm,T_NTH_NBR(ta,0));
808     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
809     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
810     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
811     error(CONSISTENCY,"Invalid topology\n");
812     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
813     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
814     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
815     error(CONSISTENCY,"Invalid topology\n");
816     n = SM_NTH_TRI(sm,T_NTH_NBR(ta,1));
817     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
818     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
819     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
820     error(CONSISTENCY,"Invalid topology\n");
821     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
822     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
823     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
824     error(CONSISTENCY,"Invalid topology\n");
825     n = SM_NTH_TRI(sm,T_NTH_NBR(ta,2));
826     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
827     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
828     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
829     error(CONSISTENCY,"Invalid topology\n");
830     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
831     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
832     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
833     error(CONSISTENCY,"Invalid topology\n");
834     n = SM_NTH_TRI(sm,T_NTH_NBR(tb,0));
835     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
836     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
837     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
838     error(CONSISTENCY,"Invalid topology\n");
839     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
840     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
841     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
842     error(CONSISTENCY,"Invalid topology\n");
843     n = SM_NTH_TRI(sm,T_NTH_NBR(tb,1));
844     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
845     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
846     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
847     error(CONSISTENCY,"Invalid topology\n");
848     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
849     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
850     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
851     error(CONSISTENCY,"Invalid topology\n");
852     n = SM_NTH_TRI(sm,T_NTH_NBR(tb,2));
853     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
854     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
855     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
856     error(CONSISTENCY,"Invalid topology\n");
857     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
858     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
859     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
860     error(CONSISTENCY,"Invalid topology\n");
861 gwlarson 3.12
862 gwlarson 3.15 if(T_NTH_NBR(tb,0) == T_NTH_NBR(tb,1) ||
863     T_NTH_NBR(tb,1) == T_NTH_NBR(tb,2) ||
864     T_NTH_NBR(tb,0) == T_NTH_NBR(tb,2))
865     error(CONSISTENCY,"Invalid topology\n");
866     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(tb,0))) ||
867     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(tb,1))) ||
868     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(tb,2))))
869     error(CONSISTENCY,"Invalid topology\n");
870 gwlarson 3.10
871 gwlarson 3.15 #endif
872     #endif
873     smRestore_Delaunay(sm,a,b,p,ta,ta_id,a_id,b_id,p_id);
874     smRestore_Delaunay(sm,a,p,c,tb,tb_id,a_id,p_id,c_id);
875     }
876 gwlarson 3.1 }
877    
878 gwlarson 3.15
879 gwlarson 3.1 /* Give the vertex "id" and a triangle "t" that it belongs to- return the
880     next nbr in a counter clockwise order about vertex "id"
881     */
882     int
883     smTri_next_ccw_nbr(sm,t,id)
884     SM *sm;
885     TRI *t;
886     int id;
887     {
888 gwlarson 3.10 int which;
889 gwlarson 3.8 int nbr_id;
890 gwlarson 3.10
891     /* Want the edge for which "id" is the destination */
892     which = T_WHICH_V(t,id);
893     if(which== INVALID)
894     return(which);
895 gwlarson 3.1
896 gwlarson 3.10 nbr_id = T_NTH_NBR(t,(which + 1)% 3);
897 gwlarson 3.8 return(nbr_id);
898 gwlarson 3.1 }
899    
900     smClear_tri_flags(sm,id)
901     SM *sm;
902     int id;
903     {
904     int i;
905    
906     for(i=0; i < T_FLAGS; i++)
907 gwlarson 3.8 SM_CLR_NTH_T_FLAG(sm,id,i);
908 gwlarson 3.1
909     }
910    
911     /* Locate the point-id in the point location structure: */
912     int
913 gwlarson 3.15 smInsert_samp_mesh(sm,s_id,tri_id,a,b,c,d,on,which)
914 gwlarson 3.1 SM *sm;
915     int s_id,tri_id;
916 gwlarson 3.15 FVECT a,b,c,d;
917 gwlarson 3.10 int on,which;
918 gwlarson 3.1 {
919 gwlarson 3.10 int v_id[3],topp_id,i;
920 gwlarson 3.15 int t0_id,t1_id,t2_id,t3_id;
921     int e0,e1,e2,opp_id,opp0,opp1,opp2;
922     TRI *tri,*nbr,*topp,*t0,*t1,*t2,*t3;
923     FVECT e;
924 gwlarson 3.1
925 gwlarson 3.10 for(i=0; i<3;i++)
926     v_id[i] = T_NTH_V(SM_NTH_TRI(sm,tri_id),i);
927 gwlarson 3.1
928 gwlarson 3.10 /* If falls on existing edge */
929     if(on == ON_E)
930     {
931 gwlarson 3.15 FVECT n,vopp;
932     double dp;
933    
934 gwlarson 3.10 tri = SM_NTH_TRI(sm,tri_id);
935     topp_id = T_NTH_NBR(tri,which);
936     e0 = which;
937     e1 = (which+1)%3;
938     e2 = (which+2)%3;
939     topp = SM_NTH_TRI(sm,topp_id);
940     opp0 = T_NTH_NBR_PTR(tri_id,topp);
941     opp1 = (opp0+1)%3;
942     opp2 = (opp0+2)%3;
943 gwlarson 3.15
944     opp_id = T_NTH_V(topp,opp0);
945 gwlarson 3.10
946     /* Create 4 triangles */
947     /* /|\ /|\
948     / | \ / | \
949     / * \ ----> /__|__\
950     \ | / \ | /
951     \ | / \ | /
952     \|/ \|/
953     */
954 gwlarson 3.15 t0_id = smAdd_tri(sm,s_id,v_id[e0],v_id[e1],&t0);
955     t1_id = smAdd_tri(sm,s_id,v_id[e2],v_id[e0],&t1);
956     t2_id = smAdd_tri(sm,s_id,v_id[e1],opp_id,&t2);
957     t3_id = smAdd_tri(sm,s_id,opp_id,v_id[e2],&t3);
958 gwlarson 3.8
959 gwlarson 3.15 /* Set the neighbor pointers for the new tris */
960     T_NTH_NBR(t0,0) = T_NTH_NBR(tri,e2);
961     T_NTH_NBR(t0,1) = t2_id;
962     T_NTH_NBR(t0,2) = t1_id;
963     T_NTH_NBR(t1,0) = T_NTH_NBR(tri,e1);
964     T_NTH_NBR(t1,1) = t0_id;
965     T_NTH_NBR(t1,2) = t3_id;
966     T_NTH_NBR(t2,0) = T_NTH_NBR(topp,opp1);
967     T_NTH_NBR(t2,1) = t3_id;
968     T_NTH_NBR(t2,2) = t0_id;
969     T_NTH_NBR(t3,0) = T_NTH_NBR(topp,opp2);
970     T_NTH_NBR(t3,1) = t1_id;
971     T_NTH_NBR(t3,2) = t2_id;
972 gwlarson 3.3
973 gwlarson 3.10 /* Reset the neigbor pointers for the neighbors of the original */
974     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,e1));
975     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t1_id;
976     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,e2));
977     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t0_id;
978     nbr = SM_NTH_TRI(sm,T_NTH_NBR(topp,opp1));
979     T_NTH_NBR(nbr,T_NTH_NBR_PTR(topp_id,nbr)) = t2_id;
980     nbr = SM_NTH_TRI(sm,T_NTH_NBR(topp,opp2));
981     T_NTH_NBR(nbr,T_NTH_NBR_PTR(topp_id,nbr)) = t3_id;
982 gwlarson 3.15
983 gwlarson 3.10 #ifdef DEBUG
984 gwlarson 3.15 #if DEBUG > 1
985     {
986     TRI *n;
987    
988     if(T_NTH_NBR(t0,0) == T_NTH_NBR(t0,1) ||
989     T_NTH_NBR(t0,1) == T_NTH_NBR(t0,2) ||
990     T_NTH_NBR(t0,0) == T_NTH_NBR(t0,2))
991     error(CONSISTENCY,"Invalid topology\n");
992     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,0))) ||
993     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,1))) ||
994     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,2))))
995     error(CONSISTENCY,"Invalid topology\n");
996     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,0));
997     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
998     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
999     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1000     error(CONSISTENCY,"Invalid topology\n");
1001     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1002     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1003     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1004     error(CONSISTENCY,"Invalid topology\n");
1005     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,1));
1006     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1007     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1008     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1009     error(CONSISTENCY,"Invalid topology\n");
1010     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1011     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1012     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1013     error(CONSISTENCY,"Invalid topology\n");
1014     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,2));
1015     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1016     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1017     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1018     error(CONSISTENCY,"Invalid topology\n");
1019     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1020     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1021     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1022     error(CONSISTENCY,"Invalid topology\n");
1023     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,0));
1024     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1025     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1026     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1027     error(CONSISTENCY,"Invalid topology\n");
1028     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1029     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1030     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1031     error(CONSISTENCY,"Invalid topology\n");
1032     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,1));
1033     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1034     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1035     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1036     error(CONSISTENCY,"Invalid topology\n");
1037     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1038     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1039     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1040     error(CONSISTENCY,"Invalid topology\n");
1041     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,2));
1042     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1043     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1044     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1045     error(CONSISTENCY,"Invalid topology\n");
1046     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1047     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1048     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1049     error(CONSISTENCY,"Invalid topology\n");
1050    
1051     if(T_NTH_NBR(t1,0) == T_NTH_NBR(t1,1) ||
1052     T_NTH_NBR(t1,1) == T_NTH_NBR(t1,2) ||
1053     T_NTH_NBR(t1,0) == T_NTH_NBR(t1,2))
1054     error(CONSISTENCY,"Invalid topology\n");
1055     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,0))) ||
1056     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,1))) ||
1057     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,2))))
1058     error(CONSISTENCY,"Invalid topology\n");
1059    
1060     if(T_NTH_NBR(t2,0) == T_NTH_NBR(t2,1) ||
1061     T_NTH_NBR(t2,1) == T_NTH_NBR(t2,2) ||
1062     T_NTH_NBR(t2,0) == T_NTH_NBR(t2,2))
1063     error(CONSISTENCY,"Invalid topology\n");
1064     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,0))) ||
1065     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,1))) ||
1066     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,2))))
1067     error(CONSISTENCY,"Invalid topology\n");
1068     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,0));
1069     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1070     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1071     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1072     error(CONSISTENCY,"Invalid topology\n");
1073     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1074     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1075     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1076     error(CONSISTENCY,"Invalid topology\n");
1077     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,1));
1078     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1079     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1080     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1081     error(CONSISTENCY,"Invalid topology\n");
1082     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1083     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1084     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1085     error(CONSISTENCY,"Invalid topology\n");
1086     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,2));
1087     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1088     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1089     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1090     error(CONSISTENCY,"Invalid topology\n");
1091     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1092     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1093     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1094     error(CONSISTENCY,"Invalid topology\n");
1095    
1096     if(T_NTH_NBR(t3,0) == T_NTH_NBR(t3,1) ||
1097     T_NTH_NBR(t3,1) == T_NTH_NBR(t3,2) ||
1098     T_NTH_NBR(t3,0) == T_NTH_NBR(t3,2))
1099     error(CONSISTENCY,"Invalid topology\n");
1100     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t3,0))) ||
1101     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t3,1))) ||
1102     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t3,2))))
1103     error(CONSISTENCY,"Invalid topology\n");
1104     n = SM_NTH_TRI(sm,T_NTH_NBR(t3,0));
1105     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1106     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1107     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1108     error(CONSISTENCY,"Invalid topology\n");
1109     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1110     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1111     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1112     error(CONSISTENCY,"Invalid topology\n");
1113     n = SM_NTH_TRI(sm,T_NTH_NBR(t3,1));
1114     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1115     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1116     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1117     error(CONSISTENCY,"Invalid topology\n");
1118     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1119     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1120     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1121     error(CONSISTENCY,"Invalid topology\n");
1122     n = SM_NTH_TRI(sm,T_NTH_NBR(t3,2));
1123     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1124     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1125     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1126     error(CONSISTENCY,"Invalid topology\n");
1127     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1128     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1129     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1130     error(CONSISTENCY,"Invalid topology\n");
1131     }
1132     #endif
1133     #endif
1134     smDir(sm,e,opp_id);
1135     if(which == 0)
1136     {
1137     smRestore_Delaunay(sm,a,b,c,t0,t0_id,s_id,v_id[e0],v_id[e1]);
1138     smRestore_Delaunay(sm,a,d,b,t1,t1_id,s_id,v_id[e2],v_id[e0]);
1139     smRestore_Delaunay(sm,a,c,e,t2,t2_id,s_id,v_id[e1],opp_id);
1140     smRestore_Delaunay(sm,a,e,d,t3,t3_id,s_id,opp_id,v_id[e2]);
1141     }
1142     else
1143     if( which==1 )
1144     {
1145     smRestore_Delaunay(sm,a,c,d,t0,t0_id,s_id,v_id[e0],v_id[e1]);
1146     smRestore_Delaunay(sm,a,b,c,t1,t1_id,s_id,v_id[e2],v_id[e0]);
1147     smRestore_Delaunay(sm,a,d,e,t2,t2_id,s_id,v_id[e1],opp_id);
1148     smRestore_Delaunay(sm,a,e,b,t3,t3_id,s_id,opp_id,v_id[e2]);
1149     }
1150     else
1151     {
1152     smRestore_Delaunay(sm,a,d,b,t0,t0_id,s_id,v_id[e0],v_id[e1]);
1153     smRestore_Delaunay(sm,a,c,d,t1,t1_id,s_id,v_id[e2],v_id[e0]);
1154     smRestore_Delaunay(sm,a,b,e,t2,t2_id,s_id,v_id[e1],opp_id);
1155     smRestore_Delaunay(sm,a,e,c,t3,t3_id,s_id,opp_id,v_id[e2]);
1156     }
1157     smDelete_tri(sm,tri_id,tri);
1158     smDelete_tri(sm,topp_id,topp);
1159     return(TRUE);
1160 gwlarson 3.10 }
1161 gwlarson 3.15 Linsert_in_tri:
1162     /* Create 3 triangles */
1163     /* / \ /|\
1164     / \ / | \
1165     / * \ ----> / | \
1166     / \ / / \ \
1167     / \ / / \ \
1168     ___________\ //_________\\
1169     */
1170     tri = SM_NTH_TRI(sm,tri_id);
1171 gwlarson 3.6
1172 gwlarson 3.15 t0_id = smAdd_tri(sm,s_id,v_id[0],v_id[1],&t0);
1173     t1_id = smAdd_tri(sm,s_id,v_id[1],v_id[2],&t1);
1174     t2_id = smAdd_tri(sm,s_id,v_id[2],v_id[0],&t2);
1175 gwlarson 3.3
1176 gwlarson 3.15 /* Set the neighbor pointers for the new tris */
1177     T_NTH_NBR(t0,0) = T_NTH_NBR(tri,2);
1178     T_NTH_NBR(t0,1) = t1_id;
1179     T_NTH_NBR(t0,2) = t2_id;
1180     T_NTH_NBR(t1,0) = T_NTH_NBR(tri,0);
1181     T_NTH_NBR(t1,1) = t2_id;
1182     T_NTH_NBR(t1,2) = t0_id;
1183     T_NTH_NBR(t2,0) = T_NTH_NBR(tri,1);
1184     T_NTH_NBR(t2,1) = t0_id;
1185     T_NTH_NBR(t2,2) = t1_id;
1186 gwlarson 3.1
1187 gwlarson 3.15 /* Reset the neigbor pointers for the neighbors of the original */
1188     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,0));
1189     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t1_id;
1190     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,1));
1191     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t2_id;
1192     nbr = SM_NTH_TRI(sm,T_NTH_NBR(tri,2));
1193     T_NTH_NBR(nbr,T_NTH_NBR_PTR(tri_id,nbr)) = t0_id;
1194     #ifdef DEBUG
1195     #if DEBUG > 1
1196     {
1197     TRI *n;
1198     if(T_NTH_NBR(t0,0) == T_NTH_NBR(t0,1) ||
1199     T_NTH_NBR(t0,1) == T_NTH_NBR(t0,2) ||
1200     T_NTH_NBR(t0,0) == T_NTH_NBR(t0,2))
1201     error(CONSISTENCY,"Invalid topology\n");
1202     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,0))) ||
1203     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,1))) ||
1204     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t0,2))))
1205     error(CONSISTENCY,"Invalid topology\n");
1206     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,0));
1207     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1208     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1209     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1210     error(CONSISTENCY,"Invalid topology\n");
1211     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1212     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1213     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1214     error(CONSISTENCY,"Invalid topology\n");
1215     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,1));
1216     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1217     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1218     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1219     error(CONSISTENCY,"Invalid topology\n");
1220     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1221     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1222     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1223     error(CONSISTENCY,"Invalid topology\n");
1224     n = SM_NTH_TRI(sm,T_NTH_NBR(t0,2));
1225     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1226     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1227     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1228     error(CONSISTENCY,"Invalid topology\n");
1229     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1230     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1231     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1232     error(CONSISTENCY,"Invalid topology\n");
1233     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,0));
1234     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1235     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1236     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1237     error(CONSISTENCY,"Invalid topology\n");
1238     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1239     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1240     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1241     error(CONSISTENCY,"Invalid topology\n");
1242     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,1));
1243     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1244     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1245     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1246     error(CONSISTENCY,"Invalid topology\n");
1247     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1248     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1249     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1250     error(CONSISTENCY,"Invalid topology\n");
1251     n = SM_NTH_TRI(sm,T_NTH_NBR(t1,2));
1252     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1253     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1254     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1255     error(CONSISTENCY,"Invalid topology\n");
1256     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1257     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1258     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1259     error(CONSISTENCY,"Invalid topology\n");
1260 gwlarson 3.6
1261 gwlarson 3.15 if(T_NTH_NBR(t1,0) == T_NTH_NBR(t1,1) ||
1262     T_NTH_NBR(t1,1) == T_NTH_NBR(t1,2) ||
1263     T_NTH_NBR(t1,0) == T_NTH_NBR(t1,2))
1264     error(CONSISTENCY,"Invalid topology\n");
1265     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,0))) ||
1266     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,1))) ||
1267     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t1,2))))
1268     error(CONSISTENCY,"Invalid topology\n");
1269 gwlarson 3.1
1270 gwlarson 3.15 if(T_NTH_NBR(t2,0) == T_NTH_NBR(t2,1) ||
1271     T_NTH_NBR(t2,1) == T_NTH_NBR(t2,2) ||
1272     T_NTH_NBR(t2,0) == T_NTH_NBR(t2,2))
1273     error(CONSISTENCY,"Invalid topology\n");
1274     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,0))) ||
1275     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,1))) ||
1276     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(t2,2))))
1277     error(CONSISTENCY,"Invalid topology\n");
1278     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,0));
1279     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1280     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1281     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1282     error(CONSISTENCY,"Invalid topology\n");
1283     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1284     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1285     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1286     error(CONSISTENCY,"Invalid topology\n");
1287     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,1));
1288     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1289     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1290     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1291     error(CONSISTENCY,"Invalid topology\n");
1292     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1293     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1294     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1295     error(CONSISTENCY,"Invalid topology\n");
1296     n = SM_NTH_TRI(sm,T_NTH_NBR(t2,2));
1297     if(T_NTH_NBR(n,0) == T_NTH_NBR(n,1) ||
1298     T_NTH_NBR(n,1) == T_NTH_NBR(n,2) ||
1299     T_NTH_NBR(n,0) == T_NTH_NBR(n,2))
1300     error(CONSISTENCY,"Invalid topology\n");
1301     if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,0))) ||
1302     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,1))) ||
1303     !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(n,2))))
1304     error(CONSISTENCY,"Invalid topology\n");
1305     }
1306     #endif
1307     #endif
1308     smRestore_Delaunay(sm,a,b,c,t0,t0_id,s_id,v_id[0],v_id[1]);
1309     smRestore_Delaunay(sm,a,c,d,t1,t1_id,s_id,v_id[1],v_id[2]);
1310     smRestore_Delaunay(sm,a,d,b,t2,t2_id,s_id,v_id[2],v_id[0]);
1311     smDelete_tri(sm,tri_id,tri);
1312     return(TRUE);
1313 gwlarson 3.1
1314 gwlarson 3.10 #ifdef DEBUG
1315     Ladderror:
1316 gwlarson 3.15 error(CONSISTENCY,"Invalid tri: smInsert_samp_mesh()\n");
1317 gwlarson 3.10 #endif
1318     }
1319    
1320 gwlarson 3.15
1321 gwlarson 3.1 int
1322 gwlarson 3.15 smWalk(sm,p,t_id,t,onptr,wptr,from,on_edge,a,b)
1323 gwlarson 3.1 SM *sm;
1324 gwlarson 3.8 FVECT p;
1325 gwlarson 3.15 int t_id;
1326     TRI *t;
1327     int *onptr,*wptr;
1328     int from;
1329     double on_edge;
1330     FVECT a,b;
1331 gwlarson 3.1 {
1332 gwlarson 3.8 FVECT n,v0,v1,v2;
1333 gwlarson 3.15 TRI *tn;
1334 gwlarson 3.10
1335 gwlarson 3.15 int tn_id;
1336    
1337     #ifdef DEBUG
1338     Wcnt++;
1339     on0 = on1 = on2 = 10;
1340     #endif
1341     switch(from){
1342     case 0:
1343     on0 = on_edge;
1344     /* Havnt calculate v0 yet: check for equality first */
1345 gwlarson 3.8 VSUB(v0,SM_T_NTH_WV(sm,t,0),SM_VIEW_CENTER(sm));
1346 gwlarson 3.15 normalize(v0);
1347     if(EQUAL_VEC3(v0,p)){ *onptr = ON_V; *wptr = 0; return(t_id); }
1348     /* determine what side of edge v0v1 (v0a) point is on*/
1349     VCROSS(n,v0,a);
1350     normalize(n);
1351     on2 = DOT(n,p);
1352     if(on2 > 0.0)
1353     {
1354     tn_id = T_NTH_NBR(t,2);
1355     tn = SM_NTH_TRI(sm,tn_id);
1356     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1357     -on2,a,v0));
1358     }
1359     else
1360     if(on2 >= -EDGE_EPS)
1361     {
1362     if(on0 >= -EDGE_EPS)
1363     {
1364     /* Could either be epsilon of vertex 1*/
1365     /* dot(p,a) == cos angle between them. Want length of chord x to
1366     be <= EDGE_EPS for test. if the perpendicular bisector of pa
1367     is d, cos@/2 = d/1, with right triangle d^2 + (x/2)^2 = 1
1368     or x^2 = 4(1-cos^2@/2) = 4(1- (1 + cos@)/2) = 2 -2cos@,
1369     so test is if x^2 <= VERT_EPS*VERT_EPS,
1370     2 - 2cos@ <= VERT_EPS*VERT_EPS, or... */
1371     if(DOT(p,a) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1372     {*onptr = ON_P; *wptr = 1;}
1373     else
1374     if(on2 > on0)
1375     {*onptr = ON_E; *wptr = 2;}
1376     else
1377     {*onptr = ON_E; *wptr = 0;}
1378     return(t_id);
1379     }
1380     }
1381 gwlarson 3.8
1382 gwlarson 3.15 VCROSS(n,b,v0);
1383     normalize(n);
1384     on1 = DOT(n,p);
1385     if(on1 > 0.0)
1386 gwlarson 3.10 {
1387 gwlarson 3.15 tn_id = T_NTH_NBR(t,1);
1388     tn = SM_NTH_TRI(sm,tn_id);
1389     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1390     -on1,v0,b));
1391 gwlarson 3.10 }
1392 gwlarson 3.15 else
1393     if(on1 >= -EDGE_EPS)
1394     { /* Either on v0 or on edge 1 */
1395     if(on0 >= -EDGE_EPS)
1396     {
1397     if(DOT(p,b) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1398     {*onptr = ON_P; *wptr = 2;}
1399     else
1400     if(on1 > on0)
1401     {*onptr = ON_E; *wptr = 1;}
1402     else
1403     {*onptr = ON_E; *wptr = 0;}
1404     return(t_id);
1405     }
1406     if(on2 >= -EDGE_EPS)
1407     {
1408     if(DOT(p,v0) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1409     {*onptr = ON_P; *wptr = 0;}
1410     else
1411     if( on1 > on2)
1412     {*onptr = ON_E; *wptr = 1;}
1413     else
1414     {*onptr = ON_E; *wptr = 2;}
1415     return(t_id);
1416     }
1417     *onptr = ON_E; *wptr = 1;
1418     return(t_id);
1419     }
1420     else
1421     if(on2 >= -EDGE_EPS)
1422     {
1423     *onptr = ON_E; *wptr = 2;
1424     return(t_id);
1425     }
1426     if(on0 >= -EDGE_EPS)
1427     {
1428     *onptr = ON_E; *wptr = 0;
1429     return(t_id);
1430     }
1431     *onptr = IN_T;
1432     return(t_id);
1433     case 1:
1434     on1 = on_edge;
1435     /* Havnt calculate v1 yet: check for equality first */
1436     VSUB(v1,SM_T_NTH_WV(sm,t,1),SM_VIEW_CENTER(sm));
1437     normalize(v1);
1438     if(EQUAL_VEC3(v1,p)){ *onptr = ON_V; *wptr = 1; return(t_id); }
1439     /* determine what side of edge v0v1 (v0a) point is on*/
1440     VCROSS(n,b,v1);
1441     normalize(n);
1442     on2 = DOT(n,p);
1443     if(on2 > 0.0)
1444 gwlarson 3.10 {
1445 gwlarson 3.15 tn_id = T_NTH_NBR(t,2);
1446     tn = SM_NTH_TRI(sm,tn_id);
1447     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1448     -on2,v1,b));
1449 gwlarson 3.10 }
1450 gwlarson 3.15 if(on2 >= -EDGE_EPS)
1451 gwlarson 3.10 {
1452 gwlarson 3.15 if(on1 >= -EDGE_EPS)
1453     {
1454     if(DOT(p,b) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1455     { *onptr = ON_P; *wptr = 0;}
1456     else
1457     if(on2 > on1)
1458     { *onptr = ON_E; *wptr = 2;}
1459     else
1460     { *onptr = ON_E; *wptr = 1;}
1461     return(t_id);
1462     }
1463 gwlarson 3.10 }
1464    
1465 gwlarson 3.15 VCROSS(n,v1,a);
1466     normalize(n);
1467     on0 = DOT(n,p);
1468     if(on0 >0.0)
1469     {
1470     tn_id = T_NTH_NBR(t,0);
1471     tn = SM_NTH_TRI(sm,tn_id);
1472     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1473     -on0,a,v1));
1474     }
1475     else
1476     if(on0 >= -EDGE_EPS)
1477     { /* Either on v0 or on edge 1 */
1478     if(on1 >= -EDGE_EPS)
1479     {
1480     if(DOT(p,a) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1481     {*onptr = ON_P; *wptr = 2;}
1482     else
1483     if(on0 > on1)
1484     { *onptr = ON_E; *wptr = 0;}
1485     else
1486     { *onptr = ON_E; *wptr = 1;}
1487     return(t_id);
1488     }
1489     if(on2 >= -EDGE_EPS)
1490     {
1491     if(DOT(p,v1) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1492     {*onptr = ON_P; *wptr = 1;}
1493     else
1494     if(on0 > on2)
1495     { *onptr = ON_E; *wptr = 0;}
1496     else
1497     { *onptr = ON_E; *wptr = 2;}
1498     return(t_id);
1499     }
1500     *onptr = ON_E; *wptr = 0;
1501     return(t_id);
1502     }
1503 gwlarson 3.10 else
1504 gwlarson 3.15 if(on2 >= -EDGE_EPS)
1505     {
1506     *onptr = ON_E; *wptr = 2;
1507     return(t_id);
1508     }
1509     if(on1 >= -EDGE_EPS)
1510     {
1511     *onptr = ON_E; *wptr = 1;
1512     return(t_id);
1513     }
1514     *onptr = IN_T;
1515     return(t_id);
1516     case 2:
1517     on2 = on_edge;
1518     VSUB(v2,SM_T_NTH_WV(sm,t,2),SM_VIEW_CENTER(sm));
1519     normalize(v2);
1520     if(EQUAL_VEC3(v2,p)){ *onptr = ON_V; *wptr = 2; return(t_id); }
1521 gwlarson 3.8
1522 gwlarson 3.15 /* determine what side of edge v0v1 (v0a) point is on*/
1523     VCROSS(n,b,v2);
1524     normalize(n);
1525     on0 = DOT(n,p);
1526     if(on0 > 0.0)
1527 gwlarson 3.10 {
1528 gwlarson 3.15 tn_id = T_NTH_NBR(t,0);
1529     tn = SM_NTH_TRI(sm,tn_id);
1530     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1531     -on0,v2,b));
1532     }
1533     else
1534     if(on0 >= -EDGE_EPS)
1535 gwlarson 3.10 {
1536 gwlarson 3.15 if(on2 >= - EDGE_EPS)
1537     {
1538     if(DOT(p,b) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1539     {*onptr = ON_P; *wptr = 1;}
1540     else
1541     if(on0 > on2)
1542     {*onptr = ON_E; *wptr = 0;}
1543     else
1544     {*onptr = ON_E; *wptr = 2;}
1545     return(t_id);
1546     }
1547 gwlarson 3.10 }
1548 gwlarson 3.15 VCROSS(n,v2,a);
1549     normalize(n);
1550     on1 = DOT(n,p);
1551     if(on1 >0.0)
1552     {
1553     tn_id = T_NTH_NBR(t,1);
1554     tn = SM_NTH_TRI(sm,tn_id);
1555     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1556     -on1,a,v2));
1557     }
1558     else
1559     if(on1 >= -EDGE_EPS)
1560     { /* Either on v0 or on edge 1 */
1561     if(on0 >= - EDGE_EPS)
1562 gwlarson 3.10 {
1563 gwlarson 3.15 if(DOT(p,v2) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1564     {*onptr = ON_P;*wptr = 2;}
1565     else
1566     if(on1 > on0)
1567     {*onptr = ON_E;*wptr = 1;}
1568     else
1569     {*onptr = ON_E;*wptr = 0;}
1570     return(t_id);
1571 gwlarson 3.10 }
1572 gwlarson 3.15 if(on2 >= -EDGE_EPS)
1573     {
1574     if(DOT(p,a) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1575     {*onptr = ON_P;*wptr = 0;}
1576 gwlarson 3.10 else
1577 gwlarson 3.15 if(on1 > on2)
1578     {*onptr = ON_E;*wptr = 1;}
1579     else
1580     {*onptr = ON_E;*wptr = 2;}
1581     return(t_id);
1582     }
1583     *onptr = ON_E;*wptr = 1;
1584     return(t_id);
1585     }
1586     else
1587     if(on0 >= -EDGE_EPS)
1588     {
1589     *onptr = ON_E;*wptr = 0;
1590     return(t_id);
1591     }
1592     if(on2 >= -EDGE_EPS)
1593     {
1594     *onptr = ON_E;*wptr = 2;
1595     return(t_id);
1596     }
1597     *onptr = IN_T;
1598     return(t_id);
1599     default:
1600     /* First time called: havnt tested anything */
1601     /* Check against vertices */
1602     VSUB(v0,SM_T_NTH_WV(sm,t,0),SM_VIEW_CENTER(sm));
1603     normalize(v0);
1604     if(EQUAL_VEC3(v0,p)){ *onptr = ON_V; *wptr = 0; return(t_id); }
1605     VSUB(v1,SM_T_NTH_WV(sm,t,1),SM_VIEW_CENTER(sm));
1606     normalize(v1);
1607     if(EQUAL_VEC3(v1,p)){ *onptr = ON_V; *wptr = 1; return(t_id); }
1608     VSUB(v2,SM_T_NTH_WV(sm,t,2),SM_VIEW_CENTER(sm));
1609     normalize(v2);
1610     if(EQUAL_VEC3(v2,p)){ *onptr = ON_V; *wptr = 2; return(t_id); }
1611    
1612     VCROSS(n,v0,v1); /* Check against v0v1, or edge 2 */
1613     normalize(n);
1614     on2 = DOT(n,p);
1615     if(on2 > 0.0)
1616     { /* Outside edge: traverse to nbr 2 */
1617     tn_id = T_NTH_NBR(t,2);
1618     tn = SM_NTH_TRI(sm,tn_id);
1619     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1620     -on2,v1,v0));
1621     }
1622     else
1623     VCROSS(n,v1,v2); /* Check against v1v2 or edge 0 */
1624     normalize(n);
1625     on0 = DOT(n,p);
1626     if(on0 > 0.0)
1627     { /* Outside edge: traverse to nbr 0 */
1628     tn_id = T_NTH_NBR(t,0);
1629     tn = SM_NTH_TRI(sm,tn_id);
1630     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1631     -on0,v2,v1));
1632     }
1633     else
1634     if(on0 >= -EDGE_EPS)
1635     { /* On the line defining edge 0 */
1636     if(on2 >= -EDGE_EPS)
1637     {
1638     if(DOT(p,v1) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1639     {*onptr = ON_P;*wptr = 1;}
1640     else
1641     if(on0 > on2)
1642     {*onptr = ON_E;*wptr = 0;}
1643     else
1644     {*onptr = ON_E;*wptr = 2;}
1645     return(t_id);
1646     }
1647     }
1648     VCROSS(n,v2,v0); /* Check against v2v0 or edge 1 */
1649     normalize(n);
1650     on1 = DOT(n,p);
1651     if(on1 >0.0)
1652     { /* Outside edge: traverse to nbr 1 */
1653     tn_id = T_NTH_NBR(t,1);
1654     tn = SM_NTH_TRI(sm,tn_id);
1655     return(smWalk(sm,p,tn_id,tn,onptr,wptr,T_NTH_NBR_PTR(t_id,tn),
1656     -on1,v0,v2));
1657     }
1658     else
1659     if(on1 >= -EDGE_EPS)
1660     { /* On the line defining edge 1 */
1661     if(on2 >= -EDGE_EPS)
1662     {
1663     if(DOT(p,v0) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1664     {*onptr = ON_P;*wptr = 0;}
1665     else
1666     if(on1 > on2)
1667     {*onptr = ON_E;*wptr = 1;}
1668     else
1669     {*onptr = ON_E;*wptr = 2;}
1670     return(t_id);
1671     }
1672     if(on0 >= -EDGE_EPS)
1673     {
1674     if(DOT(p,v2) >= 1.0-VERT_EPS*VERT_EPS/2.0)
1675     {*onptr = ON_P;*wptr = 2;}
1676     else
1677     if(on1 > on0)
1678     {*onptr = ON_E;*wptr = 1;}
1679     else
1680     {*onptr = ON_E;*wptr = 0;}
1681     return(t_id);
1682     }
1683     *onptr = ON_E; /* Only on edge 1 */
1684     *wptr = 1;
1685     return(t_id);
1686     }
1687     else
1688     if(on2 >= -EDGE_EPS) /* Is on edge 2 ? */
1689     {
1690     *onptr = ON_E; *wptr = 2;
1691     return(t_id);
1692     }
1693     if(on0 >= -EDGE_EPS) /* Is on edge 0 ? */
1694     {
1695     *onptr = ON_E; *wptr = 0;
1696 gwlarson 3.10 return(t_id);
1697     }
1698 gwlarson 3.15 *onptr = IN_T; /* Must be interior to t */
1699     return(t_id);
1700     }
1701     }
1702    
1703     #define check_edges(on0,on1,on2,o,w,t_id) \
1704     if(on0){if(on1){*o = ON_P;*w = 2;} else if(on2){*o = ON_P;*w = 1;} \
1705     else {*o = ON_E; *w = 0; } return(t_id); } \
1706     if(on1){if(on2){*o = ON_P;*w = 0;} else {*o = ON_E;*w = 1;}return(t_id);}\
1707     if(on2){*o = ON_E;*w = 2;return(t_id);}
1708    
1709     #define check_verts(p,v0,v1,v2,o,w,t_id) \
1710     if(EQUAL_VEC3(v0,p)){ *o = ON_V; *w = 0; return(t_id); } \
1711     if(EQUAL_VEC3(v1,p)){ *o = ON_V; *w = 1; return(t_id); } \
1712     if(EQUAL_VEC3(v2,p)){ *o = ON_V; *w = 2; return(t_id);}
1713    
1714    
1715     int
1716     find_neighbor(argptr,qt,f,doneptr)
1717     int *argptr;
1718     QUADTREE qt;
1719     FUNC f;
1720     int *doneptr;
1721     {
1722     int s_id,i;
1723     OBJECT *optr;
1724    
1725     if(QT_IS_EMPTY(qt))
1726     return;
1727     else
1728     if(QT_IS_TREE(qt))
1729 gwlarson 3.10 {
1730 gwlarson 3.15 for(i=0;i < 4; i++)
1731 gwlarson 3.10 {
1732 gwlarson 3.15 find_neighbor(argptr,QT_NTH_CHILD(qt,i),f,doneptr);
1733     if(*doneptr)
1734     return;
1735 gwlarson 3.10 }
1736 gwlarson 3.15 }
1737     else
1738     {
1739     optr = qtqueryset(qt);
1740     for(i = QT_SET_CNT(optr); i > 0; i--)
1741 gwlarson 3.10 {
1742 gwlarson 3.15 s_id = QT_SET_NEXT_ELEM(optr);
1743     if(s_id != ((S_ARGS *)argptr)->s_id)
1744     {
1745     *doneptr = TRUE;
1746     ((S_ARGS *)argptr)->n_id = s_id;
1747     return;
1748     }
1749 gwlarson 3.10 }
1750     }
1751 gwlarson 3.15 }
1752    
1753     smInsert_samp(sm,s_id,p,nptr)
1754     SM *sm;
1755     int s_id;
1756     FVECT p;
1757     int *nptr;
1758     {
1759     FVECT tpt;
1760     FUNC f;
1761     S_ARGS args;
1762    
1763     F_FUNC(f) = insert_samp;
1764     args.s_id = s_id;
1765     if(nptr)
1766     {
1767     args.n_id = 1;
1768     F_FUNC2(f) = find_neighbor;
1769 gwlarson 3.1 }
1770 gwlarson 3.15 else
1771     args.n_id = 0;
1772     F_ARGS(f) = (int *)(&args);
1773     stInsert_samp(SM_LOCATOR(sm),p,f);
1774    
1775     if(nptr)
1776     *nptr = args.n_id;
1777 gwlarson 3.1 }
1778    
1779 gwlarson 3.15 /* Assumed p is normalized to view sphere */
1780 gwlarson 3.8 int
1781 gwlarson 3.15 smSample_locate_tri(sm,p,s_id,onptr,whichptr,nptr)
1782 gwlarson 3.1 SM *sm;
1783 gwlarson 3.9 FVECT p;
1784 gwlarson 3.15 int s_id;
1785     int *onptr,*whichptr,*nptr;
1786 gwlarson 3.1 {
1787 gwlarson 3.15 int tri_id;
1788 gwlarson 3.8 FVECT tpt;
1789 gwlarson 3.15 TRI *tri;
1790 gwlarson 3.9
1791 gwlarson 3.15 if(SM_S_NTH_QT(sm,s_id) == EMPTY)
1792     smInsert_samp(sm,s_id,p,nptr);
1793     #ifdef DEBUG
1794     if(*nptr == INVALID)
1795     error(CONSISTENCY,"smSample_locate_tri: unable to find sample\n");
1796     #endif
1797    
1798     /* Get the triangle adjacent to a sample in qt, or if there are no other
1799     samples in qt than the one just inserted, look at siblings-from parent
1800     node
1801     */
1802 gwlarson 3.10
1803 gwlarson 3.15 tri_id = SM_NTH_VERT(sm,*nptr);
1804     #ifdef DEBUG
1805     if(tri_id == INVALID)
1806     error(CONSISTENCY,"smSample_locate_tri: Invalid tri_id\n");
1807     #endif
1808    
1809     tri = SM_NTH_TRI(sm,tri_id);
1810     #ifdef DEBUG
1811     Tcnt++;
1812     if(!T_IS_VALID(tri))
1813     error(CONSISTENCY,"smSample_locate_tri: Invalid tri\n");
1814     #endif
1815     tri_id = smWalk(sm,p,tri_id,tri,onptr,whichptr,-1,0.0,NULL,NULL);
1816     #ifdef DEBUG
1817     if(tri_id == INVALID)
1818     error(CONSISTENCY,"smSample_locate_tri: unable to find tri on walk\n");
1819     #endif
1820     return(tri_id);
1821 gwlarson 3.8 }
1822 gwlarson 3.1
1823 gwlarson 3.8 /*
1824     Determine whether this sample should:
1825     a) be added to the mesh by subdividing the triangle
1826     b) ignored
1827     c) replace values of an existing mesh vertex
1828    
1829     In case a, the routine will return TRUE, for b,c will return FALSE
1830     In case a, also determine if this sample should cause the deletion of
1831     an existing vertex. If so *rptr will contain the id of the sample to delete
1832     after the new sample has been added.
1833    
1834     ASSUMPTION: this will not be called with a new sample that is
1835     a BASE point.
1836    
1837     The following tests are performed (in order) to determine the fate
1838     of the sample:
1839    
1840 gwlarson 3.10 1) If the new sample is close in ws, and close in the spherical projection
1841 gwlarson 3.8 to one of the triangle vertex samples:
1842     pick the point with dir closest to that of the canonical view
1843     If it is the new point: mark existing point for deletion,and return
1844     TRUE,else return FALSE
1845 gwlarson 3.10 2) If the spherical projection of new is < REPLACE_EPS from a base point:
1846 gwlarson 3.8 add new and mark the base for deletion: return TRUE
1847 gwlarson 3.10 3) If the addition of the new sample point would introduce a "puncture"
1848 gwlarson 3.8 or cause new triangles with large depth differences:return FALSE
1849     This attempts to throw out points that should be occluded
1850     */
1851     int
1852 gwlarson 3.15 smTest_samp(sm,tri_id,dir,p,rptr,ns,n0,n1,n2,ds,d0,on,which)
1853 gwlarson 3.8 SM *sm;
1854 gwlarson 3.9 int tri_id;
1855     FVECT dir,p;
1856 gwlarson 3.8 int *rptr;
1857 gwlarson 3.15 FVECT ns,n0,n1,n2;
1858     double ds,d0;
1859     int on,which;
1860 gwlarson 3.8 {
1861     TRI *tri;
1862 gwlarson 3.15 double d,d2,dnear,dspt,d01,d12,d20,s0,s1,s2;
1863     double dp,dp1;
1864 gwlarson 3.8 int vid[3],i,nearid,norm,dcnt,bcnt;
1865 gwlarson 3.15 FVECT diff[3],spt,npt,n;
1866     FVECT nearpt;
1867 gwlarson 3.8
1868     *rptr = INVALID;
1869     bcnt = dcnt = 0;
1870     tri = SM_NTH_TRI(sm,tri_id);
1871     vid[0] = T_NTH_V(tri,0);
1872     vid[1] = T_NTH_V(tri,1);
1873     vid[2] = T_NTH_V(tri,2);
1874    
1875     for(i=0; i<3; i++)
1876     {
1877 gwlarson 3.12 if(SM_BASE_ID(sm,vid[i]))
1878     bcnt++;
1879 gwlarson 3.15 else
1880     if(SM_DIR_ID(sm,vid[i]))
1881     dcnt++;
1882 gwlarson 3.8 }
1883 gwlarson 3.15 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 gwlarson 3.8 }
1899 gwlarson 3.15 if(on == ON_P)
1900     nearid = which;
1901     if(on == ON_P || dnear < VERT_EPS*VERT_EPS)
1902 gwlarson 3.12 {
1903 gwlarson 3.15 FVECT edir;
1904     /* Pick the point with dir closest to that of the canonical view
1905     if it is the new sample: mark existing point for deletion
1906     */
1907     if(SM_BASE_ID(sm,vid[nearid]))
1908     return(FALSE);
1909     if(!dir)
1910     return(FALSE);
1911     if(SM_DIR_ID(sm,vid[nearid]))
1912     {
1913     *rptr = vid[nearid];
1914     return(TRUE);
1915     }
1916     decodedir(edir,SM_NTH_W_DIR(sm,vid[nearid]));
1917     if(nearid == 0)
1918     d = DOT(edir,n0);
1919     else
1920     if(nearid == 1)
1921     d = DOT(edir,n1);
1922     else
1923     d = DOT(edir,n2);
1924     d2 = DOT(dir,ns);
1925     /* The existing sample is a better sample:punt */
1926     if(d2 >= d)
1927     return(FALSE);
1928     else
1929     {
1930     /* The new sample is better: mark existing one for deletion*/
1931     *rptr = vid[nearid];
1932     return(TRUE);
1933     }
1934     }
1935 gwlarson 3.12
1936 gwlarson 3.15 /* Now test if sample epsilon is within circumcircle of enclosing tri
1937     if not punt:
1938     */
1939 gwlarson 3.12 {
1940 gwlarson 3.15 double ab[3],ac[3],r[3];
1941 gwlarson 3.12
1942 gwlarson 3.15 VSUB(ab,n2,n1);
1943     VSUB(ac,n0,n2);
1944     VCROSS(r,ab,ac);
1945     dp = DOT(r,n1);
1946     dp1 = DOT(r,ns);
1947     if(dp1*dp1 + COS_VERT_EPS*DOT(r,r) < dp*dp)
1948 gwlarson 3.12 {
1949 gwlarson 3.15 #ifdef DEBUG
1950     eputs("smTest_samp:rejecting samp,cant guarantee not within eps\n");
1951     #endif
1952     return(FALSE);
1953 gwlarson 3.12 }
1954     }
1955 gwlarson 3.15 #ifdef DEBUG
1956     #if DEBUG > 1
1957     if(on == ON_E)
1958 gwlarson 3.12 {
1959 gwlarson 3.15 TRI *topp;
1960     int opp_id;
1961     FVECT vopp;
1962    
1963     topp = SM_NTH_TRI(sm,T_NTH_NBR(tri,which));
1964     opp_id = T_NTH_V(topp, T_NTH_NBR_PTR(tri_id,topp));
1965     /* first check if valid tri created*/
1966     VSUB(vopp,SM_NTH_WV(sm,opp_id),SM_VIEW_CENTER(sm));
1967     normalize(vopp);
1968     VCROSS(n,ns,vopp);
1969     normalize(n);
1970     if(which==2)
1971     dp = DOT(n,n0) * DOT(n,n1);
1972     else
1973     if(which==0)
1974     dp = DOT(n,n1) * DOT(n,n2);
1975     else
1976     dp = DOT(n,n2) * DOT(n,n0);
1977     if(dp > 0.0)
1978     {
1979     eputs("smInsert_samp_mesh: couldn't split edge: rejecting\n");
1980     /* test epsilon for edge */
1981     return(FALSE);
1982     }
1983 gwlarson 3.12 }
1984 gwlarson 3.15 #endif
1985     #endif
1986 gwlarson 3.8 /* TEST 4:
1987     If the addition of the new sample point would introduce a "puncture"
1988     or cause new triangles with large depth differences:dont add:
1989     */
1990     if(bcnt || dcnt)
1991     return(TRUE);
1992 gwlarson 3.12
1993 gwlarson 3.15 if(ds < d0)
1994 gwlarson 3.8 return(TRUE);
1995    
1996     d01 = DIST_SQ(SM_NTH_WV(sm,vid[1]),SM_NTH_WV(sm,vid[0]));
1997 gwlarson 3.12 VSUB(diff[0],SM_NTH_WV(sm,vid[0]),p);
1998 gwlarson 3.8 s0 = DOT(diff[0],diff[0]);
1999     if(s0 < S_REPLACE_SCALE*d01)
2000     return(TRUE);
2001 gwlarson 3.12
2002 gwlarson 3.8 d12 = DIST_SQ(SM_NTH_WV(sm,vid[2]),SM_NTH_WV(sm,vid[1]));
2003     if(s0 < S_REPLACE_SCALE*d12)
2004     return(TRUE);
2005     d20 = DIST_SQ(SM_NTH_WV(sm,vid[0]),SM_NTH_WV(sm,vid[2]));
2006     if(s0 < S_REPLACE_SCALE*d20)
2007     return(TRUE);
2008     d = MIN3(d01,d12,d20);
2009 gwlarson 3.12 VSUB(diff[1],SM_NTH_WV(sm,vid[1]),p);
2010     s1 = DOT(diff[1],diff[1]);
2011 gwlarson 3.8 if(s1 < S_REPLACE_SCALE*d)
2012     return(TRUE);
2013 gwlarson 3.12 VSUB(diff[2],SM_NTH_WV(sm,vid[2]),p);
2014 gwlarson 3.8 s2 = DOT(diff[2],diff[2]);
2015     if(s2 < S_REPLACE_SCALE*d)
2016     return(TRUE);
2017    
2018 gwlarson 3.9 /* TEST 5:
2019     Check to see if triangle is relatively large and should therefore
2020     be subdivided anyway.
2021 gwlarson 3.15 */
2022     d0 = d0*d0*DIST_SQ(SM_NTH_WV(sm,vid[1]),SM_VIEW_CENTER(sm));
2023     d0 *= DIST_SQ(SM_NTH_WV(sm,vid[2]),SM_VIEW_CENTER(sm));
2024     if (d01*d12*d20/d0 > S_REPLACE_TRI)
2025 gwlarson 3.9 return(TRUE);
2026 gwlarson 3.10
2027 gwlarson 3.8 return(FALSE);
2028     }
2029     int
2030 gwlarson 3.15 smReplace_samp(sm,c,dir,p,np,s_id,t_id,o_id,on,which)
2031 gwlarson 3.10 SM *sm;
2032     COLR c;
2033 gwlarson 3.15 FVECT dir,p,np;
2034 gwlarson 3.10 int s_id,t_id,o_id,on,which;
2035     {
2036 gwlarson 3.13 int v_id,tri_id;
2037 gwlarson 3.10 TRI *t,*tri;
2038    
2039     tri = SM_NTH_TRI(sm,t_id);
2040     v_id = T_NTH_V(tri,which);
2041    
2042     /* If it is a base id, need new sample */
2043     if(SM_BASE_ID(sm,v_id))
2044 gwlarson 3.15 return(v_id);
2045    
2046     if(EQUAL_VEC3(p,SM_NTH_WV(sm,v_id)))
2047     return(INVALID);
2048    
2049 gwlarson 3.12 if(dir)
2050 gwlarson 3.15 { /* If world point */
2051     FVECT odir,no;
2052     double d,d1;
2053     int dir_id;
2054     /* if existing point is a not a dir, compare directions */
2055     if(!(dir_id = SM_DIR_ID(sm,v_id)))
2056 gwlarson 3.10 {
2057 gwlarson 3.15 decodedir(odir, SM_NTH_W_DIR(sm,v_id));
2058     VSUB(no,SM_NTH_WV(sm,v_id),SM_VIEW_CENTER(sm));
2059     d = DOT(dir,np);
2060     d1 = DOT(odir,np);
2061     /* The existing sample is a better sample:punt */
2062     }
2063     if(dir_id || (d*d*DOT(no,no) > d1*d1))
2064     {
2065     /* The new sample has better information- replace values */
2066 gwlarson 3.13 sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id);
2067 gwlarson 3.15 if(!SM_IS_NTH_T_NEW(sm,t_id))
2068     SM_SET_NTH_T_NEW(sm,t_id);
2069 gwlarson 3.12 tri_id = smTri_next_ccw_nbr(sm,tri,v_id);
2070     while(tri_id != t_id)
2071     {
2072     t = SM_NTH_TRI(sm,tri_id);
2073 gwlarson 3.15 if(!SM_IS_NTH_T_NEW(sm,tri_id))
2074 gwlarson 3.13 SM_SET_NTH_T_NEW(sm,tri_id);
2075 gwlarson 3.12 tri_id = smTri_next_ccw_nbr(sm,t,v_id);
2076     }
2077 gwlarson 3.10 }
2078 gwlarson 3.12 return(v_id);
2079     }
2080 gwlarson 3.15 else /* New point is a dir */
2081     return(INVALID);
2082    
2083 gwlarson 3.10 }
2084    
2085 gwlarson 3.12 int
2086     smAlloc_samp(sm)
2087     SM *sm;
2088     {
2089     int s_id,replaced,cnt;
2090     SAMP *s;
2091     FVECT p;
2092    
2093     s = SM_SAMP(sm);
2094     s_id = sAlloc_samp(s,&replaced);
2095     while(replaced)
2096     {
2097 gwlarson 3.15 smRemoveVertex(sm,s_id);
2098 gwlarson 3.12 s_id = sAlloc_samp(s,&replaced);
2099     }
2100     return(s_id);
2101     }
2102    
2103    
2104 gwlarson 3.10 /* Add sample to the mesh:
2105    
2106     the sample can be a world space or directional point. If o_id !=INVALID,
2107     then we have an existing sample containing the appropriate information
2108     already converted into storage format.
2109     The spherical projection of the point/ray can:
2110     a) coincide with existing vertex
2111     i) conincides with existing sample
2112     ii) projects same as existing sample
2113     iii) hits a base vertex
2114     b) coincide with existing edge
2115     c) Fall in existing triangle
2116     */
2117     int
2118 gwlarson 3.9 smAdd_samp(sm,c,dir,p,o_id)
2119 gwlarson 3.1 SM *sm;
2120 gwlarson 3.9 COLR c;
2121     FVECT dir,p;
2122     int o_id;
2123 gwlarson 3.1 {
2124 gwlarson 3.15 int t_id,s_id,r_id,on,which,n_id,nbr_id;
2125     double ds,d0;
2126     FVECT wpt,ns,n0,n1,n2;
2127     QUADTREE qt,parent;
2128     TRI *t;
2129 gwlarson 3.8
2130 gwlarson 3.9 r_id = INVALID;
2131 gwlarson 3.15 nbr_id = INVALID;
2132 gwlarson 3.10 /* Must do this first-as may change mesh */
2133     s_id = smAlloc_samp(sm);
2134 gwlarson 3.15
2135     SM_S_NTH_QT(sm,s_id)= EMPTY;
2136 gwlarson 3.9 /* If sample is a world space point */
2137     if(p)
2138     {
2139 gwlarson 3.15 VSUB(ns,p,SM_VIEW_CENTER(sm));
2140     ds = normalize(ns);
2141 gwlarson 3.12 while(1)
2142     {
2143 gwlarson 3.15 t_id = smSample_locate_tri(sm,ns,s_id,&on,&which,&nbr_id);
2144     qt = SM_S_NTH_QT(sm,s_id);
2145 gwlarson 3.12 if(t_id == INVALID)
2146 gwlarson 3.9 {
2147     #ifdef DEBUG
2148 gwlarson 3.12 eputs("smAddSamp(): unable to locate tri containing sample \n");
2149 gwlarson 3.9 #endif
2150 gwlarson 3.12 smUnalloc_samp(sm,s_id);
2151 gwlarson 3.15 qtremovelast(qt,s_id);
2152 gwlarson 3.12 return(INVALID);
2153     }
2154     /* If spherical projection coincides with existing sample: replace */
2155 gwlarson 3.15 if(on == ON_V)
2156 gwlarson 3.12 {
2157 gwlarson 3.15 n_id = smReplace_samp(sm,c,dir,p,ns,s_id,t_id,o_id,on,which);
2158     if(n_id != s_id)
2159     {
2160     smUnalloc_samp(sm,s_id);
2161     #if 0
2162     fprintf(stderr,"Unallocating sample %d\n",s_id);
2163     #endif
2164     qtremovelast(qt,s_id);
2165     }
2166 gwlarson 3.13 return(n_id);
2167 gwlarson 3.12 }
2168 gwlarson 3.15 t = SM_NTH_TRI(sm,t_id);
2169     VSUB(n0,SM_NTH_WV(sm,T_NTH_V(t,0)),SM_VIEW_CENTER(sm));
2170     d0 = normalize(n0);
2171     VSUB(n1,SM_NTH_WV(sm,T_NTH_V(t,1)),SM_VIEW_CENTER(sm));
2172     normalize(n1);
2173     VSUB(n2,SM_NTH_WV(sm,T_NTH_V(t,2)),SM_VIEW_CENTER(sm));
2174     normalize(n2);
2175     if((!(smTest_samp(sm,t_id,dir,p,&r_id,ns,n0,n1,n2,ds,d0,on,which))))
2176     {
2177 gwlarson 3.10 smUnalloc_samp(sm,s_id);
2178 gwlarson 3.15 #if 0
2179     fprintf(stderr,"Unallocating sample %d\n",s_id);
2180     #endif
2181     qtremovelast(qt,s_id);
2182 gwlarson 3.9 return(INVALID);
2183     }
2184 gwlarson 3.12 if(r_id != INVALID)
2185     {
2186     smRemoveVertex(sm,r_id);
2187 gwlarson 3.15 if(nbr_id == r_id)
2188     {
2189     qtremovelast(qt,s_id);
2190     SM_S_NTH_QT(sm,s_id) = EMPTY;
2191     }
2192 gwlarson 3.12 }
2193     else
2194     break;
2195 gwlarson 3.9 }
2196 gwlarson 3.10 /* If sample is being added in the middle of the sample array: tone
2197     map individually
2198     */
2199     /* Initialize sample */
2200 gwlarson 3.13 sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id);
2201 gwlarson 3.15 /* If not base or sky point, add distance from center to average*/
2202     smDist_sum += 1.0/ds;
2203     smInsert_samp_mesh(sm,s_id,t_id,ns,n0,n1,n2,on,which);
2204 gwlarson 3.9 }
2205     /* If sample is a direction vector */
2206     else
2207     {
2208 gwlarson 3.10 VADD(wpt,dir,SM_VIEW_CENTER(sm));
2209 gwlarson 3.12 while(1)
2210 gwlarson 3.15 {
2211     t_id = smSample_locate_tri(sm,dir,s_id,&on,&which,&nbr_id);
2212     qt = SM_S_NTH_QT(sm,s_id);
2213 gwlarson 3.1 #ifdef DEBUG
2214 gwlarson 3.15 if(t_id == INVALID)
2215     {
2216     eputs("smAddSamp():can't locate tri containing samp\n");
2217     smUnalloc_samp(sm,s_id);
2218     qtremovelast(qt,s_id);
2219     return(INVALID);
2220     }
2221 gwlarson 3.1 #endif
2222 gwlarson 3.15 if(on == ON_V)
2223     {
2224     smUnalloc_samp(sm,s_id);
2225     qtremovelast(qt,s_id);
2226     return(INVALID);
2227     }
2228     t = SM_NTH_TRI(sm,t_id);
2229     VSUB(n0,SM_NTH_WV(sm,T_NTH_V(t,0)),SM_VIEW_CENTER(sm));
2230     d0 = normalize(n0);
2231     VSUB(n1,SM_NTH_WV(sm,T_NTH_V(t,1)),SM_VIEW_CENTER(sm));
2232     normalize(n1);
2233     VSUB(n2,SM_NTH_WV(sm,T_NTH_V(t,2)),SM_VIEW_CENTER(sm));
2234     normalize(n2);
2235     if(!smTest_samp(sm,t_id,NULL,wpt,&r_id,dir,n0,n1,n2,1.0,d0,on,which))
2236     {
2237     smUnalloc_samp(sm,s_id);
2238     qtremovelast(qt,s_id);
2239     return(INVALID);
2240     }
2241     if(r_id != INVALID)
2242     {
2243     smRemoveVertex(sm,r_id);
2244     if(nbr_id == r_id)
2245 gwlarson 3.13 {
2246 gwlarson 3.15 qtremovelast(qt,s_id);
2247     SM_S_NTH_QT(sm,s_id) = EMPTY;
2248 gwlarson 3.13 }
2249 gwlarson 3.9 }
2250 gwlarson 3.15 else
2251     break;
2252     }
2253 gwlarson 3.9 /* Allocate space for a sample and initialize */
2254 gwlarson 3.13 sInit_samp(SM_SAMP(sm),s_id,c,NULL,wpt,o_id);
2255 gwlarson 3.15 smInsert_samp_mesh(sm,s_id,t_id,dir,n0,n1,n2,on,which);
2256 gwlarson 3.1 }
2257 gwlarson 3.9 return(s_id);
2258 gwlarson 3.1 }
2259    
2260     /*
2261     * int
2262     * smNewSamp(c, dir, p) : register new sample point and return index
2263     * COLR c; : pixel color (RGBE)
2264     * FVECT dir; : ray direction vector
2265     * FVECT p; : world intersection point
2266     *
2267     * Add new sample point to data structures, removing old values as necessary.
2268     * New sample representation will be output in next call to smUpdate().
2269     * If the point is a sky point: then v=NULL
2270     */
2271     int
2272     smNewSamp(c,dir,p)
2273     COLR c;
2274     FVECT dir;
2275     FVECT p;
2276     {
2277     int s_id;
2278     /* First check if this the first sample: if so initialize mesh */
2279     if(SM_NUM_SAMP(smMesh) == 0)
2280 gwlarson 3.9 {
2281     smInit_sm(smMesh,odev.v.vp);
2282     sClear_all_flags(SM_SAMP(smMesh));
2283     }
2284     /* Add the sample to the mesh */
2285     s_id = smAdd_samp(smMesh,c,dir,p,INVALID);
2286 gwlarson 3.8
2287 gwlarson 3.15 #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 gwlarson 3.1 return(s_id);
2305    
2306     }
2307     int
2308 gwlarson 3.8 smAdd_base_vertex(sm,v)
2309 gwlarson 3.1 SM *sm;
2310 gwlarson 3.8 FVECT v;
2311 gwlarson 3.1 {
2312     int id;
2313    
2314     /* First add coordinate to the sample array */
2315 gwlarson 3.8 id = sAdd_base_point(SM_SAMP(sm),v);
2316     if(id == INVALID)
2317     return(INVALID);
2318 gwlarson 3.1 /* Initialize triangle pointer to -1 */
2319     smClear_vert(sm,id);
2320     return(id);
2321     }
2322    
2323    
2324    
2325     /* Initialize a the point location DAG based on a 6 triangle tesselation
2326     of the unit sphere centered on the view center. The DAG structure
2327     contains 6 roots: one for each initial base triangle
2328     */
2329    
2330     int
2331     smCreate_base_mesh(sm,type)
2332     SM *sm;
2333     int type;
2334     {
2335 gwlarson 3.8 int i,s_id,tri_id,nbr_id;
2336 gwlarson 3.15 int p[SM_BASE_POINTS],ids[SM_BASE_TRIS];
2337 gwlarson 3.1 int v0_id,v1_id,v2_id;
2338 gwlarson 3.8 FVECT d,pt,cntr,v0,v1,v2;
2339 gwlarson 3.10 TRI *t;
2340    
2341 gwlarson 3.1 /* First insert the base vertices into the sample point array */
2342    
2343 gwlarson 3.15 for(i=0; i < SM_BASE_POINTS; i++)
2344 gwlarson 3.1 {
2345 gwlarson 3.10 VADD(cntr,icosa_verts[i],SM_VIEW_CENTER(sm));
2346 gwlarson 3.8 p[i] = smAdd_base_vertex(sm,cntr);
2347 gwlarson 3.15 smInsert_samp(sm,p[i],icosa_verts[i],NULL);
2348 gwlarson 3.1 }
2349     /* Create the base triangles */
2350 gwlarson 3.10 for(i=0;i < SM_BASE_TRIS; i++)
2351 gwlarson 3.1 {
2352 gwlarson 3.10 v0_id = p[icosa_tris[i][0]];
2353     v1_id = p[icosa_tris[i][1]];
2354     v2_id = p[icosa_tris[i][2]];
2355 gwlarson 3.15 ids[i] = smAdd_tri(sm, v0_id,v1_id,v2_id,&t);
2356 gwlarson 3.10 /* Set neighbors */
2357     for(nbr_id=0; nbr_id < 3; nbr_id++)
2358     T_NTH_NBR(SM_NTH_TRI(sm,ids[i]),nbr_id) = icosa_nbrs[i][nbr_id];
2359    
2360 gwlarson 3.1 }
2361 gwlarson 3.8 return(1);
2362 gwlarson 3.1
2363     }
2364    
2365 gwlarson 3.15 smRebuild(sm,v)
2366 gwlarson 3.1 SM *sm;
2367 gwlarson 3.8 VIEW *v;
2368 gwlarson 3.1 {
2369 gwlarson 3.8 int i,j,cnt;
2370     FVECT p,ov,dir;
2371     double d;
2372 gwlarson 3.1
2373 gwlarson 3.8 #ifdef DEBUG
2374 gwlarson 3.15 fprintf(stderr,"smRebuild(): rebuilding....");
2375 gwlarson 3.8 #endif
2376 gwlarson 3.14 smCull(sm,v,SM_ALL_LEVELS);
2377 gwlarson 3.1 /* Clear the mesh- and rebuild using the current sample array */
2378 gwlarson 3.8 /* Remember the current number of samples */
2379     cnt = SM_NUM_SAMP(sm);
2380     /* Calculate the difference between the current and new viewpoint*/
2381     /* Will need to subtract this off of sky points */
2382 gwlarson 3.9 VCOPY(ov,SM_VIEW_CENTER(sm));
2383 gwlarson 3.15
2384 gwlarson 3.8 /* Initialize the mesh to 0 samples and the base triangles */
2385 gwlarson 3.15 smInit_sm(sm,v->vp);
2386 gwlarson 3.8 /* Go through all samples and add in if in the new view frustum, and
2387     the dir is <= 30 degrees from new view
2388     */
2389     for(i=0; i < cnt; i++)
2390 gwlarson 3.1 {
2391 gwlarson 3.8 /* First check if sample visible(conservative approx: if one of tris
2392     attached to sample is in frustum) */
2393     if(!S_IS_FLAG(i))
2394     continue;
2395 gwlarson 3.15
2396     /* Next test if direction > 30 degrees from current direction */
2397 gwlarson 3.8 if(SM_NTH_W_DIR(sm,i)!=-1)
2398     {
2399     VSUB(p,SM_NTH_WV(sm,i),v->vp);
2400 gwlarson 3.9 decodedir(dir,SM_NTH_W_DIR(sm,i));
2401 gwlarson 3.15 d = DOT(dir,p);
2402     if (d*d < MAXDIFF2*DOT(p,p))
2403 gwlarson 3.8 continue;
2404 gwlarson 3.9 VCOPY(p,SM_NTH_WV(sm,i));
2405     smAdd_samp(sm,NULL,dir,p,i);
2406 gwlarson 3.8 }
2407 gwlarson 3.9 else
2408     {
2409 gwlarson 3.15 /* If the direction is > 45 degrees from current view direction:
2410     throw out
2411     */
2412 gwlarson 3.9 VSUB(dir,SM_NTH_WV(sm,i),ov);
2413 gwlarson 3.15 if(DOT(dir,v->vdir) < MAXDIR)
2414     continue;
2415    
2416 gwlarson 3.10 VADD(SM_NTH_WV(sm,i),dir,SM_VIEW_CENTER(sm));
2417 gwlarson 3.9 smAdd_samp(sm,NULL,dir,NULL,i);
2418     }
2419    
2420 gwlarson 3.1 }
2421 gwlarson 3.8 #ifdef DEBUG
2422 gwlarson 3.15 fprintf(stderr,"smRebuild():done\n");
2423 gwlarson 3.8 #endif
2424 gwlarson 3.1 }
2425 gwlarson 3.5
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 gwlarson 3.10 int i,t_id,id,base;
2433 gwlarson 3.5 int pid0,pid1,pid2;
2434     FVECT p0,p1,p2,p;
2435     TRI *t;
2436 gwlarson 3.10 double d,d1;
2437 gwlarson 3.5
2438 gwlarson 3.15 optr = t_set;
2439 gwlarson 3.5 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 gwlarson 3.14 if(!T_IS_VALID(t) || SM_IS_NTH_T_BASE(smMesh,t_id)||
2444     SM_IS_NTH_T_BG(smMesh,t_id))
2445 gwlarson 3.8 continue;
2446 gwlarson 3.5 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 gwlarson 3.14 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 gwlarson 3.10 else
2462     {
2463 gwlarson 3.14 d = DIST_SQ(p,p2);
2464     id = (d < d1)? pid2:pid1;
2465 gwlarson 3.10 }
2466 gwlarson 3.5 if(pt)
2467 gwlarson 3.10 VCOPY(pt,p);
2468     #ifdef TEST_DRIVER
2469 gwlarson 3.5 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    
2479 gwlarson 3.8 /* OS is constrained to be <= QT_MAXCSET : if the set exceeds this, the
2480     results of check_set are conservative
2481     */
2482 gwlarson 3.10 int
2483     compare_ids(id1,id2)
2484     OBJECT *id1,*id2;
2485     {
2486     int d;
2487 gwlarson 3.8
2488 gwlarson 3.10 d = *id2-*id1;
2489    
2490     if(d > 0)
2491     return(-1);
2492     if(d < 0)
2493     return(1);
2494    
2495     return(0);
2496     }
2497    
2498     ray_trace_check_set(qt,argptr,fptr)
2499     QUADTREE qt;
2500     RT_ARGS *argptr;
2501 gwlarson 3.8 int *fptr;
2502 gwlarson 3.5 {
2503 gwlarson 3.8 OBJECT tset[QT_MAXSET+1],*tptr;
2504 gwlarson 3.5 double dt,t;
2505     int found;
2506 gwlarson 3.10 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);
2518    
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 gwlarson 3.5
2527 gwlarson 3.10 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 gwlarson 3.8 return;
2537 gwlarson 3.10 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 gwlarson 3.8 memerr:
2547     error(SYSTEM,"ray_trace_check_set():Unable to allocate memory");
2548 gwlarson 3.5 }
2549    
2550 gwlarson 3.8
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 gwlarson 3.5 int
2560 gwlarson 3.6 smFindSamp(orig,dir)
2561 gwlarson 3.5 FVECT orig,dir;
2562     {
2563     FVECT b,p,o;
2564     OBJECT *ts;
2565     QUADTREE qt;
2566 gwlarson 3.10 int s_id,test;
2567 gwlarson 3.5 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 gwlarson 3.10
2588     if(EQUAL_VEC3(orig,SM_VIEW_CENTER(smMesh)))
2589 gwlarson 3.5 {
2590 gwlarson 3.15 qt = smPoint_locate_cell(smMesh,dir);
2591 gwlarson 3.10 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 gwlarson 3.15 qt = smPoint_locate_cell(smMesh,dir);
2601 gwlarson 3.10 if(QT_IS_EMPTY(qt))
2602     goto Lerror;
2603     ts = qtqueryset(qt);
2604     s_id = intersect_tri_set(ts,orig,dir,p);
2605 gwlarson 3.15 return(s_id);
2606 gwlarson 3.5 }
2607 gwlarson 3.10 if(OPP_EQUAL_VEC3(b,dir))
2608 gwlarson 3.5 {
2609 gwlarson 3.15 qt = smPoint_locate_cell(smMesh,orig);
2610 gwlarson 3.10 if(QT_IS_EMPTY(qt))
2611     goto Lerror;
2612     ts = qtqueryset(qt);
2613     s_id = intersect_tri_set(ts,orig,dir,p);
2614 gwlarson 3.15 if(s_id != INVALID)
2615     {
2616 gwlarson 3.10 #ifdef DEBUG
2617     fprintf(stderr,"Front pick returning %d\n",s_id);
2618     #endif
2619     return(s_id);
2620 gwlarson 3.15 }
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 gwlarson 3.10 #ifdef DEBUG
2627     fprintf(stderr,"Back pick returning %d\n",s_id);
2628     #endif
2629 gwlarson 3.15 return(s_id);
2630 gwlarson 3.10 }
2631     {
2632 gwlarson 3.8 OBJECT t_set[QT_MAXCSET + 1];
2633     RT_ARGS rt;
2634 gwlarson 3.10 FUNC func;
2635 gwlarson 3.8
2636 gwlarson 3.5 /* 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 gwlarson 3.8 rt.t_id = -1;
2641     rt.os = t_set;
2642     VCOPY(rt.orig,orig);
2643     VCOPY(rt.dir,dir);
2644 gwlarson 3.10 F_FUNC(func) = ray_trace_check_set;
2645     F_ARGS(func) = (int *)(&rt);
2646     stTrace_ray(SM_LOCATOR(smMesh),o,dir,func);
2647 gwlarson 3.8 s_id = rt.t_id;
2648 gwlarson 3.14
2649 gwlarson 3.10 }
2650 gwlarson 3.5 return(s_id);
2651 gwlarson 3.10
2652     Lerror:
2653     #ifdef DEBUG
2654     eputs("smFindSamp(): point not found");
2655     #endif
2656     return(INVALID);
2657    
2658 gwlarson 3.5 }
2659    
2660 gwlarson 3.14 null_func(argptr,root,qt,n)
2661     int *argptr;
2662     int root;
2663     QUADTREE qt;
2664     int n;
2665     {
2666     /* do nothing */
2667     }
2668 gwlarson 3.10
2669 gwlarson 3.15 mark_active_samples(argptr,root,qt,n)
2670 gwlarson 3.10 int *argptr;
2671     int root;
2672     QUADTREE qt;
2673 gwlarson 3.14 int n;
2674 gwlarson 3.10 {
2675 gwlarson 3.15 OBJECT *os;
2676     register int i,s_id,t_id,tri_id;
2677 gwlarson 3.10 TRI *tri;
2678    
2679     if(QT_IS_EMPTY(qt) || QT_LEAF_IS_FLAG(qt))
2680     return;
2681    
2682     /* For each triangle in the set, set the which flag*/
2683     os = qtqueryset(qt);
2684    
2685 gwlarson 3.15 for (i = QT_SET_CNT(os); i > 0; i--)
2686 gwlarson 3.10 {
2687 gwlarson 3.15 s_id = QT_SET_NEXT_ELEM(os);
2688     S_SET_FLAG(s_id);
2689    
2690     tri_id = SM_NTH_VERT(smMesh,s_id);
2691     /* Set the active flag for all adjacent triangles */
2692     tri = SM_NTH_TRI(smMesh,tri_id);
2693     SM_SET_NTH_T_ACTIVE(smMesh,tri_id);
2694     while((t_id = smTri_next_ccw_nbr(smMesh,tri,s_id)) != tri_id)
2695     {
2696     tri = SM_NTH_TRI(smMesh,t_id);
2697     SM_SET_NTH_T_ACTIVE(smMesh,t_id);
2698     }
2699 gwlarson 3.12 }
2700 gwlarson 3.15 }
2701 gwlarson 3.10
2702 gwlarson 3.14 smCull(sm,view,n)
2703     SM *sm;
2704 gwlarson 3.10 VIEW *view;
2705 gwlarson 3.14 int n;
2706 gwlarson 3.10 {
2707     FVECT nr[4],far[4];
2708     FPEQ peq;
2709     int debug=0;
2710     FUNC f;
2711    
2712 gwlarson 3.14 /* First clear all the quadtree node flags */
2713     qtClearAllFlags();
2714    
2715 gwlarson 3.10 F_ARGS(f) = NULL;
2716 gwlarson 3.14 /* If marking samples down to leaves */
2717     if(n == SM_ALL_LEVELS)
2718     {
2719 gwlarson 3.10 /* Mark triangles in approx. view frustum as being active:set
2720     LRU counter: for use in discarding samples when out
2721     of space
2722 gwlarson 3.14 */
2723 gwlarson 3.15 F_FUNC(f) = mark_active_samples;
2724 gwlarson 3.14 smClear_flags(sm,T_ACTIVE_FLAG);
2725     /* Clear all of the active sample flags*/
2726     sClear_all_flags(SM_SAMP(sm));
2727     }
2728     else
2729     /* Just mark qtree flags */
2730     F_FUNC(f) = null_func;
2731    
2732     /* calculate the world space coordinates of the view frustum:
2733 gwlarson 3.10 Radiance often has no far clipping plane: but driver will set
2734     dev_zmin,dev_zmax to satisfy OGL
2735 gwlarson 3.14 */
2736 gwlarson 3.10 calculate_view_frustum(view->vp,view->hvec,view->vvec,view->horiz,
2737     view->vert, dev_zmin,dev_zmax,nr,far);
2738    
2739     #ifdef TEST_DRIVER
2740     VCOPY(FrustumFar[0],far[0]);
2741     VCOPY(FrustumFar[1],far[1]);
2742     VCOPY(FrustumFar[2],far[2]);
2743     VCOPY(FrustumFar[3],far[3]);
2744     VCOPY(FrustumNear[0],nr[0]);
2745     VCOPY(FrustumNear[1],nr[1]);
2746     VCOPY(FrustumNear[2],nr[2]);
2747     VCOPY(FrustumNear[3],nr[3]);
2748     #endif
2749     /* Project the view frustum onto the spherical quadtree */
2750     /* For every cell intersected by the projection of the faces
2751    
2752     of the frustum: mark all triangles in the cell as ACTIVE-
2753     Also set the triangles LRU clock counter
2754     */
2755    
2756 gwlarson 3.14 if(EQUAL_VEC3(view->vp,SM_VIEW_CENTER(sm)))
2757 gwlarson 3.10 {/* Near face triangles */
2758    
2759 gwlarson 3.14 smLocator_apply(sm,nr[0],nr[2],nr[3],f,n);
2760     smLocator_apply(sm,nr[2],nr[0],nr[1],f,n);
2761 gwlarson 3.10 return;
2762     }
2763     /* Test the view against the planes: and swap orientation if inside:*/
2764     tri_plane_equation(nr[0],nr[2],nr[3], &peq,FALSE);
2765 gwlarson 3.14 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2766 gwlarson 3.10 {/* Near face triangles */
2767 gwlarson 3.14 smLocator_apply(sm,nr[3],nr[2],nr[0],f,n);
2768     smLocator_apply(sm,nr[1],nr[0],nr[2],f,n);
2769 gwlarson 3.10 }
2770     else
2771     {/* Near face triangles */
2772 gwlarson 3.14 smLocator_apply(sm,nr[0],nr[2],nr[3],f,n);
2773     smLocator_apply(sm,nr[2],nr[0],nr[1],f,n);
2774 gwlarson 3.10 }
2775     tri_plane_equation(nr[0],far[3],far[0], &peq,FALSE);
2776 gwlarson 3.14 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2777 gwlarson 3.10 { /* Right face triangles */
2778 gwlarson 3.14 smLocator_apply(sm,far[0],far[3],nr[0],f,n);
2779     smLocator_apply(sm,nr[3],nr[0],far[3],f,n);
2780 gwlarson 3.10 }
2781     else
2782     {/* Right face triangles */
2783 gwlarson 3.14 smLocator_apply(sm,nr[0],far[3],far[0],f,n);
2784     smLocator_apply(sm,far[3],nr[0],nr[3],f,n);
2785 gwlarson 3.10 }
2786    
2787     tri_plane_equation(nr[1],far[2],nr[2], &peq,FALSE);
2788     if(PT_ON_PLANE(SM_VIEW_CENTER(smMesh),peq) < 0.0)
2789     { /* Left face triangles */
2790 gwlarson 3.14 smLocator_apply(sm,nr[2],far[2],nr[1],f,n);
2791     smLocator_apply(sm,far[1],nr[1],far[2],f,n);
2792 gwlarson 3.10 }
2793     else
2794     { /* Left face triangles */
2795 gwlarson 3.14 smLocator_apply(sm,nr[1],far[2],nr[2],f,n);
2796     smLocator_apply(sm,far[2],nr[1],far[1],f,n);
2797 gwlarson 3.10 }
2798     tri_plane_equation(nr[0],far[0],nr[1], &peq,FALSE);
2799 gwlarson 3.14 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2800 gwlarson 3.10 {/* Top face triangles */
2801 gwlarson 3.14 smLocator_apply(sm,nr[1],far[0],nr[0],f,n);
2802     smLocator_apply(sm,far[1],far[0],nr[1],f,n);
2803 gwlarson 3.10 }
2804     else
2805     {/* Top face triangles */
2806 gwlarson 3.14 smLocator_apply(sm,nr[0],far[0],nr[1],f,n);
2807     smLocator_apply(sm,nr[1],far[0],far[1],f,n);
2808 gwlarson 3.10 }
2809     tri_plane_equation(nr[3],nr[2],far[3], &peq,FALSE);
2810 gwlarson 3.14 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2811 gwlarson 3.10 {/* Bottom face triangles */
2812 gwlarson 3.14 smLocator_apply(sm,far[3],nr[2],nr[3],f,n);
2813     smLocator_apply(sm,far[3],far[2],nr[2],f,n);
2814 gwlarson 3.10 }
2815     else
2816     { /* Bottom face triangles */
2817 gwlarson 3.14 smLocator_apply(sm,nr[3],nr[2],far[3],f,n);
2818     smLocator_apply(sm,nr[2],far[2],far[3],f,n);
2819 gwlarson 3.10 }
2820     tri_plane_equation(far[2],far[0],far[1], &peq,FALSE);
2821 gwlarson 3.14 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2822 gwlarson 3.10 {/* Far face triangles */
2823 gwlarson 3.14 smLocator_apply(sm,far[0],far[2],far[1],f,n);
2824     smLocator_apply(sm,far[2],far[0],far[3],f,n);
2825 gwlarson 3.10 }
2826     else
2827     {/* Far face triangles */
2828 gwlarson 3.14 smLocator_apply(sm,far[1],far[2],far[0],f,n);
2829     smLocator_apply(sm,far[3],far[0],far[2],f,n);
2830 gwlarson 3.10 }
2831    
2832     }
2833 gwlarson 3.15
2834    
2835    
2836    
2837    
2838    
2839    
2840    
2841    
2842    
2843 gwlarson 3.5
2844    
2845    
2846    
2847    
2848    
2849    
2850    
2851 gwlarson 3.1
2852