added CSimpleElement
MODIFY
ext/MitsubaLoader/CElementFactory.cpp
ext/MitsubaLoader/CElementFactory.cpp
#include <string>
#include "ParserUtil.h"
+#include "IElement.h"
#include "CElementShapeCube.h"
+#include "CSimpleElement.h"
namespace irr { namespace ext { namespace MitsubaLoader {
@@ -22,6 +24,22 @@ IElement* CElementFactory::createElement(const char* _el, const char** _atts)
{
return parseShape(_el, _atts);
}
+ if (!std::strcmp(_el, "float"))
+ {
+ return parseSimpleElement(_el, _atts, IElement::Type::FLOAT);
+ }
+ if (!std::strcmp(_el, "integer"))
+ {
+ return parseSimpleElement(_el, _atts, IElement::Type::INTEGER);
+ }
+ if (!std::strcmp(_el, "boolean"))
+ {
+ return parseSimpleElement(_el, _atts, IElement::Type::BOOLEAN);
+ }
+ if (!std::strcmp(_el, "point"))
+ {
+ return parseSimpleElement(_el, _atts, IElement::Type::POINT);
+ }
else
{
ParserLog::mitsubaLoaderError("invalid .xml file structure: element " + std::string(_el) + "is unknown. \n");
@@ -44,9 +62,7 @@ IElement* CElementFactory::parseShape(const char* _el, const char** _atts)
{
if (!std::strcmp(_atts[i + 1], "cube"))
{
- result = new CElementShapeCube();
- os::Printer::print("We have done it! we created a cube! \n");
- return result;
+ return new CElementShapeCube();
}
else
{
@@ -57,30 +73,32 @@ IElement* CElementFactory::parseShape(const char* _el, const char** _atts)
}
ParserLog::mitsubaLoaderError("There is no type attribute for shape element. \n");
+ return nullptr;
}
-//shape element processing loop
-/*std::string shapeType = "";
-for (int i = 0; _attr[i]; i += 2)
+IElement* CElementFactory::parseSimpleElement(const char* _el, const char** _atts, IElement::Type type)
{
- if (!std::strcmp(_attr[i], "type"))
+ switch (type)
{
- if (!std::strcmp(_attr[i + 1], "cube"))
+ case IElement::Type::FLOAT:
+ return new CElementFloat();
+ case IElement::Type::INTEGER:
{
+ //not implemented
+ _IRR_DEBUG_BREAK_IF(true);
return nullptr;
}
- else
- {
- std::cout << _attr[i + 1] << " is unknown shape type. \n";
- }
+ case IElement::Type::BOOLEAN:
+ return new CElementBoolean();
+ case IElement::Type::POINT:
+ return new CElementPoint();
+ default:
+ _IRR_DEBUG_BREAK_IF(true);
+ return nullptr;
}
- else
- {
- std::cout << _attr[i] << "is unknown paramater of element shape.\n";
+ return new CElementFloat();
}
-}*/
-
}
}
}
\ No newline at end of file

MODIFY
ext/MitsubaLoader/CElementFactory.h
ext/MitsubaLoader/CElementFactory.h
@@ -18,6 +18,7 @@ public:
private:
static IElement* parseScene(const char* _el, const char** _atts);
static IElement* parseShape(const char* _el, const char** _atts);
+ static IElement* parseSimpleElement(const char* _el, const char** _atts, IElement::Type type);
};
}

