ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm.c
Revision: 3.12
Committed: Tue Jan 5 16:52:37 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.11: +277 -142 lines
Log Message:
fixed logic in smTest to handle nearby and coincident points, added base tris to rendering, made list of new triangles to speed up rendering

File Contents

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