1 #include "pch.h"
2 #include "../Def_Str.h"
3 #include "SceneXml.h"
4 #include "FluidsXml.h"
5 #include "tinyxml.h"
6 #include "tinyxml2.h"
7 #include <OgreSceneNode.h>
8 #include "../vdrift/game.h"  // for surfaces map
9 using namespace std;
10 using namespace Ogre;
11 using namespace tinyxml2;
12 
13 
14 //  old
LoadStartPos(String file)15 bool Scene::LoadStartPos(String file)
16 {
17 	CONFIGFILE param;
18 	if (!param.Load(file))
19 		return false;
20 
21 	float f3[3], f1;
22 	QUATERNION <float> fixer;  fixer.Rotate(3.141593, 0,0,1);
23 
24 	param.GetParam("start position 0", f3);
25 	MATHVECTOR <float, 3> pos(f3[2], f3[0], f3[1]);
26 
27 	if (!param.GetParam("start orientation-xyz 0", f3))
28 		return false;
29 
30 	if (!param.GetParam("start orientation-w 0", f1))
31 		return false;
32 
33 	QUATERNION <float> rot(f3[2], f3[0], f3[1], f1);
34 	rot = fixer * rot;
35 
36 	startPos = pos;
37 	startRot = rot;
38 	return true;
39 }
40 
41 
42 ///  Color  . . . . . . . .
SColor()43 SColor::SColor()
44 	:h(0.f), s(0.f), v(0.f), a(0.f), n(0.f)
45 {	}
SColor(float h1,float s1,float v1,float a1,float n1)46 SColor::SColor(float h1, float s1, float v1, float a1, float n1)
47 	:h(h1), s(s1), v(v1), a(a1), n(n1)
48 {	}
49 
50 //  tool check err
Check(string t)51 string SColor::Check(string t)
52 {
53 	string e;
54 	if (h > 1.f)  e += " h>1";  if (h < 0.f)  e += " h<0";
55 	if (s > 1.f)  e += " s>1";  if (s < 0.f)  e += " s<0";
56 	if (v > 3.f)  e += " v>3";  if (v < 0.f)  e += " v<0";
57 	if (a > 2.f)  e += " a>2";  if (a < 0.f)  e += " a<0";
58 	if (n > 1.f)  e += " n>1";  if (n < 0.f)  e += " n<0";
59 	if (!e.empty())  e += "  " + t + "  " + Save();
60 	return e;
61 }
62 
63 //  load from old rgb
LoadRGB(Vector3 rgb)64 void SColor::LoadRGB(Vector3 rgb)
65 {
66 	Vector3 u = rgb;
67     float vMin = std::min(u.x, std::min(u.y, u.z));
68     n = vMin < 0.f ? -vMin : 0.f;  // neg = minimum  only for negative colors
69     if (vMin < 0.f)  u += Vector3(n,n,n);  // cancel, normalize to 0
70 
71     float vMax = std::max(u.x, std::max(u.y, u.z));  // get max for above 1 colors
72     v = vMax;
73     if (vMax > 1.f)  u /= v;  // above, normalize to 1
74 
75     ColourValue cl(u.x, u.y, u.z);  // get hue and sat
76     float vv;  // not important or 1
77     cl.getHSB(&h, &s, &vv);
78 }
79 
80 //  get clr
GetRGB1() const81 Vector3 SColor::GetRGB1() const
82 {
83 	ColourValue cl;
84 	cl.setHSB(h, s, 1.f);
85 	float vv = std::min(1.f, v);  // * (1.f - n)
86 	return Vector3(
87 		cl.r * vv,
88 		cl.g * vv,
89 		cl.b * vv);
90 }
GetRGB() const91 Vector3 SColor::GetRGB() const
92 {
93 	ColourValue cl;
94 	cl.setHSB(h, s, 1.f);
95 	return Vector3(
96 		cl.r * v -n,
97 		cl.g * v -n,
98 		cl.b * v -n);
99 }
GetClr() const100 ColourValue SColor::GetClr() const
101 {
102 	Vector3 c = SColor::GetRGB();
103 	return ColourValue(c.x, c.y, c.z);
104 }
GetRGBA() const105 Vector4 SColor::GetRGBA() const
106 {
107 	Vector3 c = GetRGB();
108 	return Vector4(c.x, c.y, c.z, a);
109 }
110 
111 //  string
Load(const char * ss)112 void SColor::Load(const char* ss)
113 {
114 	h=0.f; s=1.f; v=1.f; a=1.f; n=0.f;
115 	int i = sscanf(ss, "%f %f %f %f %f", &h,&s,&v,&a,&n);
116 	if (i == 5)
117 		return;  // new
118 
119 	if (i < 3 || i > 5)
120 	{	LogO("NOT 3..5 components color!");  }
121 
122 	//  rgb old < 2.4
123 	//float r=h,g=s,b=v,u=a;
124 	LoadRGB(Vector3(h,s,v));
125 
126 	//  test back
127 	/*Vector4 c = GetRGBA();
128 	float d = fabs(c.x-r) + fabs(c.y-g) + fabs(c.z-b) + fabs(c.w-u);
129 	LogO(String("CLR CHK ")+ss);
130 	LogO("CLR CHK r "+fToStr(c.x-r,2,5)+" g "+fToStr(c.y-g,2,5)+" b "+fToStr(c.z-b,2,5)+" a "+fToStr(c.w-u,2,5)
131 		+"  d "+fToStr(d,2,4) + (d > 0.01f ? " !!! BAD " : " ok"));/**/
132 }
133 
Save() const134 string SColor::Save() const
135 {
136 	string ss = fToStr(h,3,5)+" "+fToStr(s,3,5)+" "+fToStr(v,3,5)+" "+fToStr(std::min(3.f,a),3,5)+" "+fToStr(n,3,5);
137 	return ss;
138 }
139 
140 
141 //  Load
142 //--------------------------------------------------------------------------------------------------------------------------------------
143 
LoadXml(String file,bool bTer)144 bool Scene::LoadXml(String file, bool bTer)
145 {
146 	XMLDocument doc;
147 	XMLError er = doc.LoadFile(file.c_str());
148 	if (er != XML_SUCCESS)
149 	{	LogO("!Error: Can't load scene.xml: "+file);  return false;  }
150 
151 	XMLElement* root = doc.RootElement();
152 	if (!root)  return false;
153 
154 	// clear  --
155 	Default();
156 
157 	//  terrain, asphalt set, vdr outside
158 	asphalt = !bTer;
159 	ter = bTer;
160 
161 	//td.layers.clear();
162 	//pgLayers.clear();
163 
164 	// read
165 	XMLElement* e, *u;
166 	const char* a;
167 
168 
169  	///  ed version
170  	int ver = 2300;  // old
171  	e = root->FirstChildElement("ver");
172 	if (e)
173 	{	a = e->Attribute("num");		if (a)  ver = s2i(a);
174 		a = e->Attribute("baseTrk");	if (a)  baseTrk = string(a);
175 		a = e->Attribute("secEd");		if (a)  secEdited = s2i(a);
176 	}
177 
178  	///  car setup
179  	e = root->FirstChildElement("car");
180 	if (e)
181 	{	a = e->Attribute("tires");		if (a)  asphalt = s2i(a) > 0;
182 		a = e->Attribute("damage");		if (a)  damageMul = s2r(a);
183 		a = e->Attribute("road1mtr");	if (a)  td.road1mtr = s2i(a) > 0;
184 
185 		a = e->Attribute("denyRev");	if (a)  denyReversed = s2i(a) > 0;
186 		a = e->Attribute("gravity");	if (a)  gravity = s2r(a);
187 		a = e->Attribute("noWrongChks"); if (a)  noWrongChks = s2i(a) > 0;
188 	}
189 
190 	///  car start
191 	e = root->FirstChildElement("start");
192 	if (e)
193 	{	a = e->Attribute("pos");		if (a)  {  Vector3 v = s2v(a);   startPos = MATHVECTOR<float,3>(v.x,v.y,v.z);    }
194 		a = e->Attribute("rot");		if (a)  {  Vector4 v = s2v4(a);  startRot = QUATERNION<float>(v.x,v.y,v.z,v.w);  }
195 	}else
196 	{	LogO("!Old, loading start from track.txt");
197 		String s = StringUtil::replaceAll(file,"scene.xml","track.txt");
198 		if (!LoadStartPos(s))
199 			LogO("!Error: Can't load start from "+s);
200 	}
201 
202 	///  sound
203 	e = root->FirstChildElement("sound");
204 	if (e)
205 	{	a = e->Attribute("ambient");	if (a)  sAmbient = string(a);
206 		a = e->Attribute("reverbs");	if (a)  sReverbs = string(a);
207 		UpdRevSet();
208 	}
209 
210 	///  sky
211 	e = root->FirstChildElement("sky");
212 	if (e)
213 	{	a = e->Attribute("material");	if (a)  skyMtr = String(a);
214 		a = e->Attribute("rainEmit");	if (a)  rainEmit = s2i(a);
215 		a = e->Attribute("rainName");	if (a)  rainName = String(a);
216 		a = e->Attribute("rain2Emit");	if (a)  rain2Emit = s2i(a);
217 		a = e->Attribute("rain2Name");	if (a)  rain2Name = String(a);
218 		a = e->Attribute("windAmt");	if (a)  windAmt = s2r(a);
219 		a = e->Attribute("skyYaw");		if (a)  skyYaw = s2r(a);
220 	}
221 	///  fog
222 	e = root->FirstChildElement("fog");
223 	if (e)
224 	{	a = e->Attribute("linStart");	if (a)  fogStart = s2r(a);
225 		a = e->Attribute("linEnd");		if (a)  fogEnd = s2r(a);
226 		a = e->Attribute("color");		if (a)  fogClr.Load(a);
227 		a = e->Attribute("color2");		if (a)  fogClr2.Load(a);  else  fogClr2 = fogClr;
228 	}
229 	///  fog H
230 	e = root->FirstChildElement("fogH");
231 	if (e)
232 	{	a = e->Attribute("color");		if (a)  fogClrH.Load(a);
233 		a = e->Attribute("height");		if (a)  fogHeight = s2r(a);
234 		a = e->Attribute("dens");		if (a)  fogHDensity = s2r(a);
235 		a = e->Attribute("linStart");	if (a)  fogHStart = s2r(a);
236 		a = e->Attribute("linEnd");		if (a)  fogHEnd = s2r(a);
237 		a = e->Attribute("dmg");		if (a)  fHDamage = s2r(a);
238 	}
239 
240 	///  light
241 	e = root->FirstChildElement("light");
242 	if (e)
243 	{	a = e->Attribute("pitch");		if (a)  ldPitch = s2r(a);
244 		a = e->Attribute("yaw");		if (a)  ldYaw = s2r(a);
245 
246 		a = e->Attribute("ambient");	if (a)  lAmb.Load(a);
247 		a = e->Attribute("diffuse");	if (a)  lDiff.Load(a);
248 		a = e->Attribute("specular");	if (a)  lSpec.Load(a);
249 	}
250 
251 
252 	///  fluids
253 	e = root->FirstChildElement("fluids");
254 	if (e)
255 	{	u = e->FirstChildElement("fluid");
256 		while (u)
257 		{
258 			FluidBox fb;
259 			a = u->Attribute("name");	if (a)  fb.name = string(a);
260 
261 			a = u->Attribute("pos");	if (a)  fb.pos = s2v(a);
262 			a = u->Attribute("rot");	if (a)  fb.rot = s2v(a);
263 			a = u->Attribute("size");	if (a)  fb.size = s2v(a);
264 			a = u->Attribute("tile");	if (a)  fb.tile = s2v2(a);
265 
266 			fluids.push_back(fb);
267 			u = u->NextSiblingElement("fluid");
268 		}
269 	}
270 
271 	///  terrain
272 	e = root->FirstChildElement("terrain");
273 	if (e)
274 	{	a = e->Attribute("size");		if (a)  td.iVertsX = s2i(a);
275 		a = e->Attribute("triangle");	if (a)  td.fTriangleSize = s2r(a);
276 		a = e->Attribute("errNorm");	if (a)  td.errorNorm = s2r(a);
277 
278 		a = e->Attribute("normSc");		if (a)  td.normScale = s2r(a);
279 		a = e->Attribute("emissive");	if (a)  td.emissive = s2i(a)>0;
280 		a = e->Attribute("specPow");	if (a)  td.specularPow = s2r(a);
281 		a = e->Attribute("specPowEm");	if (a)  td.specularPowEm = s2r(a);
282 		td.UpdVals();
283 
284 		int il = 0;
285 		u = e->FirstChildElement("texture");
286 		while (u)
287 		{
288 			int road = -1;
289 			a = u->Attribute("road");	if (a)  road = s2i(a)-1;
290 			bool ter = road == -1;
291 
292 			TerLayer lay, *l = ter ? &lay : &td.layerRoad[road];
293 			lay.nFreq[0] += (il-0.7f) * 4.f;  // default, can't be same, needs variation
294 			lay.nFreq[1] += (il-0.5f) * 3.f;
295 
296 			a = u->Attribute("on");		if (a)  l->on = s2i(a)>0;  else  l->on = true;
297 			a = u->Attribute("file");	if (a)  l->texFile = String(a);
298 			a = u->Attribute("fnorm");	if (a)  l->texNorm = String(a);
299 			a = u->Attribute("scale");	if (a)  l->tiling = s2r(a);
300 			a = u->Attribute("surf");	if (a)  l->surfName = String(a);
301 
302 			a = u->Attribute("dust");	if (a)  l->dust = s2r(a);
303 			a = u->Attribute("dustS");	if (a)  l->dustS = s2r(a);
304 			a = u->Attribute("mud");	if (a)  l->mud = s2r(a);
305 			a = u->Attribute("smoke");	if (a)  l->smoke = s2r(a);
306 			a = u->Attribute("tclr");	if (a){ l->tclr.Load(a);  l->tcl = l->tclr.GetRGBA();  }
307 			a = u->Attribute("dmg");	if (a)  l->fDamage = s2r(a);
308 
309 			a = u->Attribute("angMin");	if (a)  l->angMin = s2r(a);
310 			a = u->Attribute("angMax");	if (a)  l->angMax = s2r(a);
311 			a = u->Attribute("angSm");	if (a)  l->angSm = s2r(a);
312 			a = u->Attribute("hMin");	if (a)  l->hMin = s2r(a);
313 			a = u->Attribute("hMax");	if (a)  l->hMax = s2r(a);
314 			a = u->Attribute("hSm");	if (a)  l->hSm = s2r(a);
315 
316 			a = u->Attribute("nOn");		if (a)  l->nOnly = s2i(a)>0;
317 			a = u->Attribute("triplanar");	if (a)  l->triplanar = true;  else  l->triplanar = false;
318 
319 			a = u->Attribute("noise");	if (a)  l->noise = s2r(a);
320 			a = u->Attribute("n_1");	if (a)  l->nprev = s2r(a);
321 			a = u->Attribute("n2");		if (a)  l->nnext2 = s2r(a);
322 
323 			XMLElement* eNoi = u->FirstChildElement("noise");
324 			if (eNoi)
325 			for (int n=0; n < 2; ++n)
326 			{	string sn = toStr(n), s;
327 				s = "frq"+sn;  a = eNoi->Attribute(s.c_str());  if (a)  l->nFreq[n]= s2r(a);
328 				s = "oct"+sn;  a = eNoi->Attribute(s.c_str());  if (a)  l->nOct[n] = s2i(a);
329 				s = "prs"+sn;  a = eNoi->Attribute(s.c_str());  if (a)  l->nPers[n]= s2r(a);
330 				s = "pow"+sn;  a = eNoi->Attribute(s.c_str());  if (a)  l->nPow[n] = s2r(a);
331 			}
332 			if (ter && il < td.ciNumLay)
333 				td.layersAll[il++] = lay;
334 			u = u->NextSiblingElement("texture");
335 		}
336 		td.UpdLayers();
337 
338 		u = e->FirstChildElement("par");
339 		if (u)
340 		{	a = u->Attribute("dust");	if (a)  sParDust = String(a);
341 			a = u->Attribute("mud");	if (a)  sParMud = String(a);
342 			a = u->Attribute("smoke");	if (a)  sParSmoke = String(a);
343 		}
344 	}
345 
346 	///  paged
347  	e = root->FirstChildElement("paged");
348 	if (e)
349 	{	a = e->Attribute("densTrees");		if (a)  densTrees = s2r(a);
350 		a = e->Attribute("densGrass");		if (a)  densGrass = s2r(a);
351 		//  grass
352 		a = e->Attribute("grPage");			if (a)  grPage = s2r(a);
353 		a = e->Attribute("grDist");			if (a)  grDist = s2r(a);
354 		a = e->Attribute("grDensSmooth");	if (a)  grDensSmooth = s2i(a);
355 		//  trees
356 		a = e->Attribute("trPage");			if (a)  trPage = s2r(a);
357 		a = e->Attribute("trDist");			if (a)  trDist = s2r(a);
358 		a = e->Attribute("trDistImp");		if (a)  trDistImp = s2r(a);
359 		a = e->Attribute("trRdDist");		if (a)  trRdDist = s2i(a);
360 
361 		int grl = 0;
362 		u = e->FirstChildElement("grass");
363 		while (u)
364 		{
365 			SGrassLayer g;
366 			a = u->Attribute("on");			if (a)  g.on = s2i(a);  else  g.on = 1;
367 			a = u->Attribute("mtr");		if (a)  g.material = String(a);
368 			a = u->Attribute("clr");		if (a)  g.colorMap = String(a);
369 			a = u->Attribute("dens");		if (a)  g.dens = s2r(a);
370 			a = u->Attribute("chan");		if (a)  g.iChan = s2i(a);
371 
372 			a = u->Attribute("minSx");		if (a)  g.minSx = s2r(a);
373 			a = u->Attribute("maxSx");		if (a)  g.maxSx = s2r(a);
374 			a = u->Attribute("minSy");		if (a)  g.minSy = s2r(a);
375 			a = u->Attribute("maxSy");		if (a)  g.maxSy = s2r(a);
376 
377 			a = u->Attribute("swayDistr");	if (a)  g.swayDistr = s2r(a);
378 			a = u->Attribute("swayLen");	if (a)  g.swayLen = s2r(a);
379 			a = u->Attribute("swaySpeed");	if (a)  g.swaySpeed = s2r(a);
380 
381 		#if 1  //  old < 2.3  (no channels)
382 		if (grl == 0)  {
383 			a = u->Attribute("terMaxAng");	if (a)  grChan[0].angMax = s2r(a);
384 			a = u->Attribute("terAngSm");	if (a)  grChan[0].angSm = s2r(a);
385 
386 			a = u->Attribute("terMinH");	if (a)  grChan[0].hMin = s2r(a);
387 			a = u->Attribute("terMaxH");	if (a)  grChan[0].hMax = s2r(a);
388 			a = u->Attribute("terHSm");		if (a)  grChan[0].hSm = s2r(a);  }
389 		#endif
390 			grLayersAll[grl++] = g;
391 			u = u->NextSiblingElement("grass");
392 		}
393 
394 		int c;
395 		for (c=0; c < 4; c++)
396 			grChan[c].nFreq += c * 3.f;  // default variation
397 		c = 0;
398 
399 		u = e->FirstChildElement("gchan");
400 		while (u && c < 4)
401 		{
402 			SGrassChannel& g = grChan[c++];
403 			TiXmlElement gch("gchan");
404 
405 			a = u->Attribute("amin");	if (a)  g.angMin = s2r(a);
406 			a = u->Attribute("amax");	if (a)  g.angMax = s2r(a);
407 			a = u->Attribute("asm");	if (a)  g.angSm = s2r(a);
408 
409 			a = u->Attribute("hmin");	if (a)  g.hMin = s2r(a);
410 			a = u->Attribute("hmax");	if (a)  g.hMax = s2r(a);
411 			a = u->Attribute("hsm");	if (a)  g.hSm = s2r(a);
412 
413 			a = u->Attribute("ns");		if (a)  g.noise = s2r(a);
414 			a = u->Attribute("frq");	if (a)  g.nFreq = s2r(a);
415 			a = u->Attribute("oct");	if (a)  g.nOct  = s2i(a);
416 			a = u->Attribute("prs");	if (a)  g.nPers = s2r(a);
417 			a = u->Attribute("pow");	if (a)  g.nPow  = s2r(a);
418 
419 			a = u->Attribute("rd");		if (a)  g.rdPow = s2r(a);
420 			u = u->NextSiblingElement("gchan");
421 		}
422 
423 		///  veget
424 		int pgl = 0;
425 		u = e->FirstChildElement("layer");
426 		while (u)
427 		{
428 			PagedLayer l;
429 			a = u->Attribute("on");			if (a)  l.on = s2i(a);  else  l.on = 1;
430 			a = u->Attribute("name");		if (a)  l.name = String(a);
431 			a = u->Attribute("dens");		if (a)  l.dens = s2r(a);
432 			a = u->Attribute("minScale");	if (a)  l.minScale = s2r(a);
433 			a = u->Attribute("maxScale");	if (a)  l.maxScale = s2r(a);
434 
435 			a = u->Attribute("ofsY");		if (a)  l.ofsY = s2r(a);
436 			a = u->Attribute("addTrRdDist");if (a)  l.addRdist = s2i(a);
437 			a = u->Attribute("maxRdist");	if (a)  l.maxRdist = s2i(a);
438 			a = u->Attribute("windFx");		if (a)  l.windFx = s2r(a);
439 			a = u->Attribute("windFy");		if (a)  l.windFy = s2r(a);
440 
441 			a = u->Attribute("maxTerAng");	if (a)  l.maxTerAng = s2r(a);
442 			a = u->Attribute("minTerH");	if (a)  l.minTerH = s2r(a);
443 			a = u->Attribute("maxTerH");	if (a)  l.maxTerH = s2r(a);
444 			a = u->Attribute("maxDepth");	if (a)  l.maxDepth = s2r(a);
445 
446 			pgLayersAll[pgl++] = l;
447 			u = u->NextSiblingElement("layer");
448 		}
449 		UpdPgLayers();
450 	}
451 
452  	///  camera
453  	e = root->FirstChildElement("cam");
454 	if (e)
455 	{	a = e->Attribute("pos");		if (a)  camPos = s2v(a);
456 		a = e->Attribute("dir");		if (a)  camDir = s2v(a);
457 	}
458 
459 	///  objects
460 	e = root->FirstChildElement("objects");
461 	if (e)
462 	{	u = e->FirstChildElement("o");
463 		while (u)
464 		{
465 			Object o;
466 			a = u->Attribute("name");	if (a)  o.name = string(a);
467 
468 			a = u->Attribute("pos");	if (a)  {  Vector3 v = s2v(a);  o.pos = MATHVECTOR<float,3>(v.x,v.y,v.z);  }
469 			a = u->Attribute("rot");	if (a)  {  Vector4 v = s2v4(a);  o.rot = QUATERNION<float>(v.x,v.y,v.z,v.w);  }
470 			a = u->Attribute("sc");		if (a)  o.scale = s2v(a);
471 
472 			objects.push_back(o);
473 			u = u->NextSiblingElement("o");
474 	}	}
475 
476 	UpdateFluidsId();
477 
478 	UpdateSurfId();
479 
480 	return true;
481 }
482 
483 
484 //  Save
485 //--------------------------------------------------------------------------------------------------------------------------------------
486 
SaveXml(String file)487 bool Scene::SaveXml(String file)
488 {
489 	TiXmlDocument xml;	TiXmlElement root("scene");
490 
491 	TiXmlElement ver("ver");
492 		int v = SET_VER;
493 		ver.SetAttribute("num",		toStrC( v ));
494 		ver.SetAttribute("baseTrk",	baseTrk.c_str());
495 		ver.SetAttribute("secEd",	toStrC( secEdited ));
496 	root.InsertEndChild(ver);
497 
498 
499 	TiXmlElement car("car");
500 		car.SetAttribute("tires",	asphalt ? "1":"0");
501 		if (damageMul != 1.f)
502 			car.SetAttribute("damage",	toStrC( damageMul ));
503 		if (!td.road1mtr)
504 			car.SetAttribute("road1mtr", td.road1mtr ? "1":"0");
505 		if (noWrongChks)
506 			car.SetAttribute("noWrongChks", noWrongChks ? "1":"0");
507 
508 		if (denyReversed)
509 			car.SetAttribute("denyRev",	"1");
510 		if (gravity != 9.81f)
511 			car.SetAttribute("gravity",	toStrC( gravity ));
512 	root.InsertEndChild(car);
513 
514 
515 	TiXmlElement st("start");
516 		string s = toStr(startPos[0])+" "+toStr(startPos[1])+" "+toStr(startPos[2]);
517 		st.SetAttribute("pos",	s.c_str());
518 
519 		s = toStr(startRot[0])+" "+toStr(startRot[1])+" "+toStr(startRot[2])+" "+toStr(startRot[3]);
520 		st.SetAttribute("rot",	s.c_str());
521 	root.InsertEndChild(st);
522 
523 
524 	TiXmlElement snd("sound");
525 		snd.SetAttribute("ambient",		sAmbient.c_str());
526 		snd.SetAttribute("reverbs",		sReverbs.c_str());
527 	root.InsertEndChild(snd);
528 
529 
530 	TiXmlElement sky("sky");
531 		sky.SetAttribute("material",	skyMtr.c_str());
532 		if (rainEmit > 0 && rainName != "")
533 		{	sky.SetAttribute("rainName",	rainName.c_str());
534 			sky.SetAttribute("rainEmit",	toStrC( rainEmit ));
535 		}
536 		if (rain2Emit > 0 && rain2Name != "")
537 		{	sky.SetAttribute("rain2Name",	rain2Name.c_str());
538 			sky.SetAttribute("rain2Emit",	toStrC( rain2Emit ));
539 		}
540 		if (windAmt != 0.f)
541 			sky.SetAttribute("windAmt",	toStrC( windAmt ));
542 		if (skyYaw != 0.f)
543 			sky.SetAttribute("skyYaw",	toStrC( skyYaw ));
544 	root.InsertEndChild(sky);
545 
546 	TiXmlElement fog("fog");
547 		fog.SetAttribute("color",		fogClr.Save().c_str() );
548 		fog.SetAttribute("color2",		fogClr2.Save().c_str() );
549 		fog.SetAttribute("linStart",	toStrC( fogStart ));
550 		fog.SetAttribute("linEnd",		toStrC( fogEnd ));
551 	root.InsertEndChild(fog);
552 
553 	TiXmlElement fogH("fogH");
554 		fogH.SetAttribute("color",		fogClrH.Save().c_str() );
555 		fogH.SetAttribute("height",		toStrC( fogHeight ));
556 		fogH.SetAttribute("dens",		toStrC( fogHDensity ));
557 		fogH.SetAttribute("linStart",	toStrC( fogHStart ));
558 		fogH.SetAttribute("linEnd",		toStrC( fogHEnd ));
559 		if (fHDamage > 0.f)
560 			fogH.SetAttribute("dmg",	toStrC( fHDamage ));
561 	root.InsertEndChild(fogH);
562 
563 	TiXmlElement li("light");
564 		li.SetAttribute("pitch",		toStrC( ldPitch ));
565 		li.SetAttribute("yaw",			toStrC( ldYaw ));
566 		li.SetAttribute("ambient",		lAmb.Save().c_str() );
567 		li.SetAttribute("diffuse",		lDiff.Save().c_str() );
568 		li.SetAttribute("specular",		lSpec.Save().c_str() );
569 	root.InsertEndChild(li);
570 
571 
572 	TiXmlElement fls("fluids");
573 		for (int i=0; i < fluids.size(); ++i)
574 		{
575 			const FluidBox* fb = &fluids[i];
576 			TiXmlElement fe("fluid");
577 			fe.SetAttribute("name",		fb->name.c_str() );
578 			fe.SetAttribute("pos",		toStrC( fb->pos ));
579 			fe.SetAttribute("rot",		toStrC( fb->rot ));
580 			fe.SetAttribute("size",		toStrC( fb->size ));
581 			fe.SetAttribute("tile",		toStrC( fb->tile ));
582 			fls.InsertEndChild(fe);
583 		}
584 	root.InsertEndChild(fls);
585 
586 
587 	TiXmlElement ter("terrain");
588 		ter.SetAttribute("size",		toStrC( td.iVertsX ));
589 		ter.SetAttribute("triangle",	toStrC( td.fTriangleSize ));
590 		ter.SetAttribute("errNorm",		fToStr( td.errorNorm, 2,4 ).c_str());
591 		if (td.normScale != 1.f)
592 			ter.SetAttribute("normSc",		toStrC( td.normScale ));
593 		if (td.emissive)
594 			ter.SetAttribute("emissive",	td.emissive ? 1 : 0);
595 		if (td.specularPow != 32.f)
596 			ter.SetAttribute("specPow",		toStrC( td.specularPow ));
597 		if (td.specularPowEm != 2.f)
598 			ter.SetAttribute("specPowEm",	toStrC( td.specularPowEm ));
599 
600 		const TerLayer* l;
601 		for (int i=0; i < 6; ++i)
602 		{
603 			l = &td.layersAll[i];
604 			TiXmlElement tex("texture");
605 			tex.SetAttribute("on",		l->on ? 1 : 0);
606 			tex.SetAttribute("file",	l->texFile.c_str());
607 			tex.SetAttribute("fnorm",	l->texNorm.c_str());
608 			tex.SetAttribute("scale",	toStrC( l->tiling ));
609 			tex.SetAttribute("surf",	l->surfName.c_str());
610 			#define setDmst()  \
611 				tex.SetAttribute("dust",	toStrC( l->dust ));  \
612 				tex.SetAttribute("dustS",	toStrC( l->dustS )); \
613 				tex.SetAttribute("mud",		toStrC( l->mud ));   \
614 				tex.SetAttribute("smoke",	toStrC( l->smoke )); \
615 				tex.SetAttribute("tclr",	l->tclr.Save().c_str() );
616 			setDmst();
617 			if (l->fDamage > 0.f)
618 				tex.SetAttribute("dmg",	toStrC( l->fDamage ));
619 
620 			tex.SetAttribute("angMin",	toStrC( l->angMin ));
621 			tex.SetAttribute("angMax",	toStrC( l->angMax ));
622 			tex.SetAttribute("angSm",	toStrC( l->angSm ));
623 			tex.SetAttribute("hMin",	toStrC( l->hMin ));
624 			tex.SetAttribute("hMax",	toStrC( l->hMax ));
625 			tex.SetAttribute("hSm",		toStrC( l->hSm ));
626 
627 			tex.SetAttribute("nOn",		l->nOnly ? 1 : 0);
628 			if (l->triplanar)  tex.SetAttribute("triplanar", 1);
629 
630 			tex.SetAttribute("noise",	toStrC( l->noise ));
631 			tex.SetAttribute("n_1",		toStrC( l->nprev ));
632 			tex.SetAttribute("n2",		toStrC( l->nnext2 ));
633 
634 			TiXmlElement noi("noise");
635 			for (int n=0; n < 2; ++n)
636 			{	string sn = toStr(n), s;
637 				s = "frq"+sn;  noi.SetAttribute(s.c_str(),  toStrC( l->nFreq[n] ));
638 				s = "oct"+sn;  noi.SetAttribute(s.c_str(),  toStrC( l->nOct[n] ));
639 				s = "prs"+sn;  noi.SetAttribute(s.c_str(),  toStrC( l->nPers[n] ));
640 				s = "pow"+sn;  noi.SetAttribute(s.c_str(),  toStrC( l->nPow[n] ));
641 			}
642 			tex.InsertEndChild(noi);
643 			ter.InsertEndChild(tex);
644 		}
645 		for (int i=0; i < 4; ++i)
646 		{
647 			l = &td.layerRoad[i];
648 			TiXmlElement tex("texture");
649 			tex.SetAttribute("road",	toStrC(i+1));
650 			tex.SetAttribute("surf",	l->surfName.c_str());
651 			setDmst();
652 			ter.InsertEndChild(tex);
653 		}
654 
655 		TiXmlElement par("par");
656 			par.SetAttribute("dust",	sParDust.c_str());
657 			par.SetAttribute("mud",		sParMud.c_str());
658 			par.SetAttribute("smoke",	sParSmoke.c_str());
659 		ter.InsertEndChild(par);
660 
661 	root.InsertEndChild(ter);
662 
663 
664 	TiXmlElement pgd("paged");
665 		pgd.SetAttribute("densGrass",	toStrC( densGrass ));
666 		pgd.SetAttribute("densTrees",	toStrC( densTrees ));
667 		//  grass
668 		pgd.SetAttribute("grPage",		toStrC( grPage ));
669 		pgd.SetAttribute("grDist",		toStrC( grDist ));
670 		pgd.SetAttribute("grDensSmooth",toStrC( grDensSmooth ));
671 
672 		//  trees
673 		pgd.SetAttribute("trPage",		toStrC( trPage ));
674 		pgd.SetAttribute("trDist",		toStrC( trDist ));
675 		pgd.SetAttribute("trDistImp",	toStrC( trDistImp ));
676 		pgd.SetAttribute("trRdDist",	toStrC( trRdDist  ));
677 
678 		int i;
679 		for (int i=0; i < ciNumGrLay; ++i)
680 		{
681 			const SGrassLayer& g = grLayersAll[i];
682 			TiXmlElement grl("grass");
683 			grl.SetAttribute("on",		g.on ? 1 : 0);
684 			grl.SetAttribute("mtr",		g.material.c_str());
685 			grl.SetAttribute("clr",		g.colorMap.c_str());
686 			grl.SetAttribute("dens",	toStrC( g.dens ));
687 			grl.SetAttribute("chan",	toStrC( g.iChan ));
688 
689 			grl.SetAttribute("minSx",	toStrC( g.minSx ));
690 			grl.SetAttribute("maxSx",	toStrC( g.maxSx ));
691 			grl.SetAttribute("minSy",	toStrC( g.minSy ));
692 			grl.SetAttribute("maxSy",	toStrC( g.maxSy ));
693 
694 			grl.SetAttribute("swayDistr",	toStrC( g.swayDistr ));
695 			grl.SetAttribute("swayLen",		toStrC( g.swayLen ));
696 			grl.SetAttribute("swaySpeed",	toStrC( g.swaySpeed ));
697 			pgd.InsertEndChild(grl);
698 		}
699 
700 		for (i=0; i < 4; ++i)
701 		{
702 			const SGrassChannel& g = grChan[i];
703 			TiXmlElement gch("gchan");
704 			gch.SetAttribute("amin",	toStrC( g.angMin ));
705 			gch.SetAttribute("amax",	toStrC( g.angMax ));
706 			gch.SetAttribute("asm",		toStrC( g.angSm ));
707 
708 			gch.SetAttribute("hmin",	toStrC( g.hMin ));
709 			gch.SetAttribute("hmax",	toStrC( g.hMax ));
710 			gch.SetAttribute("hsm",		toStrC( g.hSm ));
711 
712 			gch.SetAttribute("ns",		toStrC( g.noise ));
713 			gch.SetAttribute("frq",		toStrC( g.nFreq ));
714 			gch.SetAttribute("oct",		toStrC( g.nOct ));
715 			gch.SetAttribute("prs",		toStrC( g.nPers ));
716 			gch.SetAttribute("pow",		toStrC( g.nPow ));
717 
718 			gch.SetAttribute("rd",		toStrC( g.rdPow ));
719 			pgd.InsertEndChild(gch);
720 		}
721 
722 		for (i=0; i < ciNumPgLay; ++i)
723 		{
724 			const PagedLayer& l = pgLayersAll[i];
725 			TiXmlElement pgl("layer");
726 			pgl.SetAttribute("on",			l.on ? 1 : 0);
727 			pgl.SetAttribute("name",		l.name.c_str());
728 			pgl.SetAttribute("dens",		toStrC( l.dens ));
729 			pgl.SetAttribute("minScale",	toStrC( l.minScale ));
730 			pgl.SetAttribute("maxScale",	toStrC( l.maxScale ));
731 
732 			pgl.SetAttribute("ofsY",		toStrC( l.ofsY ));
733 			pgl.SetAttribute("addTrRdDist",	toStrC( l.addRdist ));
734 			pgl.SetAttribute("maxRdist",	toStrC( l.maxRdist ));
735 			pgl.SetAttribute("windFx",		toStrC( l.windFx ));
736 			pgl.SetAttribute("windFy",		toStrC( l.windFy ));
737 
738 			pgl.SetAttribute("maxTerAng",	toStrC( l.maxTerAng ));
739 			pgl.SetAttribute("minTerH",		toStrC( l.minTerH ));
740 			pgl.SetAttribute("maxTerH",		toStrC( l.maxTerH ));
741 			pgl.SetAttribute("maxDepth",	toStrC( l.maxDepth ));
742 			pgd.InsertEndChild(pgl);
743 		}
744 	root.InsertEndChild(pgd);
745 
746 
747 	TiXmlElement cam("cam");
748 		cam.SetAttribute("pos",		toStrC( camPos ));
749 		cam.SetAttribute("dir",		toStrC( camDir ));
750 	root.InsertEndChild(cam);
751 
752 
753 	TiXmlElement objs("objects");
754 		for (i=0; i < objects.size(); ++i)
755 		{
756 			const Object* o = &objects[i];
757 			TiXmlElement oe("o");
758 			oe.SetAttribute("name",		o->name.c_str() );
759 
760 			string s = toStr(o->pos[0])+" "+toStr(o->pos[1])+" "+toStr(o->pos[2]);
761 			oe.SetAttribute("pos",		s.c_str());
762 
763 			s = toStr(o->rot[0])+" "+toStr(o->rot[1])+" "+toStr(o->rot[2])+" "+toStr(o->rot[3]);
764 			oe.SetAttribute("rot",		s.c_str());
765 
766 			if (o->scale != Vector3::UNIT_SCALE)  // dont save default
767 				oe.SetAttribute("sc",	toStrC( o->scale ));
768 			objs.InsertEndChild(oe);
769 		}
770 	root.InsertEndChild(objs);
771 
772 
773 	xml.InsertEndChild(root);
774 	return xml.SaveFile(file.c_str());
775 }
776 
777 
778 ///  Load Presets
779 //--------------------------------------------------------------------------------------------------------------------------------------
780 
LoadXml(string file)781 bool Presets::LoadXml(string file)
782 {
783 	XMLDocument doc;
784 	XMLError e = doc.LoadFile(file.c_str());
785 	if (e != XML_SUCCESS)
786 	{	LogO("!Can't load presets.xml: "+file);  return false;  }
787 
788 	XMLElement* root = doc.RootElement();
789 	if (!root)  return false;
790 
791 	//  clear
792 	ter.clear();  iter.clear();
793 	rd.clear();  ird.clear();
794 	gr.clear();  igr.clear();
795 	veg.clear();  iveg.clear();
796 
797 	//  read
798 	XMLElement* eSky,*eTex,*eRd,*eVeg,*eGr;
799 	const char* a;
800 
801 	///  sky
802 	eSky = root->FirstChildElement("s");
803 	while (eSky)
804 	{
805 		PSky s;
806 		a = eSky->Attribute("m");	if (a)  s.mtr = String(a);
807 		a = eSky->Attribute("c");	if (a)  s.clr = String(a);
808 
809 		a = eSky->Attribute("y");	if (a)  s.ldYaw = s2r(a);
810 		a = eSky->Attribute("p");	if (a)  s.ldPitch = s2r(a);
811 
812 		sky.push_back(s);  isky[s.mtr] = sky.size();
813 		eSky = eSky->NextSiblingElement("s");
814 	}
815 
816 	///  terrain
817 	eTex = root->FirstChildElement("t");
818 	while (eTex)
819 	{
820 		PTer l;
821 		a = eTex->Attribute("t");	if (a)  l.texFile = String(a);
822 		a = eTex->Attribute("n");	if (a)  l.texNorm = String(a);
823 		a = eTex->Attribute("s");	if (a)  l.tiling = s2r(a);
824 		a = eTex->Attribute("su");	if (a)  l.surfName = string(a);
825 
826 		a = eTex->Attribute("sc");	if (a)  l.sc = String(a);
827 		a = eTex->Attribute("z");	if (a)  l.scn = string(a);
828 
829 		a = eTex->Attribute("du");	if (a)  l.dust = s2r(a);
830 		a = eTex->Attribute("ds");	if (a)  l.dustS = s2r(a);
831 		a = eTex->Attribute("md");	if (a)  l.mud = s2r(a);
832 		a = eTex->Attribute("tr");	if (a)  l.tclr.Load(a);
833 		a = eTex->Attribute("d");	if (a)  l.dmg = s2r(a);
834 
835 		a = eTex->Attribute("aa");	if (a)  l.angMin = s2r(a);
836 		a = eTex->Attribute("ab");	if (a)  l.angMax = s2r(a);
837 		a = eTex->Attribute("tp");	if (a)  l.triplanar = s2i(a)>0;
838 
839 		ter.push_back(l);  iter[l.texFile] = ter.size();
840 		eTex = eTex->NextSiblingElement("t");
841 	}
842 
843 	///  road
844 	eRd = root->FirstChildElement("r");
845 	while (eRd)
846 	{
847 		PRoad l;
848 		a = eRd->Attribute("m");	if (a)  l.mtr = String(a);
849 		a = eRd->Attribute("su");	if (a)  l.surfName = string(a);
850 
851 		a = eRd->Attribute("sc");	if (a)  l.sc = String(a);
852 		a = eRd->Attribute("z");	if (a)  l.scn = string(a);
853 
854 		a = eRd->Attribute("du");	if (a)  l.dust = s2r(a);
855 		a = eRd->Attribute("ds");	if (a)  l.dustS = s2r(a);
856 		a = eRd->Attribute("md");	if (a)  l.mud = s2r(a);
857 		a = eRd->Attribute("tr");	if (a)  l.tclr.Load(a);
858 
859 		rd.push_back(l);  ird[l.mtr] = rd.size();
860 		eRd = eRd->NextSiblingElement("r");
861 	}
862 
863 	///  grass
864 	eGr = root->FirstChildElement("g");
865 	while (eGr)
866 	{
867 		PGrass g;
868 		a = eGr->Attribute("g");	if (a)  g.mtr = String(a);
869 		a = eGr->Attribute("c");	if (a)  g.clr = String(a);
870 
871 		a = eGr->Attribute("sc");	if (a)  g.sc = String(a);
872 		a = eGr->Attribute("z");	if (a)  g.scn = string(a);
873 
874 		a = eGr->Attribute("xa");	if (a)  g.minSx = s2r(a);
875 		a = eGr->Attribute("xb");	if (a)  g.maxSx = s2r(a);
876 		a = eGr->Attribute("ya");	if (a)  g.minSy = s2r(a);
877 		a = eGr->Attribute("yb");	if (a)  g.maxSy = s2r(a);
878 
879 		gr.push_back(g);  igr[g.mtr] = gr.size();
880 		eGr = eGr->NextSiblingElement("g");
881 	}
882 
883 	///  veget
884  	eVeg = root->FirstChildElement("v");
885 	while (eVeg)
886 	{
887 		PVeget l;
888 		a = eVeg->Attribute("p");	if (a)  l.name = String(a);
889 		a = eVeg->Attribute("sa");	if (a)  l.minScale = s2r(a);
890 		a = eVeg->Attribute("sb");	if (a)  l.maxScale = s2r(a);
891 
892 		a = eVeg->Attribute("sc");	if (a)  l.sc = String(a);
893 		a = eVeg->Attribute("z");	if (a)  l.scn = string(a);
894 
895 		a = eVeg->Attribute("wx");	if (a)  l.windFx = s2r(a);
896 		a = eVeg->Attribute("wy");	if (a)  l.windFy = s2r(a);
897 
898 		a = eVeg->Attribute("ab");	if (a)  l.maxTerAng = s2r(a);
899 		a = eVeg->Attribute("rd");	if (a)  l.addRdist = s2i(a);
900 		a = eVeg->Attribute("fd");	if (a)  l.maxDepth = s2r(a);
901 
902 		veg.push_back(l);  iveg[l.name] = veg.size();
903 		eVeg = eVeg->NextSiblingElement("v");
904 	}
905 
906 	return true;
907 }
908