~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CDMFLoader.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 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 colour
 
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