From 7028cbe09c688437910a25623098762bf0fa592d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 28 Mar 2016 22:28:34 +1000 Subject: Move Irrlicht to src/others. --- .../source/Irrlicht/CIrrMeshFileLoader.cpp | 554 +++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 src/others/irrlicht-1.8.1/source/Irrlicht/CIrrMeshFileLoader.cpp (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CIrrMeshFileLoader.cpp') diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrMeshFileLoader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrMeshFileLoader.cpp new file mode 100644 index 0000000..6478aaf --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrMeshFileLoader.cpp @@ -0,0 +1,554 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// 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_IRR_MESH_LOADER_ + +#include "CIrrMeshFileLoader.h" +#include "os.h" +#include "IXMLReader.h" +#include "SAnimatedMesh.h" +#include "fast_atof.h" +#include "IReadFile.h" +#include "IAttributes.h" +#include "IMeshSceneNode.h" +#include "CDynamicMeshBuffer.h" +#include "SMeshBufferLightMap.h" + +namespace irr +{ +namespace scene +{ + + +//! Constructor +CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr, + io::IFileSystem* fs) + : SceneManager(smgr), FileSystem(fs) +{ + + #ifdef _DEBUG + setDebugName("CIrrMeshFileLoader"); + #endif + +} + + +//! Returns true if the file maybe is able to be loaded by this class. +/** This decision should be based only on the file extension (e.g. ".cob") */ +bool CIrrMeshFileLoader::isALoadableFileExtension(const io::path& filename) const +{ + return core::hasFileExtension ( filename, "xml", "irrmesh" ); +} + + +//! creates/loads an animated mesh from the file. +//! \return Pointer to the created mesh. Returns 0 if loading failed. +//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). +//! See IReferenceCounted::drop() for more information. +IAnimatedMesh* CIrrMeshFileLoader::createMesh(io::IReadFile* file) +{ + io::IXMLReader* reader = FileSystem->createXMLReader(file); + if (!reader) + return 0; + + // read until mesh section, skip other parts + + const core::stringc meshTagName = "mesh"; + IAnimatedMesh* mesh = 0; + + while(reader->read()) + { + if (reader->getNodeType() == io::EXN_ELEMENT) + { + if (meshTagName == reader->getNodeName()) + { + mesh = readMesh(reader); + break; + } + else + skipSection(reader, true); // unknown section + } + } + + reader->drop(); + + return mesh; +} + + +//! reads a mesh sections and creates a mesh from it +IAnimatedMesh* CIrrMeshFileLoader::readMesh(io::IXMLReader* reader) +{ + SAnimatedMesh* animatedmesh = new SAnimatedMesh(); + SMesh* mesh = new SMesh(); + + animatedmesh->addMesh(mesh); + mesh->drop(); + + core::stringc bbSectionName = "boundingBox"; + core::stringc bufferSectionName = "buffer"; + core::stringc meshSectionName = "mesh"; + + if (!reader->isEmptyElement()) + while(reader->read()) + { + if (reader->getNodeType() == io::EXN_ELEMENT) + { + const wchar_t* nodeName = reader->getNodeName(); + if (bbSectionName == nodeName) + { + // inside a bounding box, ignore it for now because + // we are calculating this anyway ourselves later. + } + else + if (bufferSectionName == nodeName) + { + // we've got a mesh buffer + + IMeshBuffer* buffer = readMeshBuffer(reader); + if (buffer) + { + mesh->addMeshBuffer(buffer); + buffer->drop(); + } + } + else + skipSection(reader, true); // unknown section + + } // end if node type is element + else + if (reader->getNodeType() == io::EXN_ELEMENT_END) + { + if (meshSectionName == reader->getNodeName()) + { + // end of mesh section reached, cancel out + break; + } + } + } // end while reader->read(); + + mesh->recalculateBoundingBox(); + animatedmesh->recalculateBoundingBox(); + + return animatedmesh; +} + + +//! reads a mesh sections and creates a mesh buffer from it +IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) +{ + CDynamicMeshBuffer* buffer = 0; + + core::stringc verticesSectionName = "vertices"; + core::stringc bbSectionName = "boundingBox"; + core::stringc materialSectionName = "material"; + core::stringc indicesSectionName = "indices"; + core::stringc bufferSectionName = "buffer"; + + bool insideVertexSection = false; + bool insideIndexSection = false; + + int vertexCount = 0; + int indexCount = 0; + + video::SMaterial material; + + if (!reader->isEmptyElement()) + while(reader->read()) + { + if (reader->getNodeType() == io::EXN_ELEMENT) + { + const wchar_t* nodeName = reader->getNodeName(); + if (bbSectionName == nodeName) + { + // inside a bounding box, ignore it for now because + // we are calculating this anyway ourselves later. + } + else + if (materialSectionName == nodeName) + { + //we've got a material + + io::IAttributes* attributes = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); + attributes->read(reader, true, L"material"); + + SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(material, attributes); + attributes->drop(); + } + else + if (verticesSectionName == nodeName) + { + // vertices section + + const core::stringc vertexTypeName1 = "standard"; + const core::stringc vertexTypeName2 = "2tcoords"; + const core::stringc vertexTypeName3 = "tangents"; + + const wchar_t* vertexType = reader->getAttributeValue(L"type"); + vertexCount = reader->getAttributeValueAsInt(L"vertexCount"); + + insideVertexSection = true; + + video::E_INDEX_TYPE itype = (vertexCount > 65536)?irr::video::EIT_32BIT:irr::video::EIT_16BIT; + if (vertexTypeName1 == vertexType) + { + buffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, itype); + + } + else + if (vertexTypeName2 == vertexType) + { + buffer = new CDynamicMeshBuffer(irr::video::EVT_2TCOORDS, itype); + } + else + if (vertexTypeName3 == vertexType) + { + buffer = new CDynamicMeshBuffer(irr::video::EVT_TANGENTS, itype); + } + buffer->getVertexBuffer().reallocate(vertexCount); + buffer->Material = material; + } + else + if (indicesSectionName == nodeName) + { + // indices section + + indexCount = reader->getAttributeValueAsInt(L"indexCount"); + insideIndexSection = true; + } + + } // end if node type is element + else + if (reader->getNodeType() == io::EXN_TEXT) + { + // read vertex data + if (insideVertexSection) + { + readMeshBuffer(reader, vertexCount, buffer); + insideVertexSection = false; + + } // end reading vertex array + else + if (insideIndexSection) + { + readIndices(reader, indexCount, buffer->getIndexBuffer()); + insideIndexSection = false; + } + + } // end if node type is text + else + if (reader->getNodeType() == io::EXN_ELEMENT_END) + { + if (bufferSectionName == reader->getNodeName()) + { + // end of buffer section reached, cancel out + break; + } + } + } // end while reader->read(); + + if (buffer) + buffer->recalculateBoundingBox(); + + return buffer; +} + + +//! read indices +void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices) +{ + indices.reallocate(indexCount); + + core::stringc data = reader->getNodeData(); + const c8* p = &data[0]; + + for (int i=0; igetNodeData(); + const c8* p = &data[0]; + scene::IVertexBuffer& Vertices = sbuffer->getVertexBuffer(); + video::E_VERTEX_TYPE vType = Vertices.getType(); + + if (sbuffer) + { + for (int i=0; igetNodeName()).c_str()); +#endif + + // skip if this element is empty anyway. + if (reader->isEmptyElement()) + return; + + // read until we've reached the last element in this section + u32 tagCounter = 1; + + while(tagCounter && reader->read()) + { + if (reader->getNodeType() == io::EXN_ELEMENT && + !reader->isEmptyElement()) + { + #ifdef _DEBUG + if (reportSkipping) + os::Printer::log("irrMesh unknown element:", core::stringc(reader->getNodeName()).c_str()); + #endif + + ++tagCounter; + } + else + if (reader->getNodeType() == io::EXN_ELEMENT_END) + --tagCounter; + } +} + + +//! parses a float from a char pointer and moves the pointer +//! to the end of the parsed float +inline f32 CIrrMeshFileLoader::readFloat(const c8** p) +{ + f32 ftmp; + *p = core::fast_atof_move(*p, ftmp); + return ftmp; +} + + +//! parses an int from a char pointer and moves the pointer to +//! the end of the parsed float +inline s32 CIrrMeshFileLoader::readInt(const c8** p) +{ + return (s32)readFloat(p); +} + + +//! places pointer to next begin of a token +void CIrrMeshFileLoader::skipCurrentNoneWhiteSpace(const c8** start) +{ + const c8* p = *start; + + while(*p && !(*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) + ++p; + + // TODO: skip comments + + *start = p; +} + +//! places pointer to next begin of a token +void CIrrMeshFileLoader::findNextNoneWhiteSpace(const c8** start) +{ + const c8* p = *start; + + while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) + ++p; + + // TODO: skip comments + + *start = p; +} + + +//! reads floats from inside of xml element until end of xml element +void CIrrMeshFileLoader::readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count) +{ + if (reader->isEmptyElement()) + return; + + while(reader->read()) + { + // TODO: check for comments inside the element + // and ignore them. + + if (reader->getNodeType() == io::EXN_TEXT) + { + // parse float data + core::stringc data = reader->getNodeData(); + const c8* p = &data[0]; + + for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) + break; // end parsing text + } +} + + + + +} // end namespace scene +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_IRR_MESH_LOADER_ -- cgit v1.1