From 2da809bc2aac996e9df7d10585f4ef50aaf50a4f Mon Sep 17 00:00:00 2001 From: irrlicht Date: Sat, 8 Sep 2007 06:10:52 +0000 Subject: [PATCH] added mesh writing features. COLLADA file writer is finished, .irrmesh writer is under construction. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@924 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 4 + include/IMeshWriter.h | 71 +++ include/ISceneManager.h | 6 + include/irrlicht.h | 1 + source/Irrlicht/CColladaMeshWriter.cpp | 685 +++++++++++++++++++++++++ source/Irrlicht/CColladaMeshWriter.h | 74 +++ source/Irrlicht/CIrrMeshWriter.cpp | 78 +++ source/Irrlicht/CIrrMeshWriter.h | 45 ++ source/Irrlicht/CSceneManager.cpp | 18 + source/Irrlicht/CSceneManager.h | 4 + source/Irrlicht/Irrlicht7.1.vcproj | 61 ++- 11 files changed, 1026 insertions(+), 21 deletions(-) create mode 100644 include/IMeshWriter.h create mode 100644 source/Irrlicht/CColladaMeshWriter.cpp create mode 100644 source/Irrlicht/CColladaMeshWriter.h create mode 100644 source/Irrlicht/CIrrMeshWriter.cpp create mode 100644 source/Irrlicht/CIrrMeshWriter.h diff --git a/changes.txt b/changes.txt index 843c8656..4296c550 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,9 @@ Changes in version 1.4 (... 2007) + - Irrlicht is now able to write Meshes out into files again. Use ISceneManager::createMeshWriter() + to obtain an interface with which you can write out meshes. Currently, an own .irrmesh + file format is supported as well as COLLADA. + - the base class for nearly all Irrlicht classes has been renamed from IUnknown to IReferenceCounted - fixed the keyboard autorepeat difference betwenn Linux and Windows. Thanks to denton we now have only KeyPressed events on both systems in case of autorepeat. diff --git a/include/IMeshWriter.h b/include/IMeshWriter.h new file mode 100644 index 00000000..30a62df1 --- /dev/null +++ b/include/IMeshWriter.h @@ -0,0 +1,71 @@ +#ifndef __IRR_I_MESH_WRITER_H_INCLUDED__ +#define __IRR_I_MESH_WRITER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "IWriteFile.h" +#include "irrTypes.h" + +namespace irr +{ + class IrrlichtDevice; + +namespace scene +{ + class IMesh; + + //! An enumeration for all supported types of built-in mesh writers + /** A scene mesh writers is represented by a four character code + such as 'irrm' or 'coll' instead of simple numbers, to avoid + name clashes with external mesh writers.*/ + enum EMESH_WRITER_TYPE + { + //! Irrlicht Native mesh writer, for static .irrmesh files. + EMWT_IRR_MESH = MAKE_IRR_ID('i','r','r','m'), + + //! COLLADA mesh writer for .dae and .xml files + EMWT_COLLADA = MAKE_IRR_ID('c','o','l','l'), + }; + + + //! flags configuring mesh writing + enum E_MESH_WRITER_FLAGS + { + //! no writer flags + EMWF_NONE = 0, + + //! write lightmap textures out if possible + EMWF_WRITE_LIGHTMAPS = 0x1 + }; + + + + // interface for writing meshes + class IMeshWriter : public virtual irr::IReferenceCounted + { + public: + + virtual ~IMeshWriter() {}; + + //! Returns the type of the mesh writer + /** For own implementations, use MAKE_IRR_ID as shown in the EMESH_WRITER_TYPE + enumeration to return your own unique mesh type id.*/ + virtual EMESH_WRITER_TYPE getType() const = 0; + + //! writes a static mesh + /** \return Returns true if sucessful */ + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, + s32 flags=EMWF_NONE) = 0; + + // writes an animated mesh + // for future use, no writer is able to write animated meshes currently + /* \return Returns true if sucessful */ + //virtual bool writeAnimatedMesh(io::IWriteFile* file, + // scene::IAnimatedMesh* mesh, + // s32 flags=EMWF_NONE) = 0; + }; + + +} // end namespace +} // end namespace + +#endif \ No newline at end of file diff --git a/include/ISceneManager.h b/include/ISceneManager.h index a8468697..b8d64dc9 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -13,6 +13,7 @@ #include "ETerrainElements.h" #include "ESceneNodeTypes.h" #include "SceneParameters.h" +#include "IMeshWriter.h" namespace irr { @@ -1216,6 +1217,11 @@ namespace scene \return Returns true if successful. */ virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; + //! Returns a mesh writer implementation if available + /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() + for details. */ + virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; + //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; diff --git a/include/irrlicht.h b/include/irrlicht.h index b8f01544..1402440d 100644 --- a/include/irrlicht.h +++ b/include/irrlicht.h @@ -87,6 +87,7 @@ #include "IMeshCache.h" #include "IMeshSceneNode.h" #include "IMeshManipulator.h" +#include "IMeshWriter.h" #include "IMetaTriangleSelector.h" #include "IReadFile.h" #include "IrrlichtDevice.h" diff --git a/source/Irrlicht/CColladaMeshWriter.cpp b/source/Irrlicht/CColladaMeshWriter.cpp new file mode 100644 index 00000000..c660c46d --- /dev/null +++ b/source/Irrlicht/CColladaMeshWriter.cpp @@ -0,0 +1,685 @@ +#include "CColladaMeshWriter.h" +#include "os.h" +#include "IXMLWriter.h" +#include "IMesh.h" +#include "IAttributes.h" + +namespace irr +{ +namespace scene +{ + + +CColladaMeshWriter::CColladaMeshWriter(irr::video::IVideoDriver* driver, + irr::io::IFileSystem* fs) +: VideoDriver(driver), FileSystem(fs) +{ + if (VideoDriver) + VideoDriver->grab(); + + if (FileSystem) + FileSystem->grab(); +} + + +CColladaMeshWriter::~CColladaMeshWriter() +{ + if (VideoDriver) + VideoDriver->drop(); + + if (FileSystem) + FileSystem->drop(); +} + + +//! Returns the type of the mesh writer +EMESH_WRITER_TYPE CColladaMeshWriter::getType() const +{ + return EMWT_COLLADA; +} + + +//! writes a mesh +bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) +{ + if (!file) + return false; + + Writer = FileSystem->createXMLWriter(file); + + if (!Writer) + { + os::Printer::log("Could not write file", file->getFileName()); + return false; + } + + os::Printer::log("Writing mesh", file->getFileName()); + + // write COLLADA header + + Writer->writeXMLHeader(); + + Writer->writeElement(L"COLLADA", false, + L"xmlns", L"http://www.collada.org/2005/COLLADASchema", + L"version", L"1.2.0"); + Writer->writeLineBreak(); + + // write asset data + + Writer->writeElement(L"asset", false); + Writer->writeLineBreak(); + + Writer->writeElement(L"revision", false); + Writer->writeText(L"1.0"); + Writer->writeClosingTag(L"revision"); + Writer->writeLineBreak(); + + Writer->writeElement(L"authoring_tool", false); + core::stringw strautoring = L"Irrlicht Engine / irrEdit"; // this code has originated from irrEdit 0.7 + Writer->writeText(strautoring.c_str()); + Writer->writeClosingTag(L"authoring_tool"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"asset"); + Writer->writeLineBreak(); + + // write all materials + + Writer->writeElement(L"library", false, L"type", L"MATERIAL"); + Writer->writeLineBreak(); + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + core::stringw strMat = "mat"; + strMat += i; + + Writer->writeElement(L"material", false, + L"name", strMat.c_str(), + L"id", strMat.c_str()); + Writer->writeLineBreak(); + + // write all interesting material parameters as parameter + + irr::io::IAttributes* attributes = VideoDriver->createAttributesFromMaterial( + mesh->getMeshBuffer(i)->getMaterial()); + + int count = attributes->getAttributeCount(); + for (int attridx=0; attridxgetAttributeName(attridx); + + Writer->writeElement(L"param", false, + L"name", str.c_str(), + L"type", attributes->getAttributeTypeString(attridx) ); + + str = attributes->getAttributeAsString(attridx).c_str(); + Writer->writeText(str.c_str()); + + Writer->writeClosingTag(L"param"); + Writer->writeLineBreak(); + } + + attributes->drop(); + + Writer->writeClosingTag(L"material"); + Writer->writeLineBreak(); + } + + Writer->writeClosingTag(L"library"); + Writer->writeLineBreak(); + + // write mesh + + Writer->writeElement(L"library", false, L"type", L"GEOMETRY"); + Writer->writeLineBreak(); + + Writer->writeElement(L"geometry", false, L"id", L"mesh", L"name", L"mesh"); + Writer->writeLineBreak(); + Writer->writeElement(L"mesh"); + Writer->writeLineBreak(); + + // do some statistics for the mesh to know which stuff needs to be saved into + // the file: + // - count vertices + // - check for the need of a second texture coordinate + // - count amount of second texture coordinates + // - check for the need of tangents (TODO) + + int totalVertexCount = 0; + int totalTCoords2Count = 0; + bool needsTangents = false; // TODO: tangents not supported here yet + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount(); + + if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType())) + totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount(); + + if (!needsTangents) + needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS; + } + + SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()]; + + // write positions + + Writer->writeElement(L"source", false, L"id", L"mesh-Pos"); + Writer->writeLineBreak(); + + core::stringw vertexCountStr = (totalVertexCount*3); + Writer->writeElement(L"array", false, L"id", L"mesh-Pos-array", + L"type", L"float", L"count", vertexCountStr.c_str()); + Writer->writeLineBreak(); + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); + int vertexCount = buffer->getVertexCount(); + + globalIndices[i].PosStartIndex = 0; + + if (i!=0) + globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1; + + globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1; + + switch(vtxType) + { + case video::EVT_STANDARD: + { + video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + } + } + + Writer->writeClosingTag(L"array"); + Writer->writeLineBreak(); + + Writer->writeElement(L"technique", false, L"profile", L"COMMON"); + Writer->writeLineBreak(); + + vertexCountStr = totalVertexCount; + + Writer->writeElement(L"accessor", false, L"source", L"#mesh-Pos-array", + L"count", vertexCountStr.c_str(), L"stride", L"3"); + Writer->writeLineBreak(); + + Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"accessor"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"technique"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"source"); + Writer->writeLineBreak(); + + // write texture coordinates + + Writer->writeElement(L"source", false, L"id", L"mesh-TexCoord0"); + Writer->writeLineBreak(); + + vertexCountStr = (totalVertexCount*2); + Writer->writeElement(L"array", false, L"id", L"mesh-TexCoord0-array", + L"type", L"float", L"count", vertexCountStr.c_str()); + Writer->writeLineBreak(); + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); + int vertexCount = buffer->getVertexCount(); + + globalIndices[i].TCoord0StartIndex = 0; + + if (i!=0) + globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1; + + globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1; + + switch(vtxType) + { + case video::EVT_STANDARD: + { + video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + } + } + + Writer->writeClosingTag(L"array"); + Writer->writeLineBreak(); + + Writer->writeElement(L"technique", false, L"profile", L"COMMON"); + Writer->writeLineBreak(); + + vertexCountStr = totalVertexCount; + + Writer->writeElement(L"accessor", false, L"source", L"#mesh-TexCoord0-array", + L"count", vertexCountStr.c_str(), L"stride", L"2"); + Writer->writeLineBreak(); + + Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"accessor"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"technique"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"source"); + Writer->writeLineBreak(); + + // write normals + + Writer->writeElement(L"source", false, L"id", L"mesh-Normal"); + Writer->writeLineBreak(); + + vertexCountStr = (totalVertexCount*3); + Writer->writeElement(L"array", false, L"id", L"mesh-Normal-array", + L"type", L"float", L"count", vertexCountStr.c_str()); + Writer->writeLineBreak(); + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); + int vertexCount = buffer->getVertexCount(); + + globalIndices[i].NormalStartIndex = 0; + + if (i!=0) + globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1; + + globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1; + + switch(vtxType) + { + case video::EVT_STANDARD: + { + video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + case video::EVT_TANGENTS: + { + video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + } + } + + Writer->writeClosingTag(L"array"); + Writer->writeLineBreak(); + + Writer->writeElement(L"technique", false, L"profile", L"COMMON"); + Writer->writeLineBreak(); + + vertexCountStr = totalVertexCount; + + Writer->writeElement(L"accessor", false, L"source", L"#mesh-Normal-array", + L"count", vertexCountStr.c_str(), L"stride", L"3"); + Writer->writeLineBreak(); + + Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"accessor"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"technique"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"source"); + Writer->writeLineBreak(); + + // write second set of texture coordinates + + if (totalTCoords2Count) + { + Writer->writeElement(L"source", false, L"id", L"mesh-TexCoord1"); + Writer->writeLineBreak(); + + vertexCountStr = (totalTCoords2Count*2); + Writer->writeElement(L"array", false, L"id", L"mesh-TexCoord1-array", + L"type", L"float", L"count", vertexCountStr.c_str()); + Writer->writeLineBreak(); + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); + int vertexCount = buffer->getVertexCount(); + + if (hasSecondTextureCoordinates(vtxType)) + { + globalIndices[i].TCoord1StartIndex = 0; + + if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1) + globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1; + + globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1; + + switch(vtxType) + { + case video::EVT_2TCOORDS: + { + video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); + for (int j=0; jwriteText(str.c_str()); + Writer->writeLineBreak(); + } + } + break; + } + } // end this buffer has 2 texture coordinates + } + + Writer->writeClosingTag(L"array"); + Writer->writeLineBreak(); + + Writer->writeElement(L"technique", false, L"profile", L"COMMON"); + Writer->writeLineBreak(); + + vertexCountStr = totalTCoords2Count; + + Writer->writeElement(L"accessor", false, L"source", L"#mesh-TexCoord1-array", + L"count", vertexCountStr.c_str(), L"stride", L"2"); + Writer->writeLineBreak(); + + Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float", L"flow", L"OUT"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"accessor"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"technique"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"source"); + Writer->writeLineBreak(); + } + + // write tangents + + // TODO + + // write vertices + + Writer->writeElement(L"vertices", false, L"id", L"mesh-Vtx"); + Writer->writeLineBreak(); + + Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", L"#mesh-Pos"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"vertices"); + Writer->writeLineBreak(); + + // write polygons + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + + int polyCount = buffer->getIndexCount() / 3; + core::stringw strPolyCount = polyCount; + core::stringw strMat = "#mat"; + strMat += i; + + Writer->writeElement(L"polygons", false, L"count", strPolyCount.c_str(), + L"material", strMat.c_str()); + Writer->writeLineBreak(); + + Writer->writeElement(L"input", true, L"semantic", L"VERTEX", L"source", L"#mesh-Vtx", L"idx", L"0"); + Writer->writeLineBreak(); + Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", L"#mesh-TexCoord0", L"idx", L"1"); + Writer->writeLineBreak(); + Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", L"#mesh-Normal", L"idx", L"2"); + Writer->writeLineBreak(); + + bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); + if (has2ndTexCoords) + { + Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", L"#mesh-TexCoord1", L"idx", L"3"); + Writer->writeLineBreak(); + } + + // write indices now + + int posIdx = globalIndices[i].PosStartIndex; + int tCoordIdx = globalIndices[i].TCoord0StartIndex; + int normalIdx = globalIndices[i].NormalStartIndex; + int tCoord2Idx = globalIndices[i].TCoord1StartIndex; + + for (int p=0; pwriteElement(L"p", false); + + core::stringw strP; + + strP += (int)(buffer->getIndices()[(p*3) + 0]) + posIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 0]) + tCoordIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 0]) + normalIdx; + strP += " "; + if (has2ndTexCoords) + { + strP += (int)(buffer->getIndices()[(p*3) + 0]) + tCoord2Idx; + strP += " "; + } + + strP += (int)(buffer->getIndices()[(p*3) + 1]) + posIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 1]) + tCoordIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 1]) + normalIdx; + strP += " "; + if (has2ndTexCoords) + { + strP += (int)(buffer->getIndices()[(p*3) + 1]) + tCoord2Idx; + strP += " "; + } + + strP += (int)(buffer->getIndices()[(p*3) + 2]) + posIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 2]) + tCoordIdx; + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 2]) + normalIdx; + if (has2ndTexCoords) + { + strP += " "; + strP += (int)(buffer->getIndices()[(p*3) + 2]) + tCoord2Idx; + } + + Writer->writeText(strP.c_str()); + + Writer->writeClosingTag(L"p"); + Writer->writeLineBreak(); + } + + // close index buffer section + + Writer->writeClosingTag(L"polygons"); + Writer->writeLineBreak(); + } + + // close mesh and geometry + + Writer->writeClosingTag(L"mesh"); + Writer->writeLineBreak(); + Writer->writeClosingTag(L"geometry"); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"library"); + Writer->writeLineBreak(); + + // close everything + + Writer->writeClosingTag(L"COLLADA"); + Writer->drop(); + + delete [] globalIndices; + + return true; +} + + +bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) +{ + return type == video::EVT_2TCOORDS; +} + + +} // end namespace +} // end namespace diff --git a/source/Irrlicht/CColladaMeshWriter.h b/source/Irrlicht/CColladaMeshWriter.h new file mode 100644 index 00000000..22b14677 --- /dev/null +++ b/source/Irrlicht/CColladaMeshWriter.h @@ -0,0 +1,74 @@ +#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ +#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ + +#include "IMeshWriter.h" +#include "S3DVertex.h" +#include "IVideoDriver.h" +#include "IFileSystem.h" + +namespace irr +{ +namespace io +{ + class IXMLWriter; +} +namespace scene +{ + +//! class to write meshes, implementing a COLLADA (.dae, .xml) writer +/** This writer implementation has been originally developed for irrEdit and then +merged out to the Irrlicht Engine */ +class CColladaMeshWriter : public IMeshWriter +{ +public: + + CColladaMeshWriter(irr::video::IVideoDriver* driver, irr::io::IFileSystem* fs); + virtual ~CColladaMeshWriter(); + + //! Returns the type of the mesh writer + virtual EMESH_WRITER_TYPE getType() const; + + //! writes a mesh + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); + +protected: + + bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type); + + struct SComponentGlobalStartPos + { + SComponentGlobalStartPos() + { + PosStartIndex = -1; + PosLastIndex = -1; + NormalStartIndex = -1; + NormalLastIndex = -1; + TCoord0LastIndex = -1; + TCoord0LastIndex = -1; + TCoord1LastIndex = -1; + TCoord1LastIndex = -1; + } + + s32 PosStartIndex; + s32 PosLastIndex; + + s32 TCoord0StartIndex; + s32 TCoord0LastIndex; + + s32 NormalStartIndex; + s32 NormalLastIndex; + + s32 TCoord1StartIndex; + s32 TCoord1LastIndex; + }; + + io::IFileSystem* FileSystem; + video::IVideoDriver* VideoDriver; + io::IXMLWriter* Writer; +}; + + +} // end namespace +} // end namespace + +#endif \ No newline at end of file diff --git a/source/Irrlicht/CIrrMeshWriter.cpp b/source/Irrlicht/CIrrMeshWriter.cpp new file mode 100644 index 00000000..21875a51 --- /dev/null +++ b/source/Irrlicht/CIrrMeshWriter.cpp @@ -0,0 +1,78 @@ +#include "CIrrMeshWriter.h" +#include "os.h" +#include "IXMLWriter.h" +#include "IMesh.h" +#include "IAttributes.h" + +namespace irr +{ +namespace scene +{ + + +CIrrMeshWriter::CIrrMeshWriter(irr::video::IVideoDriver* driver, + irr::io::IFileSystem* fs) +: VideoDriver(driver), FileSystem(fs) +{ + if (VideoDriver) + VideoDriver->grab(); + + if (FileSystem) + FileSystem->grab(); +} + + +CIrrMeshWriter::~CIrrMeshWriter() +{ + if (VideoDriver) + VideoDriver->drop(); + + if (FileSystem) + FileSystem->drop(); +} + + +//! Returns the type of the mesh writer +EMESH_WRITER_TYPE CIrrMeshWriter::getType() const +{ + return EMWT_IRR_MESH; +} + + +//! writes a mesh +bool CIrrMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) +{ + if (!file) + return false; + + Writer = FileSystem->createXMLWriter(file); + + if (!Writer) + { + os::Printer::log("Could not write file", file->getFileName()); + return false; + } + + os::Printer::log("Writing mesh", file->getFileName()); + + // write IRR MESH header + + Writer->writeXMLHeader(); + + Writer->writeElement(L"irrmesh", false, + L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_08_2007", + L"version", L"1.0"); + Writer->writeLineBreak(); + + // write mesh + + // TODO: implement + + Writer->drop(); + return true; +} + + + +} // end namespace +} // end namespace diff --git a/source/Irrlicht/CIrrMeshWriter.h b/source/Irrlicht/CIrrMeshWriter.h new file mode 100644 index 00000000..ba9f7ebd --- /dev/null +++ b/source/Irrlicht/CIrrMeshWriter.h @@ -0,0 +1,45 @@ +#ifndef __IRR_IRR_MESH_WRITER_H_INCLUDED__ +#define __IRR_IRR_MESH_WRITER_H_INCLUDED__ + +#include "IMeshWriter.h" +#include "S3DVertex.h" +#include "IVideoDriver.h" +#include "IFileSystem.h" + +namespace irr +{ +namespace io +{ + class IXMLWriter; +} +namespace scene +{ + +//! class to write meshes, implementing a IrrMesh (.irrmesh, .xml) writer +/** This writer implementation has been originally developed for irrEdit and then +merged out to the Irrlicht Engine */ +class CIrrMeshWriter : public IMeshWriter +{ +public: + + CIrrMeshWriter(irr::video::IVideoDriver* driver, irr::io::IFileSystem* fs); + virtual ~CIrrMeshWriter(); + + //! Returns the type of the mesh writer + virtual EMESH_WRITER_TYPE getType() const; + + //! writes a mesh + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); + +protected: + + io::IFileSystem* FileSystem; + video::IVideoDriver* VideoDriver; + io::IXMLWriter* Writer; +}; + + +} // end namespace +} // end namespace + +#endif \ No newline at end of file diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 27d2c110..97d81372 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -117,6 +117,9 @@ #include "CQuake3ShaderSceneNode.h" +#include "CColladaMeshWriter.h" +#include "CIrrMeshWriter.h" + //! Enable debug features #define SCENEMANAGER_DEBUG @@ -2173,6 +2176,21 @@ video::SColorf CSceneManager::getAmbientLight() } +//! Returns a mesh writer implementation if available +IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type) +{ + switch(type) + { + case EMWT_IRR_MESH: + return new CIrrMeshWriter(Driver, FileSystem); + case EMWT_COLLADA: + return new CColladaMeshWriter(Driver, FileSystem); + } + + return 0; +} + + // creates a scenemanager ISceneManager* createSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cursorcontrol, diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 17ebd69a..72df9792 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -11,6 +11,7 @@ #include "irrString.h" #include "irrArray.h" #include "IMeshLoader.h" +#include "IMeshWriter.h" #include "CAttributes.h" namespace irr @@ -424,6 +425,9 @@ namespace scene //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); + //! Returns a mesh writer implementation if available + virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type); + //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor); diff --git a/source/Irrlicht/Irrlicht7.1.vcproj b/source/Irrlicht/Irrlicht7.1.vcproj index f4eb40be..86a7e112 100644 --- a/source/Irrlicht/Irrlicht7.1.vcproj +++ b/source/Irrlicht/Irrlicht7.1.vcproj @@ -403,27 +403,6 @@ - - - - - - - - - - - - - - @@ -481,6 +460,9 @@ + + @@ -1495,12 +1477,21 @@ + + + + + + @@ -1513,12 +1504,24 @@ + + + + + + + + @@ -1610,6 +1613,22 @@ RelativePath=".\CSceneNodeAnimatorTexture.h"> + + + + + + + + + +