MODIFY
ext/MitsubaLoader/CElementShapeCube.cpp
ext/MitsubaLoader/CElementShapeCube.cpp
@@ -11,14 +11,13 @@ CElementShapeCube::CElementShapeCube()
bool CElementShapeCube::processAttributes(const char** _atts)
{
- os::Printer::print("SHAPE CUBE ON BEGIN TAG");
//only type is an acceptable argument
for (int i = 0; _atts[i]; i += 2)
{
if (std::strcmp(_atts[i], "type"))
{
- ParserLog::wrongAttribute(_atts[i], getName());
+ ParserLog::wrongAttribute(_atts[i], getLogName());
return false;
}
}
@@ -30,8 +29,6 @@ bool CElementShapeCube::onEndTag(asset::IAssetManager& _assetManager, IElement*
{
asset::ICPUMesh* cubeMesh = _assetManager.getGeometryCreator()->createCubeMesh(core::vector3df(2.0f, 2.0f, 2.0f));
- os::Printer::print("SHAPE CUBE ON END TAG");
-
if (!cubeMesh)
return false;
@@ -44,11 +41,11 @@ bool CElementShapeCube::processChildData(IElement* _child)
{
switch (_child->getType())
{
- case IElement::Type::TO_WORLD_TRANSFORM:
+ case IElement::Type::TRANSFORM:
return true;
default:
- ParserLog::wrongChildElement(getName(), _child->getName());
+ ParserLog::wrongChildElement(getLogName(), _child->getLogName());
return false;
}
}

MODIFY
ext/MitsubaLoader/CElementShapeCube.h
ext/MitsubaLoader/CElementShapeCube.h
@@ -15,7 +15,7 @@ public:
virtual bool processAttributes(const char** _args) override;
virtual bool onEndTag(asset::IAssetManager& _assetManager, IElement* _parent) override;
virtual IElement::Type getType() const override { return IElement::Type::SHAPE_CUBE; };
- virtual std::string getName() const override { return "shape cube"; };
+ virtual std::string getLogName() const override { return "shape cube"; };
virtual bool processChildData(IElement* child) override;
private:

MODIFY
ext/MitsubaLoader/CMitsubaLoader.cpp
ext/MitsubaLoader/CMitsubaLoader.cpp
@@ -16,11 +16,17 @@ namespace irr { namespace ext { namespace MitsubaLoader {
//TODO:
/*
- - smart pointers
+ - !!!!!!!! REDUCE NUMBER OF ENUMS IN IElement::Type
+ - consider if getName function is really needed (getLogName maybe?)
+
- proper handling of incorrect .xml file structure (in some situations parsing should be stoped and nullptr should be returned
from CMitsubaLoader::loadAsset, and in other situations only warning should be shown.)
- - handle situations when elementFactory returns nullptr
- - use log functions instead of std::cout
+ - handle 'version' attribute
+
+ - make sure default values for <float .. /> <boolean .. /> etc. are correct
+ - test atof function (CSimpleElement.h)
+
+
*/

MODIFY
ext/MitsubaLoader/CMitsubaScene.cpp
ext/MitsubaLoader/CMitsubaScene.cpp
@@ -10,11 +10,10 @@ namespace irr { namespace ext { namespace MitsubaLoader {
bool CMitsubaScene::processAttributes(const char** _atts)
{
- os::Printer::print("SCENE ON BEGIN TAG");
if (std::strcmp(_atts[0], "version"))
{
- ParserLog::wrongAttribute(_atts[0], getName());
+ ParserLog::wrongAttribute(_atts[0], getLogName());
return false;
}
else
@@ -27,7 +26,6 @@ bool CMitsubaScene::processAttributes(const char** _atts)
bool CMitsubaScene::onEndTag(asset::IAssetManager& assetManager, IElement* parent)
{
- os::Printer::print("SCENE ON END TAG");
return true;
}
@@ -51,9 +49,9 @@ bool CMitsubaScene::processChildData(IElement* _child)
return true;
default:
- ParserLog::wrongChildElement(getName(), _child->getName());
+ ParserLog::wrongChildElement(getLogName(), _child->getLogName());
- return false;
+ return true;
}
}

MODIFY
ext/MitsubaLoader/CMitsubaScene.h
ext/MitsubaLoader/CMitsubaScene.h
@@ -19,7 +19,7 @@ public:
virtual bool processAttributes(const char** _arguments) override;
virtual bool onEndTag(asset::IAssetManager& assetManager, IElement* parent) override;
virtual IElement::Type getType() const override { return IElement::Type::SCENE; };
- virtual std::string getName() const override { return "scene"; };
+ virtual std::string getLogName() const override { return "scene"; };
virtual bool processChildData(IElement* child) override;
asset::SCPUMesh* releaseMesh() { return mesh; mesh = nullptr; }

ADD
ext/MitsubaLoader/CSimpleElement.h
+#ifndef __C_SIMPLE_ELEMENT_H_INCLUDED__
+#define __C_SIMPLE_ELEMENT_H_INCLUDED__
+
+#include "IElement.h"
+#include "../include/irr/static_if.h"
+#include "ParserUtil.h"
+
+#include "irrlicht.h"
+
+namespace irr { namespace ext { namespace MitsubaLoader {
+
+template<typename T>
+class CSimpleElement : public IElement
+{
+ static_assert(
+ std::is_same<T, float>::value ||
+ std::is_same<T, bool>::value ||
+ std::is_same<T, core::vector3df_SIMD>::value,
+ "assertion failed: cannot use this type");
+
+public:
+ CSimpleElement()
+ :type(IElement::Type::NONE),
+ value(0.0f)
+ {
+ IRR_PSEUDO_IF_CONSTEXPR_BEGIN(std::is_same<T, float>::value)
+ {
+ logName = "float";
+ return;
+ }
+ IRR_PSEUDO_IF_CONSTEXPR_END
+
+ IRR_PSEUDO_IF_CONSTEXPR_BEGIN(std::is_same<T, bool>::value)
+ {
+ logName = "boolean";
+ return;
+ }
+ IRR_PSEUDO_IF_CONSTEXPR_END
+
+ IRR_PSEUDO_IF_CONSTEXPR_BEGIN(std::is_same<T, core::vector3df_SIMD>::value)
+ {
+ logName = "point";
+ return;
+ }
+ IRR_PSEUDO_IF_CONSTEXPR_END
+ };
+
+ virtual bool processAttributes(const char** _atts) override;
+ virtual bool onEndTag(asset::IAssetManager& _assetManager, IElement* _parent) override
+ {
+ //so far it is only for testing purpose
+
+ os::Printer::print("\t" + getLogName() + " name: " + nameAttr + " value: ");
+ //os::Printer::print(value);
+
+ return true;
+ }
+ virtual IElement::Type getType() const override { return type; };
+ virtual std::string getLogName() const override { return logName; };
+
+ inline std::string getNameAttribute() const { return nameAttr; }
+ inline T getValueAttribute() const { return valueAttr; }
+
+private:
+ T value;
+ IElement::Type type;
+ std::string logName;
+
+ std::string nameAttr;
+ T valueAttr;
+};
+
+using CElementFloat = CSimpleElement<float>;
+using CElementBoolean = CSimpleElement<bool>;
+using CElementPoint = CSimpleElement<irr::core::vector3df_SIMD>;
+
+template<typename T>
+bool CSimpleElement<T>::processAttributes(const char** _atts)
+{
+ static_assert(false);
+}
+
+template<>
+bool CSimpleElement<float>::processAttributes(const char** _atts)
+{
+ bool isNameSet = false;
+
+ for (int i = 0; _atts[i]; i += 2)
+ {
+ if (!std::strcmp(_atts[i], "name"))
+ {
+ if (!std::strcmp(_atts[i + 1], "radius") ||
+ !std::strcmp(_atts[i + 1], "maxSmoothAngle"))
+ {
+ nameAttr = _atts[i + 1];
+ isNameSet = true;
+ }
+ else
+ {
+ //print warning
+ }
+ }
+ else if (!std::strcmp(_atts[i], "value"))
+ {
+ value = static_cast<float>(atof(_atts[i + 1]));
+ }
+ else
+ {
+ //print warning
+ }
+
+ }
+
+ if (!isNameSet)
+ ;//print error
+
+ return isNameSet;
+}
+
+template<>
+bool CSimpleElement<bool>::processAttributes(const char** _atts)
+{
+ bool isNameSet = false;
+
+ for (int i = 0; _atts[i]; i += 2)
+ {
+ if (!std::strcmp(_atts[i], "name"))
+ {
+ if (!std::strcmp(_atts[i + 1], "flipNormals") ||
+ !std::strcmp(_atts[i + 1], "flipTexCoords") ||
+ !std::strcmp(_atts[i + 1], "faceNormals") ||
+ !std::strcmp(_atts[i + 1], "srgb"))
+ {
+ nameAttr = _atts[i + 1];
+ isNameSet = true;
+ }
+ else
+ {
+ //print warning
+ }
+ }
+
+
+ if (!std::strcmp(_atts[i], "value"))
+ {
+ if (!std::strcmp(_atts[i + 1], "true"))
+ value = true;
+ else if (!std::strcmp(_atts[i + 1], "true"))
+ value = false;
+ else
+ {
+ //print warning
+ }
+ }
+ }
+
+ return isNameSet;
+}
+
+template<>
+bool CSimpleElement<core::vector3df_SIMD>::processAttributes(const char** _atts)
+{
+ bool isNameSet = false;
+
+ return isNameSet;
+}
+
+}
+}
+}
+
+#endif
\ No newline at end of file

MODIFY
ext/MitsubaLoader/IElement.h
ext/MitsubaLoader/IElement.h
@@ -15,6 +15,7 @@ class IElement
public:
enum class Type
{
+ NONE,
SCENE,
//shapes
@@ -28,11 +29,13 @@ public:
SHAPE_RECTANGLE,
//vectors, points, scalars
- FLOAT_RADIUS,
- POINT_CENTER,
+ FLOAT,
+ BOOLEAN,
+ INTEGER,
+ POINT,
//other
- TO_WORLD_TRANSFORM,
+ TRANSFORM,
TEXTURE
};
@@ -42,16 +45,26 @@ public:
{
if (_atts[0])
{
- std::cout << "Invalid .xml file structure: element " << getName().c_str() << " doesn't take any attributes \n";
+ std::cout << "Invalid .xml file structure: element " << getLogName().c_str() << " doesn't take any attributes \n";
return false;
}
return true;
- };
+ }
+ //! default implementation for elements that doesnt have any children
+ virtual bool processChildData(IElement* _child)
+ {
+ if (_child != nullptr)
+ {
+ //ParserLog::wrongChildElement(getName(), _child->getName());
+ return false;
+ }
+ return true;
+ }
virtual bool onEndTag(asset::IAssetManager& _assetManager, IElement* _parent) = 0;
virtual IElement::Type getType() const = 0;
- virtual std::string getName() const = 0;
- virtual bool processChildData(IElement* child) = 0;
+ virtual std::string getLogName() const = 0;
+
};

MODIFY
ext/MitsubaLoader/ParserUtil.cpp
ext/MitsubaLoader/ParserUtil.cpp
@@ -11,6 +11,8 @@ void ParserLog::wrongAttribute(const std::string& attribName, const std::string&
//or os::Printer::log ?
os::Printer::print(message);
+
+ _IRR_DEBUG_BREAK_IF(true);
}
void ParserLog::wrongChildElement(const std::string& parentName, const std::string& childName)
@@ -20,6 +22,8 @@ void ParserLog::wrongChildElement(const std::string& parentName, const std::stri
//or os::Printer::log ?
os::Printer::print(message);
+
+ _IRR_DEBUG_BREAK_IF(true);
}
void ParserLog::mitsubaLoaderError(const std::string& errorMessage)
@@ -29,6 +33,8 @@ void ParserLog::mitsubaLoaderError(const std::string& errorMessage)
//or os::Printer::log ?
os::Printer::print(message);
+
+ _IRR_DEBUG_BREAK_IF(true);
}
void elementHandlerStart(void* _data, const char* _el, const char** _atts)
@@ -37,15 +43,14 @@ void elementHandlerStart(void* _data, const char* _el, const char** _atts)
std::unique_ptr<IElement> element(CElementFactory::createElement(_el, _atts));
- //TODO: test ! operator of std::unique_ptr
-
if (!element)
{
XML_StopParser(data->parser, false);
+ _IRR_DEBUG_BREAK_IF(true);
return;
}
- if (element->getName() == "scene")
+ if (element->getType() == IElement::Type::SCENE)
{
if (!data->scene)
{
@@ -58,6 +63,7 @@ void elementHandlerStart(void* _data, const char* _el, const char** _atts)
{
ParserLog::wrongChildElement("scene", "scene");
XML_StopParser(data->parser, false);
+ _IRR_DEBUG_BREAK_IF(true);
return;
}
}
@@ -66,12 +72,14 @@ void elementHandlerStart(void* _data, const char* _el, const char** _atts)
{
ParserLog::mitsubaLoaderError("there is no scene element");
XML_StopParser(data->parser, false);
+ _IRR_DEBUG_BREAK_IF(true);
return;
}
if (!element->processAttributes(_atts))
{
XML_StopParser(data->parser, false);
+ _IRR_DEBUG_BREAK_IF(true);
return;
}
@@ -97,6 +105,7 @@ void elementHandlerEnd(void* _data, const char* _el)
if (!element->onEndTag(data->assetManager, parent))
{
XML_StopParser(data->parser, false);
+ _IRR_DEBUG_BREAK_IF(true);
return;
}
}

MODIFY
ext/MitsubaLoader/ParserUtil.h
ext/MitsubaLoader/ParserUtil.h
+#ifndef __I_PARSER_UTIL_H_INCLUDED__
+#define __I_PARSER_UTIL_H_INCLUDED__
+
#include "../3rdparty/libexpat/expat/lib/expat.h"
#include "irr/asset/IAssetManager.h"
#include "CMitsubaScene.h"
+
#include "IElement.h"
-#include "CMitsubaScene.h"
#include "irr/asset/IAssetLoader.h"
#include "ISceneManager.h"
namespace irr { namespace ext { namespace MitsubaLoader {
+
//struct, which will be passed to expat handlers as user data (first argument) see: XML_StartElementHandler or XML_EndElementHandler in expat.h
struct ParserData
{
@@ -64,3 +68,5 @@ void elementHandlerEnd(void* _data, const char* _el);
}
}
}
+
+#endif
\ No newline at end of file

MODIFY
ext/MitsubaLoader/testScene.xml
ext/MitsubaLoader/testScene.xml
<scene version="0.5.0">
+ <float name="radius" value="70" />
+ <boolean name="flipNormals" value = "true" />
+
+ <shape type="cube">
+
+ </shape>
+
<shape type="cube">
</shape>

added CSimpleElement