diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CDMFLoader.cpp | 436 |
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 | |||
33 | namespace irr | ||
34 | { | ||
35 | namespace scene | ||
36 | { | ||
37 | |||
38 | /** Constructor*/ | ||
39 | CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys) | ||
40 | : SceneMgr(smgr), FileSystem(filesys) | ||
41 | { | ||
42 | #ifdef _DEBUG | ||
43 | IReferenceCounted::setDebugName("CDMFLoader"); | ||
44 | #endif | ||
45 | } | ||
46 | |||
47 | |||
48 | void 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.*/ | ||
78 | IAnimatedMesh* 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.*/ | ||
426 | bool 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 | |||