~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CLMTSMeshFileLoader.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
// This file was written by Jonas Petersen and modified by Nikolaus Gebhardt.
 
5
// See CLMTSMeshFileLoder.h for details.
 
6
/*
 
7
 
 
8
CLMTSMeshFileLoader.cpp
 
9
 
 
10
LMTSMeshFileLoader
 
11
Written by Jonas Petersen (a.k.a. jox)
 
12
 
 
13
Version 1.5 - 15 March 2005
 
14
 
 
15
Get the latest version here: http://development.mindfloaters.de/
 
16
 
 
17
This class allows loading meshes with lightmaps (*.lmts + *.tga files) that were created
 
18
using Pulsar LMTools by Lord Trancos (http://www.geocities.com/dxlab/index_en.html)
 
19
 
 
20
Notes:
 
21
- This version does not support user data in the *.lmts files, but still loads those files (by skipping the extra data).
 
22
 
 
23
License:
 
24
--------
 
25
 
 
26
It's free. You are encouraged to give me credit if you use it in your software.
 
27
 
 
28
Version History:
 
29
----------------
 
30
 
 
31
Version 1.5 - 15 March 2005
 
32
- Did a better cleanup. No memory leaks in case of an loading error.
 
33
- Added "#include <stdio.h>" for sprintf.
 
34
 
 
35
Version 1.4 - 12 March 2005
 
36
- Fixed bug in texture and subset loading code that would possibly cause crash.
 
37
- Fixed memory cleanup to avoid leak when loading more then one mesh
 
38
- Used the irrlicht Logger instead of cerr to output warnings and errors.
 
39
  For this I had to change the constructor
 
40
  from:
 
41
        CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver)
 
42
  to:
 
43
        CLMTSMeshFileLoader(IrrlichtDevice* device)
 
44
 
 
45
Version 1.3 - 15 February 2005
 
46
- Fixed bug that prevented loading more than one different lmts files.
 
47
- Removed unnecessary "#include <os.h>".
 
48
- Added "std::" in front of "cerr". This was necessary for Visual Studio .NET,
 
49
  I hope it's not disturbing other compilers.
 
50
- Added warning message when a texture can not be loaded.
 
51
- Changed the documentation a bit (minor).
 
52
 
 
53
Version 1.2
 
54
- To avoid confusion I skipped version 1.2 because the website was offering
 
55
version 1.2 even though it was only version 1.1. Sorry about that.
 
56
 
 
57
Version 1.1 - 29 July 2004
 
58
- Added setTexturePath() function
 
59
- Minor improvements
 
60
 
 
61
Version 1.0 - 29 July 2004
 
62
- Initial release
 
63
 
 
64
 
 
65
*/
 
66
//////////////////////////////////////////////////////////////////////
 
67
 
 
68
#include "IrrCompileConfig.h"
 
69
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
 
70
 
 
71
#include "SMeshBufferLightMap.h"
 
72
#include "SAnimatedMesh.h"
 
73
#include "SMeshBuffer.h"
 
74
#include "irrString.h"
 
75
#include "IReadFile.h"
 
76
#include "IAttributes.h"
 
77
#include "ISceneManager.h"
 
78
#include "CLMTSMeshFileLoader.h"
 
79
#include "os.h"
 
80
 
 
81
namespace irr
 
