ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.14
Committed: Fri Mar 5 16:33:17 1999 UTC (25 years, 1 month ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.13: +84 -197 lines
Log Message:
changes to support display list rendering
fixed picking not to return directional points

File Contents

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