diff --git a/include/IAttributes.h b/include/IAttributes.h index 6f1dbf14..ef9acf60 100644 --- a/include/IAttributes.h +++ b/include/IAttributes.h @@ -155,14 +155,16 @@ public: //! Reads attributes from a xml file. //! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'. + //! \param elementName: The surrounding element name. If it is null, the default one, "attributes" will be taken. //! If set to false, the first appearing list of attributes are read. - virtual bool read(irr::io::IXMLReader* reader, bool readCurrentElementOnly=false) = 0; + virtual bool read(irr::io::IXMLReader* reader, bool readCurrentElementOnly=false, const wchar_t* elementName=0) = 0; //! Write these attributes into a xml file //! \param writer: The XML writer to write to //! \param writeXMLHeader: Writes a header to the XML file, required if at the beginning of the file + //! \param elementName: The surrounding element name. If it is null, the default one, "attributes" will be taken. //! and you haven't already written one with writer->writeXMLHeader() - virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false) = 0; + virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* elementName=0) = 0; /* diff --git a/source/Irrlicht/CAttributes.cpp b/source/Irrlicht/CAttributes.cpp index 18afbe99..86382143 100644 --- a/source/Irrlicht/CAttributes.cpp +++ b/source/Irrlicht/CAttributes.cpp @@ -1378,14 +1378,17 @@ void CAttributes::setAttribute(s32 index, void* userPointer) //! Reads attributes from a xml file. //! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'. //! IF set to false, the first appearing list attributes are read. -bool CAttributes::read(irr::io::IXMLReader* reader, bool readCurrentElementOnly) +bool CAttributes::read(irr::io::IXMLReader* reader, bool readCurrentElementOnly, + const wchar_t* nonDefaultElementName) { if (!reader) return false; clear(); - const core::stringw elementName = L"attributes"; + core::stringw elementName = L"attributes"; + if (nonDefaultElementName) + elementName = nonDefaultElementName; if (readCurrentElementOnly) { @@ -1542,7 +1545,8 @@ void CAttributes::readAttributeFromXML(io::IXMLReader* reader) } //! Write these attributes into a xml file -bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader) +bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader, + const wchar_t* nonDefaultElementName) { if (!writer) return false; @@ -1550,7 +1554,11 @@ bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader) if (writeXMLHeader) writer->writeXMLHeader(); - writer->writeElement(L"attributes", false); + core::stringw elementName = L"attributes"; + if (nonDefaultElementName) + elementName = nonDefaultElementName; + + writer->writeElement(elementName.c_str(), false); writer->writeLineBreak(); s32 i=0; @@ -1594,7 +1602,7 @@ bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader) writer->writeLineBreak(); } - writer->writeClosingTag(L"attributes"); + writer->writeClosingTag(elementName.c_str()); writer->writeLineBreak(); return true; diff --git a/source/Irrlicht/CAttributes.h b/source/Irrlicht/CAttributes.h index ee876774..77d0073e 100644 --- a/source/Irrlicht/CAttributes.h +++ b/source/Irrlicht/CAttributes.h @@ -62,10 +62,11 @@ public: //! Reads attributes from a xml file. //! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'. //! IF set to false, the first appearing list attributes are read. - virtual bool read(irr::io::IXMLReader* reader, bool readCurrentElementOnly=false); + virtual bool read(irr::io::IXMLReader* reader, bool readCurrentElementOnly=false, + const wchar_t* nonDefaultElementName = 0); //! Write these attributes into a xml file - virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false); + virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* nonDefaultElementName=0); /* diff --git a/source/Irrlicht/CIrrMeshWriter.cpp b/source/Irrlicht/CIrrMeshWriter.cpp index cf90776a..57ac6cf5 100644 --- a/source/Irrlicht/CIrrMeshWriter.cpp +++ b/source/Irrlicht/CIrrMeshWriter.cpp @@ -59,20 +59,243 @@ bool CIrrMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla Writer->writeXMLHeader(); - Writer->writeElement(L"irrmesh", false, - L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_08_2007", + Writer->writeElement(L"mesh", false, + L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_09_2007", L"version", L"1.0"); Writer->writeLineBreak(); - // write mesh + // add some informational comment. Add a space after and before the comment + // tags so that some braindead xml parsers (AS anyone?) are able to parse this too. - // TODO: implement + core::stringw infoComment = L" This file contains a static mesh in the Irrlicht Engine format with "; + infoComment += core::stringw(mesh->getMeshBufferCount()); + infoComment += L" materials."; + + Writer->writeComment(infoComment.c_str()); + Writer->writeLineBreak(); + + // write mesh bounding box + + writeBoundingBox(mesh->getBoundingBox()); + Writer->writeLineBreak(); + + // write mesh buffers + + for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) + { + irr::scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); + if (buffer) + { + writeMeshBuffer(buffer); + Writer->writeLineBreak(); + } + } + + Writer->writeClosingTag(L"mesh"); Writer->drop(); return true; } +void CIrrMeshWriter::writeBoundingBox(const core::aabbox3df& box) +{ + Writer->writeElement(L"boundingBox", true, + L"minEdge", getVectorAsStringLine(box.MinEdge).c_str(), + L"maxEdge", getVectorAsStringLine(box.MaxEdge).c_str() ); +} + + +core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector3df& v) +{ + core::stringw str; + + str = core::stringw(v.X); + str += L" "; + str += core::stringw(v.Y); + str += L" "; + str += core::stringw(v.Z); + + return str; +} + + +core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector2df& v) +{ + core::stringw str; + + str = core::stringw(v.X); + str += L" "; + str += core::stringw(v.Y); + + return str; +} + + +void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) +{ + Writer->writeElement(L"buffer", false); + Writer->writeLineBreak(); + + // write bounding box + + writeBoundingBox(buffer->getBoundingBox()); + Writer->writeLineBreak(); + + // write material + + writeMaterial(buffer->getMaterial()); + + // write vertices + + const wchar_t* vertexTypeStr; + + switch(buffer->getVertexType()) + { + case video::EVT_STANDARD: + vertexTypeStr = L"standard"; + break; + case video::EVT_TANGENTS: + vertexTypeStr = L"tangents"; + break; + case video::EVT_2TCOORDS: + default: + vertexTypeStr = L"2tcoords"; + break; + } + + Writer->writeElement(L"vertices", false, + L"type", vertexTypeStr, + L"vertexCount", core::stringw(buffer->getVertexCount()).c_str()); + + Writer->writeLineBreak(); + + int vertexCount = (int)buffer->getVertexCount(); + + switch(buffer->getVertexType()) + { + 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"vertices"); + Writer->writeLineBreak(); + + // write indices + + Writer->writeElement(L"indices", false, + L"indexCount", core::stringw(buffer->getIndexCount()).c_str()); + + Writer->writeLineBreak(); + + int indexCount = (int)buffer->getIndexCount(); + const u16* idx = buffer->getIndices(); + const int maxIndicesPerLine = 25; + + for (int i=0; iwriteText(str.c_str()); + + if (i % maxIndicesPerLine != maxIndicesPerLine) + { + if (i % maxIndicesPerLine == maxIndicesPerLine-1) + Writer->writeLineBreak(); + else + Writer->writeText(L" "); + } + } + + if ((indexCount-1) % maxIndicesPerLine != maxIndicesPerLine-1) + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"indices"); + Writer->writeLineBreak(); + + // close buffer tag + + Writer->writeClosingTag(L"buffer"); +} + + +void CIrrMeshWriter::writeMaterial(const video::SMaterial& material) +{ + // simply use irrlichts built-in attribute serialization capabilities here: + + irr::io::IAttributes* attributes = + VideoDriver->createAttributesFromMaterial(material); + + if (attributes) + { + attributes->write(Writer, false, L"material"); + attributes->drop(); + } +} + } // end namespace } // end namespace diff --git a/source/Irrlicht/CIrrMeshWriter.h b/source/Irrlicht/CIrrMeshWriter.h index d1e99d10..62eabfd8 100644 --- a/source/Irrlicht/CIrrMeshWriter.h +++ b/source/Irrlicht/CIrrMeshWriter.h @@ -14,30 +14,43 @@ namespace io } namespace scene { + class IMeshBuffer; -//! 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(); + //! 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: - //! Returns the type of the mesh writer - virtual EMESH_WRITER_TYPE getType() const; + CIrrMeshWriter(irr::video::IVideoDriver* driver, irr::io::IFileSystem* fs); + virtual ~CIrrMeshWriter(); - //! writes a mesh - virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); + //! Returns the type of the mesh writer + virtual EMESH_WRITER_TYPE getType() const; -protected: + //! writes a mesh + virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); - io::IFileSystem* FileSystem; - video::IVideoDriver* VideoDriver; - io::IXMLWriter* Writer; -}; + protected: + void writeBoundingBox(const core::aabbox3df& box); + + void writeMeshBuffer(const scene::IMeshBuffer* buffer); + + void writeMaterial(const video::SMaterial& material); + + core::stringw getVectorAsStringLine(const core::vector3df& v); + + core::stringw getVectorAsStringLine(const core::vector2df& v); + + // member variables: + + io::IFileSystem* FileSystem; + video::IVideoDriver* VideoDriver; + io::IXMLWriter* Writer; + }; } // end namespace } // end namespace