82
{
 
83
namespace scene
 
84
{
 
85
 
 
86
CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs,
 
87
                video::IVideoDriver* driver, io::IAttributes* parameters)
 
88
        : Textures(0), Subsets(0), Triangles(0),
 
89
        Parameters(parameters), Driver(driver), FileSystem(fs), FlipEndianess(false)
 
90
{
 
91
        #ifdef _DEBUG
 
92
        setDebugName("CLMTSMeshFileLoader");
 
93
        #endif
 
94
 
 
95
        if (Driver)
 
96
                Driver->grab();
 
97
 
 
98
        if (FileSystem)
 
99
                FileSystem->grab();
 
100
}
 
101
 
 
102
 
 
103
CLMTSMeshFileLoader::~CLMTSMeshFileLoader()
 
104
{
 
105
        cleanup();
 
106
 
 
107
        if (Driver)
 
108
                Driver->drop();
 
109
 
 
110
        if (FileSystem)
 
111
                FileSystem->drop();
 
112
}
 
113
 
 
114
 
 
115
void CLMTSMeshFileLoader::cleanup()
 
116
{
 
117
        delete [] Textures;
 
118
        Textures = 0;
 
119
        delete [] Subsets;
 
120
        Subsets = 0;
 
121
        delete [] Triangles;
 
122
        Triangles = 0;
 
123
}
 
124
 
 
125
 
 
126
bool CLMTSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
 
127
{
 
128
        return core::hasFileExtension ( filename, "lmts" );
 
129
}
 
130
 
 
131
 
 
132
IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
 
133
{
 
134
        u32 i;
 
135
        u32 id;
 
136
 
 
137
        // HEADER
 
138
 
 
139
        file->read(&Header, sizeof(SLMTSHeader));
 
140
        if (Header.MagicID == 0x4C4D5354)
 
141
        {
 
142
                FlipEndianess = true;
 
143
                Header.MagicID = os::Byteswap::byteswap(Header.MagicID);
 
144
                Header.Version = os::Byteswap::byteswap(Header.Version);
 
145
                Header.HeaderSize = os::Byteswap::byteswap(Header.HeaderSize);
 
146
                Header.TextureCount = os::Byteswap::byteswap(Header.TextureCount);
 
147
                Header.SubsetCount = os::Byteswap::byteswap(Header.SubsetCount);
 
148
                Header.TriangleCount = os::Byteswap::byteswap(Header.TriangleCount);
 
149
                Header.SubsetSize = os::Byteswap::byteswap(Header.SubsetSize);
 
150
                Header.VertexSize = os::Byteswap::byteswap(Header.VertexSize);
 
151
        }
 
152
        if (Header.MagicID != 0x53544D4C) { // "LMTS"
 
153
                os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR);
 
154
                return 0;
 
155
        }
 
156
 
 
157
        //Skip any User Data (arbitrary app specific data)
 
158
 
 
159
        const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader);
 
160
        if (userSize>0)
 
161
                file->seek(userSize,true);
 
162
 
 
163
        // TEXTURES
 
164
 
 
165
        file->read(&id, sizeof(u32));
 
166
        if (FlipEndianess)
 
167
                id = os::Byteswap::byteswap(id);
 
168
        if (id != 0x54584554) { // "TEXT"
 
169
                os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR);
 
170
                return 0;
 
171
        }
 
172
 
 
173
        Textures = new SLMTSTextureInfoEntry[Header.TextureCount];
 
174
 
 
175
        file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount);
 
176
        if (FlipEndianess)
 
177
        {
 
178
                for (i=0; i<Header.TextureCount; ++i)
 
179
                        Textures[i].Flags = os::Byteswap::byteswap(Textures[i].Flags);
 
180
        }
 
181
 
 
182
        // SUBSETS
 
183
 
 
184
        file->read(&id, sizeof(u32));
 
185
        if (FlipEndianess)
 
186
                id = os::Byteswap::byteswap(id);
 
187
        if (id != 0x53425553) // "SUBS"
 
188
        {
 
189
                os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR);
 
190
                cleanup();
 
191
                return 0;
 
192
        }
 
193
 
 
194
        Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount];
 
195
        const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry);
 
196
 
 
197
        for (i=0; i<Header.SubsetCount; ++i)
 
198
        {
 
199
                file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry));
 
200
                if (FlipEndianess)
 
