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

# 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 gwlarson 3.1
25 gwlarson 3.13 #define SM_MIN_SAMP_DIFF 1e-4/* min edge length in radians */
26 gwlarson 3.12
27 gwlarson 3.10 /* 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 gwlarson 3.8
223 gwlarson 3.5
224 gwlarson 3.1 #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 gwlarson 3.5 int Pick_tri = -1,Picking = FALSE,Pick_samp=-1;
228 gwlarson 3.1 FVECT Pick_point[500],Pick_origin,Pick_dir;
229     FVECT Pick_v0[500], Pick_v1[500], Pick_v2[500];
230 gwlarson 3.9 int Pick_q[500];
231 gwlarson 3.1 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 gwlarson 3.8 VSUB(ps,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
242     normalize(ps);
243 gwlarson 3.1 }
244 gwlarson 3.8
245 gwlarson 3.7 smDir_in_cone(sm,ps,id)
246     SM *sm;
247     FVECT ps;
248     int id;
249     {
250    
251 gwlarson 3.8 VSUB(ps,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
252     normalize(ps);
253 gwlarson 3.7 }
254 gwlarson 3.1
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 gwlarson 3.8 bzero(SM_NTH_FLAGS(sm,i),FLAG_BYTES(SM_MAX_TRIS(sm)));
264 gwlarson 3.1 else
265 gwlarson 3.8 bzero(SM_NTH_FLAGS(sm,which),FLAG_BYTES(SM_MAX_TRIS(sm)));
266 gwlarson 3.1 }
267    
268 gwlarson 3.8 /* Given an allocated mesh- initialize */
269     smInit_mesh(sm)
270     SM *sm;
271 gwlarson 3.1 {
272 gwlarson 3.8 /* Reset the triangle counters */
273     SM_NUM_TRI(sm) = 0;
274     SM_SAMPLE_TRIS(sm) = 0;
275     SM_FREE_TRIS(sm) = -1;
276 gwlarson 3.10 SM_AVAILABLE_TRIS(sm) = -1;
277 gwlarson 3.8 smClear_flags(sm,-1);
278 gwlarson 3.1 }
279    
280    
281 gwlarson 3.8 /* Clear the SM for reuse: free any extra allocated memory:does initialization
282     as well
283     */
284 gwlarson 3.1 smClear(sm)
285     SM *sm;
286     {
287     smClear_samples(sm);
288     smClear_locator(sm);
289 gwlarson 3.8 smInit_mesh(sm);
290 gwlarson 3.1 }
291    
292 gwlarson 3.8 static int realloc_cnt=0;
293    
294 gwlarson 3.1 int
295 gwlarson 3.8 smRealloc_mesh(sm)
296 gwlarson 3.1 SM *sm;
297 gwlarson 3.8 {
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 gwlarson 3.1 int max_verts,max_tris;
325     {
326 gwlarson 3.8 int fbytes,i;
327 gwlarson 3.1
328 gwlarson 3.8 fbytes = FLAG_BYTES(max_tris);
329 gwlarson 3.1
330 gwlarson 3.8 if(!(SM_TRIS(sm) = (TRI *)realloc(NULL,max_tris*sizeof(TRI))))
331     goto memerr;
332 gwlarson 3.1
333 gwlarson 3.8 if(!(SM_VERTS(sm) = (VERT *)realloc(NULL,max_verts*sizeof(VERT))))
334     goto memerr;
335 gwlarson 3.1
336 gwlarson 3.8 for(i=0; i< T_FLAGS; i++)
337     if(!(SM_NTH_FLAGS(sm,i)=(int4 *)realloc(NULL,fbytes)))
338     goto memerr;
339    
340 gwlarson 3.1 SM_MAX_VERTS(sm) = max_verts;
341     SM_MAX_TRIS(sm) = max_tris;
342    
343 gwlarson 3.8 realloc_cnt = max_verts >> 1;
344 gwlarson 3.1
345 gwlarson 3.8 smInit_mesh(sm);
346    
347 gwlarson 3.1 return(max_tris);
348 gwlarson 3.8 memerr:
349     error(SYSTEM, "out of memory in smAlloc_mesh()");
350 gwlarson 3.1 }
351    
352    
353 gwlarson 3.10 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 gwlarson 3.1 int
379 gwlarson 3.8 smAlloc_tri(sm)
380 gwlarson 3.1 SM *sm;
381     {
382 gwlarson 3.8 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 gwlarson 3.10 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 gwlarson 3.8 if((id = SM_FREE_TRIS(sm)) != -1)
394     {
395 gwlarson 3.10 dosets(compress_set);
396     SM_AVAILABLE_TRIS(sm) = T_NEXT_FREE(SM_NTH_TRI(sm,id));
397     SM_FREE_TRIS(sm) = -1;
398 gwlarson 3.8 return(id);
399     }
400     /*Else: realloc */
401     smRealloc_mesh(sm);
402     return(SM_NUM_TRI(sm)++);
403 gwlarson 3.1 }
404    
405 gwlarson 3.8 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 gwlarson 3.1 /* 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 gwlarson 3.8 int max_tris,n;
428 gwlarson 3.1
429 gwlarson 3.8 n = max_samples;
430 gwlarson 3.1 /* If this is the first call, allocate sample,vertex and triangle lists */
431     if(!smMesh)
432     {
433     if(!(smMesh = (SM *)malloc(sizeof(SM))))
434 gwlarson 3.8 error(SYSTEM,"smAlloc():Unable to allocate memory\n");
435 gwlarson 3.1 bzero(smMesh,sizeof(SM));
436     }
437     else
438     { /* If existing structure: first deallocate */
439 gwlarson 3.8 smFree_mesh(smMesh);
440     smFree_samples(smMesh);
441     smFree_locator(smMesh);
442     }
443 gwlarson 3.1
444     /* First allocate at least n samples + extra points:at least enough
445     necessary to form the BASE MESH- Default = 4;
446     */
447 gwlarson 3.8 SM_SAMP(smMesh) = sAlloc(&n,SM_EXTRA_POINTS);
448 gwlarson 3.1
449 gwlarson 3.8 total_points = n + SM_EXTRA_POINTS;
450 gwlarson 3.1
451 gwlarson 3.13 max_tris = total_points*2;
452 gwlarson 3.1 /* Now allocate space for mesh vertices and triangles */
453 gwlarson 3.8 max_tris = smAlloc_mesh(smMesh, total_points, max_tris);
454 gwlarson 3.1
455     /* Initialize the structure for point,triangle location.
456     */
457     smAlloc_locator(smMesh);
458     }
459    
460    
461    
462 gwlarson 3.8 smInit_sm(sm,vp)
463 gwlarson 3.1 SM *sm;
464     FVECT vp;
465     {
466    
467     smDist_sum = 0;
468     smNew_tri_cnt = 0;
469    
470 gwlarson 3.8 VCOPY(SM_VIEW_CENTER(sm),vp);
471     smInit_locator(sm,vp);
472     smInit_samples(sm);
473     smInit_mesh(sm);
474 gwlarson 3.1 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 gwlarson 3.8
495 gwlarson 3.1 /* 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 gwlarson 3.8 if(smMesh && (max_vertices <= SM_MAX_VERTS(smMesh)) && SM_MAX_SAMP(smMesh) <=
509     n && SM_MAX_POINTS(smMesh) <= max_vertices)
510 gwlarson 3.1 {
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 gwlarson 3.10 smLocator_apply(sm,v0,v1,v2,func)
524 gwlarson 3.7 SM *sm;
525     FVECT v0,v1,v2;
526 gwlarson 3.10 FUNC func;
527 gwlarson 3.1 {
528     STREE *st;
529 gwlarson 3.10 FVECT tri[3];
530 gwlarson 3.1
531     st = SM_LOCATOR(sm);
532    
533 gwlarson 3.10 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 gwlarson 3.1
538     }
539    
540    
541 gwlarson 3.10 /* NEW INSERTION!!! ******************************************************/
542 gwlarson 3.8 QUADTREE
543 gwlarson 3.10 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 gwlarson 3.8 {
555 gwlarson 3.10 OBJECT *optr,*tptr,t_set[QT_MAXSET+1];
556     int i,t_id;
557 gwlarson 3.8 TRI *t;
558 gwlarson 3.10 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 gwlarson 3.8
565 gwlarson 3.10 t_id = *argptr;
566 gwlarson 3.8
567 gwlarson 3.10 /* 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 gwlarson 3.11 if(QT_SET_CNT(optr) < QT_SET_THRESHOLD || (n > (QT_MAX_LEVELS-2)))
575 gwlarson 3.10 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 gwlarson 3.8 qtfreeleaf(qt);
596     qtSubdivide(qt);
597    
598 gwlarson 3.10 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 gwlarson 3.8 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 gwlarson 3.10 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 gwlarson 3.8 }
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 gwlarson 3.5 }
641    
642    
643 gwlarson 3.8
644 gwlarson 3.10 smLocator_add_tri(sm,t_id,v0_id,v1_id,v2_id)
645 gwlarson 3.1 SM *sm;
646     int t_id;
647 gwlarson 3.7 int v0_id,v1_id,v2_id;
648 gwlarson 3.1 {
649 gwlarson 3.10 FVECT tri[3];
650     FUNC f;
651 gwlarson 3.8
652 gwlarson 3.10 #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 gwlarson 3.1
658 gwlarson 3.10 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 gwlarson 3.9 #endif
663 gwlarson 3.8
664 gwlarson 3.10 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 gwlarson 3.1
668 gwlarson 3.10 F_FUNC(f) = insert_tri;
669     F_ARGS(f) = &t_id;
670     stInsert_tri(SM_LOCATOR(sm),tri,f);
671 gwlarson 3.1 }
672    
673     /* Add a triangle to the base array with vertices v1-v2-v3 */
674     int
675 gwlarson 3.8 smAdd_tri(sm, v0_id,v1_id,v2_id)
676 gwlarson 3.1 SM *sm;
677     int v0_id,v1_id,v2_id;
678     {
679     int t_id;
680     TRI *t;
681 gwlarson 3.9 #ifdef DEBUG
682     if(v0_id==v1_id || v0_id==v2_id || v1_id==v2_id)
683 gwlarson 3.10 error(CONSISTENCY,"smAdd_tri: invalid vertex ids\n");
684 gwlarson 3.9 #endif
685 gwlarson 3.8 t_id = smAlloc_tri(sm);
686 gwlarson 3.1
687     if(t_id == -1)
688     return(t_id);
689    
690     t = SM_NTH_TRI(sm,t_id);
691 gwlarson 3.8
692 gwlarson 3.1 T_CLEAR_NBRS(t);
693 gwlarson 3.8 /* 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 gwlarson 3.1
698 gwlarson 3.8 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 gwlarson 3.1 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 gwlarson 3.13 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 gwlarson 3.12 SM_SET_NTH_T_ACTIVE(sm,t_id);
713 gwlarson 3.13 SM_SET_NTH_T_NEW(sm,t_id);
714 gwlarson 3.1
715 gwlarson 3.12 SM_SAMPLE_TRIS(sm)++;
716 gwlarson 3.13 smNew_tri_cnt++;
717 gwlarson 3.12
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.10 smUpdate_locator(sm,add_list)
848 gwlarson 3.3 SM *sm;
849 gwlarson 3.7 LIST *add_list;
850 gwlarson 3.3 {
851 gwlarson 3.13 int t_id;
852 gwlarson 3.3 TRI *t;
853 gwlarson 3.7
854 gwlarson 3.3 while(add_list)
855     {
856     t_id = pop_list(&add_list);
857 gwlarson 3.6 t = SM_NTH_TRI(sm,t_id);
858 gwlarson 3.10 smLocator_add_tri(sm,t_id,T_NTH_V(t,0),T_NTH_V(t,1),T_NTH_V(t,2));
859 gwlarson 3.3 }
860 gwlarson 3.10 }
861 gwlarson 3.7
862 gwlarson 3.3 int
863 gwlarson 3.10 smFix_tris(sm,id,tlist,add_list)
864 gwlarson 3.1 SM *sm;
865     int id;
866 gwlarson 3.8 LIST *tlist,*add_list;
867 gwlarson 3.1 {
868     TRI *t,*t_opp;
869 gwlarson 3.9 FVECT p,p0,p1,p2;
870 gwlarson 3.3 int e,e1,swapped = 0;
871 gwlarson 3.1 int t_id,t_opp_id;
872 gwlarson 3.12 LIST *del_list=NULL,*lptr;
873 gwlarson 3.3
874     VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
875 gwlarson 3.1 while(tlist)
876     {
877 gwlarson 3.3 t_id = pop_list(&tlist);
878 gwlarson 3.9 #ifdef DEBUG
879     if(t_id==INVALID || t_id > smMesh->num_tri)
880     error(CONSISTENCY,"Invalid tri id smFix_tris()\n");
881     #endif
882 gwlarson 3.1 t = SM_NTH_TRI(sm,t_id);
883 gwlarson 3.9 e = T_WHICH_V(t,id);
884 gwlarson 3.1 t_opp_id = T_NTH_NBR(t,e);
885 gwlarson 3.9 #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 gwlarson 3.10 #ifdef DEBUG
891     if(!T_IS_VALID(t_opp))
892     error(CONSISTENCY,"Invalid trismFix_tris()\n");
893     #endif
894 gwlarson 3.9 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 gwlarson 3.1 {
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 gwlarson 3.3 smTris_swap_edge(sm,t_id,t_opp_id,e,e1,&t_id,&t_opp_id,
904 gwlarson 3.10 &add_list);
905 gwlarson 3.1 tlist = push_data(tlist,t_id);
906     tlist = push_data(tlist,t_opp_id);
907     }
908     }
909 gwlarson 3.12
910 gwlarson 3.10 smUpdate_locator(sm,add_list);
911    
912 gwlarson 3.1 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 gwlarson 3.10 int which;
925 gwlarson 3.8 int nbr_id;
926 gwlarson 3.10
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 gwlarson 3.1
932 gwlarson 3.10 nbr_id = T_NTH_NBR(t,(which + 1)% 3);
933 gwlarson 3.8 return(nbr_id);
934 gwlarson 3.1 }
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 gwlarson 3.8 SM_CLR_NTH_T_FLAG(sm,id,i);
944 gwlarson 3.1
945     }
946    
947     /* Locate the point-id in the point location structure: */
948     int
949 gwlarson 3.10 smInsert_samp(sm,s_id,tri_id,on,which)
950 gwlarson 3.1 SM *sm;
951     int s_id,tri_id;
952 gwlarson 3.10 int on,which;
953 gwlarson 3.1 {
954 gwlarson 3.10 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 gwlarson 3.7 LIST *tlist,*add_list;
958 gwlarson 3.1 FVECT npt;
959 gwlarson 3.10 TRI *tri,*nbr,*topp;
960 gwlarson 3.1
961 gwlarson 3.7 add_list = NULL;
962 gwlarson 3.10 for(i=0; i<3;i++)
963     v_id[i] = T_NTH_V(SM_NTH_TRI(sm,tri_id),i);
964 gwlarson 3.1
965 gwlarson 3.10 /* 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 gwlarson 3.8
999 gwlarson 3.10 /* 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 gwlarson 3.3
1013 gwlarson 3.10 /* 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 gwlarson 3.6
1042 gwlarson 3.10 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 gwlarson 3.3
1049 gwlarson 3.10 /* 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 gwlarson 3.1
1062 gwlarson 3.10 /* 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 gwlarson 3.6
1070 gwlarson 3.10 tlist = push_data(NULL,t0_id);
1071     tlist = push_data(tlist,t1_id);
1072     tlist = push_data(tlist,t2_id);
1073     }
1074 gwlarson 3.1 /* Fix up the new triangles*/
1075 gwlarson 3.10 smFix_tris(sm,s_id,tlist,add_list);
1076 gwlarson 3.1
1077 gwlarson 3.10 smDelete_tri(sm,tri_id);
1078     if(on==ON_E)
1079     smDelete_tri(sm,topp_id);
1080 gwlarson 3.1
1081 gwlarson 3.8 return(TRUE);
1082 gwlarson 3.1
1083 gwlarson 3.10 #ifdef DEBUG
1084     Ladderror:
1085     error(CONSISTENCY,"Invalid tri: smInsert_samp()\n");
1086     #endif
1087     }
1088    
1089 gwlarson 3.1 int
1090 gwlarson 3.10 smTri_in_set(sm,p,optr,onptr,whichptr)
1091 gwlarson 3.1 SM *sm;
1092 gwlarson 3.8 FVECT p;
1093     OBJECT *optr;
1094 gwlarson 3.10 int *onptr,*whichptr;
1095 gwlarson 3.1 {
1096 gwlarson 3.10 int i,t_id,on0,on1,on2;
1097 gwlarson 3.8 FVECT n,v0,v1,v2;
1098     TRI *t;
1099 gwlarson 3.10 double side;
1100    
1101 gwlarson 3.8 for (i = QT_SET_CNT(optr),optr = QT_SET_PTR(optr);i > 0; i--)
1102 gwlarson 3.1 {
1103 gwlarson 3.8 /* 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 gwlarson 3.10 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 gwlarson 3.8
1131 gwlarson 3.10 on0 = on1 =on2 = 0;
1132 gwlarson 3.9 VCROSS(n,v0,v1);
1133 gwlarson 3.10 side = DOT(n,p);
1134     if(ZERO(side))
1135     on2 = TRUE;
1136     else
1137     if(side >0.0)
1138     continue;
1139    
1140 gwlarson 3.9 VCROSS(n,v1,v2);
1141 gwlarson 3.10 side = DOT(n,p);
1142     if(ZERO(side))
1143     on0 = TRUE;
1144     else
1145     if(side >0.0)
1146     continue;
1147 gwlarson 3.8
1148 gwlarson 3.9 VCROSS(n,v2,v0);
1149 gwlarson 3.10 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 gwlarson 3.8 return(t_id);
1197 gwlarson 3.1 }
1198 gwlarson 3.8 return(INVALID);
1199 gwlarson 3.1 }
1200    
1201 gwlarson 3.8 int
1202 gwlarson 3.10 smPointLocateTri(sm,p,onptr,whichptr)
1203 gwlarson 3.1 SM *sm;
1204 gwlarson 3.9 FVECT p;
1205 gwlarson 3.10 int *onptr,*whichptr;
1206 gwlarson 3.1 {
1207 gwlarson 3.9 QUADTREE qt,*optr;
1208 gwlarson 3.8 FVECT tpt;
1209 gwlarson 3.10 int tri_id;
1210 gwlarson 3.9
1211     VSUB(tpt,p,SM_VIEW_CENTER(sm));
1212 gwlarson 3.8 qt = smPointLocateCell(sm,tpt);
1213     if(QT_IS_EMPTY(qt))
1214     return(INVALID);
1215    
1216     optr = qtqueryset(qt);
1217 gwlarson 3.10 tri_id = smTri_in_set(sm,tpt,optr,onptr,whichptr);
1218    
1219     return(tri_id);
1220 gwlarson 3.8 }
1221 gwlarson 3.1
1222 gwlarson 3.8
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 gwlarson 3.10 1) If the new sample is close in ws, and close in the spherical projection
1241 gwlarson 3.8 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 gwlarson 3.10 2) If the spherical projection of new is < REPLACE_EPS from a base point:
1246 gwlarson 3.8 add new and mark the base for deletion: return TRUE
1247 gwlarson 3.10 3) If the addition of the new sample point would introduce a "puncture"
1248 gwlarson 3.8 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 gwlarson 3.10 smTest_sample(sm,tri_id,dir,p,rptr)
1253 gwlarson 3.8 SM *sm;
1254 gwlarson 3.9 int tri_id;
1255     FVECT dir,p;
1256 gwlarson 3.8 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 gwlarson 3.12 if(SM_BASE_ID(sm,vid[i]))
1273     bcnt++;
1274     if(SM_DIR_ID(sm,vid[i]))
1275     dcnt++;
1276    
1277 gwlarson 3.8 }
1278 gwlarson 3.10 /* TEST 1: If the new sample is close in ws, and close in the spherical
1279 gwlarson 3.8 projection to one of the triangle vertex samples
1280     */
1281 gwlarson 3.12 #if 0
1282 gwlarson 3.8 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 gwlarson 3.12 if(dnear <= SM_MIN_SAMP_DIFF*SM_MIN_SAMP_DIFF)
1297 gwlarson 3.8 {
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 gwlarson 3.12 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 gwlarson 3.8 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 gwlarson 3.9 d2 = 2. - 2.*DOT(dir,spt);
1319 gwlarson 3.8 /* The existing sample is a better sample:punt */
1320 gwlarson 3.12 if(d2 > d)
1321 gwlarson 3.8 return(FALSE);
1322 gwlarson 3.12 else
1323     {
1324     /* The new sample is better: mark the existing one
1325 gwlarson 3.8 for deletion after the new one is added*/
1326 gwlarson 3.12 *rptr = nearid;
1327     return(TRUE);
1328 gwlarson 3.8 }
1329 gwlarson 3.12 }
1330    
1331 gwlarson 3.8 /* TEST 3: If the spherical projection of new is < S_REPLACE_EPS
1332 gwlarson 3.10 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 gwlarson 3.8 */
1336 gwlarson 3.12
1337 gwlarson 3.8 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 gwlarson 3.12 if(dnear <= SM_MIN_SAMP_DIFF*SM_MIN_SAMP_DIFF && d< near)
1350 gwlarson 3.8 {
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 gwlarson 3.12 #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 gwlarson 3.8
1373 gwlarson 3.12 VSUB(npt,SM_NTH_WV(sm,vid[i]),SM_VIEW_CENTER(sm));
1374    
1375 gwlarson 3.13 if(!SM_BASE_ID(sm,vid[i]) && !SM_DIR_ID(sm,vid[i]))
1376 gwlarson 3.12 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 gwlarson 3.8 /* 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 gwlarson 3.12
1426 gwlarson 3.8 /* 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 gwlarson 3.12 VSUB(diff[0],SM_NTH_WV(sm,vid[0]),p);
1433 gwlarson 3.8 s0 = DOT(diff[0],diff[0]);
1434     if(s0 < S_REPLACE_SCALE*d01)
1435     return(TRUE);
1436 gwlarson 3.12
1437 gwlarson 3.8 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 gwlarson 3.12 VSUB(diff[1],SM_NTH_WV(sm,vid[1]),p);
1445     s1 = DOT(diff[1],diff[1]);
1446 gwlarson 3.8 if(s1 < S_REPLACE_SCALE*d)
1447     return(TRUE);
1448 gwlarson 3.12 VSUB(diff[2],SM_NTH_WV(sm,vid[2]),p);
1449 gwlarson 3.8 s2 = DOT(diff[2],diff[2]);
1450     if(s2 < S_REPLACE_SCALE*d)
1451     return(TRUE);
1452    
1453 gwlarson 3.9 /* 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 gwlarson 3.10
1462 gwlarson 3.8 return(FALSE);
1463     }
1464    
1465 gwlarson 3.13 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 gwlarson 3.8
1473 gwlarson 3.13 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 gwlarson 3.8 int
1503 gwlarson 3.10 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 gwlarson 3.13 int v_id,tri_id;
1510 gwlarson 3.10 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 gwlarson 3.13 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 gwlarson 3.10 return(s_id);
1521     }
1522 gwlarson 3.12 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 gwlarson 3.10 {
1530 gwlarson 3.13 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 gwlarson 3.12 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 gwlarson 3.13 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 gwlarson 3.12 tri_id = smTri_next_ccw_nbr(sm,t,v_id);
1548     }
1549 gwlarson 3.10 return(v_id);
1550     }
1551 gwlarson 3.12 /* on == ON_P */
1552     else
1553     {
1554     FVECT spt,npt;
1555     double d,d2;
1556 gwlarson 3.10
1557 gwlarson 3.12 /* Need to check which sample is preferable */
1558     VSUB(spt,p,SM_VIEW_CENTER(sm));
1559     normalize(spt);
1560 gwlarson 3.10
1561 gwlarson 3.12 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 gwlarson 3.10 /* The existing sample is a better sample:punt */
1566 gwlarson 3.12 if(d2 < d)
1567     {
1568     /* The new sample has better information- replace values */
1569 gwlarson 3.13 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 gwlarson 3.12 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 gwlarson 3.13 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 gwlarson 3.12 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 gwlarson 3.10 }
1595     }
1596    
1597 gwlarson 3.12 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 gwlarson 3.10 /* 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 gwlarson 3.9 smAdd_samp(sm,c,dir,p,o_id)
1637 gwlarson 3.1 SM *sm;
1638 gwlarson 3.9 COLR c;
1639     FVECT dir,p;
1640     int o_id;
1641 gwlarson 3.1 {
1642 gwlarson 3.10 int t_id,s_id,r_id,on,which,n_id;
1643 gwlarson 3.9 double d;
1644     FVECT wpt;
1645 gwlarson 3.8
1646 gwlarson 3.9 r_id = INVALID;
1647 gwlarson 3.10
1648     /* Must do this first-as may change mesh */
1649     s_id = smAlloc_samp(sm);
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 gwlarson 3.13 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 gwlarson 3.12 }
1672     if((!(smTest_sample(sm,t_id,dir,p,&r_id))))
1673     {
1674 gwlarson 3.10 smUnalloc_samp(sm,s_id);
1675 gwlarson 3.9 return(INVALID);
1676     }
1677 gwlarson 3.12 if(r_id != INVALID)
1678     {
1679     smRemoveVertex(sm,r_id);
1680     sDelete_samp(SM_SAMP(sm),r_id);
1681     }
1682     else
1683     break;
1684 gwlarson 3.9 }
1685 gwlarson 3.10 /* If sample is being added in the middle of the sample array: tone
1686     map individually
1687     */
1688     /* Initialize sample */
1689 gwlarson 3.13 sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id);
1690 gwlarson 3.10
1691 gwlarson 3.9 }
1692     /* If sample is a direction vector */
1693     else
1694     {
1695 gwlarson 3.10 VADD(wpt,dir,SM_VIEW_CENTER(sm));
1696 gwlarson 3.12 while(1)
1697 gwlarson 3.13 {
1698     t_id = smPointLocateTri(sm,wpt,&on,&which);
1699     if(t_id == INVALID)
1700     {
1701 gwlarson 3.1 #ifdef DEBUG
1702 gwlarson 3.13 eputs("smAddSamp(): can'tlocate tri containing samp\n");
1703 gwlarson 3.1 #endif
1704 gwlarson 3.13 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 gwlarson 3.9 }
1727     /* Allocate space for a sample and initialize */
1728 gwlarson 3.13 sInit_samp(SM_SAMP(sm),s_id,c,NULL,wpt,o_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 gwlarson 3.13
1863 gwlarson 3.1 int
1864     smNext_valid_tri(sm,i)
1865     SM *sm;
1866     int i;
1867     {
1868    
1869 gwlarson 3.8 while( i < SM_NUM_TRI(sm) && !T_IS_VALID(SM_NTH_TRI(sm,i)))
1870 gwlarson 3.1 i++;
1871    
1872     return(i);
1873     }
1874    
1875    
1876    
1877 gwlarson 3.8 qtTri_from_id(t_id,v0,v1,v2)
1878 gwlarson 3.1 int t_id;
1879     FVECT v0,v1,v2;
1880     {
1881     TRI *t;
1882    
1883     t = SM_NTH_TRI(smMesh,t_id);
1884 gwlarson 3.8 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 gwlarson 3.1 }
1891    
1892    
1893 gwlarson 3.8 smRebuild_mesh(sm,v)
1894 gwlarson 3.1 SM *sm;
1895 gwlarson 3.8 VIEW *v;
1896 gwlarson 3.1 {
1897 gwlarson 3.8 int i,j,cnt;
1898     FVECT p,ov,dir;
1899     double d;
1900 gwlarson 3.1
1901 gwlarson 3.8 #ifdef DEBUG
1902 gwlarson 3.10 fprintf(stderr,"smRebuild_mesh(): rebuilding....");
1903 gwlarson 3.8 #endif
1904 gwlarson 3.1 /* Clear the mesh- and rebuild using the current sample array */
1905 gwlarson 3.8 /* 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 gwlarson 3.9 VCOPY(ov,SM_VIEW_CENTER(sm));
1910 gwlarson 3.8 /* Initialize the mesh to 0 samples and the base triangles */
1911 gwlarson 3.1
1912 gwlarson 3.8 /* 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 gwlarson 3.9 smInit_sm(sm,v->vp);
1916 gwlarson 3.8 for(i=0; i < cnt; i++)
1917 gwlarson 3.1 {
1918 gwlarson 3.8 /* 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 gwlarson 3.9 decodedir(dir,SM_NTH_W_DIR(sm,i));
1929     d = 2. - 2.*DOT(dir,p);
1930 gwlarson 3.8 if (d > MAXDIFF2)
1931     continue;
1932 gwlarson 3.9 VCOPY(p,SM_NTH_WV(sm,i));
1933     smAdd_samp(sm,NULL,dir,p,i);
1934 gwlarson 3.8 }
1935 gwlarson 3.9 else
1936     {
1937     VSUB(dir,SM_NTH_WV(sm,i),ov);
1938 gwlarson 3.10 VADD(SM_NTH_WV(sm,i),dir,SM_VIEW_CENTER(sm));
1939 gwlarson 3.9 smAdd_samp(sm,NULL,dir,NULL,i);
1940     }
1941    
1942 gwlarson 3.1 }
1943 gwlarson 3.8 #ifdef DEBUG
1944 gwlarson 3.10 fprintf(stderr,"smRebuild_mesh():done\n");
1945 gwlarson 3.8 #endif
1946 gwlarson 3.1 }
1947 gwlarson 3.5
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 gwlarson 3.10 int i,t_id,id,base;
1955 gwlarson 3.5 int pid0,pid1,pid2;
1956     FVECT p0,p1,p2,p;
1957     TRI *t;
1958 gwlarson 3.10 double d,d1;
1959 gwlarson 3.5
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 gwlarson 3.8 if(!T_IS_VALID(t))
1966     continue;
1967 gwlarson 3.5 pid0 = T_NTH_V(t,0);
1968     pid1 = T_NTH_V(t,1);
1969     pid2 = T_NTH_V(t,2);
1970 gwlarson 3.10 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 gwlarson 3.5 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 gwlarson 3.10 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 gwlarson 3.5 if(pt)
2041 gwlarson 3.10 VCOPY(pt,p);
2042     #ifdef TEST_DRIVER
2043 gwlarson 3.5 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 gwlarson 3.8 /* OS is constrained to be <= QT_MAXCSET : if the set exceeds this, the
2054     results of check_set are conservative
2055     */
2056 gwlarson 3.10 int
2057     compare_ids(id1,id2)
2058     OBJECT *id1,*id2;
2059     {
2060     int d;
2061 gwlarson 3.8
2062 gwlarson 3.10 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 gwlarson 3.8 int *fptr;
2076 gwlarson 3.5 {
2077 gwlarson 3.8 OBJECT tset[QT_MAXSET+1],*tptr;
2078 gwlarson 3.5 double dt,t;
2079     int found;
2080 gwlarson 3.10 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 gwlarson 3.5
2101 gwlarson 3.10 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 gwlarson 3.8 return;
2111 gwlarson 3.10 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 gwlarson 3.8 memerr:
2121     error(SYSTEM,"ray_trace_check_set():Unable to allocate memory");
2122 gwlarson 3.5 }
2123    
2124 gwlarson 3.8
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 gwlarson 3.5 int
2134 gwlarson 3.6 smFindSamp(orig,dir)
2135 gwlarson 3.5 FVECT orig,dir;
2136     {
2137     FVECT b,p,o;
2138     OBJECT *ts;
2139     QUADTREE qt;
2140 gwlarson 3.10 int s_id,test;
2141 gwlarson 3.5 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 gwlarson 3.9 #ifdef TEST_DRIVER
2162     Picking= TRUE;
2163     #endif
2164 gwlarson 3.10
2165     if(EQUAL_VEC3(orig,SM_VIEW_CENTER(smMesh)))
2166 gwlarson 3.5 {
2167 gwlarson 3.10 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 gwlarson 3.8 #ifdef DEBUG
2176 gwlarson 3.10 fprintf(stderr,"Simple pick returning %d\n",s_id);
2177 gwlarson 3.8 #endif
2178 gwlarson 3.10
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 gwlarson 3.5 #ifdef DEBUG_TEST_DRIVER
2190 gwlarson 3.10 VCOPY(Pick_point[0],p);
2191 gwlarson 3.5 #endif
2192 gwlarson 3.10 #ifdef DEBUG
2193     fprintf(stderr,"Simple pick2 returning %d\n",s_id);
2194     #endif
2195     return(s_id);
2196 gwlarson 3.5 }
2197 gwlarson 3.10 if(OPP_EQUAL_VEC3(b,dir))
2198 gwlarson 3.5 {
2199 gwlarson 3.10 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 gwlarson 3.8 OBJECT t_set[QT_MAXCSET + 1];
2229     RT_ARGS rt;
2230 gwlarson 3.10 FUNC func;
2231 gwlarson 3.8
2232 gwlarson 3.5 /* 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 gwlarson 3.8 rt.t_id = -1;
2237     rt.os = t_set;
2238     VCOPY(rt.orig,orig);
2239     VCOPY(rt.dir,dir);
2240 gwlarson 3.10 F_FUNC(func) = ray_trace_check_set;
2241     F_ARGS(func) = (int *)(&rt);
2242     stTrace_ray(SM_LOCATOR(smMesh),o,dir,func);
2243 gwlarson 3.8 s_id = rt.t_id;
2244 gwlarson 3.10 }
2245     #ifdef DEBUG
2246     fprintf(stderr,"Trace pick returning %d\n",s_id);
2247     #endif
2248 gwlarson 3.5 return(s_id);
2249 gwlarson 3.10
2250     Lerror:
2251     #ifdef DEBUG
2252     eputs("smFindSamp(): point not found");
2253     #endif
2254     return(INVALID);
2255    
2256 gwlarson 3.5 }
2257    
2258 gwlarson 3.10
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 gwlarson 3.12 if(!T_IS_VALID(tri))
2280 gwlarson 3.10 continue;
2281     SM_SET_NTH_T_ACTIVE(smMesh,t_id);
2282     /* Set the Active bits of the Vertices */
2283 gwlarson 3.13 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 gwlarson 3.12 }
2287 gwlarson 3.10 }
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 gwlarson 3.5
2414    
2415    
2416    
2417    
2418    
2419    
2420    
2421 gwlarson 3.1
2422