Added SMF loader, supporting 3D World Studio meshes. Originally written by Joseph Ellis

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3575 dfc29bdd-3216-0410-991c-e03cc46cb475
master
bitplane 2011-01-31 10:43:08 +00:00
parent d41aeab701
commit d9798dafe7
7 changed files with 325 additions and 5 deletions

View File

@ -1,5 +1,7 @@
Changes in 1.8 (??.??.2011)
- Added SMF mesh loader, loads meshes from 3D World Studio. Originally written by Joseph Ellis
- The loader selection process now consistently checks loader lists in reverse order, so new loaders added to Irrlicht override the internal ones. This applies when adding external mesh, image, scene and archive loaders, image writers, plus node, animator and GUI element factories.
- Added getters to retrieve mesh, scene and archive loaders.
@ -4135,6 +4137,7 @@ Changes in version 0.4.2: (13 Dec 2003)
-------------------------------------------------------------------------------------
Changes in version 0.4.1: (18 Sep 2003)
- Input events are now processed faster than repaint and window events. This
means that input commands now effect things directly, in earlier versions
there could be a delay when there were low frames per second. Some people

View File

@ -167,7 +167,13 @@ namespace scene
* <TD>3D Studio (.3ds)</TD>
* <TD>Loader for 3D-Studio files which lots of 3D packages
* are able to export. Only static meshes are currently
* supported by this importer. </TD>
* supported by this importer.</TD>
* </TR>
* <TR>
* <TD>3D World Studio (.smf)</TD>
* <TD>Loader for Leadwerks SMF mesh files, a simple mesh format
* containing static geometry for games. The proprietary .STF texture format
* is not supported yet. This loader was originally written by Joseph Ellis. </TD>
* </TR>
* <TR>
* <TD>Bliz Basic B3D (.b3d)</TD>

View File

@ -431,6 +431,11 @@ B3D, MS3D or X meshes */
#ifdef NO_IRR_COMPILE_WITH_PLY_LOADER_
#undef _IRR_COMPILE_WITH_PLY_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_SMF_LOADER_ if you want to load 3D World Studio mesh files
#define _IRR_COMPILE_WITH_SMF_LOADER_
#ifdef NO_IRR_COMPILE_WITH_SMF_LOADER_
#undef _IRR_COMPILE_WITH_SMF_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irrMesh files
#define _IRR_COMPILE_WITH_IRR_WRITER_

View File

@ -0,0 +1,230 @@
// Copyright (C) 2010-2011 Gaz Davidson / Joseph Ellis
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
#include "CSMFMeshFileLoader.h"
#include "SAnimatedMesh.h"
#include "SMeshBuffer.h"
#include "IReadFile.h"
#include "coreutil.h"
#include "os.h"
#include "IVideoDriver.h"
namespace irr
{
namespace scene
{
CSMFMeshFileLoader::CSMFMeshFileLoader(video::IVideoDriver* driver)
: Driver(driver)
{
}
//! Returns true if the file might be loaded by this class.
bool CSMFMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "smf");
}
//! Creates/loads an animated mesh from the file.
IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file)
{
// create empty mesh
SMesh *mesh = new SMesh();
// load file
u16 version;
u8 flags;
s32 limbCount;
s32 i;
io::BinaryFile::read(file, version);
io::BinaryFile::read(file, flags);
io::BinaryFile::read(file, limbCount);
// load mesh data
core::matrix4 identity;
for (i=0; i < limbCount; ++i)
loadLimb(file, mesh, identity);
// recalculate buffer bounding boxes
for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i)
mesh->getMeshBuffer(i)->recalculateBoundingBox();
mesh->recalculateBoundingBox();
SAnimatedMesh *am = new SAnimatedMesh();
am->addMesh(mesh);
mesh->drop();
am->recalculateBoundingBox();
return am;
}
void CSMFMeshFileLoader::loadLimb(io::IReadFile* file, SMesh* mesh, const core::matrix4 &parentTransformation)
{
core::matrix4 transformation;
// limb transformation
core::vector3df translate, rotate, scale;
io::BinaryFile::read(file, translate);
io::BinaryFile::read(file, rotate);
io::BinaryFile::read(file, scale);
transformation.setTranslation(translate);
transformation.setRotationDegrees(rotate);
transformation.setScale(scale);
transformation = parentTransformation * transformation;
core::stringc textureName, textureGroupName;
// texture information
io::BinaryFile::read(file, textureGroupName);
io::BinaryFile::read(file, textureName);
// attempt to load texture using known formats
video::ITexture* texture = 0;
const c8* extensions[] = {".jpg", ".png", ".tga", ".bmp", 0};
for (const c8 **ext = extensions; !texture && *ext; ++ext)
{
texture = Driver->getTexture(textureName + *ext);
if (texture)
textureName = textureName + *ext;
}
// find the correct mesh buffer
u32 i;
for (i=0; i<mesh->MeshBuffers.size(); ++i)
if (mesh->MeshBuffers[i]->getMaterial().TextureLayer[0].Texture == texture)
break;
// create mesh buffer if none was found
if (i == mesh->MeshBuffers.size())
{
CMeshBuffer<video::S3DVertex>* mb = new CMeshBuffer<video::S3DVertex>();
mb->Material.TextureLayer[0].Texture = texture;
// horribly hacky way to do this, maybe it's in the flags?
if (core::hasFileExtension(textureName, "tga", "png"))
mb->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
else
mb->Material.MaterialType = video::EMT_SOLID;
mesh->MeshBuffers.push_back(mb);
}
CMeshBuffer<video::S3DVertex>* mb = (CMeshBuffer<video::S3DVertex>*)mesh->MeshBuffers[i];
u16 vertexCount, firstVertex = mb->getVertexCount();
io::BinaryFile::read(file, vertexCount);
mb->Vertices.reallocate(mb->Vertices.size() + vertexCount);
// add vertices and set positions
for (i=0; i<vertexCount; ++i)
{
core::vector3df pos;
io::BinaryFile::read(file, pos);
transformation.transformVect(pos);
video::S3DVertex vert;
vert.Color = 0xFFFFFFFF;
vert.Pos = pos;
mb->Vertices.push_back(vert);
}
// set vertex normals
for (i=0; i < vertexCount; ++i)
{
core::vector3df normal;
io::BinaryFile::read(file, normal);
transformation.rotateVect(normal);
mb->Vertices[firstVertex + i].Normal = normal;
}
// set texture coordinates
for (i=0; i < vertexCount; ++i)
{
core::vector2df tcoords;
io::BinaryFile::read(file, tcoords);
mb->Vertices[firstVertex + i].TCoords = tcoords;
}
// triangles
u16 triangleCount;
io::BinaryFile::read(file, triangleCount);
mb->Indices.reallocate(mb->Indices.size() + triangleCount * 3);
for (i=0; i < triangleCount*3; ++i)
{
u16 index;
io::BinaryFile::read(file, index);
mb->Indices.push_back(firstVertex + index);
}
// read limbs
s32 limbCount;
io::BinaryFile::read(file, limbCount);
for (s32 l=0; l < limbCount; ++l)
loadLimb(file, mesh, transformation);
}
} // namespace scene
// todo: at some point in the future let's move these to a place where everyone can use them.
namespace io
{
#if _BIGENDIAN
#define _SYSTEM_BIG_ENDIAN_ (true)
#else
#define _SYSTEM_BIG_ENDIAN_ (false)
#endif
template <class T>
void BinaryFile::read(io::IReadFile* file, T &out, bool bigEndian)
{
file->read((void*)&out, sizeof(out));
if (bigEndian != (_SYSTEM_BIG_ENDIAN_))
out = os::Byteswap::byteswap(out);
}
//! reads a 3d vector from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian)
{
BinaryFile::read(file, outVector2d.X, bigEndian);
BinaryFile::read(file, outVector2d.Y, bigEndian);
BinaryFile::read(file, outVector2d.Z, bigEndian);
}
//! reads a 2d vector from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian)
{
BinaryFile::read(file, outVector2d.X, bigEndian);
BinaryFile::read(file, outVector2d.Y, bigEndian);
}
//! reads a null terminated string from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::stringc &outString, bool bigEndian)
{
c8 c;
file->read((void*)&c, 1);
while (c)
{
outString += c;
file->read((void*)&c, 1);
}
}
} // namespace io
} // namespace irr
#endif // compile with SMF loader

View File

@ -0,0 +1,67 @@
// Copyright (C) 2010-2011 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_SMF_MESH_LOADER_H_INCLUDED__
#define __C_SMF_MESH_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "SMesh.h"
namespace irr
{
namespace video
{
class IVideoDriver;
}
namespace scene
{
//! Class which can load
class CSMFMeshFileLoader : public virtual IMeshLoader
{
public:
CSMFMeshFileLoader(video::IVideoDriver* driver);
//! Returns true if the file might be loaded by this class.
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! Creates/loads an animated mesh from the file.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
void loadLimb(io::IReadFile* file, scene::SMesh* mesh, const core::matrix4 &parentTransformation);
video::IVideoDriver* Driver;
};
} // end namespace scene
namespace io
{
class BinaryFile
{
public:
//! reads most types from the given file, moving the file pointer along
template <class T>
static void read(io::IReadFile* file, T &out, bool bigEndian=false);
//! reads a 3d vector from the file, moving the file pointer along
static void read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian=false);
//! reads a 2d vector from the file, moving the file pointer along
static void read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian=false);
//! reads a null terminated string from the file, moving the file pointer along
static void read(io::IReadFile* file, core::stringc &outString, bool bigEndian=false);
};
}
} // end namespace irr
#endif // __C_SMF_MESH_LOADER_H_INCLUDED__

View File

@ -98,6 +98,10 @@
#include "CPLYMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
#include "CSMFMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#include "CSceneLoaderIrr.h"
#endif
@ -229,6 +233,9 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
MeshLoaderList.push_back(new CPLYMeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
MeshLoaderList.push_back(new CSMFMeshFileLoader(Driver));
#endif
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
MeshLoaderList.push_back(new COCTLoader(this, FileSystem));
#endif

View File

@ -890,6 +890,8 @@
<Unit filename="CQuake3ShaderSceneNode.h" />
<Unit filename="CReadFile.cpp" />
<Unit filename="CReadFile.h" />
<Unit filename="CSMFMeshFileLoader.cpp" />
<Unit filename="CSMFMeshFileLoader.h" />
<Unit filename="CSTLMeshFileLoader.cpp" />
<Unit filename="CSTLMeshFileLoader.h" />
<Unit filename="CSTLMeshWriter.cpp" />