201
                {
 
202
                        Subsets[i].Offset = os::Byteswap::byteswap(Subsets[i].Offset);
 
203
                        Subsets[i].Count = os::Byteswap::byteswap(Subsets[i].Count);
 
204
                        Subsets[i].TextID1 = os::Byteswap::byteswap(Subsets[i].TextID1);
 
205
                        Subsets[i].TextID2 = os::Byteswap::byteswap(Subsets[i].TextID2);
 
206
                }
 
207
                if (subsetUserSize>0)
 
208
                        file->seek(subsetUserSize,true);
 
209
        }
 
210
 
 
211
        // TRIANGLES
 
212
 
 
213
        file->read(&id, sizeof(u32));
 
214
        if (FlipEndianess)
 
215
                id = os::Byteswap::byteswap(id);
 
216
        if (id != 0x53495254) // "TRIS"
 
217
        {
 
218
                os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR);
 
219
                cleanup();
 
220
                return 0;
 
221
        }
 
222
 
 
223
        Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)];
 
224
        const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry);
 
225
 
 
226
        for (i=0; i<(Header.TriangleCount*3); ++i)
 
227
        {
 
228
                file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry));
 
229
                if (FlipEndianess)
 
230
                {
 
231
                        Triangles[i].X = os::Byteswap::byteswap(Triangles[i].X);
 
232
                        Triangles[i].Y = os::Byteswap::byteswap(Triangles[i].Y);
 
233
                        Triangles[i].Z = os::Byteswap::byteswap(Triangles[i].Z);
 
234
                        Triangles[i].U1 = os::Byteswap::byteswap(Triangles[i].U1);
 
235
                        Triangles[i].V1 = os::Byteswap::byteswap(Triangles[i].U2);
 
236
                        Triangles[i].U2 = os::Byteswap::byteswap(Triangles[i].V1);
 
237
                        Triangles[i].V2 = os::Byteswap::byteswap(Triangles[i].V2);
 
238
                }
 
239
                if (triUserSize>0)
 
240
                        file->seek(triUserSize,true);
 
241
        }
 
242
 
 
243
        /////////////////////////////////////////////////////////////////
 
244
 
 
245
        SMesh* mesh = new SMesh();
 
246
 
 
247
        constructMesh(mesh);
 
248
 
 
249
        loadTextures(mesh);
 
250
 
 
251
        cleanup();
 
252
 
 
253
        SAnimatedMesh* am = new SAnimatedMesh();
 
254
        am->Type = EAMT_LMTS; // not unknown to irrlicht anymore
 
255
 
 
256
        am->addMesh(mesh);
 
257
        am->recalculateBoundingBox();
 
258
        mesh->drop();
 
259
        return am;
 
260
}
 
261
 
 
262
 
 
263
void CLMTSMeshFileLoader::constructMesh(SMesh* mesh)
 
