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.
8
CLMTSMeshFileLoader.cpp
11
Written by Jonas Petersen (a.k.a. jox)
13
Version 1.5 - 15 March 2005
15
Get the latest version here: http://development.mindfloaters.de/
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)
21
- This version does not support user data in the *.lmts files, but still loads those files (by skipping the extra data).
26
It's free. You are encouraged to give me credit if you use it in your software.
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.
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
41
CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver)
43
CLMTSMeshFileLoader(IrrlichtDevice* device)
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).
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.
57
Version 1.1 - 29 July 2004
58
- Added setTexturePath() function
61
Version 1.0 - 29 July 2004
66
//////////////////////////////////////////////////////////////////////
68
#include "IrrCompileConfig.h"
69
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
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"
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)
92
setDebugName("CLMTSMeshFileLoader");
103
CLMTSMeshFileLoader::~CLMTSMeshFileLoader()
115
void CLMTSMeshFileLoader::cleanup()
126
bool CLMTSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
128
return core::hasFileExtension ( filename, "lmts" );
132
IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
139
file->read(&Header, sizeof(SLMTSHeader));
140
if (Header.MagicID == 0x4C4D5354)
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);
152
if (Header.MagicID != 0x53544D4C) { // "LMTS"
153
os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR);
157
//Skip any User Data (arbitrary app specific data)
159
const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader);
161
file->seek(userSize,true);
165
file->read(&id, sizeof(u32));
167
id = os::Byteswap::byteswap(id);
168
if (id != 0x54584554) { // "TEXT"
169
os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR);
173
Textures = new SLMTSTextureInfoEntry[Header.TextureCount];
175
file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount);
178
for (i=0; i<Header.TextureCount; ++i)
179
Textures[i].Flags = os::Byteswap::byteswap(Textures[i].Flags);
184
file->read(&id, sizeof(u32));
186
id = os::Byteswap::byteswap(id);
187
if (id != 0x53425553) // "SUBS"
189
os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR);
194
Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount];
195
const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry);
197
for (i=0; i<Header.SubsetCount; ++i)
199
file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry));
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);
207
if (subsetUserSize>0)
208
file->seek(subsetUserSize,true);
213
file->read(&id, sizeof(u32));
215
id = os::Byteswap::byteswap(id);
216
if (id != 0x53495254) // "TRIS"
218
os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR);
223
Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)];
224
const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry);
226
for (i=0; i<(Header.TriangleCount*3); ++i)
228
file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry));
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);
240
file->seek(triUserSize,true);
243
/////////////////////////////////////////////////////////////////
245
SMesh* mesh = new SMesh();
253
SAnimatedMesh* am = new SAnimatedMesh();
254
am->Type = EAMT_LMTS; // not unknown to irrlicht anymore
257
am->recalculateBoundingBox();
263
void CLMTSMeshFileLoader::constructMesh(SMesh* mesh)
265
for (s32 i=0; i<Header.SubsetCount; ++i)
267
scene::SMeshBufferLightMap* meshBuffer = new scene::SMeshBufferLightMap();
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;
274
mesh->addMeshBuffer(meshBuffer);
276
const u32 offs = Subsets[i].Offset * 3;
278
for (u32 sc=0; sc<Subsets[i].Count; sc++)
280
const u32 idx = meshBuffer->getVertexCount();
282
for (u32 vu=0; vu<3; ++vu)
284
const SLMTSTriangleDataEntry& v = Triangles[offs+(3*sc)+vu];
285
meshBuffer->Vertices.push_back(
286
video::S3DVertex2TCoords(
288
video::SColor(255,255,255,255),
289
v.U1, v.V1, v.U2, v.V2));
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;
296
meshBuffer->Vertices[idx].Normal = normal;
297
meshBuffer->Vertices[idx+1].Normal = normal;
298
meshBuffer->Vertices[idx+2].Normal = normal;
300
meshBuffer->Indices.push_back(idx);
301
meshBuffer->Indices.push_back(idx+1);
302
meshBuffer->Indices.push_back(idx+2);
307
for (u32 j=0; j<mesh->MeshBuffers.size(); ++j)
308
mesh->MeshBuffers[j]->recalculateBoundingBox();
310
mesh->recalculateBoundingBox();
314
void CLMTSMeshFileLoader::loadTextures(SMesh* mesh)
316
if (!Driver || !FileSystem)
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);
329
const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH);
332
for (u32 t=0; t<Header.TextureCount; ++t)
334
video::ITexture* tmptex = 0;
336
s.append(Textures[t].Filename);
338
if (FileSystem->existFile(s))
339
tmptex = Driver->getTexture(s);
341
os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING);
343
if (Textures[t].Flags & 0x01)
345
id2id.push_back(lig.size());
346
lig.push_back(tmptex);
350
id2id.push_back(tex.size());
351
tex.push_back(tmptex);
355
// attach textures to materials.
357
for (u32 i=0; i<Header.SubsetCount; ++i)
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]]);
364
if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1))
365
mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID;
370
} // end namespace scene
371
} // end namespace irr
373
#endif // _IRR_COMPILE_WITH_LMTS_LOADER_