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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: sm.c,v 3.18 2003/06/20 00:25:49 greg Exp $";
3 #endif
4 /*
5 * sm.c
6 */
7
8 #include <string.h>
9
10 #include "standard.h"
11 #include "sm_flag.h"
12 #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 #ifdef DEBUG
20 int Tcnt=0,Wcnt=0;
21 #endif
22 /* Each edge extends .372 radians */
23 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 {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 {37,127,123},{127,38,128},{123,128,39},{127,128,123},{11,125,132},{125,37,131},
134 {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 {131,135,41},{134,135,131},{6,65,94},{65,18,138},{94,138,28},{65,138,94},
138 {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 {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 {158,133,104},{23,157,156},{157,40,158},{156,158,30},{157,158,156},{
157 11,132,121},
158 {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 {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 {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 {226,224,225},{231,236,24},{64,231,26},{66,237,231},{230,228,229},
204 {235,98,238},
205 {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 {242,240,241},{247,252,86},{26,247,85},{25,253,247},{246,244,245},
208 {251,137,254},
209 {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
225
226 #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 int Pick_tri = -1,Picking = FALSE,Pick_samp=-1;
230 FVECT Pick_point[500],Pick_origin,Pick_dir;
231 FVECT Pick_v0[500], Pick_v1[500], Pick_v2[500];
232 int Pick_q[500];
233 FVECT P0,P1,P2;
234 FVECT FrustumNear[4],FrustumFar[4];
235 double dev_zmin=.01,dev_zmax=1000;
236 #endif
237
238
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 tempbuf = realloc((void *)tempbuf, len);
264 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 smDir(sm,ps,id)
275 SM *sm;
276 FVECT ps;
277 S_ID id;
278 {
279 VSUB(ps,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
280 normalize(ps);
281 }
282
283 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 memset(SM_NTH_FLAGS(sm,i), '\0', FLAG_BYTES(SM_MAX_TRIS(sm)));
292 else
293 memset(SM_NTH_FLAGS(sm,which), '\0', FLAG_BYTES(SM_MAX_TRIS(sm)));
294 }
295
296 /* Given an allocated mesh- initialize */
297 smInit_mesh(sm)
298 SM *sm;
299 {
300 /* Reset the triangle counters */
301 SM_NUM_TRI(sm) = 0;
302 SM_FREE_TRIS(sm) = -1;
303 smClear_flags(sm,-1);
304 }
305
306
307 /* Clear the SM for reuse: free any extra allocated memory:does initialization
308 as well
309 */
310 smClear(sm)
311 SM *sm;
312 {
313 smDist_sum = 0;
314 smInit_samples(sm);
315 smInit_locator(sm);
316 smInit_mesh(sm);
317 }
318
319 /* 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 int max_verts,max_tris;
324 {
325 int fbytes,i;
326
327 fbytes = FLAG_BYTES(max_tris);
328
329 if(!(SM_TRIS(sm) = (TRI *)malloc(max_tris*sizeof(TRI))))
330 goto memerr;
331
332 for(i=0; i< T_FLAGS; i++)
333 if(!(SM_NTH_FLAGS(sm,i)=(int32 *)malloc(fbytes)))
334 goto memerr;
335
336 SM_MAX_VERTS(sm) = max_verts;
337 SM_MAX_TRIS(sm) = max_tris;
338
339 smInit_mesh(sm);
340
341 return(max_tris);
342 memerr:
343 error(SYSTEM, "out of memory in smAlloc_mesh()");
344 }
345
346
347 /*
348 * smAlloc_tri(sm) : Allocate a new mesh triangle
349 * SM *sm; : mesh
350 *
351 * Returns ptr to next available tri
352 */
353 int
354 smAlloc_tri(sm)
355 SM *sm;
356 {
357 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 SM_FREE_TRIS(sm) = T_NEXT_FREE(SM_NTH_TRI(sm,id));
366 return(id);
367 }
368
369 error(CONSISTENCY,"smAlloc_tri: no more available triangles\n");
370 return(INVALID);
371 }
372
373
374 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
387 /*
388 * smAlloc(max_samples) : Initialize/clear global sample list for at least
389 * max_samples
390 * int max_samples;
391 *
392 */
393 smAlloc(max_samples)
394 register int max_samples;
395 {
396 unsigned nbytes;
397 register unsigned i;
398 int total_points;
399 int max_tris,n;
400
401 n = max_samples;
402 /* If this is the first call, allocate sample,vertex and triangle lists */
403 if(!smMesh)
404 {
405 if(!(smMesh = (SM *)malloc(sizeof(SM))))
406 error(SYSTEM,"smAlloc():Unable to allocate memory\n");
407 memset(smMesh, '\0', sizeof(SM));
408 }
409 else
410 { /* If existing structure: first deallocate */
411 smFree_mesh(smMesh);
412 smFree_samples(smMesh);
413 smFree_locator(smMesh);
414 }
415
416 /* First allocate at least n samples + extra points:at least enough
417 necessary to form the BASE MESH- Default = 4;
418 */
419 SM_SAMP(smMesh) = sAlloc(&n,SM_BASE_POINTS);
420
421 total_points = n + SM_BASE_POINTS;
422
423 /* 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 /* Now allocate space for mesh vertices and triangles */
428 max_tris = smAlloc_mesh(smMesh, total_points, max_tris);
429
430 /* Initialize the structure for point,triangle location.
431 */
432 smAlloc_locator(smMesh);
433 }
434
435
436
437 smInit_sm(sm,vp)
438 SM *sm;
439 FVECT vp;
440 {
441 VCOPY(SM_VIEW_CENTER(sm),vp);
442 smClear(sm);
443 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 sleep(5);
462 /* If n <=0, Just clear the existing structures */
463 if(n <= 0)
464 {
465 #ifdef DEBUG
466 fprintf(stderr,"Tcnt=%d Wcnt = %d, avg = %f\n",Tcnt,Wcnt,(float)Wcnt/Tcnt);
467 #endif
468 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 max_vertices = n + SM_BASE_POINTS;
476
477 /* If the current mesh contains enough room, clear and return */
478 if(smMesh && (max_vertices <= SM_MAX_VERTS(smMesh)) && SM_MAX_SAMP(smMesh) <=
479 n && SM_MAX_POINTS(smMesh) <= max_vertices)
480 {
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 #ifdef DEBUG
490 fprintf(stderr,"smInit: allocating room for %d samples\n",
491 SM_MAX_SAMP(smMesh));
492 #endif
493 return(SM_MAX_SAMP(smMesh));
494 }
495
496
497 smLocator_apply(sm,v0,v1,v2,func,n)
498 SM *sm;
499 FVECT v0,v1,v2;
500 FUNC func;
501 int n;
502 {
503 STREE *st;
504 FVECT tri[3];
505
506 st = SM_LOCATOR(sm);
507
508 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 stVisit(st,tri,func,n);
512
513 }
514
515 /*
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 QUADTREE
532 insert_samp(argptr,root,qt,parent,q0,q1,q2,bc,scale,rev,f,n,doneptr)
533 int *argptr;
534 int root;
535 QUADTREE qt,parent;
536 BCOORD q0[3],q1[3],q2[3],bc[3];
537 unsigned int scale,rev;
538 FUNC f;
539 int n,*doneptr;
540 {
541 S_ID s_id;
542 S_ID *optr;
543
544 s_id = ((S_ARGS *)argptr)->s_id;
545 /* If the set is empty - just add */
546 if(QT_IS_EMPTY(qt))
547 {
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 /* If the set size is below expansion threshold,or at maximum
557 number of quadtree levels : just add */
558 optr = qtqueryset(qt);
559 if(QT_SET_CNT(optr) < QT_SET_THRESHOLD || (n > (QT_MAX_LEVELS-2)))
560 {
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 in set to children of new node
578 */
579 {
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
595 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
627 if( sptr != s_set)
628 free(sptr);
629
630 return(qt);
631 }
632 memerr:
633 error(SYSTEM,"expand_node():Unable to allocate memory");
634
635 }
636
637
638 /*
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 int
650 smAdd_tri(sm, v0_id,v1_id,v2_id,tptr)
651 SM *sm;
652 S_ID v0_id,v1_id,v2_id;
653 TRI **tptr;
654 {
655 int t_id;
656 TRI *t;
657
658 #ifdef DEBUG
659 if(v0_id==v1_id || v0_id==v2_id || v1_id==v2_id)
660 error(CONSISTENCY,"smAdd_tri: invalid vertex ids\n");
661
662 #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 double ab[3],ac[3];
670 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
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 if((dp=DOT(v0,n)) < 0.0)
684 {
685 eputs("backwards tri\n");
686 }
687 }
688 #endif
689 #endif
690
691 t = SM_NTH_TRI(sm,t_id);
692 #ifdef DEBUG
693 T_CLEAR_NBRS(t);
694 #endif
695 /* 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
700 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 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 else
707 SM_CLR_NTH_T_BASE(sm,t_id);
708 if(SM_DIR_ID(sm,v0_id) || SM_DIR_ID(sm,v1_id) || SM_DIR_ID(sm,v2_id))
709 SM_SET_NTH_T_BG(sm,t_id);
710 else
711 SM_CLR_NTH_T_BG(sm,t_id);
712 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 SM_SET_NTH_T_ACTIVE(sm,t_id);
717 SM_SET_NTH_T_NEW(sm,t_id);
718
719 *tptr = t;
720 /* return initialized triangle */
721 return(t_id);
722 }
723
724
725
726 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 int e1,topp_id;
733 S_ID p_id;
734 TRI *topp;
735 FVECT p;
736
737 topp_id = T_NTH_NBR(t,0);
738 #ifdef DEBUG
739 if(topp_id==INVALID)
740 {
741 eputs("Invalid tri id smRestore_delaunay()\n");
742 return;
743 }
744 #endif
745 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 return;
751 }
752 #endif
753 e1 = T_NTH_NBR_PTR(t_id,topp);
754 p_id = T_NTH_V(topp,e1);
755
756 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 {
760 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
768 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
788 #ifdef DEBUG
789 #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
853 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
862 #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 }
868
869
870 /* 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 S_ID id;
878 {
879 int which;
880 int nbr_id;
881
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
887 nbr_id = T_NTH_NBR(t,(which + 1)% 3);
888 return(nbr_id);
889 }
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 SM_CLR_NTH_T_FLAG(sm,id,i);
899
900 }
901
902 /* Locate the point-id in the point location structure: */
903 int
904 smInsert_samp_mesh(sm,s_id,tri_id,a,b,c,d,on,which)
905 SM *sm;
906 S_ID s_id;
907 int tri_id;
908 FVECT a,b,c,d;
909 int on,which;
910 {
911 S_ID v_id[3],opp_id;
912 int topp_id,i;
913 int t0_id,t1_id,t2_id,t3_id;
914 int e0,e1,e2,opp0,opp1,opp2;
915 TRI *tri,*nbr,*topp,*t0,*t1,*t2,*t3;
916 FVECT e;
917
918 for(i=0; i<3;i++)
919 v_id[i] = T_NTH_V(SM_NTH_TRI(sm,tri_id),i);
920
921 /* If falls on existing edge */
922 if(on == ON_E)
923 {
924 FVECT n,vopp;
925 double dp;
926
927 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
937 opp_id = T_NTH_V(topp,opp0);
938
939 /* Create 4 triangles */
940 /* /|\ /|\
941 / | \ / | \
942 / * \ ----> /__|__\
943 \ | / \ | /
944 \ | / \ | /
945 \|/ \|/
946 */
947 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
952 /* 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
966 /* 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
976 #ifdef DEBUG
977 #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 }
1154 Linsert_in_tri:
1155 /* Create 3 triangles */
1156 /* / \ /|\
1157 / \ / | \
1158 / * \ ----> / | \
1159 / \ / / \ \
1160 / \ / / \ \
1161 ___________\ //_________\\
1162 */
1163 tri = SM_NTH_TRI(sm,tri_id);
1164
1165 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
1169 /* 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
1180 /* 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
1254 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
1263 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
1307 #ifdef DEBUG
1308 Ladderror:
1309 error(CONSISTENCY,"Invalid tri: smInsert_samp_mesh()\n");
1310 #endif
1311 }
1312
1313
1314 int
1315 smWalk(sm,p,t_id,t,onptr,wptr,from,on_edge,a,b)
1316 SM *sm;
1317 FVECT p;
1318 int t_id;
1319 TRI *t;
1320 int *onptr,*wptr;
1321 int from;
1322 double on_edge;
1323 FVECT a,b;
1324 {
1325 FVECT n,v0,v1,v2;
1326 TRI *tn;
1327 double on0,on1,on2;
1328 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 VSUB(v0,SM_T_NTH_WV(sm,t,0),SM_VIEW_CENTER(sm));
1339 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
1375 VCROSS(n,b,v0);
1376 normalize(n);
1377 on1 = DOT(n,p);
1378 if(on1 > 0.0)
1379 {
1380 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 }
1385 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 {
1438 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 }
1443 if(on2 >= -EDGE_EPS)
1444 {
1445 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 }
1457
1458 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 else
1497 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
1515 /* 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 {
1521 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 {
1529 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 }
1541 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 {
1556 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 }
1565 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 else
1570 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 return(t_id);
1690 }
1691 *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
1709 find_neighbor(argptr,qt,f,doneptr)
1710 int *argptr;
1711 QUADTREE qt;
1712 FUNC f;
1713 int *doneptr;
1714 {
1715 S_ID s_id;
1716 int i;
1717 S_ID *optr;
1718
1719 if(QT_IS_EMPTY(qt))
1720 return;
1721 else
1722 if(QT_IS_TREE(qt))
1723 {
1724 for(i=0;i < 4; i++)
1725 {
1726 find_neighbor(argptr,QT_NTH_CHILD(qt,i),f,doneptr);
1727 if(*doneptr)
1728 return;
1729 }
1730 }
1731 else
1732 {
1733 optr = qtqueryset(qt);
1734 for(i = QT_SET_CNT(optr); i > 0; i--)
1735 {
1736 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 }
1744 }
1745 }
1746
1747 smInsert_samp(sm,s_id,p,nptr)
1748 SM *sm;
1749 S_ID s_id;
1750 FVECT p;
1751 S_ID *nptr;
1752 {
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 }
1764 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 }
1772
1773 /* Assumed p is normalized to view sphere */
1774 int
1775 smSample_locate_tri(sm,p,s_id,onptr,whichptr,nptr)
1776 SM *sm;
1777 FVECT p;
1778 S_ID s_id;
1779 int *onptr,*whichptr;
1780 S_ID *nptr;
1781 {
1782 int tri_id;
1783 FVECT tpt;
1784 TRI *tri;
1785
1786 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
1798 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 }
1817
1818 /*
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 1) If the new sample is close in ws, and close in the spherical projection
1836 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 2) If the spherical projection of new is < REPLACE_EPS from a base point:
1841 add new and mark the base for deletion: return TRUE
1842 3) If the addition of the new sample point would introduce a "puncture"
1843 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 smTest_samp(sm,tri_id,dir,p,rptr,ns,n0,n1,n2,ds,d0,on,which)
1848 SM *sm;
1849 int tri_id;
1850 FVECT dir,p;
1851 S_ID *rptr;
1852 FVECT ns,n0,n1,n2;
1853 double ds,d0;
1854 int on,which;
1855 {
1856 TRI *tri;
1857 double d,d2,dnear,dspt,d01,d12,d20,s0,s1,s2;
1858 double dp,dp1;
1859 S_ID vid[3];
1860 int i,norm,dcnt,bcnt;
1861 FVECT diff[3],spt,npt,n;
1862 FVECT nearpt;
1863
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 if(SM_BASE_ID(sm,vid[i]))
1874 bcnt++;
1875 else
1876 if(SM_DIR_ID(sm,vid[i]))
1877 dcnt++;
1878 }
1879 if(on == ON_P)
1880 {
1881 FVECT edir;
1882 /* 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 if(!dir)
1886 return(FALSE);
1887 if(SM_BASE_ID(sm,vid[which]))
1888 return(FALSE);
1889 if(SM_DIR_ID(sm,vid[which]))
1890 {
1891 *rptr = vid[which];
1892 return(TRUE);
1893 }
1894 decodedir(edir,SM_NTH_W_DIR(sm,vid[which]));
1895 if(which == 0)
1896 d = DOT(edir,n0);
1897 else
1898 if(which == 1)
1899 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 *rptr = vid[which];
1910 return(TRUE);
1911 }
1912 }
1913
1914 /* Now test if sample epsilon is within circumcircle of enclosing tri
1915 if not punt:
1916 */
1917 {
1918 double ab[3],ac[3],r[3];
1919
1920 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 {
1927 #ifdef DEBUG
1928 eputs("smTest_samp:rejecting samp,cant guarantee not within eps\n");
1929 #endif
1930 return(FALSE);
1931 }
1932 }
1933 #ifdef DEBUG
1934 #if DEBUG > 1
1935 if(on == ON_E)
1936 {
1937 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 }
1962 #endif
1963 #endif
1964 /* 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
1971 if(ds < d0)
1972 return(TRUE);
1973
1974 d01 = DIST_SQ(SM_NTH_WV(sm,vid[1]),SM_NTH_WV(sm,vid[0]));
1975 VSUB(diff[0],SM_NTH_WV(sm,vid[0]),p);
1976 s0 = DOT(diff[0],diff[0]);
1977 if(s0 < S_REPLACE_SCALE*d01)
1978 return(TRUE);
1979
1980 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 VSUB(diff[1],SM_NTH_WV(sm,vid[1]),p);
1988 s1 = DOT(diff[1],diff[1]);
1989 if(s1 < S_REPLACE_SCALE*d)
1990 return(TRUE);
1991 VSUB(diff[2],SM_NTH_WV(sm,vid[2]),p);
1992 s2 = DOT(diff[2],diff[2]);
1993 if(s2 < S_REPLACE_SCALE*d)
1994 return(TRUE);
1995
1996 /* TEST 5:
1997 Check to see if triangle is relatively large and should therefore
1998 be subdivided anyway.
1999 */
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 return(TRUE);
2004
2005 return(FALSE);
2006 }
2007 S_ID
2008 smReplace_samp(sm,c,dir,p,np,s_id,t_id,o_id,on,which)
2009 SM *sm;
2010 COLR c;
2011 FVECT dir,p,np;
2012 S_ID s_id;
2013 int t_id;
2014 S_ID o_id;
2015 int on,which;
2016 {
2017 S_ID v_id;
2018 int tri_id;
2019 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 return(v_id);
2027
2028 if(EQUAL_VEC3(p,SM_NTH_WV(sm,v_id)))
2029 return(INVALID);
2030
2031 if(dir)
2032 { /* 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 {
2039 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 sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id);
2049 if(!SM_IS_NTH_T_NEW(sm,t_id))
2050 SM_SET_NTH_T_NEW(sm,t_id);
2051 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 if(!SM_IS_NTH_T_NEW(sm,tri_id))
2056 SM_SET_NTH_T_NEW(sm,tri_id);
2057 tri_id = smTri_next_ccw_nbr(sm,t,v_id);
2058 }
2059 }
2060 return(v_id);
2061 }
2062 else /* New point is a dir */
2063 return(INVALID);
2064
2065 }
2066
2067 S_ID
2068 smAlloc_samp(sm)
2069 SM *sm;
2070 {
2071 S_ID s_id;
2072 int replaced,cnt;
2073 SAMP *s;
2074 FVECT p;
2075
2076 s = SM_SAMP(sm);
2077 s_id = sAlloc_samp(s,&replaced);
2078 while(replaced)
2079 {
2080 smRemoveVertex(sm,s_id);
2081 s_id = sAlloc_samp(s,&replaced);
2082 }
2083 return(s_id);
2084 }
2085
2086
2087 /* 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 S_ID
2101 smAdd_samp(sm,c,dir,p,o_id)
2102 SM *sm;
2103 COLR c;
2104 FVECT dir,p;
2105 S_ID o_id;
2106 {
2107 int t_id,on,which,n_id;
2108 S_ID s_id,r_id,nbr_id;
2109 double ds,d0;
2110 FVECT wpt,ns,n0,n1,n2;
2111 QUADTREE qt,parent;
2112 TRI *t;
2113
2114 r_id = INVALID;
2115 nbr_id = INVALID;
2116 /* Must do this first-as may change mesh */
2117 s_id = smAlloc_samp(sm);
2118 SM_S_NTH_QT(sm,s_id)= EMPTY;
2119 /* If sample is a world space point */
2120 if(p)
2121 {
2122 VSUB(ns,p,SM_VIEW_CENTER(sm));
2123 ds = normalize(ns);
2124 while(1)
2125 {
2126 t_id = smSample_locate_tri(sm,ns,s_id,&on,&which,&nbr_id);
2127 qt = SM_S_NTH_QT(sm,s_id);
2128 if(t_id == INVALID)
2129 {
2130 #ifdef DEBUG
2131 eputs("smAddSamp(): unable to locate tri containing sample \n");
2132 #endif
2133 smUnalloc_samp(sm,s_id);
2134 qtremovelast(qt,s_id);
2135 return(INVALID);
2136 }
2137 /* If spherical projection coincides with existing sample: replace */
2138 if(on == ON_V)
2139 {
2140 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 return(n_id);
2150 }
2151 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 smUnalloc_samp(sm,s_id);
2161 #if 0
2162 fprintf(stderr,"Unallocating sample %d\n",s_id);
2163 #endif
2164 qtremovelast(qt,s_id);
2165 return(INVALID);
2166 }
2167 if(r_id != INVALID)
2168 {
2169 smRemoveVertex(sm,r_id);
2170 if(nbr_id == r_id)
2171 {
2172 qtremovelast(qt,s_id);
2173 SM_S_NTH_QT(sm,s_id) = EMPTY;
2174 }
2175 }
2176 else
2177 break;
2178 }
2179 /* If sample is being added in the middle of the sample array: tone
2180 map individually
2181 */
2182 /* If not base or sky point, add distance from center to average*/
2183 smDist_sum += 1.0/ds;
2184 /* Initialize sample */
2185 sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id);
2186 smInsert_samp_mesh(sm,s_id,t_id,ns,n0,n1,n2,on,which);
2187 }
2188 /* If sample is a direction vector */
2189 else
2190 {
2191 VADD(wpt,dir,SM_VIEW_CENTER(sm));
2192 /* Allocate space for a sample and initialize */
2193 while(1)
2194 {
2195 t_id = smSample_locate_tri(sm,dir,s_id,&on,&which,&nbr_id);
2196 qt = SM_S_NTH_QT(sm,s_id);
2197 #ifdef DEBUG
2198 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 #endif
2206 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 {
2230 qtremovelast(qt,s_id);
2231 SM_S_NTH_QT(sm,s_id) = EMPTY;
2232 }
2233 }
2234 else
2235 break;
2236 }
2237 sInit_samp(SM_SAMP(sm),s_id,c,NULL,wpt,o_id);
2238 smInsert_samp_mesh(sm,s_id,t_id,dir,n0,n1,n2,on,which);
2239 }
2240 return(s_id);
2241 }
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 #define FVECT_TO_SFLOAT(p) \
2255 (p[0]=(SFLOAT)p[0],p[1]=(SFLOAT)p[1],p[2]=(SFLOAT)p[2])
2256 int
2257 smNewSamp(c,dir,p)
2258 COLR c;
2259 FVECT dir;
2260 FVECT p;
2261 {
2262 S_ID s_id;
2263
2264 /* First check if this the first sample: if so initialize mesh */
2265 if(SM_NUM_SAMP(smMesh) == 0)
2266 {
2267 smInit_sm(smMesh,odev.v.vp);
2268 sClear_all_flags(SM_SAMP(smMesh));
2269 }
2270 FVECT_TO_SFLOAT(p);
2271 FVECT_TO_SFLOAT(dir);
2272 /* Add the sample to the mesh */
2273 s_id = smAdd_samp(smMesh,c,dir,p,INVALID);
2274
2275 return((int)s_id);
2276
2277 }
2278 S_ID
2279 smAdd_base_vertex(sm,v)
2280 SM *sm;
2281 FVECT v;
2282 {
2283 S_ID id;
2284
2285 /* First add coordinate to the sample array */
2286 id = sAdd_base_point(SM_SAMP(sm),v);
2287 if(id == INVALID)
2288 return(INVALID);
2289 /* 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 int i,s_id,tri_id,nbr_id;
2307 S_ID p[SM_BASE_POINTS];
2308 int ids[SM_BASE_TRIS];
2309 S_ID v0_id,v1_id,v2_id;
2310 FVECT d,pt,cntr,v0,v1,v2;
2311 TRI *t;
2312
2313 /* First insert the base vertices into the sample point array */
2314 for(i=0; i < SM_BASE_POINTS; i++)
2315 {
2316 VADD(cntr,icosa_verts[i],SM_VIEW_CENTER(sm));
2317 p[i] = smAdd_base_vertex(sm,cntr);
2318 smInsert_samp(sm,p[i],icosa_verts[i],NULL);
2319 }
2320 /* Create the base triangles */
2321 for(i=0;i < SM_BASE_TRIS; i++)
2322 {
2323 v0_id = p[icosa_tris[i][0]];
2324 v1_id = p[icosa_tris[i][1]];
2325 v2_id = p[icosa_tris[i][2]];
2326 ids[i] = smAdd_tri(sm, v0_id,v1_id,v2_id,&t);
2327 /* 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 }
2332 return(1);
2333
2334 }
2335
2336 smRebuild(sm,v)
2337 SM *sm;
2338 VIEW *v;
2339 {
2340 S_ID s_id;
2341 int j,cnt;
2342 FVECT p,ov,dir;
2343 double d;
2344
2345 #ifdef DEBUG
2346 fprintf(stderr,"smRebuild(): rebuilding....");
2347 #endif
2348 smCull(sm,v,SM_ALL_LEVELS);
2349 /* Clear the mesh- and rebuild using the current sample array */
2350 /* 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 VCOPY(ov,SM_VIEW_CENTER(sm));
2355
2356 /* Initialize the mesh to 0 samples and the base triangles */
2357 smInit_sm(sm,v->vp);
2358 /* 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 for(s_id=0; s_id < cnt; s_id++)
2362 {
2363 /* First check if sample visible(conservative approx: if one of tris
2364 attached to sample is in frustum) */
2365 if(!S_IS_FLAG(s_id))
2366 continue;
2367
2368 /* Next test if direction > 30 degrees from current direction */
2369 if(SM_NTH_W_DIR(sm,s_id)!=-1)
2370 {
2371 VSUB(p,SM_NTH_WV(sm,s_id),v->vp);
2372 decodedir(dir,SM_NTH_W_DIR(sm,s_id));
2373 d = DOT(dir,p);
2374 if (d*d < MAXDIFF2*DOT(p,p))
2375 continue;
2376 VCOPY(p,SM_NTH_WV(sm,s_id));
2377 smAdd_samp(sm,NULL,dir,p,s_id);
2378 }
2379 else
2380 {
2381 /* If the direction is > 45 degrees from current view direction:
2382 throw out
2383 */
2384 VSUB(dir,SM_NTH_WV(sm,s_id),ov);
2385 if(DOT(dir,v->vdir) < MAXDIR)
2386 continue;
2387
2388 VADD(SM_NTH_WV(sm,s_id),dir,SM_VIEW_CENTER(sm));
2389 smAdd_samp(sm,NULL,dir,NULL,s_id);
2390 }
2391
2392 }
2393 #ifdef DEBUG
2394 fprintf(stderr,"smRebuild():done\n");
2395 #endif
2396 }
2397
2398 /* OS is constrained to be <= QT_MAXCSET : if the set exceeds this, the
2399 results of check_set are conservative
2400 */
2401 int
2402 compare_ids(id1,id2)
2403 S_ID *id1,*id2;
2404 {
2405 int d;
2406
2407 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
2418 null_func(argptr,root,qt,n)
2419 int *argptr;
2420 int root;
2421 QUADTREE qt;
2422 int n;
2423 {
2424 /* do nothing */
2425 }
2426
2427 mark_active_samples(argptr,root,qt,n)
2428 int *argptr;
2429 int root;
2430 QUADTREE qt;
2431 int n;
2432 {
2433 S_ID *os,s_id;
2434 register int i,t_id,tri_id;
2435 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 for (i = QT_SET_CNT(os); i > 0; i--)
2444 {
2445 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 }
2458 }
2459
2460 smCull(sm,view,n)
2461 SM *sm;
2462 VIEW *view;
2463 int n;
2464 {
2465 FVECT nr[4],far[4];
2466 FPEQ peq;
2467 int debug=0;
2468 FUNC f;
2469
2470 /* First clear all the quadtree node flags */
2471 qtClearAllFlags();
2472
2473 F_ARGS(f) = NULL;
2474 /* If marking samples down to leaves */
2475 if(n == SM_ALL_LEVELS)
2476 {
2477 /* Mark triangles in approx. view frustum as being active:set
2478 LRU counter: for use in discarding samples when out
2479 of space
2480 */
2481 F_FUNC(f) = mark_active_samples;
2482 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 Radiance often has no far clipping plane: but driver will set
2492 dev_zmin,dev_zmax to satisfy OGL
2493 */
2494 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 if(EQUAL_VEC3(view->vp,SM_VIEW_CENTER(sm)))
2515 {/* Near face triangles */
2516
2517 smLocator_apply(sm,nr[0],nr[2],nr[3],f,n);
2518 smLocator_apply(sm,nr[2],nr[0],nr[1],f,n);
2519 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 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2524 {/* Near face triangles */
2525 smLocator_apply(sm,nr[3],nr[2],nr[0],f,n);
2526 smLocator_apply(sm,nr[1],nr[0],nr[2],f,n);
2527 }
2528 else
2529 {/* Near face triangles */
2530 smLocator_apply(sm,nr[0],nr[2],nr[3],f,n);
2531 smLocator_apply(sm,nr[2],nr[0],nr[1],f,n);
2532 }
2533 tri_plane_equation(nr[0],far[3],far[0], &peq,FALSE);
2534 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2535 { /* Right face triangles */
2536 smLocator_apply(sm,far[0],far[3],nr[0],f,n);
2537 smLocator_apply(sm,nr[3],nr[0],far[3],f,n);
2538 }
2539 else
2540 {/* Right face triangles */
2541 smLocator_apply(sm,nr[0],far[3],far[0],f,n);
2542 smLocator_apply(sm,far[3],nr[0],nr[3],f,n);
2543 }
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 smLocator_apply(sm,nr[2],far[2],nr[1],f,n);
2549 smLocator_apply(sm,far[1],nr[1],far[2],f,n);
2550 }
2551 else
2552 { /* Left face triangles */
2553 smLocator_apply(sm,nr[1],far[2],nr[2],f,n);
2554 smLocator_apply(sm,far[2],nr[1],far[1],f,n);
2555 }
2556 tri_plane_equation(nr[0],far[0],nr[1], &peq,FALSE);
2557 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2558 {/* Top face triangles */
2559 smLocator_apply(sm,nr[1],far[0],nr[0],f,n);
2560 smLocator_apply(sm,far[1],far[0],nr[1],f,n);
2561 }
2562 else
2563 {/* Top face triangles */
2564 smLocator_apply(sm,nr[0],far[0],nr[1],f,n);
2565 smLocator_apply(sm,nr[1],far[0],far[1],f,n);
2566 }
2567 tri_plane_equation(nr[3],nr[2],far[3], &peq,FALSE);
2568 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2569 {/* Bottom face triangles */
2570 smLocator_apply(sm,far[3],nr[2],nr[3],f,n);
2571 smLocator_apply(sm,far[3],far[2],nr[2],f,n);
2572 }
2573 else
2574 { /* Bottom face triangles */
2575 smLocator_apply(sm,nr[3],nr[2],far[3],f,n);
2576 smLocator_apply(sm,nr[2],far[2],far[3],f,n);
2577 }
2578 tri_plane_equation(far[2],far[0],far[1], &peq,FALSE);
2579 if(PT_ON_PLANE(SM_VIEW_CENTER(sm),peq) < 0.0)
2580 {/* Far face triangles */
2581 smLocator_apply(sm,far[0],far[2],far[1],f,n);
2582 smLocator_apply(sm,far[2],far[0],far[3],f,n);
2583 }
2584 else
2585 {/* Far face triangles */
2586 smLocator_apply(sm,far[1],far[2],far[0],f,n);
2587 smLocator_apply(sm,far[3],far[0],far[2],f,n);
2588 }
2589
2590 }
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610