1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 //
5 // This file was originally written by Salvatore Russo.
6 // I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated
7 // it into Irrlicht:
8 // - removed STL dependency
9 // - removed log file and replaced it with irrlicht logging
10 // - adapted code formatting a bit to Irrlicht style
11 // - removed memory leaks
12 // Thanks a lot to Salvatore for his work on this and that he gave me
13 // his permission to add it into Irrlicht.
14 
15 // This support library has been made by Salvatore Russo and is released under GNU public license for general uses.
16 // For uses in Irrlicht core and only for Irrlicht related uses I release this library under zlib license.
17 
18 #ifndef __DMF_SUPPORT_H_INCLUDED__
19 #define __DMF_SUPPORT_H_INCLUDED__
20 
21 #include "irrString.h"
22 #include "fast_atof.h"
23 
24 namespace irr
25 {
26 namespace scene
27 {
28 namespace
29 {
30 
31 /** A structure representing some DeleD infos.
32 This structure contains data about DeleD level file like: version, ambient color, number of objects etc...*/
33 struct dmfHeader
34 {
35 	//main file header
36 	core::stringc dmfName; //!<Scene name
37 	f32 dmfVersion;     //!<File version
38 	video::SColor dmfAmbient; //!<Ambient color
39 	f32 dmfShadow;     //!<Shadow intensity
40 	u32 numObjects;    //!<Number of objects in this scene
41 	u32 numMaterials;  //!<Number of materials in this scene
42 	u32 numVertices;   //!<Total number of vertices faces*(vertices for each face)
43 	u32 numFaces;      //!<Total number of faces
44 	u32 numLights;     //!<Number of dynamic lights in this scene
45 	u32 numWatVertices; //!<Total number of vertices of water plains watfaces*(vertices for each face)
46 	u32 numWatFaces;   //!<Total number of faces for water plains.Note that each water plane is a rectangle with one face only.
47 };
48 
49 
50 /** A structure representing a DeleD material.
51 This structure contains texture names, an ID and some flags.*/
52 struct dmfMaterial
53 {
54 	u32 materialID;//!<This material unique ID.
55 	u32 textureLayers;//!<First texture Flag (0=Normal, 1=Color).
56 	u32 textureFlag;//!<First texture Flag (0=Normal, 1=Color).
57 	u32 lightmapFlag;//!<Lightmap Flag (0=Normal, others not considered).
58 	u32 textureBlend;//!<Texture Blend mode used to support alpha maps (4=Alpha map, others not implemented yet).
59 	core::stringc pathName;//!<Name of path defined in path element.
60 	core::stringc textureName;//!<Name of first texture (only file name, no path).
61 	core::stringc lightmapName;//!<Name of lightmap (only file name, no path).
62 	u32 lightmapBlend;//!<Blend mode used to support alpha maps (not implemented yet).
63 };
64 
65 
66 /** A structure representing a single face.
67 This structure contains first vertice index, number of vertices and the material used.*/
68 struct dmfFace
69 {
70 	u32 firstVert;//!<First vertex index.
71 	u32 numVerts;//!<Number of vertices for this face.
72 	u32 materialID;//!<Material used for this face.
73 };
74 
75 
76 /** A structure representing a single vertice.
77 This structure contains vertice position coordinates and texture an lightmap UV.*/
78 struct dmfVert
79 {
80 	core::vector3df pos;//!<Position of vertex
81 	core::vector2df tc;//!<Texture UV coords
82 	core::vector2df lc;//!<Lightmap UV coords
83 };
84 
85 
86 /** A structure representing a single dynamic light.
87 This structure contains light position coordinates, diffuse color, specular color and maximum radius of light.*/
88 struct dmfLight
89 {
90 	core::vector3df pos;//!<Position of this light.
91 	video::SColorf diffuseColor;//!<Diffuse color.
92 	video::SColorf specularColor;//!<Specular color.
93 	f32 radius;//!<Maximum radius of light.
94 };
95 
96 /** A structure representing a single water plane.
97 This structure contains light position coordinates, diffuse color, specular color and maximum radius of light.*/
98 struct dmfWaterPlane
99 {
100 	u32 waterID;//!<ID of specified water plane.
101 	u32 numFaces;//!<number of faces that make this plain.Owing to the fact that this is a rectangle you'll have 1 every time.
102 	u32 firstFace;//!<first face of this plain.
103 	core::dimension2d<u32> tileNum;//!<number of tiles of this water plain.
104 	f32 waveHeight;//!<height of waves.
105 	f32 waveSpeed;//!<waves speed.
106 	f32 waveLength;//!<waves length.
107 };
108 
109 
110 /** A function to convert a hexstring to a int.
111 This function converts an hex string (i.e. FF) to its int value (i.e. 255).
112 \return An int representing the hex input value.*/
axtoi(const char * hexStg)113 int axtoi(const char *hexStg)
114 {
115 	unsigned int intValue = 0;  // integer value of hex string
116 	sscanf(hexStg, "%x", &intValue);
117 	return (intValue);
118 }
119 
120 typedef core::array<core::stringc> StringList;
121 
122 //Loads a stringlist from a file
123 //note that each String added to StringList
124 //is separated by a \\n character and it's present
125 //at the end of line.
126 /** Loads a StringList from a file.
127 This function loads a StringList from a file where each string is divided by a \\n char.*/
LoadFromFile(io::IReadFile * file,StringList & strlist)128 void LoadFromFile(io::IReadFile* file, StringList& strlist)
129 {
130 	const long sz = file->getSize();
131 	char* buf = new char[sz+1];
132 	file->read(buf, sz);
133 	buf[sz] = 0;
134 	char* p = buf;
135 	char* start = p;
136 
137 	while(*p)
138 	{
139 		if (*p == '\n')
140 		{
141 			core::stringc str(start, (u32)(p - start - 1));
142 			str.trim();
143 			strlist.push_back(str);
144 			start = p+1;
145 		}
146 
147 		++p;
148 	}
149 
150 	if (p - start > 1)
151 	{
152 		core::stringc str(start, (u32)(p - start - 1));
153 		str.trim();
154 		strlist.push_back(str);
155 	}
156 
157 	delete [] buf;
158 };
159 
160 //This function subdivides a string in a list of strings
161 /** This function subdivides strings divided by divider in a list of strings.
162 \return A StringList made of all strings divided by divider.*/
SubdivideString(const core::stringc & str,const core::stringc & divider)163 StringList SubdivideString(const core::stringc& str, const core::stringc& divider)
164 {
165 	StringList strings; //returned StringList
166 	strings.clear();    //clear returned stringlist
167 
168 	int c=0;
169 	int l=str.size();
170 
171 	//process entire string
172 	while(c<l)
173 	{
174 		core::stringc resultstr;
175 		resultstr = "";
176 		//read characters until divider is encountered
177 		while((str[c]!=divider[0]) && c<l)
178 		{
179 			resultstr += str[c];
180 			++c;
181 		}
182 
183 		//Remove spaces \t and \n from string in my implementation...
184 		//pay attention or change it in dll.h if you don't want to remove
185 		//a particular char.
186 		resultstr.trim();//trims string resultstr
187 		strings.push_back(resultstr);//add trimmed string
188 		++c;
189 	}
190 
191 	return strings;
192 }
193 
194 
195 //Get DeleD informations and convert in dmfHeader
196 /**This function extract a dmfHeader from a DMF file.
197 You must give in input a StringList representing a DMF file loaded with LoadFromFile.
198 \return true if function succeed or false on fail.*/
GetDMFHeader(const StringList & RawFile,dmfHeader & header)199 bool GetDMFHeader(const StringList& RawFile, dmfHeader& header)
200 {
201 	StringList temp;
202 	RawFile[0].split(temp, ";"); //file info
203 //	StringList temp=SubdivideString(RawFile[0],";"); //file info
204 
205 	if ( temp[0] != "DeleD Map File" )
206 		return false; //not a deled file
207 
208 	temp.clear();
209 	temp = SubdivideString(RawFile[1]," ");//get version
210 	StringList temp1=SubdivideString(temp[1],";");
211 
212 	header.dmfVersion = (float)atof(temp1[0].c_str());//save version
213 	if (header.dmfVersion < 0.91)
214 		return false;//not correct version
215 
216 	temp.clear();
217 	temp = SubdivideString(RawFile[2],";");//get name,ambient color and shadow opacity
218 	header.dmfName=temp[0];//save name
219 
220 	//set ambient color
221 	header.dmfAmbient.set(axtoi(temp[1].c_str()));
222 
223 	//set Shadow intensity
224 	header.dmfShadow = (float)atof(temp[2].c_str());
225 
226 	//set current position
227 	int offs=3;
228 
229 	//set Materials Number
230 	header.numMaterials=atoi(RawFile[offs].c_str());
231 	offs+=header.numMaterials;
232 	++offs;
233 
234 	//set Object Number
235 	header.numObjects=atoi(RawFile[offs].c_str());
236 
237 	//retrieve face and vertices number
238 	header.numVertices=0;
239 	header.numFaces=0;
240 	header.numWatFaces=0;
241 	header.numWatVertices=0;
242 	offs++;
243 
244 	s32 fac;
245 	int i;
246 
247 	for(i=0; i < (int)header.numObjects; i++)
248 	{
249 		StringList wat=SubdivideString(RawFile[offs],";");
250 		StringList wat1=SubdivideString(wat[0],"_");
251 
252 		++offs;
253 		offs += atoi(RawFile[offs].c_str());
254 		++offs;
255 
256 		fac=atoi(RawFile[offs].c_str());
257 
258 		if(!(wat1[0]=="water" && wat[2]=="0"))
259 			header.numFaces = header.numFaces + fac;
260 		else
261 			header.numWatFaces = header.numWatFaces + fac;
262 
263 		offs++;
264 
265 		for(int j=0; j<fac; j++)
266 		{
267 			if(!(wat1[0] == "water" && wat[2] == "0"))
268 				header.numVertices=header.numVertices + atoi(RawFile[offs+j].c_str());
269 			else
270 				header.numWatVertices=header.numWatVertices + atoi(RawFile[offs + j].c_str());
271 		}
272 
273 		offs = offs + fac;
274 	}
275 
276 	//retrieve number of dynamic lights
277 	header.numLights=0;
278 	temp.clear();
279 	temp1.clear();
280 	s32 lit = atoi(RawFile[offs].c_str());
281 
282 	for (i=0; i<lit; i++)
283 	{
284 		offs++;
285 		temp=SubdivideString(RawFile[offs],";");
286 
287 		if(atoi(temp[0].c_str())==1)
288 		{
289 			temp1=SubdivideString(temp[18],"_");
290 
291 			if(temp1[0]=="dynamic")
292 			header.numLights++;
293 		}
294 		temp.clear();
295 		temp1.clear();
296 	}
297 
298 	return true; //everything is OK so loading is correct
299 }
300 
301 
302 /**This function extract an array of dmfMaterial from a DMF file.
303 You must give in input a StringList representing a DMF file loaded with LoadFromFile.
304 \param RawFile StringList representing a DMF file.
305 \param materials Materials returned.
306 \param num_material Number of materials contained in DMF file.
307 \param use_material_dirs Here you can choose to use default DeleD structure for material dirs.
308 \return true if function succeed or false on fail.*/
GetDMFMaterials(const StringList & RawFile,core::array<dmfMaterial> & materials,int num_material)309 bool GetDMFMaterials(const StringList& RawFile,
310 			core::array<dmfMaterial>& materials,
311 			int num_material)
312 {
313 	// offset for already handled lines
314 	const int offs=4;
315 
316 	StringList temp;
317 	StringList temp1;
318 
319 	// The number of materials is predetermined
320 	materials.reallocate(num_material);
321 	for(int i=0; i<num_material; ++i)
322 	{
323 		materials.push_back(dmfMaterial());
324 		// get all tokens
325 		temp=SubdivideString(RawFile[offs+i],";");
326 		// should be equal to first token
327 		materials[i].materialID = i;
328 		// The path used for the texture
329 		materials[i].pathName = temp[2];
330 		materials[i].pathName.replace('\\','/');
331 		materials[i].pathName += "/";
332 		// temp[3] is reserved, temp[4] is the number of texture layers
333 		materials[i].textureLayers = core::strtoul10(temp[4].c_str());
334 		// Three values are separated by commas
335 		temp1=SubdivideString(temp[5],",");
336 
337 		materials[i].textureFlag = atoi(temp1[0].c_str());
338 		materials[i].textureName=temp1[1];
339 		materials[i].textureName.replace('\\','/');
340 		materials[i].textureBlend = atoi(temp1[2].c_str());
341 		if(temp.size()>=9)
342 		{
343 			temp1=SubdivideString(temp[temp.size() - 1],",");
344 			materials[i].lightmapFlag=atoi(temp1[0].c_str());
345 			materials[i].lightmapName=temp1[1];
346 			materials[i].lightmapName.replace('\\','/');
347 			materials[i].lightmapBlend = atoi(temp1[2].c_str());
348 		}
349 		else
350 		{
351 			materials[i].lightmapFlag=1;
352 			materials[i].lightmapName="";
353 		}
354 	}
355 	return true;
356 }
357 
358 
359 /**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains.
360 You must give in input a StringList representing a DMF file loaded with LoadFromFile.
361 \return true if function succeed or false on fail.*/
GetDMFWaterMaterials(const StringList & RawFile,core::array<dmfMaterial> & materials,int num_material)362 bool GetDMFWaterMaterials(const StringList& RawFile /**<StringList representing a DMF file.*/,
363 		core::array<dmfMaterial>& materials/**<Materials returned.*/,
364 		int num_material/**<Number of materials contained in DMF file.*/
365 		)
366 {
367 	int offs=4;
368 	StringList temp;
369 	StringList temp1;
370 	StringList temp2;
371 	//Checking if this is a DeleD map File of version >= 0.91
372 	temp=SubdivideString(RawFile[0],";");//file info
373 
374 	if ( temp[0] != "DeleD Map File" )
375 		return false;//not a deled file
376 
377 	temp.clear();
378 	temp=SubdivideString(RawFile[1]," ");//get version
379 	temp1=SubdivideString(temp[1],";");
380 
381 	if (atof(temp1[0].c_str()) < 0.91)
382 		return false;//not correct version
383 
384 	//end checking
385 	temp.clear();
386 	temp1.clear();
387 
388 	for(int i=0;i<num_material;i++)
389 	{
390 		temp = SubdivideString(RawFile[offs+i],";");
391 		materials[i].materialID=i;
392 
393 		temp1 = SubdivideString(temp[5],",");
394 		materials[i].textureFlag=atoi(temp1[0].c_str());
395 		temp2 = SubdivideString(temp1[1],"\\");
396 
397 		materials[i].textureName=temp2.getLast();
398 		temp1.clear();
399 		temp2.clear();
400 		int a=temp.size();
401 		if(a==7)
402 		{
403 			temp1=SubdivideString(temp[6],",");
404 			materials[i].lightmapFlag=atoi(temp1[0].c_str());
405 			temp2=SubdivideString(temp1[1],"\\");
406 			materials[i].lightmapName=temp2.getLast();
407 		}
408 		else
409 		{
410 			materials[i].lightmapFlag=1;
411 			materials[i].lightmapName="FFFFFFFF";
412 		}
413 		temp1.clear();
414 		temp2.clear();
415 	}
416 	return true;
417 }
418 
419 
420 /**This function extract an array of dmfVert and dmfFace from a DMF file.
421 You must give in input a StringList representing a DMF file loaded with LoadFromFile and two arrays long enough.
422 Please use GetDMFHeader() before this function to know number of vertices and faces.
423 \return true if function succeed or false on fail.*/
GetDMFVerticesFaces(const StringList & RawFile,dmfVert vertices[],dmfFace faces[])424 bool GetDMFVerticesFaces(const StringList& RawFile/**<StringList representing a DMF file.*/,
425 		dmfVert vertices[]/**<Vertices returned*/,
426 		dmfFace faces[]/**Faces returned*/
427 		)
428 {
429 	StringList temp,temp1;
430 
431 	// skip materials
432 	s32 offs = 4 + atoi(RawFile[3].c_str());
433 
434 	const s32 objs = atoi(RawFile[offs].c_str());
435 	offs++;
436 #ifdef _IRR_DMF_DEBUG_
437 	os::Printer::log("Reading objects", core::stringc(objs).c_str());
438 #endif
439 
440 	s32 vert_cnt=0, face_cnt=0;
441 	for (int i=0; i<objs; ++i)
442 	{
443 		StringList wat=SubdivideString(RawFile[offs],";");
444 		StringList wat1=SubdivideString(wat[0],"_");
445 #ifdef _IRR_DMF_DEBUG_
446 	os::Printer::log("Reading object", wat[0].c_str());
447 #endif
448 
449 		offs++;
450 		// load vertices
451 		core::array<core::vector3df> pos;
452 		const u32 posCount = core::strtoul10(RawFile[offs].c_str());
453 		++offs;
454 		pos.reallocate(posCount);
455 		for (u32 i=0; i<posCount; ++i)
456 		{
457 			temp1=SubdivideString(RawFile[offs].c_str(),";");
458 			pos.push_back(core::vector3df(core::fast_atof(temp1[0].c_str()),
459 					core::fast_atof(temp1[1].c_str()),
460 					-core::fast_atof(temp1[2].c_str())));
461 			++offs;
462 		}
463 
464 		const u32 numFaces=core::strtoul10(RawFile[offs].c_str());
465 		offs++;
466 		if(!(wat1[0]=="water" && wat[2]=="0"))
467 		{
468 			for(u32 j=0; j<numFaces; ++j)
469 			{
470 				temp=SubdivideString(RawFile[offs+j],";");
471 
472 				//first value is vertices number for this face
473 				const u32 vert=core::strtoul10(temp[0].c_str());
474 				faces[face_cnt].numVerts=vert;
475 				//second is material ID
476 				faces[face_cnt].materialID=core::strtoul10(temp[1].c_str());
477 				//vertices are ordined
478 				faces[face_cnt].firstVert=vert_cnt;
479 
480 				//now we'll create vertices structure
481 				for(u32 k=0; k<vert; ++k)
482 				{
483 					//copy position
484 					vertices[vert_cnt].pos.set(pos[core::strtoul10(temp[2+k].c_str())]);
485 					//get uv coords for tex and light if any
486 					vertices[vert_cnt].tc.set(core::fast_atof(temp[2+vert+(2*k)].c_str()),
487 							core::fast_atof(temp[2+vert+(2*k)+1].c_str()));
488 					const u32 tmp_sz=temp.size();
489 					vertices[vert_cnt].lc.set(core::fast_atof(temp[tmp_sz-(2*vert)+(2*k)].c_str()),
490 							core::fast_atof(temp[tmp_sz-(2*vert)+(2*k)+1].c_str()));
491 					vert_cnt++;
492 				}
493 
494 				face_cnt++;
495 			}
496 		}
497 
498 		offs+=numFaces;
499 	}
500 
501 	return true;
502 }
503 
504 
505 /**This function extract an array of dmfLights from a DMF file.
506 You must give in input a StringList representing a DMF file loaded with
507 LoadFromFile and one array long enough.  Please use GetDMFHeader() before this
508 function to know number of dynamic lights.
509 \return true if function succeed or false on fail.*/
GetDMFLights(const StringList & RawFile,dmfLight lights[])510 bool GetDMFLights(const StringList& RawFile/**<StringList representing a DMF file.*/,
511 		dmfLight lights[]/**<Lights returned.*/
512 		)
513 {
514 	int offs=3;
515 	StringList temp,temp1;
516 
517 	//Checking if this is a DeleD map File of version >= 0.91
518 	temp=SubdivideString(RawFile[0],";");//file info
519 
520 	if ( temp[0] != "DeleD Map File" )
521 		return false;//not a deled file
522 
523 	temp.clear();
524 	temp=SubdivideString(RawFile[1]," ");//get version
525 	temp1=SubdivideString(temp[1],";");
526 
527 	if (atof(temp1[0].c_str()) < 0.91)
528 		return false;//not correct version
529 
530 	//end checking
531 
532 	temp.clear();
533 	temp1.clear();
534 	offs=offs + atoi(RawFile[offs].c_str());
535 	offs++;
536 	s32 objs = atoi(RawFile[offs].c_str());
537 	s32 lit=0;
538 	s32 d_lit=0;
539 	offs++;
540 
541 	//let's get position of lights in file
542 	int i;
543 	for(i=0;i<objs;i++)
544 	{
545 		offs++;
546 
547 		offs = offs + atoi(RawFile[offs].c_str());
548 		offs++;
549 
550 		offs = offs + atoi(RawFile[offs].c_str());
551 		offs++;
552 	}
553 
554 	//let's find dynamic lights
555 	lit = atoi(RawFile[offs].c_str());
556 
557 	for(i=0;i<lit;i++)
558 	{
559 		offs++;
560 		temp=SubdivideString(RawFile[offs],";");
561 		if(atoi(temp[0].c_str())==1)
562 		{
563 			temp1=SubdivideString(temp[18],"_");
564 			if(temp1[0]=="dynamic")
565 			{
566 				lights[d_lit].radius = (float)atof(temp[4].c_str());
567 				lights[d_lit].pos.set((float)atof(temp[5].c_str()),
568 						(float)atof(temp[6].c_str()),
569 						(float)-atof(temp[7].c_str()));
570 
571 				lights[d_lit].diffuseColor = video::SColorf(
572 						video::SColor(255, atoi(temp[10].c_str()), atoi(temp[11].c_str()),
573 						atoi(temp[12].c_str())));
574 
575 				lights[d_lit].specularColor = video::SColorf(
576 						video::SColor(255, atoi(temp[13].c_str()), atoi(temp[14].c_str()),
577 						atoi(temp[15].c_str())));
578 
579 				d_lit++;
580 			}
581 		}
582 		temp.clear();
583 		temp1.clear();
584 	}
585 
586 	return true;
587 }
588 
589 
590 /**This function extracts an array of dmfWaterPlane,dmfVert and dmfFace from a DMF file.
591 You must give in input a StringList representing a DMF file loaded with LoadFromFile and three arrays long enough.
592 Please use GetDMFHeader() before this function to know number of water plains and water faces as well as water vertices.
593 \return true if function succeed or false on fail.*/
GetDMFWaterPlanes(const StringList & RawFile,dmfWaterPlane wat_planes[],dmfVert vertices[],dmfFace faces[])594 bool GetDMFWaterPlanes(const StringList& RawFile/**<StringList representing a DMF file.*/,
595 		dmfWaterPlane wat_planes[]/**<Water planes returned.*/,
596 		dmfVert vertices[]/**<Vertices returned*/,
597 		dmfFace faces[]/**Faces returned*/
598 		)
599 {
600 	int offs=3;
601 	int offs1=0;
602 	StringList temp,temp1;
603 
604 	//Checking if this is a DeleD map File of version >= 0.91
605 	temp=SubdivideString(RawFile[0],";");//file info
606 
607 	if ( temp[0] != "DeleD Map File" )
608 		return false;//not a deled file
609 
610 	temp.clear();
611 	temp=SubdivideString(RawFile[1]," ");//get version
612 	temp1=SubdivideString(temp[1],";");
613 
614 	if (atof(temp1[0].c_str()) < 0.91)
615 		return false;//not correct version
616 
617 	//end checking
618 
619 	temp.clear();
620 	temp1.clear();
621 	offs=offs+atoi(RawFile[offs].c_str());
622 	offs++;
623 	s32 objs=atoi(RawFile[offs].c_str());
624 	s32 fac=0,vert=0,tmp_sz=0,vert_cnt=0,face_cnt=0,wat_id=0;
625 	core::dimension2d<u32> tilenum(40,40);
626 	f32 waveheight=3.0f;
627 	f32 wavespeed=300.0f;
628 	f32 wavelength=80.0f;
629 	offs++;
630 
631 	for(int i=0;i<objs;i++)
632 	{
633 		StringList wat=SubdivideString(RawFile[offs],";");
634 		StringList wat1=SubdivideString(wat[0],"_");
635 		offs++;
636 		offs1=offs;
637 		offs=offs+atoi(RawFile[offs].c_str());
638 		offs++;
639 		offs1++;
640 		fac=atoi(RawFile[offs].c_str());
641 		offs++;
642 
643 		if(wat1[0]=="water" && wat[2]=="0")
644 		{
645 			StringList userinfo=SubdivideString(wat[7],",");
646 
647 			int j;
648 
649 			for (j=0; j<(int)userinfo.size(); j++)
650 			{
651 				switch(j)
652 				{
653 				case 0:
654 					if(atoi(userinfo[0].c_str()))
655 						tilenum.Width = atoi(userinfo[0].c_str());
656 				break;
657 				case 1:
658 					if(atoi(userinfo[1].c_str()))
659 						tilenum.Height = atoi(userinfo[1].c_str());
660 				break;
661 				case 2:
662 					if(atof(userinfo[2].c_str()))
663 						waveheight = (float)atof(userinfo[2].c_str());
664 				break;
665 				case 3:
666 					if(atof(userinfo[3].c_str()))
667 						wavespeed = (float)atof(userinfo[3].c_str());
668 				break;
669 				case 4:
670 					if(atof(userinfo[4].c_str()))
671 						wavelength = (float)atof(userinfo[4].c_str());
672 				break;
673 				}
674 			}
675 
676 			wat_planes[wat_id].waterID=wat_id;
677 			wat_planes[wat_id].numFaces=fac;
678 			wat_planes[wat_id].firstFace=face_cnt;
679 			wat_planes[wat_id].tileNum=tilenum;
680 			wat_planes[wat_id].waveHeight=waveheight;
681 			wat_planes[wat_id].waveSpeed=wavespeed;
682 			wat_planes[wat_id].waveLength=wavelength;
683 
684 			for(j=0;j<fac;j++)
685 			{
686 				temp=SubdivideString(RawFile[offs+j],";");
687 
688 				//first value is vertices number for this face
689 				faces[face_cnt].numVerts=atoi(temp[0].c_str());
690 				vert=faces[face_cnt].numVerts;
691 				//second is material ID
692 				faces[face_cnt].materialID=atoi(temp[1].c_str());
693 				//vertices are ordined
694 				faces[face_cnt].firstVert=vert_cnt;
695 
696 				//now we'll create vertices structure
697 				for(int k=0;k<vert;k++)
698 				{
699 					//get vertex position
700 					temp1=SubdivideString(RawFile[offs1+atoi(temp[2+k].c_str())], ";");
701 
702 					//copy x,y,z values
703 					vertices[vert_cnt].pos.set((float)atof(temp1[0].c_str()),
704 							(float)atof(temp1[1].c_str()),
705 							(float)-atof(temp1[2].c_str()));
706 
707 					//get uv coords for tex and light if any
708 					vertices[vert_cnt].tc.set((float)atof(temp[2+vert+(2*k)].c_str()),
709 							(float)atof(temp[2+vert+(2*k)+1].c_str()));
710 					tmp_sz=temp.size();
711 
712 					vertices[vert_cnt].lc.set((float)atof(temp[tmp_sz-(2*vert)+(2*k)].c_str()),
713 							(float)atof(temp[tmp_sz-(2*vert)+(2*k)+1].c_str()));
714 					++vert_cnt;
715 					temp1.clear();
716 				}
717 				++face_cnt;
718 				temp.clear();
719 			}
720 		}
721 		offs=offs+fac;
722 	}
723 
724 	return true;
725 }
726 
727 } // end namespace
728 } // end namespace scene
729 } // end namespace irr
730 
731 #endif /* __DMF_SUPPORT_H__ */
732 
733