.irrMesh writer implementation finished
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@927 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
71a1e46d7b
commit
8a3a2a2ad5
|
@ -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;
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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; j<vertexCount; ++j)
|
||||
{
|
||||
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].Normal);
|
||||
|
||||
char tmp[12];
|
||||
sprintf(tmp, " %08x ", vtx[j].Color);
|
||||
str += tmp;
|
||||
|
||||
str += getVectorAsStringLine(vtx[j].TCoords);
|
||||
|
||||
Writer->writeText(str.c_str());
|
||||
Writer->writeLineBreak();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
|
||||
for (int j=0; j<vertexCount; ++j)
|
||||
{
|
||||
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].Normal);
|
||||
|
||||
char tmp[12];
|
||||
sprintf(tmp, " %08x ", vtx[j].Color);
|
||||
str += tmp;
|
||||
|
||||
str += getVectorAsStringLine(vtx[j].TCoords);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].TCoords2);
|
||||
|
||||
Writer->writeText(str.c_str());
|
||||
Writer->writeLineBreak();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
|
||||
for (int j=0; j<vertexCount; ++j)
|
||||
{
|
||||
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].Normal);
|
||||
|
||||
char tmp[12];
|
||||
sprintf(tmp, " %08x ", vtx[j].Color);
|
||||
str += tmp;
|
||||
|
||||
str += getVectorAsStringLine(vtx[j].TCoords);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].Tangent);
|
||||
str += L" ";
|
||||
str += getVectorAsStringLine(vtx[j].Binormal);
|
||||
|
||||
Writer->writeText(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; i<indexCount; ++i)
|
||||
{
|
||||
core::stringw str((int)idx[i]);
|
||||
Writer->writeText(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
|
||||
|
|
|
@ -14,6 +14,8 @@ 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
|
||||
|
@ -33,12 +35,23 @@ public:
|
|||
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue