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

File Contents

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