Compare commits

...

2 Commits

Author SHA1 Message Date
Kim Kulling 21888c5596 Fix: first update for fixing irrloader 2023-03-29 23:37:35 +02:00
Kim Kulling 1d125affb4 Fix: Fix utf8 encoding and first steps of irrloader. 2023-03-22 19:03:51 +01:00
10 changed files with 169 additions and 71 deletions

View File

@ -86,10 +86,6 @@ IRRImporter::IRRImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IRRImporter::~IRRImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -837,12 +833,107 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. void setupXmlTree(const std::string &filename, IOSystem *pIOHandler, XmlParser &xmlParser, pugi::xml_node &rootElement) {
void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
// Check whether we can read from the file // Check whether we can read from the file
if (file == nullptr) { if (file == nullptr) {
throw DeadlyImportError("Failed to open IRR file ", filename);
}
// Construct the irrXML parser
if (!xmlParser.parse(file.get())) {
throw DeadlyImportError("XML parse error while loading IRR file ", filename);
}
rootElement = xmlParser.getRootNode().child("irr_scene");
}
void IRRImporter::parseIrrNode(pugi::xml_node &node) {
// ***********************************************************************
/* What we're going to do with the node depends
* on its type:
*
* "mesh" - Load a mesh from an external file
* "cube" - Generate a cube
* "skybox" - Generate a skybox
* "light" - A light source
* "sphere" - Generate a sphere mesh
* "animatedMesh" - Load an animated mesh from an external file
* and join its animation channels with ours.
* "empty" - A dummy node
* "camera" - A camera
* "terrain" - a terrain node (data comes from a heightmap)
* "billboard", ""
*
* Each of these nodes can be animated and all can have multiple
* materials assigned (except lights, cameras and dummies, of course).
*/
// ***********************************************************************
pugi::xml_attribute attrib = node.attribute("type");
Node *nd;
if (!ASSIMP_stricmp(attrib.value(), "mesh") || !ASSIMP_stricmp(attrib.value(), "octTree")) {
// OctTree's and meshes are treated equally
nd = new Node(Node::MESH);
} else if (!ASSIMP_stricmp(attrib.value(), "cube")) {
nd = new Node(Node::CUBE);
++guessedMeshCnt;
} else if (!ASSIMP_stricmp(attrib.value(), "skybox")) {
nd = new Node(Node::SKYBOX);
guessedMeshCnt += 6;
} else if (!ASSIMP_stricmp(attrib.value(), "camera")) {
nd = new Node(Node::CAMERA);
// Setup a temporary name for the camera
aiCamera *cam = new aiCamera();
cam->mName.Set(nd->name);
cameras.push_back(cam);
} else if (!ASSIMP_stricmp(attrib.value(), "light")) {
nd = new Node(Node::LIGHT);
// Setup a temporary name for the light
aiLight *cam = new aiLight();
cam->mName.Set(nd->name);
lights.push_back(cam);
} else if (!ASSIMP_stricmp(attrib.value(), "sphere")) {
nd = new Node(Node::SPHERE);
++guessedMeshCnt;
} else if (!ASSIMP_stricmp(attrib.value(), "animatedMesh")) {
nd = new Node(Node::ANIMMESH);
} else if (!ASSIMP_stricmp(attrib.value(), "empty")) {
nd = new Node(Node::DUMMY);
} else if (!ASSIMP_stricmp(attrib.value(), "terrain")) {
nd = new Node(Node::TERRAIN);
} else if (!ASSIMP_stricmp(attrib.value(), "billBoard")) {
// We don't support billboards, so ignore them
ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
nd = new Node(Node::DUMMY);
} else {
ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.value());
/* We skip the contents of nodes we don't know.
* We parse the transformation and all animators
* and skip the rest.
*/
nd = new Node(Node::DUMMY);
}
/* Attach the newly created node to the scene-graph
*/
curNode = nd;
nd->parent = curParent;
curParent->children.push_back(nd);
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void IRRImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
pugi::xml_node rootElement;
XmlParser xmlParser;
setupXmlTree(filename, pIOHandler, xmlParser, rootElement);
//std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
// Check whether we can read from the file
/* if (file == nullptr) {
throw DeadlyImportError("Failed to open IRR file ", pFile); throw DeadlyImportError("Failed to open IRR file ", pFile);
} }
@ -851,7 +942,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (!st.parse( file.get() )) { if (!st.parse( file.get() )) {
throw DeadlyImportError("XML parse error while loading IRR file ", pFile); throw DeadlyImportError("XML parse error while loading IRR file ", pFile);
} }
pugi::xml_node rootElement = st.getRootNode(); pugi::xml_node rootElement = st.getRootNode().child("irr_scene");*/
// The root node of the scene // The root node of the scene
Node *root = new Node(Node::DUMMY); Node *root = new Node(Node::DUMMY);
@ -872,7 +963,6 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Batch loader used to load external models // Batch loader used to load external models
BatchLoader batch(pIOHandler); BatchLoader batch(pIOHandler);
//batch.SetBasePath(pFile);
cameras.reserve(5); cameras.reserve(5);
lights.reserve(5); lights.reserve(5);
@ -881,9 +971,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0; unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
// Parse the XML file // Parse the XML file
for (const pugi::xml_node &child : rootElement.children())
//while (reader->read()) {
for (pugi::xml_node child : rootElement.children())
switch (child.type()) { switch (child.type()) {
case pugi::node_element: case pugi::node_element:
if (!ASSIMP_stricmp(child.name(), "node")) { if (!ASSIMP_stricmp(child.name(), "node")) {
@ -907,47 +995,46 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
* materials assigned (except lights, cameras and dummies, of course). * materials assigned (except lights, cameras and dummies, of course).
*/ */
// *********************************************************************** // ***********************************************************************
//const char *sz = reader->getAttributeValueSafe("type");
pugi::xml_attribute attrib = child.attribute("type"); pugi::xml_attribute attrib = child.attribute("type");
Node *nd; Node *nd;
if (!ASSIMP_stricmp(attrib.name(), "mesh") || !ASSIMP_stricmp(attrib.name(), "octTree")) { if (!ASSIMP_stricmp(attrib.value(), "mesh") || !ASSIMP_stricmp(attrib.value(), "octTree")) {
// OctTree's and meshes are treated equally // OctTree's and meshes are treated equally
nd = new Node(Node::MESH); nd = new Node(Node::MESH);
} else if (!ASSIMP_stricmp(attrib.name(), "cube")) { } else if (!ASSIMP_stricmp(attrib.value(), "cube")) {
nd = new Node(Node::CUBE); nd = new Node(Node::CUBE);
++guessedMeshCnt; ++guessedMeshCnt;
} else if (!ASSIMP_stricmp(attrib.name(), "skybox")) { } else if (!ASSIMP_stricmp(attrib.value(), "skybox")) {
nd = new Node(Node::SKYBOX); nd = new Node(Node::SKYBOX);
guessedMeshCnt += 6; guessedMeshCnt += 6;
} else if (!ASSIMP_stricmp(attrib.name(), "camera")) { } else if (!ASSIMP_stricmp(attrib.value(), "camera")) {
nd = new Node(Node::CAMERA); nd = new Node(Node::CAMERA);
// Setup a temporary name for the camera // Setup a temporary name for the camera
aiCamera *cam = new aiCamera(); aiCamera *cam = new aiCamera();
cam->mName.Set(nd->name); cam->mName.Set(nd->name);
cameras.push_back(cam); cameras.push_back(cam);
} else if (!ASSIMP_stricmp(attrib.name(), "light")) { } else if (!ASSIMP_stricmp(attrib.value(), "light")) {
nd = new Node(Node::LIGHT); nd = new Node(Node::LIGHT);
// Setup a temporary name for the light // Setup a temporary name for the light
aiLight *cam = new aiLight(); aiLight *cam = new aiLight();
cam->mName.Set(nd->name); cam->mName.Set(nd->name);
lights.push_back(cam); lights.push_back(cam);
} else if (!ASSIMP_stricmp(attrib.name(), "sphere")) { } else if (!ASSIMP_stricmp(attrib.value(), "sphere")) {
nd = new Node(Node::SPHERE); nd = new Node(Node::SPHERE);
++guessedMeshCnt; ++guessedMeshCnt;
} else if (!ASSIMP_stricmp(attrib.name(), "animatedMesh")) { } else if (!ASSIMP_stricmp(attrib.value(), "animatedMesh")) {
nd = new Node(Node::ANIMMESH); nd = new Node(Node::ANIMMESH);
} else if (!ASSIMP_stricmp(attrib.name(), "empty")) { } else if (!ASSIMP_stricmp(attrib.value(), "empty")) {
nd = new Node(Node::DUMMY); nd = new Node(Node::DUMMY);
} else if (!ASSIMP_stricmp(attrib.name(), "terrain")) { } else if (!ASSIMP_stricmp(attrib.value(), "terrain")) {
nd = new Node(Node::TERRAIN); nd = new Node(Node::TERRAIN);
} else if (!ASSIMP_stricmp(attrib.name(), "billBoard")) { } else if (!ASSIMP_stricmp(attrib.value(), "billBoard")) {
// We don't support billboards, so ignore them // We don't support billboards, so ignore them
ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
nd = new Node(Node::DUMMY); nd = new Node(Node::DUMMY);
} else { } else {
ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.name()); ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.value());
/* We skip the contents of nodes we don't know. /* We skip the contents of nodes we don't know.
* We parse the transformation and all animators * We parse the transformation and all animators
@ -992,10 +1079,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
++guessedAnimCnt; ++guessedAnimCnt;
} }
/* Parse all elements in the attributes block // Parse all elements in the attributes block and process them.
* and process them.
*/
// while (reader->read()) {
for (pugi::xml_node attrib : child.children()) { for (pugi::xml_node attrib : child.children()) {
if (attrib.type() == pugi::node_element) { if (attrib.type() == pugi::node_element) {
//if (reader->getNodeType() == EXN_ELEMENT) { //if (reader->getNodeType() == EXN_ELEMENT) {
@ -1083,10 +1167,9 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) { if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
curNode->framesPerSecond = prop.value; curNode->framesPerSecond = prop.value;
} else if (Node::CAMERA == curNode->type) { } else if (Node::CAMERA == curNode->type) {
/* This is the vertical, not the horizontal FOV. // This is the vertical, not the horizontal FOV.
* We need to compute the right FOV from the // We need to compute the right FOV from the
* screen aspect which we don't know yet. // screen aspect which we don't know yet.
*/
if (prop.name == "Fovy") { if (prop.name == "Fovy") {
cameras.back()->mHorizontalFOV = prop.value; cameras.back()->mHorizontalFOV = prop.value;
} else if (prop.name == "Aspect") { } else if (prop.name == "Aspect") {
@ -1097,8 +1180,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
cameras.back()->mClipPlaneFar = prop.value; cameras.back()->mClipPlaneFar = prop.value;
} }
} else if (Node::LIGHT == curNode->type) { } else if (Node::LIGHT == curNode->type) {
/* Additional light information // Additional light information
*/
if (prop.name == "Attenuation") { if (prop.name == "Attenuation") {
lights.back()->mAttenuationLinear = prop.value; lights.back()->mAttenuationLinear = prop.value;
} else if (prop.name == "OuterCone") { } else if (prop.name == "OuterCone") {

View File

@ -65,7 +65,7 @@ namespace Assimp {
class IRRImporter : public BaseImporter, public IrrlichtBase { class IRRImporter : public BaseImporter, public IrrlichtBase {
public: public:
IRRImporter(); IRRImporter();
~IRRImporter() override; ~IRRImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
@ -78,6 +78,7 @@ protected:
const aiImporterDesc* GetInfo () const override; const aiImporterDesc* GetInfo () const override;
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
void SetupProperties(const Importer* pImp) override; void SetupProperties(const Importer* pImp) override;
void parseIrrNode();
private: private:
/** Data structure for a scene-graph node animator /** Data structure for a scene-graph node animator

View File

@ -69,14 +69,6 @@ static const aiImporterDesc desc = {
"xml irrmesh" "xml irrmesh"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IRRMeshImporter::IRRMeshImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IRRMeshImporter::~IRRMeshImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool IRRMeshImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool IRRMeshImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -62,8 +62,8 @@ namespace Assimp {
*/ */
class IRRMeshImporter : public BaseImporter, public IrrlichtBase { class IRRMeshImporter : public BaseImporter, public IrrlichtBase {
public: public:
IRRMeshImporter(); IRRMeshImporter() = default;
~IRRMeshImporter() override; ~IRRMeshImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -64,7 +64,7 @@ const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a property in hexadecimal format (i.e. ffffffff) // read a property in hexadecimal format (i.e. ffffffff)
void IrrlichtBase::ReadHexProperty(HexProperty &out ) { void IrrlichtBase::ReadHexProperty(HexProperty &out ) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")) { if (!ASSIMP_stricmp(attrib.name(), "name")) {
out.name = std::string( attrib.value() ); out.name = std::string( attrib.value() );
} else if (!ASSIMP_stricmp(attrib.name(),"value")) { } else if (!ASSIMP_stricmp(attrib.name(),"value")) {
@ -77,7 +77,7 @@ void IrrlichtBase::ReadHexProperty(HexProperty &out ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a decimal property // read a decimal property
void IrrlichtBase::ReadIntProperty(IntProperty & out) { void IrrlichtBase::ReadIntProperty(IntProperty & out) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")) { if (!ASSIMP_stricmp(attrib.name(), "name")) {
out.name = std::string(attrib.value()); out.name = std::string(attrib.value());
} else if (!ASSIMP_stricmp(attrib.value(),"value")) { } else if (!ASSIMP_stricmp(attrib.value(),"value")) {
@ -90,7 +90,7 @@ void IrrlichtBase::ReadIntProperty(IntProperty & out) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a string property // read a string property
void IrrlichtBase::ReadStringProperty( StringProperty& out) { void IrrlichtBase::ReadStringProperty( StringProperty& out) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")) { if (!ASSIMP_stricmp(attrib.name(), "name")) {
out.name = std::string(attrib.value()); out.name = std::string(attrib.value());
} else if (!ASSIMP_stricmp(attrib.name(), "value")) { } else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@ -103,7 +103,7 @@ void IrrlichtBase::ReadStringProperty( StringProperty& out) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a boolean property // read a boolean property
void IrrlichtBase::ReadBoolProperty(BoolProperty &out) { void IrrlichtBase::ReadBoolProperty(BoolProperty &out) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")){ if (!ASSIMP_stricmp(attrib.name(), "name")){
out.name = std::string(attrib.value()); out.name = std::string(attrib.value());
} else if (!ASSIMP_stricmp(attrib.name(), "value")) { } else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@ -116,7 +116,7 @@ void IrrlichtBase::ReadBoolProperty(BoolProperty &out) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a float property // read a float property
void IrrlichtBase::ReadFloatProperty(FloatProperty &out) { void IrrlichtBase::ReadFloatProperty(FloatProperty &out) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")) { if (!ASSIMP_stricmp(attrib.name(), "name")) {
out.name = std::string(attrib.value()); out.name = std::string(attrib.value());
} else if (!ASSIMP_stricmp(attrib.name(), "value")) { } else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@ -129,7 +129,7 @@ void IrrlichtBase::ReadFloatProperty(FloatProperty &out) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a vector property // read a vector property
void IrrlichtBase::ReadVectorProperty( VectorProperty &out ) { void IrrlichtBase::ReadVectorProperty( VectorProperty &out ) {
for (pugi::xml_attribute attrib : mNode->attributes()) { for (const pugi::xml_attribute &attrib : mNode->attributes()) {
if (!ASSIMP_stricmp(attrib.name(), "name")) { if (!ASSIMP_stricmp(attrib.name(), "name")) {
out.name = std::string(attrib.value()); out.name = std::string(attrib.value());
} else if (!ASSIMP_stricmp(attrib.name(), "value")) { } else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@ -179,7 +179,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) {
int cnt = 0; // number of used texture channels int cnt = 0; // number of used texture channels
unsigned int nd = 0; unsigned int nd = 0;
for (pugi::xml_node child : mNode->children()) { for (const pugi::xml_node &child : mNode->children()) {
if (!ASSIMP_stricmp(child.name(), "color")) { // Hex properties if (!ASSIMP_stricmp(child.name(), "color")) { // Hex properties
HexProperty prop; HexProperty prop;
ReadHexProperty(prop); ReadHexProperty(prop);

View File

@ -389,9 +389,18 @@ void BaseImporter::ConvertToUTF8(std::vector<char> &data) {
// UTF 16 LE with BOM // UTF 16 LE with BOM
if (*((uint16_t *)&data.front()) == 0xFEFF) { if (*((uint16_t *)&data.front()) == 0xFEFF) {
ASSIMP_LOG_DEBUG("Found UTF-16 BOM ..."); ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
const size_t size = data.size();
std::vector<unsigned char> output; const uint16_t *sourceStart = (uint16_t *)data.data();
utf8::utf16to8(data.begin(), data.end(), back_inserter(output)); const size_t targetSize = size * 3; // enough to encode
char *targetStart = new char[targetSize];
std::memset(targetStart, 0, targetSize * sizeof(char));
utf8::utf16to8(sourceStart, sourceStart + size / 2, targetStart);
std::string result(targetStart);
data.clear();
for (size_t i = 0; i < result.size(); ++i) {
data.push_back(result[i]);
}
delete[] targetStart;
return; return;
} }
} }

View File

@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BASE64_HPP_INC #ifndef AI_BASE64_HPP_INC
#define AI_BASE64_HPP_INC #define AI_BASE64_HPP_INC
#include <stdint.h> #include <cstdint>
#include <vector> #include <vector>
#include <string> #include <string>

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <cstdint> #include <cstdint>
#include <set> #include <set>
#include <vector> #include <vector>
@ -62,7 +63,9 @@ namespace Assimp {
class BlobIOSystem; class BlobIOSystem;
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/** Redirect IOStream to a blob */ /**
* @brief Redirect IOStream to a blob
*/
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
class BlobIOStream : public IOStream { class BlobIOStream : public IOStream {
public: public:
@ -84,7 +87,6 @@ public:
/// @brief The class destructor. /// @brief The class destructor.
~BlobIOStream() override; ~BlobIOStream() override;
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
aiExportDataBlob *GetBlob() { aiExportDataBlob *GetBlob() {
aiExportDataBlob *blob = new aiExportDataBlob(); aiExportDataBlob *blob = new aiExportDataBlob();
@ -194,15 +196,14 @@ private:
/** Redirect IOSystem to a blob */ /** Redirect IOSystem to a blob */
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
class BlobIOSystem : public IOSystem { class BlobIOSystem : public IOSystem {
friend class BlobIOStream; friend class BlobIOStream;
typedef std::pair<std::string, aiExportDataBlob *> BlobEntry; typedef std::pair<std::string, aiExportDataBlob *> BlobEntry;
public: public:
/// @brief The default class constructor. /// @brief The default class constructor.
BlobIOSystem() : BlobIOSystem() :
baseName{AI_BLOBIO_MAGIC} { baseName{AI_BLOBIO_MAGIC} {
//
} }
/// @brief The class constructor with the base name. /// @brief The class constructor with the base name.
@ -218,7 +219,6 @@ public:
} }
} }
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
const char *GetMagicFileName() const { const char *GetMagicFileName() const {
return baseName.c_str(); return baseName.c_str();
@ -269,7 +269,6 @@ public:
return master; return master;
} }
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool Exists(const char *pFile) const override { bool Exists(const char *pFile) const override {
return created.find(std::string(pFile)) != created.end(); return created.find(std::string(pFile)) != created.end();

View File

@ -44,13 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/BaseImporter.h>
#include "BaseImporter.h"
#include "IOStream.hpp" #include "IOStream.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <cinttypes>
namespace Assimp { namespace Assimp {
@ -127,6 +128,8 @@ public:
/// @return true, if the parsing was successful, false if not. /// @return true, if the parsing was successful, false if not.
bool parse(IOStream *stream); bool parse(IOStream *stream);
bool parseFromBuffer(std::vector<char> &buffer);
/// @brief Will return true if a root node is there. /// @brief Will return true if a root node is there.
/// @return true in case of an existing root. /// @return true in case of an existing root.
bool hasRoot() const; bool hasRoot() const;
@ -287,22 +290,34 @@ bool TXmlParser<TNodeType>::hasNode(const std::string &name) {
template <class TNodeType> template <class TNodeType>
bool TXmlParser<TNodeType>::parse(IOStream *stream) { bool TXmlParser<TNodeType>::parse(IOStream *stream) {
if (hasRoot()) {
clear();
}
if (nullptr == stream) { if (nullptr == stream) {
ASSIMP_LOG_DEBUG("Stream is nullptr."); ASSIMP_LOG_DEBUG("Stream is nullptr.");
return false; return false;
} }
const size_t len = stream->FileSize(); const size_t len = stream->FileSize();
if (len == 0) {
ASSIMP_LOG_DEBUG("The xml file is empty.");
return false;
}
mData.resize(len + 1); mData.resize(len + 1);
memset(&mData[0], '\0', len + 1); memset(&mData[0], '\0', len + 1);
stream->Read(&mData[0], 1, len); stream->Read(&mData[0], 1, len);
return parseFromBuffer(mData);
}
template <class TNodeType>
bool TXmlParser<TNodeType>::parseFromBuffer(std::vector<char> &buffer) {
if (hasRoot()) {
clear();
}
BaseImporter::ConvertToUTF8(mData);
mDoc = new pugi::xml_document(); mDoc = new pugi::xml_document();
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full); pugi::xml_parse_result parse_result = mDoc->load_string(&buffer[0], pugi::parse_full);
if (parse_result.status == pugi::status_ok) { if (parse_result.status == pugi::status_ok) {
return true; return true;
} }