ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.19
Committed: Mon Jun 30 14:59:12 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6P1, rad3R6
Changes since 3.18: +7 -4 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

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