finish migration of collada.

pull/2966/head
Kim Kulling 2020-08-26 22:31:46 +02:00
parent 904f17f29f
commit c359b973bb
4 changed files with 241 additions and 470 deletions

View File

@ -224,7 +224,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read bool from text contents of current element // Read bool from text contents of current element
bool ColladaParser::ReadBoolFromTextContent() { /*bool ColladaParser::ReadBoolFromTextContent() {
const char *cur = GetTextContent(); const char *cur = GetTextContent();
if (nullptr == cur) { if (nullptr == cur) {
return false; return false;
@ -240,7 +240,7 @@ ai_real ColladaParser::ReadFloatFromTextContent() {
return 0.0; return 0.0;
} }
return fast_atof(cur); return fast_atof(cur);
} }*/
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the contents of the file // Reads the contents of the file
@ -664,11 +664,11 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
} }
} else if (currentName == "source") { } else if (currentName == "source") {
ReadSource(currentNode); ReadSource(currentNode);
} else if (IsElement("joints")) { } else if (currentName == "joints" ) {
ReadControllerJoints(currentNode, pController); ReadControllerJoints(currentNode, pController);
} else if (IsElement("vertex_weights")) { } else if (currentName == "vertex_weights") {
ReadControllerWeights(currentNode, pController); ReadControllerWeights(currentNode, pController);
} else if (IsElement("targets")) { } else if (currentName == "targets") {
for (XmlNode currendChildNode : currentNode.children()) { for (XmlNode currendChildNode : currentNode.children()) {
const std::string currentChildName = currendChildNode.name(); const std::string currentChildName = currendChildNode.name();
if (currentChildName == "input") { if (currentChildName == "input") {
@ -713,13 +713,8 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
// Reads the joint weights for the given controller // Reads the joint weights for the given controller
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) { void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
// Read vertex count from attributes and resize the array accordingly // Read vertex count from attributes and resize the array accordingly
int vertexCount = node.attribute("count").as_int(); int vertexCount;
pController.mWeightCounts.resize(vertexCount); XmlParser::getIntAttribute(node, "count", vertexCount);
/*// read vertex count from attributes and resize the array accordingly
int indexCount = GetAttribute("count");
size_t vertexCount = (size_t)mReader->getAttributeValueAsInt(indexCount);
pController.mWeightCounts.resize(vertexCount);*/
for (XmlNode currentNode : node.children()) { for (XmlNode currentNode : node.children()) {
std::string currentName = currentNode.name(); std::string currentName = currentNode.name();
@ -810,7 +805,7 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
// FIX: C4D exporter writes empty <init_from/> tags // FIX: C4D exporter writes empty <init_from/> tags
if (!currentNode.empty()) { if (!currentNode.empty()) {
// element content is filename - hopefully // element content is filename - hopefully
const char *sz = TestTextContent(); const char *sz = currentNode.value();
if (sz) { if (sz) {
aiString filepath(sz); aiString filepath(sz);
UriDecodePath(filepath); UriDecodePath(filepath);
@ -981,7 +976,7 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
pLight.mType = aiLightSource_POINT; pLight.mType = aiLightSource_POINT;
} else if (currentName == "color") { } else if (currentName == "color") {
// text content contains 3 floats // text content contains 3 floats
const char *content = GetTextContent(); const char *content = currentNode.value();
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r); content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
SkipSpacesAndLineEnd(&content); SkipSpacesAndLineEnd(&content);
@ -992,35 +987,33 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b); content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
SkipSpacesAndLineEnd(&content); SkipSpacesAndLineEnd(&content);
} else if (currentName == "constant_attenuation") { } else if (currentName == "constant_attenuation") {
pLight.mAttConstant = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "constant_attenuation", pLight.mAttConstant);
} else if (currentName == "linear_attenuation") { } else if (currentName == "linear_attenuation") {
pLight.mAttLinear = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "linear_attenuation", pLight.mAttLinear);
} else if (currentName == "quadratic_attenuation") { } else if (currentName == "quadratic_attenuation") {
pLight.mAttQuadratic = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "quadratic_attenuation", pLight.mAttQuadratic);
} else if (currentName == "falloff_angle") { } else if (currentName == "falloff_angle") {
pLight.mFalloffAngle = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "falloff_angle", pLight.mFalloffAngle);
} else if (currentName == "falloff_exponent") { } else if (currentName == "falloff_exponent") {
pLight.mFalloffExponent = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "falloff_exponent", pLight.mFalloffExponent);
} }
// FCOLLADA extensions // FCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "outer_cone") { else if (currentName == "outer_cone") {
pLight.mOuterAngle = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "outer_cone", pLight.mOuterAngle);
} } else if (currentName == "penumbra_angle") { // ... and this one is even deprecated
// ... and this one is even deprecated XmlParser::getFloatAttribute(currentNode, "penumbra_angle", pLight.mPenumbraAngle);
else if (currentName == "penumbra_angle") {
pLight.mPenumbraAngle = ReadFloatFromTextContent();
} else if (currentName == "intensity") { } else if (currentName == "intensity") {
pLight.mIntensity = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "intensity", pLight.mIntensity);
} else if (currentName == "falloff") { } else if (currentName == "falloff") {
pLight.mOuterAngle = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "falloff", pLight.mOuterAngle);
} else if (currentName == "hotspot_beam") { } else if (currentName == "hotspot_beam") {
pLight.mFalloffAngle = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "hotspot_beam", pLight.mFalloffAngle);
} }
// OpenCOLLADA extensions // OpenCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "decay_falloff") { else if (currentName == "decay_falloff") {
pLight.mOuterAngle = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, "decay_falloff", pLight.mOuterAngle);
} }
} }
} }
@ -1033,15 +1026,15 @@ void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
if (currentName == "orthographic") { if (currentName == "orthographic") {
camera.mOrtho = true; camera.mOrtho = true;
} else if (currentName == "xfov" || currentName == "xmag") { } else if (currentName == "xfov" || currentName == "xmag") {
camera.mHorFov = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), (ai_real &)camera.mHorFov);
} else if (currentName == "yfov" || currentName == "ymag") { } else if (currentName == "yfov" || currentName == "ymag") {
camera.mVerFov = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), (ai_real &)camera.mVerFov);
} else if (currentName == "aspect_ratio") { } else if (currentName == "aspect_ratio") {
camera.mAspect = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), (ai_real &)camera.mAspect);
} else if (currentName == "znear") { } else if (currentName == "znear") {
camera.mZNear = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), (ai_real &)camera.mZNear);
} else if (currentName == "zfar") { } else if (currentName == "zfar") {
camera.mZFar = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), (ai_real &)camera.mZFar);
} }
} }
} }
@ -1158,7 +1151,7 @@ void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEff
// GOOGLEEARTH/OKINO extensions // GOOGLEEARTH/OKINO extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "double_sided") else if (currentName == "double_sided")
pEffect.mDoubleSided = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), pEffect.mDoubleSided);
// FCOLLADA extensions // FCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
@ -1170,9 +1163,9 @@ void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEff
// MAX3D extensions // MAX3D extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "wireframe") { else if (currentName == "wireframe") {
pEffect.mWireframe = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), pEffect.mWireframe);
} else if (currentName == "faceted") { } else if (currentName == "faceted") {
pEffect.mFaceted = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), pEffect.mFaceted);
} }
} }
} }
@ -1188,26 +1181,26 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
// MAYA extensions // MAYA extensions
// ------------------------------------------------------- // -------------------------------------------------------
if (currentName == "wrapU") { if (currentName == "wrapU") {
out.mWrapU = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mWrapU);
} else if (currentName == "wrapV") { } else if (currentName == "wrapV") {
out.mWrapV = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mWrapV);
} else if (currentName == "mirrorU") { } else if (currentName == "mirrorU") {
out.mMirrorU = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mMirrorU);
} else if (currentName == "mirrorV") { } else if (currentName == "mirrorV") {
out.mMirrorV = ReadBoolFromTextContent(); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mMirrorV);
} else if (currentName == "repeatU") { } else if (currentName == "repeatU") {
out.mTransform.mScaling.x = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.x);
} else if (currentName == "repeatV") { } else if (currentName == "repeatV") {
out.mTransform.mScaling.y = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.y);
} else if (currentName == "offsetU") { } else if (currentName == "offsetU") {
out.mTransform.mTranslation.x = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.x);
} else if (currentName == "offsetV") { } else if (currentName == "offsetV") {
out.mTransform.mTranslation.y = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.y);
} else if (currentName == "rotateUV") { } else if (currentName == "rotateUV") {
out.mTransform.mRotation = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mRotation);
} else if (currentName == "blend_mode") { } else if (currentName == "blend_mode") {
const char *sz = GetTextContent(); const char *sz = currentNode.value();
// http://www.feelingsoftware.com/content/view/55/72/lang,en/ // http://www.feelingsoftware.com/content/view/55/72/lang,en/
// NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE // NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE
if (0 == ASSIMP_strincmp(sz, "ADD", 3)) if (0 == ASSIMP_strincmp(sz, "ADD", 3))
@ -1223,14 +1216,14 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
// OKINO extensions // OKINO extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "weighting") { else if (currentName == "weighting") {
out.mWeighting = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mWeighting);
} else if (currentName == "mix_with_previous_layer") { } else if (currentName == "mix_with_previous_layer") {
out.mMixWithPrevious = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mMixWithPrevious);
} }
// MAX3D extensions // MAX3D extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "amount") { else if (currentName == "amount") {
out.mWeighting = ReadFloatFromTextContent(); XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mWeighting);
} }
} }
} }
@ -1289,7 +1282,7 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
// Reads an effect entry containing a float // Reads an effect entry containing a float
void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pFloat) { void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pFloat) {
pFloat = 0.f; pFloat = 0.f;
if (node.name() == "float") { if (node.name() == std::string("float")) {
XmlParser::getFloatAttribute(node, "float", pFloat); XmlParser::getFloatAttribute(node, "float", pFloat);
} }
} }
@ -1415,13 +1408,13 @@ void ColladaParser::ReadSource(XmlNode &node) {
void ColladaParser::ReadDataArray(XmlNode &node) { void ColladaParser::ReadDataArray(XmlNode &node) {
std::string name = node.name(); std::string name = node.name();
bool isStringArray = (name == "IDREF_array" || name == "Name_array"); bool isStringArray = (name == "IDREF_array" || name == "Name_array");
bool isEmptyElement = node.empty(); //bool isEmptyElement = node.empty();
// read attributes // read attributes
std::string id; std::string id;
XmlParser::getStdStrAttribute(node, "id", id); XmlParser::getStdStrAttribute(node, "id", id);
int count; unsigned int count;
XmlParser::getIntAttribute(node, "count", count); XmlParser::getUIntAttribute(node, "count", count);
const char *content = node.value(); const char *content = node.value();
// read values and store inside an array in the data library // read values and store inside an array in the data library
@ -1565,10 +1558,10 @@ void ColladaParser::ReadVertexData(XmlNode &node, Mesh &pMesh) {
XmlParser::getStdStrAttribute(node, "id", pMesh.mVertexID); XmlParser::getStdStrAttribute(node, "id", pMesh.mVertexID);
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "input" ) { if (currentName == "input") {
ReadInputChannel(currentNode, pMesh.mPerVertexData); ReadInputChannel(currentNode, pMesh.mPerVertexData);
} else { } else {
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <vertices>"); ThrowException(format() << "Unexpected sub element <" << currentName << "> in tag <vertices>");
} }
} }
} }
@ -1579,7 +1572,8 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
std::vector<size_t> vcount; std::vector<size_t> vcount;
std::vector<InputChannel> perIndexData; std::vector<InputChannel> perIndexData;
XmlParser::getIntAttribute(node, "count", (int) numPrimitives); unsigned int numPrimitives;
XmlParser::getUIntAttribute(node, "count", (unsigned int)numPrimitives);
// read primitive count from the attribute // read primitive count from the attribute
//int attrCount = GetAttribute("count"); //int attrCount = GetAttribute("count");
//size_t numPrimitives = (size_t)mReader->getAttributeValueAsInt(attrCount); //size_t numPrimitives = (size_t)mReader->getAttributeValueAsInt(attrCount);
@ -1587,11 +1581,11 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
// so we need to sum up the actual number of primitives while we read the <p>-tags // so we need to sum up the actual number of primitives while we read the <p>-tags
size_t actualPrimitives = 0; size_t actualPrimitives = 0;
SubMesh subgroup; SubMesh subgroup;
if (XmlParser::hasAttribute("material")) { if (XmlParser::hasAttribute(node, "material")) {
XmlParser::getStdStrAttribute(node, "material", subgroup.mMaterial); XmlParser::getStdStrAttribute(node, "material", subgroup.mMaterial);
} }
// material subgroup // material subgroup
// int attrMaterial = TestAttribute("material"); // int attrMaterial = TestAttribute("material");
//if (attrMaterial > -1) //if (attrMaterial > -1)
// subgroup.mMaterial = mReader->getAttributeValue(attrMaterial); // subgroup.mMaterial = mReader->getAttributeValue(attrMaterial);
@ -1626,7 +1620,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
if (numPrimitives) // It is possible to define a mesh without any primitives if (numPrimitives) // It is possible to define a mesh without any primitives
{ {
// case <polylist> - specifies the number of indices for each polygon // case <polylist> - specifies the number of indices for each polygon
const char *content = GetTextContent(); const char *content = currentNode.value();
vcount.reserve(numPrimitives); vcount.reserve(numPrimitives);
for (unsigned int a = 0; a < numPrimitives; a++) { for (unsigned int a = 0; a < numPrimitives; a++) {
if (*content == 0) if (*content == 0)
@ -1648,7 +1642,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
} else if (currentName == "ph") { } else if (currentName == "ph") {
// skip // skip
} else { } else {
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">"); ThrowException(format() << "Unexpected sub element <" << currentName << "> in tag <" << elementName << ">");
} }
} }
@ -1686,31 +1680,26 @@ void ColladaParser::ReadInputChannel(XmlNode &node, std::vector<InputChannel> &p
channel.mAccessor = source.c_str() + 1; // skipping the leading #, hopefully the remaining text is the accessor ID only channel.mAccessor = source.c_str() + 1; // skipping the leading #, hopefully the remaining text is the accessor ID only
// read index offset, if per-index <input> // read index offset, if per-index <input>
if (XmlParser::hasAttribute("offset")) { if (XmlParser::hasAttribute(node, "offset")) {
XmlParser::getStdStrAttribute(node, "offset", channel.mOffset); XmlParser::getUIntAttribute(node, "offset", (unsigned int &)channel.mOffset);
} }
//int attrOffset = TestAttribute("offset"); //int attrOffset = TestAttribute("offset");
//if (attrOffset > -1) //if (attrOffset > -1)
// channel.mOffset = mReader->getAttributeValueAsInt(attrOffset); // channel.mOffset = mReader->getAttributeValueAsInt(attrOffset);
// read set if texture coordinates // read set if texture coordinates
if (channel.mType == IT_Texcoord || channel.mType == IT_Color) { if (channel.mType == IT_Texcoord || channel.mType == IT_Color) {
int attrSet = TestAttribute("set"); int attrSet = -1;
if (attrSet > -1) { if (XmlParser::hasAttribute(node, "set")) {
attrSet = mReader->getAttributeValueAsInt(attrSet); XmlParser::getIntAttribute(node, "set", attrSet);
if (attrSet < 0) }
ThrowException(format() << "Invalid index \"" << (attrSet) << "\" in set attribute of <input> element");
channel.mIndex = attrSet; channel.mIndex = attrSet;
} }
}
// store, if valid type // store, if valid type
if (channel.mType != IT_Invalid) if (channel.mType != IT_Invalid)
poChannels.push_back(channel); poChannels.push_back(channel);
// skip remaining stuff of this element, if any
SkipElement();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1753,7 +1742,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
if (pNumPrimitives > 0) // It is possible to not contain any indices if (pNumPrimitives > 0) // It is possible to not contain any indices
{ {
const char *content = GetTextContent(); const char *content = node.value();
while (*content != 0) { while (*content != 0) {
// read a value. // read a value.
// Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways. // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways.
@ -1875,7 +1864,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
} }
// if I ever get my hands on that guy who invented this steaming pile of indirection... // if I ever get my hands on that guy who invented this steaming pile of indirection...
TestClosing("p");
return numPrimitives; return numPrimitives;
} }
@ -2024,36 +2012,32 @@ void ColladaParser::ReadSceneLibrary(XmlNode &node) {
/*if (mReader->isEmptyElement()) /*if (mReader->isEmptyElement())
return;*/ return;*/
while (mReader->read()) { for (XmlNode &currentNode : node.children()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { const std::string &currentName = currentNode.name();
// a visual scene - generate root node under its ID and let ReadNode() do the recursive work if (currentName == "visual_scene") {
if (IsElement("visual_scene")) {
// read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then? // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then?
int indexID = GetAttribute("id"); std::string id;
const char *attrID = mReader->getAttributeValue(indexID); XmlParser::getStdStrAttribute(currentNode, "id", id);
//int indexID = GetAttribute("id");
//const char *attrID = mReader->getAttributeValue(indexID);
std::string attrName = "Scene";
if (XmlParser::hasAttribute(currentNode, "name")) {
XmlParser::getStdStrAttribute(currentNode, "name", attrName);
}
// read name if given. // read name if given.
int indexName = TestAttribute("name"); //int indexName = TestAttribute("name");
const char *attrName = "Scene"; //const char *attrName = "Scene";
if (indexName > -1) //if (indexName > -1)
attrName = mReader->getAttributeValue(indexName); //attrName = mReader->getAttributeValue(indexName);
// create a node and store it in the library under its ID // create a node and store it in the library under its ID
Node *node = new Node; Node *sceneNode = new Node;
node->mID = attrID; sceneNode->mID = id;
node->mName = attrName; sceneNode->mName = attrName;
mNodeLibrary[node->mID] = node; mNodeLibrary[sceneNode->mID] = sceneNode;
ReadSceneNode(node); ReadSceneNode(node, sceneNode);
} else {
// ignore the rest
SkipElement();
}
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (strcmp(mReader->getNodeName(), "library_visual_scenes") == 0)
//ThrowException( "Expected end of \"library_visual_scenes\" element.");
break;
} }
} }
} }
@ -2066,24 +2050,19 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
return; return;
} }
/* if (mReader->isEmptyElement()) for (XmlNode &currentNode : node.children()) {
return;*/ const std::string &currentName = currentNode.name();
if (currentName == "node") {
while (mReader->read()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
if (IsElement("node")) {
Node *child = new Node; Node *child = new Node;
int attrID = TestAttribute("id"); if (XmlParser::hasAttribute(currentNode, "id")) {
if (attrID > -1) XmlParser::getStdStrAttribute(currentNode, "id", child->mID);
child->mID = mReader->getAttributeValue(attrID); }
int attrSID = TestAttribute("sid"); if (XmlParser::hasAttribute(currentNode, "sid")) {
if (attrSID > -1) XmlParser::getStdStrAttribute(currentNode, "id", child->mSID);
child->mSID = mReader->getAttributeValue(attrSID); }
if (XmlParser::hasAttribute(currentNode, "name")) {
int attrName = TestAttribute("name"); XmlParser::getStdStrAttribute(currentNode, "name", child->mName);
if (attrName > -1) }
child->mName = mReader->getAttributeValue(attrName);
if (pNode) { if (pNode) {
pNode->mChildren.push_back(child); pNode->mChildren.push_back(child);
child->mParent = pNode; child->mParent = pNode;
@ -2094,85 +2073,75 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
} }
// read on recursively from there // read on recursively from there
ReadSceneNode(child); ReadSceneNode(currentNode, child);
continue;
} else if (!pNode) {
// For any further stuff we need a valid node to work on
continue; continue;
} }
// For any further stuff we need a valid node to work on if (currentName == "lookat") {
else if (!pNode) ReadNodeTransformation(currentNode, pNode, TF_LOOKAT);
continue; } else if (currentName == "matrix") {
ReadNodeTransformation(currentNode, pNode, TF_MATRIX);
if (IsElement("lookat")) } else if (currentName == "rotate") {
ReadNodeTransformation(pNode, TF_LOOKAT); ReadNodeTransformation(currentNode, pNode, TF_ROTATE);
else if (IsElement("matrix")) } else if (currentName == "scale") {
ReadNodeTransformation(pNode, TF_MATRIX); ReadNodeTransformation(currentNode, pNode, TF_SCALE);
else if (IsElement("rotate")) } else if (currentName == "skew") {
ReadNodeTransformation(pNode, TF_ROTATE); ReadNodeTransformation(currentNode, pNode, TF_SKEW);
else if (IsElement("scale")) } else if (currentName == "translate") {
ReadNodeTransformation(pNode, TF_SCALE); ReadNodeTransformation(currentNode, pNode, TF_TRANSLATE);
else if (IsElement("skew")) } else if (currentName == "render" && pNode->mParent == nullptr && 0 == pNode->mPrimaryCamera.length()) {
ReadNodeTransformation(pNode, TF_SKEW);
else if (IsElement("translate"))
ReadNodeTransformation(pNode, TF_TRANSLATE);
else if (IsElement("render") && pNode->mParent == nullptr && 0 == pNode->mPrimaryCamera.length()) {
// ... scene evaluation or, in other words, postprocessing pipeline, // ... scene evaluation or, in other words, postprocessing pipeline,
// or, again in other words, a turing-complete description how to // or, again in other words, a turing-complete description how to
// render a Collada scene. The only thing that is interesting for // render a Collada scene. The only thing that is interesting for
// us is the primary camera. // us is the primary camera.
int attrId = TestAttribute("camera_node"); if (XmlParser::hasAttribute(currentNode, "camera_node")) {
if (-1 != attrId) { std::string s;
const char *s = mReader->getAttributeValue(attrId); XmlParser::getStdStrAttribute(currentNode, "camera_node", s);
if (s[0] != '#') if (s[0] != '#') {
ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera"); ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera");
else } else {
pNode->mPrimaryCamera = s + 1; pNode->mPrimaryCamera = s.c_str() + 1;
} }
} else if (IsElement("instance_node")) { }
} else if (currentName == "instance_node") {
// find the node in the library // find the node in the library
int attrID = TestAttribute("url"); if (XmlParser::hasAttribute(currentNode, "url")) {
if (attrID != -1) { std::string s;
const char *s = mReader->getAttributeValue(attrID); XmlParser::getStdStrAttribute(currentNode, "url", s);
if (s[0] != '#') if (s[0] != '#') {
ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node"); ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node");
else { } else {
pNode->mNodeInstances.push_back(NodeInstance()); pNode->mNodeInstances.push_back(NodeInstance());
pNode->mNodeInstances.back().mNode = s + 1; pNode->mNodeInstances.back().mNode = s.c_str() + 1;
} }
} }
} else if (IsElement("instance_geometry") || IsElement("instance_controller")) { } else if (currentName == "instance_geometry" || currentName == "instance_controller") {
// Reference to a mesh or controller, with possible material associations // Reference to a mesh or controller, with possible material associations
ReadNodeGeometry(pNode); ReadNodeGeometry(currentNode, pNode);
} else if (IsElement("instance_light")) { } else if (currentName == "instance_light") {
// Reference to a light, name given in 'url' attribute // Reference to a light, name given in 'url' attribute
int attrID = TestAttribute("url"); if (XmlParser::hasAttribute(currentNode, "url")) {
if (-1 == attrID) std::string url;
ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_light> element"); XmlParser::getStdStrAttribute(currentNode, "url", url);
else {
const char *url = mReader->getAttributeValue(attrID);
if (url[0] != '#') if (url[0] != '#')
ThrowException("Unknown reference format in <instance_light> element"); ThrowException("Unknown reference format in <instance_light> element");
pNode->mLights.push_back(LightInstance()); pNode->mLights.push_back(LightInstance());
pNode->mLights.back().mLight = url + 1; pNode->mLights.back().mLight = url.c_str() + 1;
} }
} else if (IsElement("instance_camera")) { } else if (currentName == "instance_camera") {
// Reference to a camera, name given in 'url' attribute // Reference to a camera, name given in 'url' attribute
int attrID = TestAttribute("url"); if (XmlParser::hasAttribute(currentNode, "url")) {
if (-1 == attrID) std::string url;
ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_camera> element"); XmlParser::getStdStrAttribute(currentNode, "url", url);
else { if (url[0] != '#') {
const char *url = mReader->getAttributeValue(attrID);
if (url[0] != '#')
ThrowException("Unknown reference format in <instance_camera> element"); ThrowException("Unknown reference format in <instance_camera> element");
}
pNode->mCameras.push_back(CameraInstance()); pNode->mCameras.push_back(CameraInstance());
pNode->mCameras.back().mCamera = url + 1; pNode->mCameras.back().mCamera = url.c_str() + 1;
} }
} else {
// skip everything else for the moment
SkipElement();
}
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
break;
} }
} }
} }
@ -2183,22 +2152,20 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
if (node.empty()) { if (node.empty()) {
return; return;
} }
/*if (mReader->isEmptyElement())
return;*/
std::string tagName = mReader->getNodeName(); std::string tagName = node.name();
Transform tf; Transform tf;
tf.mType = pType; tf.mType = pType;
// read SID // read SID
int indexSID = TestAttribute("sid"); if (XmlParser::hasAttribute(node, "sid")) {
if (indexSID >= 0) XmlParser::getStdStrAttribute(node, "sid", tf.mID);
tf.mID = mReader->getAttributeValue(indexSID); }
// how many parameters to read per transformation type // how many parameters to read per transformation type
static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 }; static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
const char *content = GetTextContent(); const char *content = node.value();
// read as many parameters and store in the transformation // read as many parameters and store in the transformation
for (unsigned int a = 0; a < sNumParameters[pType]; a++) { for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
@ -2210,40 +2177,37 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
// place the transformation at the queue of the node // place the transformation at the queue of the node
pNode->mTransforms.push_back(tf); pNode->mTransforms.push_back(tf);
// and consume the closing tag
TestClosing(tagName.c_str());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Processes bind_vertex_input and bind elements // Processes bind_vertex_input and bind elements
void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl) { void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl) {
while (mReader->read()) { for (XmlNode &currentNode : node.children()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { const std::string &currentName = currentNode.name();
if (IsElement("bind_vertex_input")) { if (currentName == "bind_vertex_input") {
Collada::InputSemanticMapEntry vn; Collada::InputSemanticMapEntry vn;
// effect semantic // effect semantic
int n = GetAttribute("semantic"); if (XmlParser::hasAttribute(currentNode, "semantic")) {
std::string s = mReader->getAttributeValue(n); std::string s;
XmlParser::getStdStrAttribute(currentNode, "semantic", s);
XmlParser::getUIntAttribute(currentNode, "input_semantic", (unsigned int &)vn.mType);
}
std::string s;
XmlParser::getStdStrAttribute(currentNode, "semantic", s);
// input semantic // input semantic
n = GetAttribute("input_semantic"); XmlParser::getUIntAttribute(currentNode, "input_semantic", (unsigned int &)vn.mType);
vn.mType = GetTypeForSemantic(mReader->getAttributeValue(n));
// index of input set // index of input set
n = TestAttribute("input_set"); if (XmlParser::hasAttribute(currentNode, "input_set")) {
if (-1 != n) XmlParser::getUIntAttribute(currentNode, "input_set", vn.mSet);
vn.mSet = mReader->getAttributeValueAsInt(n); }
tbl.mMap[s] = vn; tbl.mMap[s] = vn;
} else if (IsElement("bind")) { } else if (currentName == "bind") {
ASSIMP_LOG_WARN("Collada: Found unsupported <bind> element"); ASSIMP_LOG_WARN("Collada: Found unsupported <bind> element");
} }
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (strcmp(mReader->getNodeName(), "instance_material") == 0)
break;
}
} }
} }
@ -2270,42 +2234,32 @@ void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) {
// Reads a mesh reference in a node and adds it to the node's mesh list // Reads a mesh reference in a node and adds it to the node's mesh list
void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) { void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
// referred mesh is given as an attribute of the <instance_geometry> element // referred mesh is given as an attribute of the <instance_geometry> element
int attrUrl = GetAttribute("url"); std::string url;
const char *url = mReader->getAttributeValue(attrUrl); XmlParser::getStdStrAttribute(node, "url", url);
if (url[0] != '#') if (url[0] != '#')
ThrowException("Unknown reference format"); ThrowException("Unknown reference format");
Collada::MeshInstance instance; Collada::MeshInstance instance;
instance.mMeshOrController = url + 1; // skipping the leading # instance.mMeshOrController = url.c_str() + 1; // skipping the leading #
if (!mReader->isEmptyElement()) { for (XmlNode &currentNode : node.children()) {
// read material associations. Ignore additional elements in between const std::string &currentName = currentNode.name();
while (mReader->read()) { if (currentName=="instance_material") {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
if (IsElement("instance_material")) {
// read ID of the geometry subgroup and the target material // read ID of the geometry subgroup and the target material
int attrGroup = GetAttribute("symbol"); std::string group;
std::string group = mReader->getAttributeValue(attrGroup); XmlParser::getStdStrAttribute(currentNode, "symbol", group);
int attrMaterial = GetAttribute("target"); XmlParser::getStdStrAttribute(currentNode, "symbol", url);
const char *urlMat = mReader->getAttributeValue(attrMaterial); const char *urlMat = url.c_str();
Collada::SemanticMappingTable s; Collada::SemanticMappingTable s;
if (urlMat[0] == '#') if (urlMat[0] == '#')
urlMat++; urlMat++;
s.mMatName = urlMat; s.mMatName = urlMat;
// resolve further material details + THIS UGLY AND NASTY semantic mapping stuff
if (!mReader->isEmptyElement())
ReadMaterialVertexInputBinding(s);
// store the association // store the association
instance.mMaterials[group] = s; instance.mMaterials[group] = s;
} }
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (strcmp(mReader->getNodeName(), "instance_geometry") == 0 || strcmp(mReader->getNodeName(), "instance_controller") == 0)
break;
}
}
} }
// store it // store it
@ -2318,8 +2272,6 @@ void ColladaParser::ReadScene(XmlNode &node) {
if (node.empty()) { if (node.empty()) {
return; return;
} }
/*if (mReader->isEmptyElement())
return;*/
for (XmlNode currentNode : node.children()) { for (XmlNode currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
@ -2329,46 +2281,20 @@ void ColladaParser::ReadScene(XmlNode &node) {
ThrowException("Invalid scene containing multiple root nodes in <instance_visual_scene> element"); ThrowException("Invalid scene containing multiple root nodes in <instance_visual_scene> element");
// read the url of the scene to instance. Should be of format "#some_name" // read the url of the scene to instance. Should be of format "#some_name"
int urlIndex = currentNode.attribute("url").as_int(); std::string url;
const char *url = currentNode.attributes.begin() + urlIndex; XmlParser::getStdStrAttribute(currentNode, "url", url);
if (url[0] != '#') { if (url[0] != '#') {
ThrowException("Unknown reference format in <instance_visual_scene> element"); ThrowException("Unknown reference format in <instance_visual_scene> element");
} }
// find the referred scene, skip the leading # // find the referred scene, skip the leading #
NodeLibrary::const_iterator sit = mNodeLibrary.find(url + 1); NodeLibrary::const_iterator sit = mNodeLibrary.find(url.c_str() + 1);
if (sit == mNodeLibrary.end()) { if (sit == mNodeLibrary.end()) {
ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element."); ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
} }
mRootNode = sit->second; mRootNode = sit->second;
} }
} }
/*while (mReader->read()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
if (IsElement("instance_visual_scene")) {
// should be the first and only occurrence
if (mRootNode)
ThrowException("Invalid scene containing multiple root nodes in <instance_visual_scene> element");
// read the url of the scene to instance. Should be of format "#some_name"
int urlIndex = GetAttribute("url");
const char *url = mReader->getAttributeValue(urlIndex);
if (url[0] != '#')
ThrowException("Unknown reference format in <instance_visual_scene> element");
// find the referred scene, skip the leading #
NodeLibrary::const_iterator sit = mNodeLibrary.find(url + 1);
if (sit == mNodeLibrary.end())
ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
mRootNode = sit->second;
} else {
SkipElement();
}
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
break;
}
}*/
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -2391,136 +2317,6 @@ void ColladaParser::ReportWarning(const char *msg, ...) {
ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen)); ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen));
} }
// ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the current element
/*void ColladaParser::SkipElement() {
// nothing to skip if it's an <element />
if (mReader->isEmptyElement()) {
return;
}
// reroute
SkipElement(mReader->getNodeName());
}*/
// ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the given element
/*void ColladaParser::SkipElement(const char *pElement) {
// copy the current node's name because it'a pointer to the reader's internal buffer,
// which is going to change with the upcoming parsing
std::string element = pElement;
while (mReader->read()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (mReader->getNodeName() == element) {
break;
}
}
}
}*/
// ------------------------------------------------------------------------------------------------
// Tests for an opening element of the given name, throws an exception if not found
/*void ColladaParser::TestOpening(const char *pName) {
// read element start
if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element.");
}
// whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading beginning of <" << pName << "> element.");
}
}
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected start of <" << pName << "> element.");
}
}*/
// ------------------------------------------------------------------------------------------------
// Tests for the closing tag of the given element, throws an exception if not found
/*void ColladaParser::TestClosing(const char *pName) {
// check if we have an empty (self-closing) element
if (mReader->isEmptyElement()) {
return;
}
// check if we're already on the closing tag and return right away
if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0) {
return;
}
// if not, read some more
if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element.");
}
// whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element.");
}
}
// but this has the be the closing tag, or we're lost
if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected end of <" << pName << "> element.");
}
}*/
// ------------------------------------------------------------------------------------------------
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
/*int ColladaParser::GetAttribute(const char *pAttr) const {
int index = TestAttribute(pAttr);
if (index == -1) {
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
}
// attribute not found -> throw an exception
return index;
}*/
// ------------------------------------------------------------------------------------------------
// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
/*int ColladaParser::TestAttribute(const char *pAttr) const {
for (int a = 0; a < mReader->getAttributeCount(); a++)
if (strcmp(mReader->getAttributeName(a), pAttr) == 0)
return a;
return -1;
}*/
// ------------------------------------------------------------------------------------------------
// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
/*const char *ColladaParser::GetTextContent() {
const char *sz = TestTextContent();
if (!sz) {
ThrowException("Invalid contents in element \"n\".");
}
return sz;
}*/
// ------------------------------------------------------------------------------------------------
// Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace.
/*const char *ColladaParser::TestTextContent() {
// present node should be the beginning of an element
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
return nullptr;
// read contents of the element
if (!mReader->read()) {
return nullptr;
}
if (mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) {
return nullptr;
}
// skip leading whitespace
const char *text = mReader->getNodeData();
SkipSpacesAndLineEnd(&text);
return text;
}*/
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Calculates the resulting transformation from all the given transform steps // Calculates the resulting transformation from all the given transform steps
aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector<Transform> &pTransforms) const { aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector<Transform> &pTransforms) const {

View File

@ -247,43 +247,6 @@ protected:
AI_WONT_RETURN void ThrowException(const std::string &pError) const AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowException(const std::string &pError) const AI_WONT_RETURN_SUFFIX;
void ReportWarning(const char *msg, ...); void ReportWarning(const char *msg, ...);
/** Skips all data until the end node of the current element */
//void SkipElement();
/** Skips all data until the end node of the given element */
//void SkipElement(const char *pElement);
/** Compares the current xml element name to the given string and returns true if equal */
bool IsElement(const char *pName) const;
/** Tests for the opening tag of the given element, throws an exception if not found */
//void TestOpening(const char *pName);
/** Tests for the closing tag of the given element, throws an exception if not found */
//void TestClosing(const char *pName);
/** Checks the present element for the presence of the attribute, returns its index
or throws an exception if not found */
int GetAttribute(const char *pAttr) const;
/** Returns the index of the named attribute or -1 if not found. Does not throw,
therefore useful for optional attributes */
int TestAttribute(const char *pAttr) const;
/** Reads the text contents of an element, throws an exception if not given.
Skips leading whitespace. */
const char *GetTextContent();
/** Reads the text contents of an element, returns nullptr if not given.
Skips leading whitespace. */
const char *TestTextContent();
/** Reads a single bool from current text content */
bool ReadBoolFromTextContent();
/** Reads a single float from current text content */
ai_real ReadFloatFromTextContent();
/** Calculates the resulting transformation from all the given transform steps */ /** Calculates the resulting transformation from all the given transform steps */
aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const; aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;

View File

@ -1146,9 +1146,10 @@ IF(ASSIMP_HUNTER_ENABLED)
RapidJSON::rapidjson RapidJSON::rapidjson
utf8::utf8 utf8::utf8
zip::zip zip::zip
pugixml::pugixml
) )
ELSE() ELSE()
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} ) TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} pugixml )
ENDIF() ENDIF()
if(ASSIMP_ANDROID_JNIIOSYSTEM) if(ASSIMP_ANDROID_JNIIOSYSTEM)

View File

@ -199,6 +199,17 @@ public:
return true; return true;
} }
static inline bool getBoolAttribute( XmlNode &xmlNode, const char *name, bool &val ) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_bool();
return true;
}
private: private:
pugi::xml_document *mDoc; pugi::xml_document *mDoc;
TNodeType *mRoot; TNodeType *mRoot;