Commit b9f35ed0 authored by hybrid's avatar hybrid

Fixed several issues with the LMTS format. Simplified the general loading procedure.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1762 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 16640845
...@@ -21,7 +21,7 @@ This class allows loading meshes with lightmaps (*.lmts + *.tga files) that were ...@@ -21,7 +21,7 @@ This class allows loading meshes with lightmaps (*.lmts + *.tga files) that were
using Pulsar LMTools by Lord Trancos (http://www.geocities.com/dxlab/index_en.html) using Pulsar LMTools by Lord Trancos (http://www.geocities.com/dxlab/index_en.html)
Notes: Notes:
- This version does not recognice/support user data in the *.lmts files. - This version does not support user data in the *.lmts files, but still loads those files (by skipping the extra data).
- The lightmap TGA's generated by LMTools doesn't work in Irrlicht for some reason (the - The lightmap TGA's generated by LMTools doesn't work in Irrlicht for some reason (the
lightmaps look messed up). Opening and resaving them in a graphics app will solve lightmaps look messed up). Opening and resaving them in a graphics app will solve
the problem (tested only with Photoshop). the problem (tested only with Photoshop).
...@@ -93,7 +93,7 @@ namespace scene ...@@ -93,7 +93,7 @@ namespace scene
CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs, CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs,
video::IVideoDriver* driver, io::IAttributes* parameters) video::IVideoDriver* driver, io::IAttributes* parameters)
: Textures(0), Subsets(0), Triangles(0), : Textures(0), Subsets(0), Triangles(0),
Parameters(parameters), Driver(driver), FileSystem(fs) Parameters(parameters), Driver(driver), FileSystem(fs), FlipEndianess(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CLMTSMeshFileLoader"); setDebugName("CLMTSMeshFileLoader");
...@@ -109,6 +109,8 @@ CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs, ...@@ -109,6 +109,8 @@ CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs,
CLMTSMeshFileLoader::~CLMTSMeshFileLoader() CLMTSMeshFileLoader::~CLMTSMeshFileLoader()
{ {
cleanup();
if (Driver) if (Driver)
Driver->drop(); Driver->drop();
...@@ -120,8 +122,11 @@ CLMTSMeshFileLoader::~CLMTSMeshFileLoader() ...@@ -120,8 +122,11 @@ CLMTSMeshFileLoader::~CLMTSMeshFileLoader()
void CLMTSMeshFileLoader::cleanup() void CLMTSMeshFileLoader::cleanup()
{ {
delete [] Textures; delete [] Textures;
Textures = 0;
delete [] Subsets; delete [] Subsets;
Subsets = 0;
delete [] Triangles; delete [] Triangles;
Triangles = 0;
} }
...@@ -139,44 +144,53 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) ...@@ -139,44 +144,53 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
// HEADER // HEADER
file->read(&Header, sizeof(SLMTSHeader)); file->read(&Header, sizeof(SLMTSHeader));
if (Header.MagicID == 0x4C4D5354)
{
FlipEndianess = true;
Header.MagicID = os::Byteswap::byteswap(Header.MagicID);
Header.Version = os::Byteswap::byteswap(Header.Version);
Header.HeaderSize = os::Byteswap::byteswap(Header.HeaderSize);
Header.TextureCount = os::Byteswap::byteswap(Header.TextureCount);
Header.SubsetCount = os::Byteswap::byteswap(Header.SubsetCount);
Header.TriangleCount = os::Byteswap::byteswap(Header.TriangleCount);
Header.SubsetSize = os::Byteswap::byteswap(Header.SubsetSize);
Header.VertexSize = os::Byteswap::byteswap(Header.VertexSize);
}
if (Header.MagicID != 0x53544D4C) { // "LMTS" if (Header.MagicID != 0x53544D4C) { // "LMTS"
os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR); os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR);
return 0; return 0;
} }
//Skip any User Data (additional chunk of data called MATI) //Skip any User Data (arbitrary app specific data)
const s32 UserSize = Header.HeaderSize - sizeof(SLMTSHeader); const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader);
if (UserSize>0) if (userSize>0)
file->seek(UserSize,true); file->seek(userSize,true);
// TEXTURES // TEXTURES
file->read(&id, sizeof(u32)); file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x54584554) { // "TEXT" if (id != 0x54584554) { // "TEXT"
os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR); os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR);
return 0; return 0;
} }
Textures = new SLMTSTextureInfoEntry[Header.TextureCount]; Textures = new SLMTSTextureInfoEntry[Header.TextureCount];
core::array<u32> textureIDs;
textureIDs.reallocate(Header.TextureCount);
u32 numLightMaps = 0;
u32 numTextures = 0;
for (i=0; i<Header.TextureCount; ++i) file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount);
if (FlipEndianess)
{ {
file->read(&Textures[i], sizeof(SLMTSTextureInfoEntry)); for (i=0; i<Header.TextureCount; ++i)
if (Textures[i].Flags & 1) Textures[i].Flags = os::Byteswap::byteswap(Textures[i].Flags);
textureIDs.push_back(numLightMaps++);
else
textureIDs.push_back(numTextures++);
} }
// SUBSETS // SUBSETS
file->read(&id, sizeof(u32)); file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x53425553) // "SUBS" if (id != 0x53425553) // "SUBS"
{ {
os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR); os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR);
...@@ -185,13 +199,27 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) ...@@ -185,13 +199,27 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
} }
Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount]; Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount];
const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry);
for (i=0; i<Header.SubsetCount; ++i) for (i=0; i<Header.SubsetCount; ++i)
{
file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry)); file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry));
if (FlipEndianess)
{
Subsets[i].Offset = os::Byteswap::byteswap(Subsets[i].Offset);
Subsets[i].Count = os::Byteswap::byteswap(Subsets[i].Count);
Subsets[i].TextID1 = os::Byteswap::byteswap(Subsets[i].TextID1);
Subsets[i].TextID2 = os::Byteswap::byteswap(Subsets[i].TextID2);
}
if (subsetUserSize>0)
file->seek(subsetUserSize,true);
}
// TRIANGLES // TRIANGLES
file->read(&id, sizeof(u32)); file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x53495254) // "TRIS" if (id != 0x53495254) // "TRIS"
{ {
os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR); os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR);
...@@ -200,9 +228,24 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) ...@@ -200,9 +228,24 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
} }
Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)]; Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)];
const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry);
for (i=0; i<(Header.TriangleCount*3); ++i) for (i=0; i<(Header.TriangleCount*3); ++i)
{
file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry)); file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry));
if (FlipEndianess)
{
Triangles[i].X = os::Byteswap::byteswap(Triangles[i].X);
Triangles[i].Y = os::Byteswap::byteswap(Triangles[i].Y);
Triangles[i].Z = os::Byteswap::byteswap(Triangles[i].Z);
Triangles[i].U1 = os::Byteswap::byteswap(Triangles[i].U1);
Triangles[i].V1 = os::Byteswap::byteswap(Triangles[i].U2);
Triangles[i].U2 = os::Byteswap::byteswap(Triangles[i].V1);
Triangles[i].V2 = os::Byteswap::byteswap(Triangles[i].V2);
}
if (triUserSize>0)
file->seek(triUserSize,true);
}
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -210,7 +253,7 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) ...@@ -210,7 +253,7 @@ IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
constructMesh(mesh); constructMesh(mesh);
loadTextures(mesh, numLightMaps, numTextures, textureIDs); loadTextures(mesh);
cleanup(); cleanup();
...@@ -275,49 +318,55 @@ void CLMTSMeshFileLoader::constructMesh(SMesh* mesh) ...@@ -275,49 +318,55 @@ void CLMTSMeshFileLoader::constructMesh(SMesh* mesh)
} }
void CLMTSMeshFileLoader::loadTextures(SMesh* mesh, u32 numTextures, u32 numLightMaps, const core::array<u32>& textureIDs) void CLMTSMeshFileLoader::loadTextures(SMesh* mesh)
{ {
if (!Driver || !FileSystem) if (!Driver || !FileSystem)
return; return;
// load textures // load textures
// a little too much space, but won't matter here
core::array<video::ITexture*> tex; core::array<video::ITexture*> tex;
tex.set_used(numTextures); tex.reallocate(Header.TextureCount);
core::array<video::ITexture*> lig; core::array<video::ITexture*> lig;
lig.set_used(numLightMaps); lig.reallocate(Header.TextureCount);
core::array<u32> id2id;
id2id.reallocate(Header.TextureCount);
s32 tx_count = 0;
s32 lm_count = 0;
const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH); const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH);
core::stringc s; core::stringc s;
for (s32 t=0; t<Header.TextureCount; ++t) for (u32 t=0; t<Header.TextureCount; ++t)
{ {
video::ITexture* tmptex = 0; video::ITexture* tmptex = 0;
s = Path; s = Path;
s.append(Textures[t].Filename); s.append(Textures[t].Filename);
if (FileSystem->existFile(s.c_str())) if (FileSystem->existFile(s))
tmptex = Driver->getTexture(s.c_str()); tmptex = Driver->getTexture(s);
else else
os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING); os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING);
if (Textures[t].Flags & 1) if (Textures[t].Flags & 0x01)
lig[lm_count++] = tmptex; {
id2id.push_back(lig.size());
lig.push_back(tmptex);
}
else else
tex[tx_count++] = tmptex; {
id2id.push_back(tex.size());
tex.push_back(tmptex);
}
} }
// attach textures to materials. // attach textures to materials.
for (s32 i=0; i<Header.SubsetCount; ++i) for (u32 i=0; i<Header.SubsetCount; ++i)
{ {
if (Subsets[i].TextID1 < Header.TextureCount) if (Subsets[i].TextID1 < Header.TextureCount && id2id[Subsets[i].TextID1] < tex.size())
mesh->getMeshBuffer(i)->getMaterial().setTexture(0, tex[textureIDs[Subsets[i].TextID1]]); mesh->getMeshBuffer(i)->getMaterial().setTexture(0, tex[id2id[Subsets[i].TextID1]]);
if (Subsets[i].TextID2 < Header.TextureCount) if (Subsets[i].TextID2 < Header.TextureCount && id2id[Subsets[i].TextID2] < lig.size())
mesh->getMeshBuffer(i)->getMaterial().setTexture(1, lig[textureIDs[Subsets[i].TextID2]]); mesh->getMeshBuffer(i)->getMaterial().setTexture(1, lig[id2id[Subsets[i].TextID2]]);
if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1)) if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1))
mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID; mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID;
...@@ -329,4 +378,3 @@ void CLMTSMeshFileLoader::loadTextures(SMesh* mesh, u32 numTextures, u32 numLigh ...@@ -329,4 +378,3 @@ void CLMTSMeshFileLoader::loadTextures(SMesh* mesh, u32 numTextures, u32 numLigh
} // end namespace irr } // end namespace irr
#endif // _IRR_COMPILE_WITH_LMTS_LOADER_ #endif // _IRR_COMPILE_WITH_LMTS_LOADER_
...@@ -46,7 +46,7 @@ public: ...@@ -46,7 +46,7 @@ public:
private: private:
void constructMesh(SMesh* mesh); void constructMesh(SMesh* mesh);
void loadTextures(SMesh* mesh, u32 numTextures, u32 numLightMaps, const core::array<u32>& textureIDs); void loadTextures(SMesh* mesh);
void cleanup(); void cleanup();
// byte-align structures // byte-align structures
...@@ -112,10 +112,10 @@ private: ...@@ -112,10 +112,10 @@ private:
io::IAttributes* Parameters; io::IAttributes* Parameters;
video::IVideoDriver* Driver; video::IVideoDriver* Driver;
io::IFileSystem* FileSystem; io::IFileSystem* FileSystem;
bool FlipEndianess;
}; };
} // end namespace scene } // end namespace scene
} // end namespace irr } // end namespace irr
#endif // !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__) #endif // !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment