diff --git a/changes.txt b/changes.txt index ac1fcf46..bed9f929 100644 --- a/changes.txt +++ b/changes.txt @@ -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 diff --git a/include/ISceneManager.h b/include/ISceneManager.h index c88fa804..83eb9c17 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -167,7 +167,13 @@ namespace scene * 3D Studio (.3ds) * Loader for 3D-Studio files which lots of 3D packages * are able to export. Only static meshes are currently - * supported by this importer. + * supported by this importer. + * + * + * 3D World Studio (.smf) + * 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. * * * Bliz Basic B3D (.b3d) diff --git a/include/IrrCompileConfig.h b/include/IrrCompileConfig.h index dc0560c6..41b6644a 100644 --- a/include/IrrCompileConfig.h +++ b/include/IrrCompileConfig.h @@ -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_ diff --git a/source/Irrlicht/CSMFMeshFileLoader.cpp b/source/Irrlicht/CSMFMeshFileLoader.cpp new file mode 100644 index 00000000..c68aa52a --- /dev/null +++ b/source/Irrlicht/CSMFMeshFileLoader.cpp @@ -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; iMeshBuffers.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* mb = new CMeshBuffer(); + 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* mb = (CMeshBuffer*)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; iVertices.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 +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 + diff --git a/source/Irrlicht/CSMFMeshFileLoader.h b/source/Irrlicht/CSMFMeshFileLoader.h new file mode 100644 index 00000000..e018b405 --- /dev/null +++ b/source/Irrlicht/CSMFMeshFileLoader.h @@ -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 + 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__ + diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 9ea5f9e7..75b323c1 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -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 @@ -1727,7 +1734,7 @@ void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader) } //! Returns the number of mesh loaders supported by Irrlicht at this time -u32 CSceneManager::getMeshLoaderCount() const +u32 CSceneManager::getMeshLoaderCount() const { return MeshLoaderList.size(); } @@ -1739,7 +1746,7 @@ IMeshLoader* CSceneManager::getMeshLoader(u32 index) const if (index < MeshLoaderList.size()) return MeshLoaderList[index]; else - return 0; + return 0; } //! Adds an external scene loader. @@ -1753,7 +1760,7 @@ void CSceneManager::addExternalSceneLoader(ISceneLoader* externalLoader) } //! Returns the number of scene loaders -u32 CSceneManager::getSceneLoaderCount() const +u32 CSceneManager::getSceneLoaderCount() const { return SceneLoaderList.size(); } @@ -1765,7 +1772,7 @@ ISceneLoader* CSceneManager::getSceneLoader(u32 index) const if (index < SceneLoaderList.size()) return SceneLoaderList[index]; else - return 0; + return 0; } //! Returns a pointer to the scene collision manager. diff --git a/source/Irrlicht/Irrlicht-gcc.cbp b/source/Irrlicht/Irrlicht-gcc.cbp index 540e4797..30dad9ae 100644 --- a/source/Irrlicht/Irrlicht-gcc.cbp +++ b/source/Irrlicht/Irrlicht-gcc.cbp @@ -890,6 +890,8 @@ + +