1 #include "pch.h"
2 #include "../ogre/common/Def_Str.h"
3 #include "../ogre/common/Gui_Def.h"
4 #include "settings.h"
5 #include "CGui.h"
6 #include "CApp.h"
7 #include "../ogre/common/GuiCom.h"
8 #include "../ogre/common/CScene.h"
9 #include "../ogre/common/data/CData.h"
10 #include "../road/Road.h"
11 #include "../ogre/common/Slider.h"
12 #include "../ogre/common/MultiList2.h"
13 #include "../vdrift/pathmanager.h"
14 #include <fstream>
15 #include <MyGUI.h>
16 #include <OgreRenderTexture.h>
17 #include "../shiny/Main/Factory.hpp"
18 using namespace MyGUI;
19 using namespace Ogre;
20
21
22 /// [Terrain]
23 //-----------------------------------------------------------------------------------------------------------
24
25 /// Change terrain texture layer, update values
26 //
tabTerLayer(Tab wp,size_t id)27 void CGui::tabTerLayer(Tab wp, size_t id)
28 {
29 idTerLay = id; // help var
30 TerLayer* l = &sc->td.layersAll[idTerLay];
31
32 noBlendUpd = true;
33 SldUpd_TerL();
34
35 // tex
36 String s = l->texFile.substr(0, l->texFile.length()-6);
37 btnTexDiff->setCaption(s); // no _d.jpg
38 cmbTexNorm->setIndexSelected( cmbTexNorm->findItemIndexWith(l->texNorm) );
39
40 for (int i=0; i < liTex->getItemCount(); ++i) /// upd pick
41 if (liTex->getSubItemNameAt(1,i).substr(7) == s)
42 liTex->setIndexSelected(i);
43
44 // auto norm check
45 String sTex,sNorm, sExt;
46 StringUtil::splitBaseFilename(l->texFile,sTex,sExt);
47 StringUtil::splitBaseFilename(l->texNorm,sNorm,sExt);
48
49 String sTexN = StringUtil::replaceAll(sTex,"_d","_n");
50 bool bAuto = sTexN == sNorm; //_T
51 bTexNormAuto = bAuto;
52 ckTexNormAuto.Upd();
53
54 // image
55 imgTexDiff->setImageTexture(l->texFile);
56
57 updUsedTer();
58 SldUpd_TerLNvis();
59
60 noBlendUpd = false;
61 }
62
SldUpd_TerLNvis()63 void CGui::SldUpd_TerLNvis()
64 {
65 // upd vis of layer noise sliders
66 // check for valid +1,-1,+2 layers
67 int ll = sc->td.layers.size();
68 int l1 = -1, last = 8, last_2 = 8, nu = 0, ncl = 0;
69 for (int i=0; i < TerData::ciNumLay; ++i)
70 if (sc->td.layersAll[i].on)
71 { ++nu;
72 if (i==idTerLay) ncl = nu;
73 if (nu==1) l1 = i;
74 if (nu==ll) last = i;
75 if (nu==ll-2) last_2 = i;
76 }
77 bool ok = idTerLay >= l1 && idTerLay <= last;
78 svTerLNoise.setVisible(ok && idTerLay < last);
79 svTerLNprev.setVisible(ok && idTerLay > l1);
80 svTerLNnext2.setVisible(ok && idTerLay <= last_2 && nu > 2);
81 // dbg img clr
82 const static Colour lc[5] = {Colour::Black, Colour::Red, Colour::Green, Colour::Blue, Colour(0.5,0.5,0.5)};
83 dbgLclr->setColour(lc[ncl]);
84 }
85
SldUpd_TerL()86 void CGui::SldUpd_TerL()
87 {
88 TerLayer* l = &sc->td.layersAll[idTerLay];
89 ckTerLayOn.Upd(&l->on);
90 svTerLScale.UpdF(&l->tiling);
91 ckTerLayTripl.Upd(&l->triplanar);
92 // blmap
93 svTerLAngMin.UpdF(&l->angMin); svTerLHMin.UpdF(&l->hMin);
94 svTerLAngMax.UpdF(&l->angMax); svTerLHMax.UpdF(&l->hMax);
95 svTerLAngSm.UpdF(&l->angSm); svTerLHSm.UpdF(&l->hSm);
96 ckTerLNOnly.Upd(&l->nOnly);
97 // noise
98 svTerLNoise.UpdF(&l->noise); svTerLNprev.UpdF(&l->nprev);
99 svTerLNnext2.UpdF(&l->nnext2);
100 svTerLDmg.UpdF(&l->fDamage);
101 // noise params
102 for (int i=0; i<2; ++i)
103 { svTerLN_Freq[i].UpdF(&l->nFreq[i]);
104 svTerLN_Oct[i].UpdI(&l->nOct[i]);
105 svTerLN_Pers[i].UpdF(&l->nPers[i]);
106 svTerLN_Pow[i].UpdF(&l->nPow[i]);
107 }
108 }
109
110 // Tri size
slTerTriSize(SV * sv)111 void CGui::slTerTriSize(SV* sv)
112 {
113 sc->td.UpdVals();
114 UpdTxtTerSize();
115 }
116
UpdTxtTerSize(float mul)117 int CGui::UpdTxtTerSize(float mul)
118 {
119 int size = getHMapSizeTab() * mul;
120 float res = sc->td.fTriangleSize * size; // result size
121 svTerTriSize.setText(fToStr(res,0,3));
122 return size;
123 }
124
125 // HMap size tab
updTabHmap()126 void CGui::updTabHmap()
127 {
128 static std::map<int,int> h;
129 if (h.empty()) { h[128]=0; h[256]=1; h[512]=2; h[1024]=3; h[2048]=4; }
130 tabsHmap->setIndexSelected( h[ sc->td.iTerSize- 1] );
131 tabHmap(0,0);
132 }
getHMapSizeTab()133 int CGui::getHMapSizeTab()
134 {
135 static std::map<int,int> h;
136 if (h.empty()) { h[0]=128; h[1]=256; h[2]=512; h[3]=1024; h[4]=2048; }
137 return h[ tabsHmap->getIndexSelected() ];
138 }
tabHmap(Tab,size_t)139 void CGui::tabHmap(Tab, size_t)
140 {
141 UpdTxtTerSize();
142 }
143
slTerErrorNorm(SV * sv)144 void CGui::slTerErrorNorm(SV*sv)
145 {
146 scn->UpdTerErr();
147 }
148
149 // upd ter sh par
slTerPar(SV * sv)150 void CGui::slTerPar(SV*sv)
151 {
152 app->mFactory->setSharedParameter("ter_scaleNormal", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(1.f / sc->td.normScale)));
153 app->mFactory->setSharedParameter("ter_specular_pow", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(sc->td.specularPow)));
154 app->mFactory->setSharedParameter("ter_specular_pow_em", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(sc->td.specularPowEm)));
155 }
156
157 // - - - - Hmap tools - - - -
getHMapNew()158 String CGui::getHMapNew()
159 {
160 return gcom->TrkDir() + "heightmap-new.f32";
161 }
162
163 //----------------------------------------------------------------------------------------------------------
btnTerrainNew(WP)164 void CGui::btnTerrainNew(WP)
165 {
166 int size = UpdTxtTerSize();
167 sc->td.iVertsX = size+1; sc->td.UpdVals(); // new hf
168
169 float* hfData = new float[sc->td.iVertsX * sc->td.iVertsY];
170 int siz = sc->td.iVertsX * sc->td.iVertsY * sizeof(float);
171
172 // generate Hmap
173 for (int j=0; j < sc->td.iVertsY; ++j)
174 {
175 int a = j * sc->td.iVertsX;
176 for (int i=0; i < sc->td.iVertsX; ++i,++a)
177 hfData[a] = 0.f; //sc->td.getHeight(i,j);
178 }
179 std::ofstream of;
180 of.open(getHMapNew().c_str(), std::ios_base::binary);
181 of.write((const char*)&hfData[0], siz);
182 of.close();
183
184 delete[] hfData;
185 app->bNewHmap = true; app->UpdateTrack();
186 }
187
188
189 // Terrain half --------------------------------
btnTerrainHalf(WP)190 void CGui::btnTerrainHalf(WP)
191 {
192 int halfSize = (sc->td.iVertsX-1) / 2 +1;
193 float* hfData = new float[halfSize * halfSize];
194 int siz = halfSize * halfSize * sizeof(float);
195
196 // resize Hmap by half
197 for (int j=0; j < halfSize; ++j)
198 {
199 int a = j * halfSize, a2 = j*2 * sc->td.iVertsX;
200 for (int i=0; i < halfSize; ++i,++a)
201 { hfData[a] = sc->td.hfHeight[a2]; a2+=2; }
202 }
203 std::ofstream of;
204 of.open(getHMapNew().c_str(), std::ios_base::binary);
205 of.write((const char*)&hfData[0], siz);
206 of.close();
207 delete[] hfData;
208
209 sc->td.fTriangleSize *= 2.f;
210 sc->td.iVertsX = halfSize; sc->td.UpdVals();
211 updTabHmap(); svTerTriSize.Upd();
212 app->bNewHmap = true; app->UpdateTrack();
213 }
214
215 // Terrain double --------------------------------
216 #if 1
btnTerrainDouble(WP)217 void CGui::btnTerrainDouble(WP)
218 {
219 int dblSize = (sc->td.iVertsX-1) * 2 +1;
220 float* hfData = new float[dblSize * dblSize];
221 int siz = dblSize * dblSize * sizeof(float);
222
223 // resize Hmap by half
224 for (int j=0; j < sc->td.iVertsX; ++j)
225 {
226 int a = (j +dblSize/4) * dblSize + dblSize/4, a2 = j * sc->td.iVertsX;
227 for (int i=0; i < sc->td.iVertsX; ++i,++a)
228 { hfData[a] = sc->td.hfHeight[a2]; ++a2; }
229 }
230 std::ofstream of;
231 of.open(getHMapNew().c_str(), std::ios_base::binary);
232 of.write((const char*)&hfData[0], siz);
233 of.close();
234 delete[] hfData;
235
236 sc->td.iVertsX = dblSize; sc->td.UpdVals();
237 updTabHmap();
238 app->bNewHmap = true; app->UpdateTrack();
239 }
240 #else
241 // Terrain resize .. --------------------------------
btnTerrainDouble(WP)242 void CGui::btnTerrainDouble(WP)
243 {
244 int size = getHMapSizeTab() / 2;
245 if (valTerTriSize){ valTerTriSize->setCaption(fToStr(sc->td.fTriangleSize * size,2,4)); }
246
247 int oldSize = sc->td.iVertsX, osi = oldSize*oldSize,
248 newSize = (oldSize-1) * 2 +1;
249 float scale = 1.f / 2.f / 2.f;
250 float* hfData = new float[si];
251 for (int i=0; i < si; ++i) hfData[i] = 0.f; // clear out
252
253 // resize
254 register int i,j,x,y,a;
255 for (j=0; j < newSize; ++j)
256 {
257 y = scale * j;
258 a = j * newSize;
259 for (i=0; i < newSize; ++i,++a)
260 {
261 x = y * oldSize + scale * i;
262 x = std::max(0, std::min(osi-1, x));
263 hfData[a] = sc->td.hfHeight[ x ];
264 }
265 }
266 std::ofstream of;
267 of.open(getHMapNew().c_str(), std::ios_base::binary);
268 of.write((const char*)&hfData[0], si * sizeof(float));
269 of.close();
270 delete[] hfData;
271
272 sc->td.fTriangleSize * scale * 2.f;
273 sc->td.iVertsX = newSize; sc->td.UpdVals();
274 updTabHmap(); svTerTriSize.Upd();
275 app->bNewHmap = true; app->UpdateTrack(); //SetGuiFromXmls();
276 }
277 #endif
278
279 // Terrain move --------------------------------
btnTerrainMove(WP)280 void CGui::btnTerrainMove(WP)
281 {
282 Ed ex = (Ed)app->mWndEdit->findWidget("TerMoveX");
283 Ed ey = (Ed)app->mWndEdit->findWidget("TerMoveY");
284 int mx = ex ? s2i(ex->getCaption()) : 0;
285 int my = ey ?-s2i(ey->getCaption()) : 0;
286
287 int newSize = sc->td.iVertsX, si = newSize * newSize;
288 float* hfData = new float[si];
289
290 // resize
291 register int i,j,a,aa;
292 for (j=0; j < newSize; ++j)
293 {
294 a = j * newSize;
295 for (i=0; i < newSize; ++i,++a)
296 {
297 aa = std::max(0, std::min(si-1, (j-mx) * newSize + i+my));
298 hfData[a] = sc->td.hfHeight[aa];
299 }
300 }
301 std::ofstream of;
302 of.open(getHMapNew().c_str(), std::ios_base::binary);
303 of.write((const char*)&hfData[0], si * sizeof(float));
304 of.close();
305 delete[] hfData;
306
307 app->scn->road->SelAll();
308 app->scn->road->Move(Vector3(my,0,mx) * -sc->td.fTriangleSize);
309 app->scn->road->SelClear();
310 //start, objects-
311
312 app->bNewHmap = true; app->UpdateTrack();
313 }
314
315 // Terrain height scale --------------------------------
btnScaleTerH(WP)316 void CGui::btnScaleTerH(WP)
317 {
318 if (!app->scn->road) return;
319 Real sf = std::max(0.1f, fScaleTer); // scale mul
320
321 // road
322 for (int i=0; i < app->scn->road->getNumPoints(); ++i)
323 app->scn->road->Scale1(i, 0.f, sf);
324 app->scn->road->bSelChng = true;
325
326 // fluids
327 for (int i=0; i < sc->fluids.size(); ++i)
328 {
329 FluidBox& fb = sc->fluids[i];
330 fb.pos.y *= sf; fb.size.y *= sf;
331 }
332
333 // objs h
334 for (int i=0; i < sc->objects.size(); ++i)
335 {
336 Object& o = sc->objects[i];
337 o.pos[2] *= sf;
338 o.SetFromBlt();
339 }
340
341 // ter ---
342 float* hfData = new float[sc->td.iVertsX * sc->td.iVertsY];
343 int siz = sc->td.iVertsX * sc->td.iVertsY * sizeof(float);
344
345 // generate Hmap
346 for (int j=0; j < sc->td.iVertsY; ++j)
347 {
348 int a = j * sc->td.iVertsX;
349 for (int i=0; i < sc->td.iVertsX; ++i,++a)
350 hfData[a] = sc->td.hfHeight[a] * sf;
351 }
352 std::ofstream of;
353 of.open(getHMapNew().c_str(), std::ios_base::binary);
354 of.write((const char*)&hfData[0], siz);
355 of.close();
356
357 delete[] hfData;
358 app->bNewHmap = true; app->UpdateTrack();
359
360 // road upd
361 if (0) //road) // doesnt work here..
362 { app->scn->road->UpdPointsH();
363 app->scn->road->Rebuild(true);
364 }
365
366 // start pos
367 app->scn->sc->startPos[2] *= sf; app->UpdStartPos();
368 }
369 //----------------------------------------------------------------------------------------------------------
370
371
372 // generator . . . . . . .
slTerGen(SV *)373 void CGui::slTerGen(SV*)
374 {
375 app->bUpdTerPrv = true;
376 }
377
378 // debug
chkDebugBlend(Ck *)379 void CGui::chkDebugBlend(Ck*)
380 {
381 app->mFactory->setGlobalSetting("debug_blend", b2s(bDebugBlend));
382 dbgLclr->setVisible(bDebugBlend);
383 }
384
385
386 /// Terrain layers -----------------------------
387 //
chkTerLayOn(Ck * ck)388 void CGui::chkTerLayOn(Ck* ck)
389 {
390 sc->td.UpdLayers();
391 if (sc->td.layers.size()==0) // would crash, surf
392 {
393 *ck->pBool = true; // turn it back on
394 ck->Upd();
395 }
396
397 sc->td.UpdLayers();
398 updUsedTer();
399
400 //todo.. !! save hmap if changed
401 app->UpdateTrack();
402
403 SldUpd_TerLNvis();
404 UpdSurfList();
405 }
406
updUsedTer()407 void CGui::updUsedTer()
408 {
409 SetUsedStr(valTerLAll, sc->td.layers.size(), 3);
410 int t = sc->td.triplCnt;
411 valTriplAll->setCaption(TR("#{Used}") + ": " + toStr(t));
412 valTriplAll->setTextColour(sUsedClr[ t > 2 ? 6 : (t + 2)]);
413 }
414
chkTerLayTripl(Ck *)415 void CGui::chkTerLayTripl(Ck*)
416 {
417 sc->td.UpdLayers();
418 updUsedTer();
419 }
420
comboTexNorm(Cmb cmb,size_t val)421 void CGui::comboTexNorm(Cmb cmb, size_t val)
422 {
423 String s = cmb->getItemNameAt(val);
424 sc->td.layersAll[idTerLay].texNorm = s;
425 }
426
427 // Terrain BlendMap
slTerLay(SV *)428 void CGui::slTerLay(SV*)
429 {
430 //app->bTerUpdBlend = true;
431 scn->UpdLayerPars();
432 if (scn->angleRTT.rnd) scn->angleRTT.rnd->update();
433 if (scn->blendRTT.rnd) scn->blendRTT.rnd->update();
434 }
chkTerLNOnly(Ck *)435 void CGui::chkTerLNOnly(Ck*)
436 {
437 slTerLay(0);
438 }
439
440 // move layer order
btnTerLmoveL(WP)441 void CGui::btnTerLmoveL(WP) // -1
442 {
443 if (idTerLay <= 0) return;
444
445 TerLayer& t = sc->td.layersAll[idTerLay], st,
446 &t1 = sc->td.layersAll[idTerLay-1];
447 st = t; t = t1; t1 = st;
448
449 sc->td.UpdLayers(); NumTabNext(-1);
450 app->scn->UpdBlendmap();
451 }
452
btnTerLmoveR(WP)453 void CGui::btnTerLmoveR(WP) // +1
454 {
455 if (idTerLay >= TerData::ciNumLay-1) return;
456
457 TerLayer& t = sc->td.layersAll[idTerLay], st,
458 &t1 = sc->td.layersAll[idTerLay+1];
459 st = t; t = t1; t1 = st;
460
461 sc->td.UpdLayers(); NumTabNext(1);
462 app->scn->UpdBlendmap();
463 }
464
465 /// Noise preset buttons
radN1(WP)466 void CGui::radN1(WP) { Radio2(bRn1, bRn2, bRn2->getStateSelected()); }
radN2(WP)467 void CGui::radN2(WP) { Radio2(bRn1, bRn2, bRn2->getStateSelected()); }
468
469 const static float ns[15][4] = { // freq, oct, pers, pow
470 { 30.4f, 3, 0.33f, 1.5f },{ 36.6f, 4, 0.49f, 1.9f },{ 30.7f, 3, 0.30f, 1.5f },{ 29.5f, 2, 0.13f, 1.8f },{ 40.5f, 3, 0.43f, 2.0f },
471 { 25.3f, 3, 0.30f, 1.2f },{ 31.3f, 5, 0.70f, 2.0f },{ 28.4f, 4, 0.70f, 1.5f },{ 34.5f, 4, 0.40f, 0.9f },{ 34.3f, 4, 0.54f, 1.0f },
472 { 44.6f, 2, 0.30f, 1.1f },{ 48.2f, 3, 0.12f, 1.6f },{ 56.6f, 4, 0.49f, 2.0f },{ 60.4f, 4, 0.51f, 2.0f },{ 62.6f, 3, 0.12f, 2.1f }};
473
btnNpreset(WP wp)474 void CGui::btnNpreset(WP wp)
475 {
476 int l = bRn2->getStateSelected() ? 1 : 0;
477 String s = wp->getName(); //"TerLN_"
478 int i = s2i(s.substr(6));
479
480 TerLayer& t = sc->td.layersAll[idTerLay];
481 t.nFreq[l] = ns[i][0];
482 t.nOct[l] = int(ns[i][1]);
483 t.nPers[l] = ns[i][2];
484 t.nPow[l] = ns[i][3];
485 SldUpd_TerL();
486 app->scn->UpdBlendmap();
487 }
btnNrandom(WP wp)488 void CGui::btnNrandom(WP wp)
489 {
490 int l = bRn2->getStateSelected() ? 1 : 0;
491
492 TerLayer& t = sc->td.layersAll[idTerLay];
493 t.nFreq[l] = Math::RangeRandom(20.f,70.f);
494 t.nOct[l] = Math::RangeRandom(2.f,5.f);
495 t.nPers[l] = Math::RangeRandom(0.1f,0.7f);
496 t.nPow[l] = Math::RangeRandom(0.8f,2.4f);
497 SldUpd_TerL();
498 app->scn->UpdBlendmap();
499 }
500
501 // swap noise 1 and 2 params
btnNswap(WP wp)502 void CGui::btnNswap(WP wp)
503 {
504 TerLayer& t = sc->td.layersAll[idTerLay];
505 std::swap(t.nFreq[0], t.nFreq[1]);
506 std::swap(t.nOct[0] , t.nOct[1] );
507 std::swap(t.nPers[0], t.nPers[1]);
508 std::swap(t.nPow[0] , t.nPow[1] );
509 SldUpd_TerL();
510 app->scn->UpdBlendmap();
511 }
512
513
514 /// Terrain Particles -----------------------------
515 //
comboParDust(Cmb cmb,size_t val)516 void CGui::comboParDust(Cmb cmb, size_t val) // par type
517 {
518 String s = cmb->getItemNameAt(val);
519 String n = cmb->getName();
520
521 if (n=="CmbParDust") sc->sParDust = s;
522 else if (n=="CmbParMud") sc->sParMud = s;
523 else if (n=="CmbParSmoke") sc->sParSmoke = s;
524 }
525
526
527 /// Terrain Surface -----------------------------
528 //
comboSurface(Cmb cmb,size_t val)529 void CGui::comboSurface(Cmb cmb, size_t val)
530 {
531 TerLayer* l = GetTerRdLay();
532 //std::string s = cmb->getItemNameAt(val);
533 std::string s = cmbSurface->getCaption();
534 LogO("SURF cmb = "+s);
535 l->surfName = s;
536 UpdSurfInfo();
537 }
538
UpdSurfInfo()539 void CGui::UpdSurfInfo()
540 {
541 TerLayer* l = GetTerRdLay();
542 int id = app->surf_map[l->surfName]-1;
543 if (id == -1) return; //not found..
544 const TRACKSURFACE& su = app->surfaces[id];
545
546 txtSurfTire->setCaption(su.tireName);
547 txtSuBumpWave->setCaption(fToStr(su.bumpWaveLength, 1,3));
548 txtSuBumpAmp->setCaption(fToStr(su.bumpAmplitude, 2,4));
549 txtSuRollDrag->setCaption(fToStr(su.rollingDrag, 1,3));
550 txtSuFrict->setCaption(fToStr(su.friction, 2,4));
551 txtSurfType->setCaption(csTRKsurf[su.type]);
552 }
553
554
555 /// Surfaces all in data/cars/surfaces.cfg
556 //------------------------------------------------------------------------------------------------------------------------------
LoadAllSurfaces()557 bool App::LoadAllSurfaces()
558 {
559 surfaces.clear();
560 surf_map.clear();
561
562 std::string path = PATHMANAGER::CarSim() + "/normal/surfaces.cfg";
563 CONFIGFILE param;
564 if (!param.Load(path))
565 {
566 LogO("Can't find surfaces configfile: " + path);
567 return false;
568 }
569
570 std::list <std::string> sectionlist;
571 param.GetSectionList(sectionlist);
572
573 for (std::list<std::string>::const_iterator section = sectionlist.begin(); section != sectionlist.end(); ++section)
574 {
575 TRACKSURFACE surf;
576 surf.name = *section;
577
578 int id;
579 param.GetParam(*section + ".ID", id); // for sound..
580 //-assert(indexnum >= 0 && indexnum < (int)tracksurfaces.size());
581 surf.setType(id);
582
583 float temp = 0.0;
584 param.GetParam(*section + ".BumpWaveLength", temp); surf.bumpWaveLength = temp;
585 param.GetParam(*section + ".BumpAmplitude", temp); surf.bumpAmplitude = temp;
586
587 //frictionX, frictionY, bumpWaveLength2, bumpAmplitude2, not shown ..
588 param.GetParam(*section + ".FrictionTread", temp); surf.friction = temp;
589
590 if (param.GetParam(*section + ".RollResistance", temp)) surf.rollingResist = temp;
591 param.GetParam(*section + ".RollingDrag", temp); surf.rollingDrag = temp;
592
593 ///--- Tire ---
594 std::string tireFile;
595 if (!param.GetParam(*section + "." + "Tire", tireFile))
596 tireFile = "Default"; // default surface if not found
597 surf.tireName = tireFile;
598 ///---
599
600 surfaces.push_back(surf);
601 surf_map[surf.name] = (int)surfaces.size(); //+1, 0 = not found
602 }
603
604 return true;
605 }
606