ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.13
Committed: Sun Jan 10 10:27:48 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.12: +114 -120 lines
Log Message:
sm.c, sm_del.c sm_ogl.c sm.h
Fixed failure to tone-map on start up
added code for temporary buffer allocation
added bg flag, and fast flag checking routines for drawing
provided graceful backout if deletion triangulation fails

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