264
{
 
265
        for (s32 i=0; i<Header.SubsetCount; ++i)
 
266
        {
 
267
                scene::SMeshBufferLightMap* meshBuffer = new scene::SMeshBufferLightMap();
 
268
 
 
269
                // EMT_LIGHTMAP_M2/EMT_LIGHTMAP_M4 also possible
 
270
                meshBuffer->Material.MaterialType = video::EMT_LIGHTMAP;
 
271
                meshBuffer->Material.Wireframe = false;
 
272
                meshBuffer->Material.Lighting = false;
 
273
 
 
274
                mesh->addMeshBuffer(meshBuffer);
 
275
 
 
276
                const u32 offs = Subsets[i].Offset * 3;
 
277
 
 
278
                for (u32 sc=0; sc<Subsets[i].Count; sc++)
 
279
                {
 
280
                        const u32 idx = meshBuffer->getVertexCount();
 
281
 
 
282
                        for (u32 vu=0; vu<3; ++vu)
 
283
                        {
 
284
                                const SLMTSTriangleDataEntry& v = Triangles[offs+(3*sc)+vu];
 
285
                                meshBuffer->Vertices.push_back(
 
286
                                                video::S3DVertex2TCoords(
 
287
                                                        v.X, v.Y, v.Z,
 
288
                                                        video::SColor(255,255,255,255),
 
289
                                                        v.U1, v.V1, v.U2, v.V2));
 
290
                        }
 
291
                        const core::vector3df normal = core::plane3df(
 
292
                                meshBuffer->Vertices[idx].Pos,
 
293
                                meshBuffer->Vertices[idx+1].Pos,
 
294
                                meshBuffer->Vertices[idx+2].Pos).Normal;
 
295
 
 
296
                        meshBuffer->Vertices[idx].Normal = normal;
 
297
                        meshBuffer->Vertices[idx+1].Normal = normal;
 
298
                        meshBuffer->Vertices[idx+2].Normal = normal;
 
299
 
 
300
                        meshBuffer->Indices.push_back(idx);
 
301
                        meshBuffer->Indices.push_back(idx+1);
 
302
                        meshBuffer->Indices.push_back(idx+2);
 
303
                }
 
304
                meshBuffer->drop();
 
305
        }
 
306
 
 
307
        for (u32 j=0; j<mesh->MeshBuffers.size(); ++j)
 
308
                mesh->MeshBuffers[j]->recalculateBoundingBox();
 
309
 
 
310
        mesh->recalculateBoundingBox();
 
311
}
 
312
 
 
313
 
 
314
void CLMTSMeshFileLoader::loadTextures(SMesh* mesh)
 
315
{
 
316
        if (!Driver || !FileSystem)
 
317
                return;
 
318
 
 
319
        // load textures
 
320
 
 
321
        // a little too much space, but won't matter here
 
322
        core::array<video::ITexture*> tex;
 
323
        tex.reallocate(Header.TextureCount);
 
324
        core::array<video::ITexture*> lig;
 
325
        lig.reallocate(Header.TextureCount);
 
326
        core::array<u32> id2id;
 
327
        id2id.reallocate(Header.TextureCount);
 
328
 
 
329
        const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH);
 
330
 
 
331
        core::stringc s;
 
332
        for (u32 t=0; t<Header.TextureCount; ++t)
 
333
        {
 
334
                video::ITexture* tmptex = 0;
 
335
                s = Path;
 
336
                s.append(Textures[t].Filename);
 
337
 
 
338
                if (FileSystem->existFile(s))
 
339
                        tmptex = Driver->getTexture(s);
 
340
                else
 
341
                        os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING);
 
342
 
 
343
                if (Textures[t].Flags & 0x01)
 
344
                {
 
345
                        id2id.push_back(lig.size());
 
346
                        lig.push_back(tmptex);
 
347
                }
 
348
                else
 
349
                {
 
350
                        id2id.push_back(tex.size());
 
351
                        tex.push_back(tmptex);
 
352
                }
 
353
        }
 
354
 
 
355
        // attach textures to materials.
 
356
 
 
357
        for (u32 i=0; i<Header.SubsetCount; ++i)
 
358
        {
 
359
                if (Subsets[i].TextID1 < Header.TextureCount && id2id[Subsets[i].TextID1] < tex.size())
 
360
                        mesh->getMeshBuffer(i)->getMaterial().setTexture(0, tex[id2id[Subsets[i].TextID1]]);
 
361
                if (Subsets[i].TextID2 < Header.TextureCount && id2id[Subsets[i].TextID2] < lig.size())
 
362
                        mesh->getMeshBuffer(i)->getMaterial().setTexture(1, lig[id2id[Subsets[i].TextID2]]);
 
363
 
 
364
                if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1))
 
365
                        mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID;
 
366
        }
 
367
}
 
368
 
 
369
 
 
370
} // end namespace scene
 
371
} // end namespace irr
 
372
 
 
373
#endif // _IRR_COMPILE_WITH_LMTS_LOADER_