aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp436
1 files changed, 436 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp
new file mode 100644
index 0000000..b6ed57b
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp
@@ -0,0 +1,436 @@
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 and changes to it and
7// integrated it into Irrlicht.
8// Thanks a lot to Salvatore for his work on this and that he gave me
9// his permission to add it into Irrlicht using the zlib license.
10/*
11 CDMFLoader by Salvatore Russo (September 2005)
12
13 See the header file for additional information including use and distribution rights.
14*/
15
16#include "IrrCompileConfig.h"
17#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
18
19#ifdef _DEBUG
20#define _IRR_DMF_DEBUG_
21#include "os.h"
22#endif
23
24#include "CDMFLoader.h"
25#include "ISceneManager.h"
26#include "IAttributes.h"
27#include "SAnimatedMesh.h"
28#include "SSkinMeshBuffer.h"
29#include "irrString.h"
30#include "irrMath.h"
31#include "dmfsupport.h"
32
33namespace irr
34{
35namespace scene
36{
37
38/** Constructor*/
39CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys)
40: SceneMgr(smgr), FileSystem(filesys)
41{
42 #ifdef _DEBUG
43 IReferenceCounted::setDebugName("CDMFLoader");
44 #endif
45}
46
47
48void CDMFLoader::findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename)
49{
50 // path + texpath + full name
51 if (use_mat_dirs && FileSystem->existFile(path+matPath+filename))
52 filename = path+matPath+filename;
53 // path + full name
54 else if (FileSystem->existFile(path+filename))
55 filename = path+filename;
56 // path + texpath + base name
57 else if (use_mat_dirs && FileSystem->existFile(path+matPath+FileSystem->getFileBasename(filename)))
58 filename = path+matPath+FileSystem->getFileBasename(filename);
59 // path + base name
60 else if (FileSystem->existFile(path+FileSystem->getFileBasename(filename)))
61 filename = path+FileSystem->getFileBasename(filename);
62 // texpath + full name
63 else if (use_mat_dirs && FileSystem->existFile(matPath+filename))
64 filename = matPath+filename;
65 // texpath + base name
66 else if (use_mat_dirs && FileSystem->existFile(matPath+FileSystem->getFileBasename(filename)))
67 filename = matPath+FileSystem->getFileBasename(filename);
68 // base name
69 else if (FileSystem->existFile(FileSystem->getFileBasename(filename)))
70 filename = FileSystem->getFileBasename(filename);
71}
72
73
74/**Creates/loads an animated mesh from the file.
75 \return Pointer to the created mesh. Returns 0 if loading failed.
76 If you no longer need the mesh, you should call IAnimatedMesh::drop().
77 See IReferenceCounted::drop() for more information.*/
78IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file)
79{
80 if (!file)
81 return 0;
82 video::IVideoDriver* driver = SceneMgr->getVideoDriver();
83
84 //Load stringlist
85 StringList dmfRawFile;
86 LoadFromFile(file, dmfRawFile);
87
88 if (dmfRawFile.size()==0)
89 return 0;
90
91 SMesh * mesh = new SMesh();
92
93 u32 i;
94
95 dmfHeader header;
96
97 //load header
98 core::array<dmfMaterial> materiali;
99 if (GetDMFHeader(dmfRawFile, header))
100 {
101 //let's set ambient light
102 SceneMgr->setAmbientLight(header.dmfAmbient);
103
104 //let's create the correct number of materials, vertices and faces
105 dmfVert *verts=new dmfVert[header.numVertices];
106 dmfFace *faces=new dmfFace[header.numFaces];
107
108 //let's get the materials
109#ifdef _IRR_DMF_DEBUG_
110 os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str());
111#endif
112 GetDMFMaterials(dmfRawFile, materiali, header.numMaterials);
113
114 //let's get vertices and faces
115#ifdef _IRR_DMF_DEBUG_
116 os::Printer::log("Loading geometry");
117#endif
118 GetDMFVerticesFaces(dmfRawFile, verts, faces);
119
120 //create a meshbuffer for each material, then we'll remove empty ones
121#ifdef _IRR_DMF_DEBUG_
122 os::Printer::log("Creating meshbuffers.");
123#endif
124 for (i=0; i<header.numMaterials; i++)
125 {
126 //create a new SMeshBufferLightMap for each material
127 SSkinMeshBuffer* buffer = new SSkinMeshBuffer();
128 buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING;
129 buffer->Material.Wireframe = false;
130 buffer->Material.Lighting = true;
131 mesh->addMeshBuffer(buffer);
132 buffer->drop();
133 }
134
135 // Build the mesh buffers
136#ifdef _IRR_DMF_DEBUG_
137 os::Printer::log("Adding geometry to mesh.");
138#endif
139 for (i = 0; i < header.numFaces; i++)
140 {
141#ifdef _IRR_DMF_DEBUG_
142 os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str());
143#endif
144 if (faces[i].numVerts < 3)
145 continue;
146
147 const core::vector3df normal =
148 core::triangle3df(verts[faces[i].firstVert].pos,
149 verts[faces[i].firstVert+1].pos,
150 verts[faces[i].firstVert+2].pos).getNormal().normalize();
151
152 SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer(
153 faces[i].materialID);
154
155 const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() ||
156 materiali[faces[i].materialID].lightmapName.size();
157 if (use2TCoords && meshBuffer->Vertices_Standard.size())
158 meshBuffer->convertTo2TCoords();
159 const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size();
160
161 // Add this face's verts
162 if (use2TCoords)
163 {
164 // make sure we have the proper type set
165 meshBuffer->VertexType=video::EVT_2TCOORDS;
166 for (u32 v = 0; v < faces[i].numVerts; v++)
167 {
168 const dmfVert& vv = verts[faces[i].firstVert + v];
169 video::S3DVertex2TCoords vert(vv.pos,
170 normal, video::SColor(255,255,255,255), vv.tc, vv.lc);
171 if (materiali[faces[i].materialID].textureBlend==4 &&
172 SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
173 {
174 vert.TCoords.set(vv.tc.X,-vv.tc.Y);
175 }
176 meshBuffer->Vertices_2TCoords.push_back(vert);
177 }
178 }
179 else
180 {
181 for (u32 v = 0; v < faces[i].numVerts; v++)
182 {
183 const dmfVert& vv = verts[faces[i].firstVert + v];
184 video::S3DVertex vert(vv.pos,
185 normal, video::SColor(255,255,255,255), vv.tc);
186 if (materiali[faces[i].materialID].textureBlend==4 &&
187 SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
188 {
189 vert.TCoords.set(vv.tc.X,-vv.tc.Y);
190 }
191 meshBuffer->Vertices_Standard.push_back(vert);
192 }
193 }
194
195 // Now add the indices
196 // This weird loop turns convex polygons into triangle strips.
197 // I do it this way instead of a simple fan because it usually
198 // looks a lot better in wireframe, for example.
199 u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center
200 for (u32 v = 0; v < faces[i].numVerts - 2; v++)
201 {
202 if (v & 1) // odd
203 c = h - 1;
204 else // even
205 c = l + 1;
206
207 meshBuffer->Indices.push_back(base + h);
208 meshBuffer->Indices.push_back(base + l);
209 meshBuffer->Indices.push_back(base + c);
210
211 if (v & 1) // odd
212 h--;
213 else // even
214 l++;
215 }
216 }
217
218 delete [] verts;
219 delete [] faces;
220 }
221
222 // delete all buffers without geometry in it.
223#ifdef _IRR_DMF_DEBUG_
224 os::Printer::log("Cleaning meshbuffers.");
225#endif
226 i = 0;
227 while(i < mesh->MeshBuffers.size())
228 {
229 if (mesh->MeshBuffers[i]->getVertexCount() == 0 ||
230 mesh->MeshBuffers[i]->getIndexCount() == 0)
231 {
232 // Meshbuffer is empty -- drop it
233 mesh->MeshBuffers[i]->drop();
234 mesh->MeshBuffers.erase(i);
235 materiali.erase(i);
236 }
237 else
238 {
239 i++;
240 }
241 }
242
243
244 {
245 //load textures and lightmaps in materials.
246 //don't worry if you receive a could not load texture, cause if you don't need
247 //a particular material in your scene it will be loaded and then destroyed.
248#ifdef _IRR_DMF_DEBUG_
249 os::Printer::log("Loading textures.");
250#endif
251 const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS);
252
253 core::stringc path;
254 if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) )
255 path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH);
256 else
257 path = FileSystem->getFileDir(file->getFileName());
258 path += ('/');
259
260 for (i=0; i<mesh->getMeshBufferCount(); i++)
261 {
262 //texture and lightmap
263 video::ITexture *tex = 0;
264 video::ITexture *lig = 0;
265
266 //current buffer to apply material
267 video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial();
268
269 //Primary texture is normal
270 if (materiali[i].textureFlag==0)
271 {
272 if (materiali[i].textureBlend==4)
273 driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
274 findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName);
275 tex = driver->getTexture(materiali[i].textureName);
276 }
277 //Primary texture is just a color
278 else if(materiali[i].textureFlag==1)
279 {
280 video::SColor color(axtoi(materiali[i].textureName.c_str()));
281
282 //just for compatibility with older Irrlicht versions
283 //to support transparent materials
284 if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
285 driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
286
287 video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8,
288 core::dimension2d<u32>(8,8));
289 immagine->fill(color);
290 tex = driver->addTexture("", immagine);
291 immagine->drop();
292
293 //to support transparent materials
294 if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
295 {
296 mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
297 mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f);
298 }
299 }
300
301 //Lightmap is present
302 if (materiali[i].lightmapFlag == 0)
303 {
304 findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName);
305 lig = driver->getTexture(materiali[i].lightmapName);
306 }
307 else //no lightmap
308 {
309 mat.MaterialType = video::EMT_SOLID;
310 const f32 mult = 100.0f - header.dmfShadow;
311 mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f);
312 }
313
314 if (materiali[i].textureBlend==4)
315 {
316 mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
317 mat.MaterialTypeParam =
318 SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF);
319 }
320
321 //if texture is present mirror vertically owing to DeleD representation
322 if (tex && header.dmfVersion<1.1)
323 {
324 const core::dimension2d<u32> texsize = tex->getSize();
325 void* pp = tex->lock();
326 if (pp)
327 {
328 const video::ECOLOR_FORMAT format = tex->getColorFormat();
329 if (format == video::ECF_A1R5G5B5)
330 {
331 s16* p = (s16*)pp;
332 s16 tmp=0;
333 for (u32 x=0; x<texsize.Width; x++)
334 for (u32 y=0; y<texsize.Height/2; y++)
335 {
336 tmp=p[y*texsize.Width + x];
337 p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
338 p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
339 }
340 }
341 else
342 if (format == video::ECF_A8R8G8B8)
343 {
344 s32* p = (s32*)pp;
345 s32 tmp=0;
346 for (u32 x=0; x<texsize.Width; x++)
347 for (u32 y=0; y<texsize.Height/2; y++)
348 {
349 tmp=p[y*texsize.Width + x];
350 p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
351 p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
352 }
353 }
354 }
355 tex->unlock();
356 tex->regenerateMipMapLevels();
357 }
358
359 //if lightmap is present mirror vertically owing to DeleD rapresentation
360 if (lig && header.dmfVersion<1.1)
361 {
362 const core::dimension2d<u32> ligsize=lig->getSize();
363 void* pp = lig->lock();
364 if (pp)
365 {
366 video::ECOLOR_FORMAT format = lig->getColorFormat();
367 if (format == video::ECF_A1R5G5B5)
368 {
369 s16* p = (s16*)pp;
370 s16 tmp=0;
371 for (u32 x=0; x<ligsize.Width; x++)
372 {
373 for (u32 y=0; y<ligsize.Height/2; y++)
374 {
375 tmp=p[y*ligsize.Width + x];
376 p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
377 p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
378 }
379 }
380 }
381 else if (format == video::ECF_A8R8G8B8)
382 {
383 s32* p = (s32*)pp;
384 s32 tmp=0;
385 for (u32 x=0; x<ligsize.Width; x++)
386 {
387 for (u32 y=0; y<ligsize.Height/2; y++)
388 {
389 tmp=p[y*ligsize.Width + x];
390 p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
391 p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
392 }
393 }
394 }
395 }
396 lig->unlock();
397 lig->regenerateMipMapLevels();
398 }
399
400 mat.setTexture(0, tex);
401 mat.setTexture(1, lig);
402 }
403 }
404
405 // create bounding box
406 for (i = 0; i < mesh->MeshBuffers.size(); ++i)
407 {
408 mesh->MeshBuffers[i]->recalculateBoundingBox();
409 }
410 mesh->recalculateBoundingBox();
411
412 // Set up an animated mesh to hold the mesh
413 SAnimatedMesh* AMesh = new SAnimatedMesh();
414 AMesh->Type = EAMT_UNKNOWN;
415 AMesh->addMesh(mesh);
416 AMesh->recalculateBoundingBox();
417 mesh->drop();
418
419 return AMesh;
420}
421
422
423/** \brief Tell us if this file is able to be loaded by this class
424 based on the file extension (e.g. ".bsp")
425 \return true if file is loadable.*/
426bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const
427{
428 return core::hasFileExtension ( filename, "dmf" );
429}
430
431
432} // end namespace scene
433} // end namespace irr
434
435#endif // _IRR_COMPILE_WITH_DMF_LOADER_
436