move hasAttribute to XmlParser scope.
commit
56381241c5
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -46,12 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <assimp/StringComparison.h>
|
#include <assimp/StringComparison.h>
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
|
#include <assimp/XmlParser.h>
|
||||||
#include <assimp/ZipArchiveIOSystem.h>
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
#include <assimp/importerdesc.h>
|
#include <assimp/importerdesc.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -61,7 +60,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "3MFXmlTags.h"
|
#include "3MFXmlTags.h"
|
||||||
#include "D3MFOpcPackage.h"
|
#include "D3MFOpcPackage.h"
|
||||||
#include <assimp/fast_atof.h>
|
#include <assimp/fast_atof.h>
|
||||||
#include <assimp/irrXMLWrapper.h>
|
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
@ -73,12 +71,12 @@ public:
|
||||||
using MatArray = std::vector<aiMaterial *>;
|
using MatArray = std::vector<aiMaterial *>;
|
||||||
using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
|
using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
|
||||||
|
|
||||||
XmlSerializer(XmlReader *xmlReader) :
|
XmlSerializer(XmlParser *xmlParser) :
|
||||||
mMeshes(),
|
mMeshes(),
|
||||||
mMatArray(),
|
mMatArray(),
|
||||||
mActiveMatGroup(99999999),
|
mActiveMatGroup(99999999),
|
||||||
mMatId2MatArray(),
|
mMatId2MatArray(),
|
||||||
xmlReader(xmlReader) {
|
mXmlParser(xmlParser) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,16 +93,17 @@ public:
|
||||||
std::vector<aiNode *> children;
|
std::vector<aiNode *> children;
|
||||||
|
|
||||||
std::string nodeName;
|
std::string nodeName;
|
||||||
while (ReadToEndElement(D3MF::XmlTag::model)) {
|
XmlNode *root = mXmlParser->getRootNode();
|
||||||
nodeName = xmlReader->getNodeName();
|
for (XmlNode ¤tNode : root->children()) {
|
||||||
if (nodeName == D3MF::XmlTag::object) {
|
const std::string ¤tNodeName = currentNode.name();
|
||||||
children.push_back(ReadObject(scene));
|
if (currentNodeName == D3MF::XmlTag::object) {
|
||||||
} else if (nodeName == D3MF::XmlTag::build) {
|
children.push_back(ReadObject(currentNode, scene));
|
||||||
|
} else if (currentNodeName == D3MF::XmlTag::build) {
|
||||||
//
|
//
|
||||||
} else if (nodeName == D3MF::XmlTag::basematerials) {
|
} else if (currentNodeName == D3MF::XmlTag::basematerials) {
|
||||||
ReadBaseMaterials();
|
ReadBaseMaterials(currentNode);
|
||||||
} else if (nodeName == D3MF::XmlTag::meta) {
|
} else if (currentNodeName == D3MF::XmlTag::meta) {
|
||||||
ReadMetadata();
|
ReadMetadata(currentNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,31 +140,30 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
aiNode *ReadObject(aiScene *scene) {
|
aiNode *ReadObject(XmlNode &node, aiScene *scene) {
|
||||||
std::unique_ptr<aiNode> node(new aiNode());
|
std::unique_ptr<aiNode> nodePtr(new aiNode());
|
||||||
|
|
||||||
std::vector<unsigned long> meshIds;
|
std::vector<unsigned long> meshIds;
|
||||||
|
|
||||||
const char *attrib(nullptr);
|
|
||||||
std::string name, type;
|
std::string name, type;
|
||||||
attrib = xmlReader->getAttributeValue(D3MF::XmlTag::id.c_str());
|
pugi::xml_attribute attr = node.attribute(D3MF::XmlTag::id.c_str());
|
||||||
if (nullptr != attrib) {
|
if (!attr.empty()) {
|
||||||
name = attrib;
|
name = attr.as_string();
|
||||||
}
|
}
|
||||||
attrib = xmlReader->getAttributeValue(D3MF::XmlTag::type.c_str());
|
attr = node.attribute(D3MF::XmlTag::id.c_str());
|
||||||
if (nullptr != attrib) {
|
if (!attr.empty()) {
|
||||||
type = attrib;
|
type = attr.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
node->mParent = scene->mRootNode;
|
nodePtr->mParent = scene->mRootNode;
|
||||||
node->mName.Set(name);
|
nodePtr->mName.Set(name);
|
||||||
|
|
||||||
size_t meshIdx = mMeshes.size();
|
size_t meshIdx = mMeshes.size();
|
||||||
|
|
||||||
while (ReadToEndElement(D3MF::XmlTag::object)) {
|
for (pugi::xml_node ¤tNode : node.children()) {
|
||||||
if (xmlReader->getNodeName() == D3MF::XmlTag::mesh) {
|
const std::string ¤tName = currentNode.name();
|
||||||
auto mesh = ReadMesh();
|
if (currentName == D3MF::XmlTag::mesh) {
|
||||||
|
auto mesh = ReadMesh(currentNode);
|
||||||
mesh->mName.Set(name);
|
mesh->mName.Set(name);
|
||||||
mMeshes.push_back(mesh);
|
mMeshes.push_back(mesh);
|
||||||
meshIds.push_back(static_cast<unsigned long>(meshIdx));
|
meshIds.push_back(static_cast<unsigned long>(meshIdx));
|
||||||
|
@ -173,33 +171,34 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node->mNumMeshes = static_cast<unsigned int>(meshIds.size());
|
nodePtr->mNumMeshes = static_cast<unsigned int>(meshIds.size());
|
||||||
|
|
||||||
node->mMeshes = new unsigned int[node->mNumMeshes];
|
nodePtr->mMeshes = new unsigned int[nodePtr->mNumMeshes];
|
||||||
|
|
||||||
std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
|
std::copy(meshIds.begin(), meshIds.end(), nodePtr->mMeshes);
|
||||||
|
|
||||||
return node.release();
|
return nodePtr.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh *ReadMesh() {
|
aiMesh *ReadMesh(XmlNode &node) {
|
||||||
aiMesh *mesh = new aiMesh();
|
aiMesh *mesh = new aiMesh();
|
||||||
while (ReadToEndElement(D3MF::XmlTag::mesh)) {
|
for (pugi::xml_node ¤tNode : node.children()) {
|
||||||
if (xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
|
const std::string ¤tName = currentNode.name();
|
||||||
ImportVertices(mesh);
|
if (currentName == D3MF::XmlTag::vertices) {
|
||||||
} else if (xmlReader->getNodeName() == D3MF::XmlTag::triangles) {
|
ImportVertices(currentNode, mesh);
|
||||||
ImportTriangles(mesh);
|
} else if (currentName == D3MF::XmlTag::triangles) {
|
||||||
|
ImportTriangles(currentNode, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadMetadata() {
|
void ReadMetadata(XmlNode &node) {
|
||||||
const std::string name = xmlReader->getAttributeValue(D3MF::XmlTag::meta_name.c_str());
|
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str());
|
||||||
xmlReader->read();
|
const std::string name = attribute.as_string();
|
||||||
const std::string value = xmlReader->getNodeData();
|
const std::string value = node.value();
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -210,37 +209,36 @@ private:
|
||||||
mMetaData.push_back(entry);
|
mMetaData.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportVertices(aiMesh *mesh) {
|
void ImportVertices(XmlNode &node, aiMesh *mesh) {
|
||||||
std::vector<aiVector3D> vertices;
|
std::vector<aiVector3D> vertices;
|
||||||
while (ReadToEndElement(D3MF::XmlTag::vertices)) {
|
for (pugi::xml_node ¤tNode : node.children()) {
|
||||||
if (xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
|
const std::string ¤tName = currentNode.name();
|
||||||
vertices.push_back(ReadVertex());
|
if (currentName == D3MF::XmlTag::vertex) {
|
||||||
|
vertices.push_back(ReadVertex(currentNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
|
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
|
||||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||||
|
|
||||||
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
|
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
aiVector3D ReadVertex() {
|
aiVector3D ReadVertex(XmlNode &node) {
|
||||||
aiVector3D vertex;
|
aiVector3D vertex;
|
||||||
|
vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr);
|
||||||
vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
|
vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr);
|
||||||
vertex.y = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::y.c_str()), nullptr);
|
vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr);
|
||||||
vertex.z = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
|
|
||||||
|
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportTriangles(aiMesh *mesh) {
|
void ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||||
std::vector<aiFace> faces;
|
std::vector<aiFace> faces;
|
||||||
|
for (pugi::xml_node ¤tNode : node.children()) {
|
||||||
while (ReadToEndElement(D3MF::XmlTag::triangles)) {
|
const std::string ¤tName = currentNode.name();
|
||||||
const std::string nodeName(xmlReader->getNodeName());
|
if (currentName == D3MF::XmlTag::triangle) {
|
||||||
if (xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
|
faces.push_back(ReadTriangle(currentNode));
|
||||||
faces.push_back(ReadTriangle());
|
const char *pidToken = currentNode.attribute(D3MF::XmlTag::p1.c_str()).as_string();
|
||||||
const char *pidToken(xmlReader->getAttributeValue(D3MF::XmlTag::p1.c_str()));
|
|
||||||
if (nullptr != pidToken) {
|
if (nullptr != pidToken) {
|
||||||
int matIdx(std::atoi(pidToken));
|
int matIdx(std::atoi(pidToken));
|
||||||
mesh->mMaterialIndex = matIdx;
|
mesh->mMaterialIndex = matIdx;
|
||||||
|
@ -255,21 +253,21 @@ private:
|
||||||
std::copy(faces.begin(), faces.end(), mesh->mFaces);
|
std::copy(faces.begin(), faces.end(), mesh->mFaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
aiFace ReadTriangle() {
|
aiFace ReadTriangle(XmlNode &node) {
|
||||||
aiFace face;
|
aiFace face;
|
||||||
|
|
||||||
face.mNumIndices = 3;
|
face.mNumIndices = 3;
|
||||||
face.mIndices = new unsigned int[face.mNumIndices];
|
face.mIndices = new unsigned int[face.mNumIndices];
|
||||||
face.mIndices[0] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v1.c_str())));
|
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string()));
|
||||||
face.mIndices[1] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v2.c_str())));
|
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string()));
|
||||||
face.mIndices[2] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v3.c_str())));
|
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string()));
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBaseMaterials() {
|
void ReadBaseMaterials(XmlNode &node) {
|
||||||
std::vector<unsigned int> MatIdArray;
|
std::vector<unsigned int> MatIdArray;
|
||||||
const char *baseMaterialId(xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_id.c_str()));
|
const char *baseMaterialId = node.attribute(D3MF::XmlTag::basematerials_id.c_str()).as_string();
|
||||||
if (nullptr != baseMaterialId) {
|
if (nullptr != baseMaterialId) {
|
||||||
unsigned int id = std::atoi(baseMaterialId);
|
unsigned int id = std::atoi(baseMaterialId);
|
||||||
const size_t newMatIdx(mMatArray.size());
|
const size_t newMatIdx(mMatArray.size());
|
||||||
|
@ -287,9 +285,7 @@ private:
|
||||||
mMatId2MatArray[mActiveMatGroup] = MatIdArray;
|
mMatId2MatArray[mActiveMatGroup] = MatIdArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ReadToEndElement(D3MF::XmlTag::basematerials)) {
|
mMatArray.push_back(readMaterialDef(node));
|
||||||
mMatArray.push_back(readMaterialDef());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseColor(const char *color, aiColor4D &diffuse) {
|
bool parseColor(const char *color, aiColor4D &diffuse) {
|
||||||
|
@ -339,19 +335,23 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assignDiffuseColor(aiMaterial *mat) {
|
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
|
||||||
const char *color = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_displaycolor.c_str());
|
const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string();
|
||||||
|
//const char *color = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_displaycolor.c_str());
|
||||||
aiColor4D diffuse;
|
aiColor4D diffuse;
|
||||||
if (parseColor(color, diffuse)) {
|
if (parseColor(color, diffuse)) {
|
||||||
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aiMaterial *readMaterialDef() {
|
|
||||||
|
aiMaterial *readMaterialDef(XmlNode &node) {
|
||||||
aiMaterial *mat(nullptr);
|
aiMaterial *mat(nullptr);
|
||||||
const char *name(nullptr);
|
const char *name(nullptr);
|
||||||
const std::string nodeName(xmlReader->getNodeName());
|
const std::string nodeName = node.name();
|
||||||
|
//const std::string nodeName(xmlReader->getNodeName());
|
||||||
if (nodeName == D3MF::XmlTag::basematerials_base) {
|
if (nodeName == D3MF::XmlTag::basematerials_base) {
|
||||||
name = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_name.c_str());
|
name = node.attribute(D3MF::XmlTag::basematerials_name.c_str()).as_string();
|
||||||
|
//name = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_name.c_str());
|
||||||
std::string stdMatName;
|
std::string stdMatName;
|
||||||
aiString matName;
|
aiString matName;
|
||||||
std::string strId(to_string(mActiveMatGroup));
|
std::string strId(to_string(mActiveMatGroup));
|
||||||
|
@ -368,40 +368,12 @@ private:
|
||||||
mat = new aiMaterial;
|
mat = new aiMaterial;
|
||||||
mat->AddProperty(&matName, AI_MATKEY_NAME);
|
mat->AddProperty(&matName, AI_MATKEY_NAME);
|
||||||
|
|
||||||
assignDiffuseColor(mat);
|
assignDiffuseColor(node, mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool ReadToStartElement(const std::string &startTag) {
|
|
||||||
while (xmlReader->read()) {
|
|
||||||
const std::string &nodeName(xmlReader->getNodeName());
|
|
||||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
|
|
||||||
return true;
|
|
||||||
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReadToEndElement(const std::string &closeTag) {
|
|
||||||
while (xmlReader->read()) {
|
|
||||||
const std::string &nodeName(xmlReader->getNodeName());
|
|
||||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
|
||||||
return true;
|
|
||||||
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MetaEntry {
|
struct MetaEntry {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -412,7 +384,7 @@ private:
|
||||||
MatArray mMatArray;
|
MatArray mMatArray;
|
||||||
unsigned int mActiveMatGroup;
|
unsigned int mActiveMatGroup;
|
||||||
MatId2MatArray mMatId2MatArray;
|
MatId2MatArray mMatId2MatArray;
|
||||||
XmlReader *xmlReader;
|
XmlParser *mXmlParser;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace D3MF
|
} //namespace D3MF
|
||||||
|
@ -468,12 +440,14 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
|
||||||
void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
|
void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
|
||||||
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
|
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
|
||||||
|
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
|
//std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
|
||||||
std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
|
//std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||||
|
|
||||||
D3MF::XmlSerializer xmlSerializer(xmlReader.get());
|
|
||||||
|
|
||||||
|
XmlParser xmlParser;
|
||||||
|
if (xmlParser.parse(opcPackage.RootStream())) {
|
||||||
|
D3MF::XmlSerializer xmlSerializer(&xmlParser);
|
||||||
xmlSerializer.ImportXml(pScene);
|
xmlSerializer.ImportXml(pScene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -45,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "D3MFOpcPackage.h"
|
#include "D3MFOpcPackage.h"
|
||||||
#include <assimp/Exceptional.h>
|
#include <assimp/Exceptional.h>
|
||||||
|
|
||||||
|
#include <assimp/XmlParser.h>
|
||||||
#include <assimp/ZipArchiveIOSystem.h>
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
@ -68,27 +68,23 @@ typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
|
||||||
|
|
||||||
class OpcPackageRelationshipReader {
|
class OpcPackageRelationshipReader {
|
||||||
public:
|
public:
|
||||||
OpcPackageRelationshipReader(XmlReader *xmlReader) {
|
OpcPackageRelationshipReader(XmlParser &parser) {
|
||||||
while (xmlReader->read()) {
|
XmlNode *root = parser.getRootNode();
|
||||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
|
if (nullptr != root) {
|
||||||
xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) {
|
ParseRootNode(*root);
|
||||||
ParseRootNode(xmlReader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseRootNode(XmlReader *xmlReader) {
|
void ParseRootNode(XmlNode &node) {
|
||||||
ParseAttributes(xmlReader);
|
ParseAttributes(node);
|
||||||
|
|
||||||
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
ParseChildNode(currentNode);
|
||||||
|
|
||||||
while (xmlReader->read()) {
|
|
||||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
|
|
||||||
xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) {
|
|
||||||
ParseChildNode(xmlReader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseAttributes(XmlReader *) {
|
void ParseAttributes(XmlNode &/*node*/) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,12 +95,12 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseChildNode(XmlReader *xmlReader) {
|
void ParseChildNode(XmlNode &node) {
|
||||||
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
|
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
|
||||||
|
|
||||||
relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
|
relPtr->id = node.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string();
|
||||||
relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
|
relPtr->type = node.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string();
|
||||||
relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
|
relPtr->target = node.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string();
|
||||||
if (validateRels(relPtr)) {
|
if (validateRels(relPtr)) {
|
||||||
m_relationShips.push_back(relPtr);
|
m_relationShips.push_back(relPtr);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +111,8 @@ public:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||||
mRootStream(nullptr), mZipArchive() {
|
mRootStream(nullptr),
|
||||||
|
mZipArchive() {
|
||||||
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
|
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
|
||||||
if (!mZipArchive->isOpen()) {
|
if (!mZipArchive->isOpen()) {
|
||||||
throw DeadlyImportError("Failed to open file " + rFile + ".");
|
throw DeadlyImportError("Failed to open file " + rFile + ".");
|
||||||
|
@ -182,10 +179,12 @@ bool D3MFOpcPackage::validate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
|
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
|
XmlParser xmlParser;
|
||||||
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
|
if (!xmlParser.parse(stream)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
OpcPackageRelationshipReader reader(xml.get());
|
OpcPackageRelationshipReader reader(xmlParser);
|
||||||
|
|
||||||
auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
|
auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
|
||||||
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
|
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -44,18 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define D3MFOPCPACKAGE_H
|
#define D3MFOPCPACKAGE_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
#include <assimp/irrXMLWrapper.h>
|
//#include <assimp/irrXMLWrapper.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
class ZipArchiveIOSystem;
|
class ZipArchiveIOSystem;
|
||||||
|
|
||||||
namespace D3MF {
|
namespace D3MF {
|
||||||
|
|
||||||
using XmlReader = irr::io::IrrXMLReader ;
|
|
||||||
using XmlReaderPtr = std::shared_ptr<XmlReader> ;
|
|
||||||
|
|
||||||
struct OpcPackageRelationship {
|
struct OpcPackageRelationship {
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string type;
|
std::string type;
|
||||||
|
@ -64,7 +60,7 @@ struct OpcPackageRelationship {
|
||||||
|
|
||||||
class D3MFOpcPackage {
|
class D3MFOpcPackage {
|
||||||
public:
|
public:
|
||||||
D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
|
D3MFOpcPackage( IOSystem* pIOHandler, const std::string& file );
|
||||||
~D3MFOpcPackage();
|
~D3MFOpcPackage();
|
||||||
IOStream* RootStream() const;
|
IOStream* RootStream() const;
|
||||||
bool validate();
|
bool validate();
|
||||||
|
|
|
@ -68,7 +68,7 @@ AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::s
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(XmlNode &xmlNode, const char *name) const {
|
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!hasAttribute(xmlNode, name )) {
|
if (!XmlParser::hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(mParser, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
@ -77,7 +77,7 @@ int32_t OgreXmlSerializer::ReadAttribute<int32_t>(XmlNode &xmlNode, const char *
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(XmlNode &xmlNode, const char *name) const {
|
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!hasAttribute(xmlNode, name)) {
|
if (!XmlParser::hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(mParser, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(XmlNode &xmlNode, const char
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(XmlNode &xmlNode, const char *name) const {
|
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!hasAttribute(xmlNode, name)) {
|
if (!XmlParser::hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(mParser, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(XmlNode &xmlNode, const char
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float OgreXmlSerializer::ReadAttribute<float>(XmlNode &xmlNode, const char *name) const {
|
float OgreXmlSerializer::ReadAttribute<float>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!hasAttribute(xmlNode, name)) {
|
if (!XmlParser::hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(mParser, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ float OgreXmlSerializer::ReadAttribute<float>(XmlNode &xmlNode, const char *name
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, const char *name) const {
|
std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!hasAttribute(xmlNode, name)) {
|
if (!XmlParser::hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(mParser, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,10 +298,10 @@ void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest) {
|
void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest) {
|
||||||
bool positions = (hasAttribute(node, "positions") && ReadAttribute<bool>(node, "positions"));
|
bool positions = (XmlParser::hasAttribute(node, "positions") && ReadAttribute<bool>(node, "positions"));
|
||||||
bool normals = (hasAttribute(node, "normals") && ReadAttribute<bool>(node, "normals"));
|
bool normals = (XmlParser::hasAttribute(node, "normals") && ReadAttribute<bool>(node, "normals"));
|
||||||
bool tangents = (hasAttribute(node, "tangents") && ReadAttribute<bool>(node, "tangents"));
|
bool tangents = (XmlParser::hasAttribute(node, "tangents") && ReadAttribute<bool>(node, "tangents"));
|
||||||
uint32_t uvs = (hasAttribute(node, "texture_coords") ? ReadAttribute<uint32_t>(node, "texture_coords") : 0);
|
uint32_t uvs = (XmlParser::hasAttribute(node, "texture_coords") ? ReadAttribute<uint32_t>(node, "texture_coords") : 0);
|
||||||
|
|
||||||
// Not having positions is a error only if a previous vertex buffer did not have them.
|
// Not having positions is a error only if a previous vertex buffer did not have them.
|
||||||
if (!positions && !dest->HasPositions()) {
|
if (!positions && !dest->HasPositions()) {
|
||||||
|
@ -470,10 +470,10 @@ void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) {
|
||||||
|
|
||||||
SubMeshXml *submesh = new SubMeshXml();
|
SubMeshXml *submesh = new SubMeshXml();
|
||||||
|
|
||||||
if (hasAttribute(node, anMaterial)) {
|
if (XmlParser::hasAttribute(node, anMaterial)) {
|
||||||
submesh->materialRef = ReadAttribute<std::string>(node, anMaterial);
|
submesh->materialRef = ReadAttribute<std::string>(node, anMaterial);
|
||||||
}
|
}
|
||||||
if (hasAttribute(node, anUseSharedVertices)) {
|
if (XmlParser::hasAttribute(node, anUseSharedVertices)) {
|
||||||
submesh->usesSharedVertexData = ReadAttribute<bool>(node, anUseSharedVertices);
|
submesh->usesSharedVertexData = ReadAttribute<bool>(node, anUseSharedVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) {
|
||||||
face.mIndices[1] = ReadAttribute<uint32_t>(currentChildNode, anV2);
|
face.mIndices[1] = ReadAttribute<uint32_t>(currentChildNode, anV2);
|
||||||
face.mIndices[2] = ReadAttribute<uint32_t>(currentChildNode, anV3);
|
face.mIndices[2] = ReadAttribute<uint32_t>(currentChildNode, anV3);
|
||||||
/// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
|
/// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
|
||||||
if (!quadWarned && hasAttribute(currentChildNode, anV4)) {
|
if (!quadWarned && XmlParser::hasAttribute(currentChildNode, anV4)) {
|
||||||
ASSIMP_LOG_WARN("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
|
ASSIMP_LOG_WARN("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
|
||||||
quadWarned = true;
|
quadWarned = true;
|
||||||
}
|
}
|
||||||
|
@ -722,7 +722,7 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
|
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
|
||||||
|
|
||||||
// Optional blend mode from root node
|
// Optional blend mode from root node
|
||||||
if (hasAttribute(node, "blendmode")) {
|
if (XmlParser::hasAttribute(node, "blendmode")) {
|
||||||
skeleton->blendMode = (ToLower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
skeleton->blendMode = (ToLower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,15 +997,15 @@ void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (currentChildName == nnScale) {
|
} else if (currentChildName == nnScale) {
|
||||||
if (hasAttribute(currentChildNode, "factor")) {
|
if (XmlParser::hasAttribute(currentChildNode, "factor")) {
|
||||||
float factor = ReadAttribute<float>(currentChildNode, "factor");
|
float factor = ReadAttribute<float>(currentChildNode, "factor");
|
||||||
bone->scale.Set(factor, factor, factor);
|
bone->scale.Set(factor, factor, factor);
|
||||||
} else {
|
} else {
|
||||||
if (hasAttribute(currentChildNode, anX))
|
if (XmlParser::hasAttribute(currentChildNode, anX))
|
||||||
bone->scale.x = ReadAttribute<float>(currentChildNode, anX);
|
bone->scale.x = ReadAttribute<float>(currentChildNode, anX);
|
||||||
if (hasAttribute(currentChildNode, anY))
|
if (XmlParser::hasAttribute(currentChildNode, anY))
|
||||||
bone->scale.y = ReadAttribute<float>(currentChildNode, anY);
|
bone->scale.y = ReadAttribute<float>(currentChildNode, anY);
|
||||||
if (hasAttribute(currentChildNode, anZ))
|
if (XmlParser::hasAttribute(currentChildNode, anZ))
|
||||||
bone->scale.z = ReadAttribute<float>(currentChildNode, anZ);
|
bone->scale.z = ReadAttribute<float>(currentChildNode, anZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,186 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file FIReader.hpp
|
|
||||||
/// \brief Reader for Fast Infoset encoded binary XML files.
|
|
||||||
/// \date 2017
|
|
||||||
/// \author Patrick Daehne
|
|
||||||
|
|
||||||
#ifndef INCLUDED_AI_FI_READER_H
|
|
||||||
#define INCLUDED_AI_FI_READER_H
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cwchar>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <assimp/XmlParser.h>
|
|
||||||
|
|
||||||
namespace Assimp {
|
|
||||||
|
|
||||||
struct FIValue {
|
|
||||||
virtual const std::string &toString() const = 0;
|
|
||||||
virtual ~FIValue() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIStringValue : public FIValue {
|
|
||||||
std::string value;
|
|
||||||
static std::shared_ptr<FIStringValue> create(std::string &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIByteValue : public FIValue {
|
|
||||||
std::vector<uint8_t> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIHexValue : public FIByteValue {
|
|
||||||
static std::shared_ptr<FIHexValue> create(std::vector<uint8_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIBase64Value : public FIByteValue {
|
|
||||||
static std::shared_ptr<FIBase64Value> create(std::vector<uint8_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIShortValue : public FIValue {
|
|
||||||
std::vector<int16_t> value;
|
|
||||||
static std::shared_ptr<FIShortValue> create(std::vector<int16_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIIntValue : public FIValue {
|
|
||||||
std::vector<int32_t> value;
|
|
||||||
static std::shared_ptr<FIIntValue> create(std::vector<int32_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FILongValue : public FIValue {
|
|
||||||
std::vector<int64_t> value;
|
|
||||||
static std::shared_ptr<FILongValue> create(std::vector<int64_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIBoolValue : public FIValue {
|
|
||||||
std::vector<bool> value;
|
|
||||||
static std::shared_ptr<FIBoolValue> create(std::vector<bool> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIFloatValue : public FIValue {
|
|
||||||
std::vector<float> value;
|
|
||||||
static std::shared_ptr<FIFloatValue> create(std::vector<float> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIDoubleValue : public FIValue {
|
|
||||||
std::vector<double> value;
|
|
||||||
static std::shared_ptr<FIDoubleValue> create(std::vector<double> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIUUIDValue : public FIByteValue {
|
|
||||||
static std::shared_ptr<FIUUIDValue> create(std::vector<uint8_t> &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FICDATAValue : public FIStringValue {
|
|
||||||
static std::shared_ptr<FICDATAValue> create(std::string &&value);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIDecoder {
|
|
||||||
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) = 0;
|
|
||||||
virtual ~FIDecoder() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIQName {
|
|
||||||
const char *name;
|
|
||||||
const char *prefix;
|
|
||||||
const char *uri;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FIVocabulary {
|
|
||||||
const char **restrictedAlphabetTable;
|
|
||||||
size_t restrictedAlphabetTableSize;
|
|
||||||
const char **encodingAlgorithmTable;
|
|
||||||
size_t encodingAlgorithmTableSize;
|
|
||||||
const char **prefixTable;
|
|
||||||
size_t prefixTableSize;
|
|
||||||
const char **namespaceNameTable;
|
|
||||||
size_t namespaceNameTableSize;
|
|
||||||
const char **localNameTable;
|
|
||||||
size_t localNameTableSize;
|
|
||||||
const char **otherNCNameTable;
|
|
||||||
size_t otherNCNameTableSize;
|
|
||||||
const char **otherURITable;
|
|
||||||
size_t otherURITableSize;
|
|
||||||
const std::shared_ptr<const FIValue> *attributeValueTable;
|
|
||||||
size_t attributeValueTableSize;
|
|
||||||
const std::shared_ptr<const FIValue> *charactersTable;
|
|
||||||
size_t charactersTableSize;
|
|
||||||
const std::shared_ptr<const FIValue> *otherStringTable;
|
|
||||||
size_t otherStringTableSize;
|
|
||||||
const FIQName *elementNameTable;
|
|
||||||
size_t elementNameTableSize;
|
|
||||||
const FIQName *attributeNameTable;
|
|
||||||
size_t attributeNameTableSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IOStream;
|
|
||||||
|
|
||||||
class FIReader {
|
|
||||||
public:
|
|
||||||
virtual ~FIReader();
|
|
||||||
|
|
||||||
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const = 0;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const = 0;
|
|
||||||
|
|
||||||
virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) = 0;
|
|
||||||
|
|
||||||
virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) = 0;
|
|
||||||
|
|
||||||
virtual bool read() = 0;
|
|
||||||
|
|
||||||
static std::unique_ptr<FIReader> create(IOStream *stream);
|
|
||||||
|
|
||||||
}; // class IFIReader
|
|
||||||
|
|
||||||
inline FIReader::~FIReader() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Assimp
|
|
||||||
|
|
||||||
#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#endif // INCLUDED_AI_FI_READER_H
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -48,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
||||||
#define INCLUDED_AI_X3D_IMPORTER_H
|
#define INCLUDED_AI_X3D_IMPORTER_H
|
||||||
|
|
||||||
#include "X3DImporter_Node.hpp"
|
|
||||||
|
|
||||||
// Header files, Assimp.
|
// Header files, Assimp.
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
@ -57,8 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
#include <assimp/BaseImporter.h>
|
#include <assimp/BaseImporter.h>
|
||||||
#include <assimp/XmlParser.h>
|
#include <assimp/XmlParser.h>
|
||||||
#include "FIReader.hpp"
|
#include <assimp/scene.h>
|
||||||
//#include <regex>
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
@ -234,6 +233,62 @@ inline void LogInfo(const std::string &message) {
|
||||||
///
|
///
|
||||||
/// That's all for now. Enjoy
|
/// That's all for now. Enjoy
|
||||||
///
|
///
|
||||||
|
enum class X3DElemType {
|
||||||
|
ENET_Group, ///< Element has type "Group".
|
||||||
|
ENET_MetaBoolean, ///< Element has type "Metadata boolean".
|
||||||
|
ENET_MetaDouble, ///< Element has type "Metadata double".
|
||||||
|
ENET_MetaFloat, ///< Element has type "Metadata float".
|
||||||
|
ENET_MetaInteger, ///< Element has type "Metadata integer".
|
||||||
|
ENET_MetaSet, ///< Element has type "Metadata set".
|
||||||
|
ENET_MetaString, ///< Element has type "Metadata string".
|
||||||
|
ENET_Arc2D, ///< Element has type "Arc2D".
|
||||||
|
ENET_ArcClose2D, ///< Element has type "ArcClose2D".
|
||||||
|
ENET_Circle2D, ///< Element has type "Circle2D".
|
||||||
|
ENET_Disk2D, ///< Element has type "Disk2D".
|
||||||
|
ENET_Polyline2D, ///< Element has type "Polyline2D".
|
||||||
|
ENET_Polypoint2D, ///< Element has type "Polypoint2D".
|
||||||
|
ENET_Rectangle2D, ///< Element has type "Rectangle2D".
|
||||||
|
ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
|
||||||
|
ENET_Box, ///< Element has type "Box".
|
||||||
|
ENET_Cone, ///< Element has type "Cone".
|
||||||
|
ENET_Cylinder, ///< Element has type "Cylinder".
|
||||||
|
ENET_Sphere, ///< Element has type "Sphere".
|
||||||
|
ENET_ElevationGrid, ///< Element has type "ElevationGrid".
|
||||||
|
ENET_Extrusion, ///< Element has type "Extrusion".
|
||||||
|
ENET_Coordinate, ///< Element has type "Coordinate".
|
||||||
|
ENET_Normal, ///< Element has type "Normal".
|
||||||
|
ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
|
||||||
|
ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
|
||||||
|
ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
|
||||||
|
ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
|
||||||
|
ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
|
||||||
|
ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
|
||||||
|
ENET_LineSet, ///< Element has type "LineSet".
|
||||||
|
ENET_PointSet, ///< Element has type "PointSet".
|
||||||
|
ENET_TriangleSet, ///< Element has type "TriangleSet".
|
||||||
|
ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
|
||||||
|
ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
|
||||||
|
ENET_Color, ///< Element has type "Color".
|
||||||
|
ENET_ColorRGBA, ///< Element has type "ColorRGBA".
|
||||||
|
ENET_Shape, ///< Element has type "Shape".
|
||||||
|
ENET_Appearance, ///< Element has type "Appearance".
|
||||||
|
ENET_Material, ///< Element has type "Material".
|
||||||
|
ENET_ImageTexture, ///< Element has type "ImageTexture".
|
||||||
|
ENET_TextureTransform, ///< Element has type "TextureTransform".
|
||||||
|
ENET_DirectionalLight, ///< Element has type "DirectionalLight".
|
||||||
|
ENET_PointLight, ///< Element has type "PointLight".
|
||||||
|
ENET_SpotLight, ///< Element has type "SpotLight".
|
||||||
|
|
||||||
|
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementBase {
|
||||||
|
X3DNodeElementBase *Parent;
|
||||||
|
std::string ID;
|
||||||
|
std::list<X3DNodeElementBase *> Child;
|
||||||
|
X3DElemType Type;
|
||||||
|
};
|
||||||
|
|
||||||
class X3DImporter : public BaseImporter
|
class X3DImporter : public BaseImporter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -259,526 +314,12 @@ public:
|
||||||
/// \param [in] pFile - name of file to be parsed.
|
/// \param [in] pFile - name of file to be parsed.
|
||||||
/// \param [in] pIOHandler - pointer to IO helper object.
|
/// \param [in] pIOHandler - pointer to IO helper object.
|
||||||
void ParseFile( const std::string& pFile, IOSystem* pIOHandler );
|
void ParseFile( const std::string& pFile, IOSystem* pIOHandler );
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/********* Functions: BaseImporter set *********/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig ) const;
|
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig ) const;
|
||||||
void GetExtensionList( std::set<std::string>& pExtensionList );
|
void GetExtensionList( std::set<std::string>& pExtensionList );
|
||||||
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
|
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
|
||||||
const aiImporterDesc* GetInfo()const;
|
const aiImporterDesc* GetInfo()const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Disabled copy constructor.
|
|
||||||
X3DImporter(const X3DImporter& pScene);
|
|
||||||
|
|
||||||
/// Disabled assign operator.
|
|
||||||
X3DImporter& operator=(const X3DImporter& pScene);
|
|
||||||
|
|
||||||
/// Clear all temporary data.
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/************* Functions: find set *************/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
/// Find requested node element. Search will be made in all existing nodes.
|
|
||||||
/// \param [in] pID - ID of requested element.
|
|
||||||
/// \param [in] pType - type of requested element.
|
|
||||||
/// \param [out] pElement - pointer to pointer to item found.
|
|
||||||
/// \return true - if the element is found, else - false.
|
|
||||||
bool FindNodeElement_FromRoot(const std::string& pID, const X3DNodeElementBase::EType pType, X3DNodeElementBase** pElement);
|
|
||||||
|
|
||||||
/// Find requested node element. Search will be made from pointed node down to childs.
|
|
||||||
/// \param [in] pStartNode - pointer to start node.
|
|
||||||
/// \param [in] pID - ID of requested element.
|
|
||||||
/// \param [in] pType - type of requested element.
|
|
||||||
/// \param [out] pElement - pointer to pointer to item found.
|
|
||||||
/// \return true - if the element is found, else - false.
|
|
||||||
bool FindNodeElement_FromNode(X3DNodeElementBase* pStartNode, const std::string& pID, const X3DNodeElementBase::EType pType,
|
|
||||||
X3DNodeElementBase** pElement);
|
|
||||||
|
|
||||||
/// Find requested node element. For "Node"'s accounting flag "Static".
|
|
||||||
/// \param [in] pName - name of requested element.
|
|
||||||
/// \param [in] pType - type of requested element.
|
|
||||||
/// \param [out] pElement - pointer to pointer to item found.
|
|
||||||
/// \return true - if the element is found, else - false.
|
|
||||||
bool FindNodeElement(const std::string& pName, const X3DNodeElementBase::EType pType, X3DNodeElementBase** pElement);
|
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/********* Functions: postprocess set **********/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
/// \return transformation matrix from global coordinate system to local.
|
|
||||||
aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
|
|
||||||
|
|
||||||
/// Check if child elements of node element is metadata and add it to temporary list.
|
|
||||||
/// \param [in] pNodeElement - node element where metadata is searching.
|
|
||||||
/// \param [out] pList - temporary list for collected metadata.
|
|
||||||
void PostprocessHelper_CollectMetadata(const X3DNodeElementBase& pNodeElement, std::list<X3DNodeElementBase*>& pList) const;
|
|
||||||
|
|
||||||
/// Check if type of node element is metadata. E.g. <MetadataSet>, <MetadataString>.
|
|
||||||
/// \param [in] pType - checked type.
|
|
||||||
/// \return true - if the type corresponds to the metadata.
|
|
||||||
bool PostprocessHelper_ElementIsMetadata(const X3DNodeElementBase::EType pType) const;
|
|
||||||
|
|
||||||
/// Check if type of node element is geometry object and can be used to build mesh. E.g. <Box>, <Arc2D>.
|
|
||||||
/// \param [in] pType - checked type.
|
|
||||||
/// \return true - if the type corresponds to the mesh.
|
|
||||||
bool PostprocessHelper_ElementIsMesh(const X3DNodeElementBase::EType pType) const;
|
|
||||||
|
|
||||||
/// Read CX3DImporter_NodeElement_Light, create aiLight and add it to list of the lights.
|
|
||||||
/// \param [in] pNodeElement - reference to lisght element(<DirectionalLight>, <PointLight>, <SpotLight>).
|
|
||||||
/// \param [out] pSceneLightList - reference to list of the lights.
|
|
||||||
void Postprocess_BuildLight(const X3DNodeElementBase& pNodeElement, std::list<aiLight*>& pSceneLightList) const;
|
|
||||||
|
|
||||||
/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
|
|
||||||
/// all needed data from scene graph.
|
|
||||||
/// \param [in] pNodeElement - reference to material element(<Appearance>).
|
|
||||||
/// \param [out] pMaterial - pointer to pointer to created material. *pMaterial must be nullptr.
|
|
||||||
void Postprocess_BuildMaterial(const X3DNodeElementBase& pNodeElement, aiMaterial** pMaterial) const;
|
|
||||||
|
|
||||||
/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
|
|
||||||
/// all needed data from scene graph.
|
|
||||||
/// \param [in] pNodeElement - reference to geometry object.
|
|
||||||
/// \param [out] pMesh - pointer to pointer to created mesh. *pMesh must be nullptr.
|
|
||||||
void Postprocess_BuildMesh(const X3DNodeElementBase& pNodeElement, aiMesh** pMesh) const;
|
|
||||||
|
|
||||||
/// Create aiNode from CX3DImporter_NodeElement. Also function check children and make recursive call.
|
|
||||||
/// \param [out] pNode - pointer to pointer to created node. *pNode must be nullptr.
|
|
||||||
/// \param [in] pNodeElement - CX3DImporter_NodeElement which read.
|
|
||||||
/// \param [out] pSceneNode - aiNode for filling.
|
|
||||||
/// \param [out] pSceneMeshList - list with aiMesh which belong to scene.
|
|
||||||
/// \param [out] pSceneMaterialList - list with aiMaterial which belong to scene.
|
|
||||||
/// \param [out] pSceneLightList - list with aiLight which belong to scene.
|
|
||||||
void Postprocess_BuildNode(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
|
|
||||||
std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const;
|
|
||||||
|
|
||||||
/// To create mesh and material kept in <Schape>.
|
|
||||||
/// \param pShapeNodeElement - reference to node element which kept <Shape> data.
|
|
||||||
/// \param pNodeMeshInd - reference to list with mesh indices. When pShapeNodeElement will read new mesh index will be added to this list.
|
|
||||||
/// \param pSceneMeshList - reference to list with meshes. When pShapeNodeElement will read new mesh will be added to this list.
|
|
||||||
/// \param pSceneMaterialList - reference to list with materials. When pShapeNodeElement will read new material will be added to this list.
|
|
||||||
void Postprocess_BuildShape(const X3DShape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
|
|
||||||
std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const;
|
|
||||||
|
|
||||||
/// Check if child elements of node element is metadata and add it to scene node.
|
|
||||||
/// \param [in] pNodeElement - node element where metadata is searching.
|
|
||||||
/// \param [out] pSceneNode - scene node in which metadata will be added.
|
|
||||||
void Postprocess_CollectMetadata(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode) const;
|
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/************** Functions: XML set *************/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
/// Check if current node is empty: <node />. If not then exception will throwed.
|
|
||||||
void XML_CheckNode_MustBeEmpty(XmlNode &node);
|
|
||||||
|
|
||||||
/// Check if current node name is equal to pNodeName.
|
|
||||||
/// \param [in] pNodeName - name for checking.
|
|
||||||
/// return true if current node name is equal to pNodeName, else - false.
|
|
||||||
//bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
|
|
||||||
|
|
||||||
/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
|
|
||||||
/// \param [in] pParentNodeName - parent node name. Used for reporting.
|
|
||||||
void XML_CheckNode_SkipUnsupported(XmlNode &node, const std::string &pParentNodeName);
|
|
||||||
|
|
||||||
/// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
|
|
||||||
/// \param [in] pNodeName - requested node name.
|
|
||||||
/// return true - if node is found, else - false.
|
|
||||||
bool XML_SearchNode(XmlNode &node, const std::string &pNodeName);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \return read data.
|
|
||||||
bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \return read data.
|
|
||||||
float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \return read data.
|
|
||||||
int32_t XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue);
|
|
||||||
|
|
||||||
/// \overload void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue);
|
|
||||||
|
|
||||||
/// \overload void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue);
|
|
||||||
|
|
||||||
/// \overload void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue);
|
|
||||||
|
|
||||||
/// \overload void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
|
|
||||||
void XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue);
|
|
||||||
|
|
||||||
/// Read attribute value.
|
|
||||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
|
||||||
/// \param [out] pValue - read data.
|
|
||||||
void XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue);
|
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/******* Functions: geometry helper set *******/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
/// Make point on surface oXY.
|
|
||||||
/// \param [in] pAngle - angle in radians between radius-vector of point and oX axis. Angle extends from the oX axis counterclockwise to the radius-vector.
|
|
||||||
/// \param [in] pRadius - length of radius-vector.
|
|
||||||
/// \return made point coordinates.
|
|
||||||
aiVector3D GeometryHelper_Make_Point2D(const float pAngle, const float pRadius);
|
|
||||||
|
|
||||||
/// Make 2D figure - linear circular arc with center in (0, 0). The z-coordinate is 0. The arc extends from the pStartAngle counterclockwise
|
|
||||||
/// to the pEndAngle. If pStartAngle and pEndAngle have the same value, a circle is specified. If the absolute difference between pStartAngle
|
|
||||||
/// and pEndAngle is greater than or equal to 2pi, a circle is specified.
|
|
||||||
/// \param [in] pStartAngle - angle in radians of start of the arc.
|
|
||||||
/// \param [in] pEndAngle - angle in radians of end of the arc.
|
|
||||||
/// \param [in] pRadius - radius of the arc.
|
|
||||||
/// \param [out] pNumSegments - number of segments in arc. In other words - tessellation factor.
|
|
||||||
/// \param [out] pVertices - generated vertices.
|
|
||||||
void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices);
|
|
||||||
|
|
||||||
/// Create line set from point set.
|
|
||||||
/// \param [in] pPoint - input points list.
|
|
||||||
/// \param [out] pLine - made lines list.
|
|
||||||
void GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine);
|
|
||||||
|
|
||||||
/// Create CoordIdx of line set from CoordIdx of polyline set.
|
|
||||||
/// \param [in] pPolylineCoordIdx - vertices indices divided by delimiter "-1". Must contain faces with two or more indices.
|
|
||||||
/// \param [out] pLineCoordIdx - made CoordIdx of line set.
|
|
||||||
void GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx);
|
|
||||||
|
|
||||||
/// Make 3D body - rectangular parallelepiped with center in (0, 0). QL mean quadlist (\sa pVertices).
|
|
||||||
/// \param [in] pSize - scale factor for body for every axis. E.g. (1, 2, 1) mean: X-size and Z-size - 1, Y-size - 2.
|
|
||||||
/// \param [out] pVertices - generated vertices. The list of vertices is grouped in quads.
|
|
||||||
void GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices);
|
|
||||||
|
|
||||||
/// Create faces array from vertices indices array.
|
|
||||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
|
||||||
/// \param [in] pFaces - created faces array.
|
|
||||||
/// \param [in] pPrimitiveTypes - type of primitives in faces.
|
|
||||||
void GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
|
|
||||||
|
|
||||||
/// Add colors to mesh.
|
|
||||||
/// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
|
|
||||||
/// If the colorIndex field is not empty, one colour is used for each face of the mesh. There shall be at least as many indices in the
|
|
||||||
/// colorIndex field as there are faces in the mesh. The colorIndex field shall not contain any negative entries.
|
|
||||||
/// If the colorIndex field is empty, the colours in the X3DColorNode node are applied to each face of the mesh in order.
|
|
||||||
/// There shall be at least as many colours in the X3DColorNode node as there are faces.
|
|
||||||
/// b. If colorPerVertex is TRUE, colours are applied to each vertex, as follows:
|
|
||||||
/// If the colorIndex field is not empty, colours are applied to each vertex of the mesh in exactly the same manner that the coordIndex
|
|
||||||
/// field is used to choose coordinates for each vertex from the <Coordinate> node. The colorIndex field shall contain end-of-face markers (-1)
|
|
||||||
/// in exactly the same places as the coordIndex field.
|
|
||||||
/// If the colorIndex field is empty, the coordIndex field is used to choose colours from the X3DColorNode node.
|
|
||||||
/// \param [in] pMesh - mesh for adding data.
|
|
||||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
|
||||||
/// \param [in] pColorIdx - color indices for every vertex divided by delimiter "-1" if \ref pColorPerVertex is true. if \ref pColorPerVertex is false
|
|
||||||
/// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
|
|
||||||
/// \param [in] pColors - defined colors.
|
|
||||||
/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
|
|
||||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
|
|
||||||
const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
|
||||||
|
|
||||||
/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
|
||||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
|
|
||||||
const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
|
|
||||||
|
|
||||||
/// Add colors to mesh.
|
|
||||||
/// \param [in] pMesh - mesh for adding data.
|
|
||||||
/// \param [in] pColors - defined colors.
|
|
||||||
/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
|
|
||||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
|
||||||
|
|
||||||
/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
|
|
||||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
|
|
||||||
|
|
||||||
/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
|
||||||
void MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
|
|
||||||
const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
|
|
||||||
|
|
||||||
/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
|
||||||
void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
|
|
||||||
|
|
||||||
/// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
|
||||||
void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
|
|
||||||
const std::list<aiVector2D>& pTexCoords) const;
|
|
||||||
|
|
||||||
/// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
|
||||||
void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const;
|
|
||||||
|
|
||||||
/// Create mesh.
|
|
||||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
|
||||||
/// \param [in] pVertices - vertices of mesh.
|
|
||||||
/// \return created mesh.
|
|
||||||
aiMesh* GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
|
|
||||||
|
|
||||||
/***********************************************/
|
|
||||||
/******** Functions: parse set private *********/
|
|
||||||
/***********************************************/
|
|
||||||
|
|
||||||
/// Create node element with type "Node" in scene graph. That operation is needed when you enter to X3D group node
|
|
||||||
/// like <Group>, <Transform> etc. When exiting from X3D group node(e.g. </Group>) \ref ParseHelper_Node_Exit must
|
|
||||||
/// be called.
|
|
||||||
/// \param [in] pStatic - flag: if true then static node is created(e.g. <StaticGroup>).
|
|
||||||
void ParseHelper_Group_Begin(const bool pStatic = false);
|
|
||||||
|
|
||||||
/// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
|
|
||||||
/// \param [in] pNode - new current node.
|
|
||||||
void ParseHelper_Node_Enter(X3DNodeElementBase* pNode);
|
|
||||||
|
|
||||||
/// This function must be called when exiting from X3D group node(e.g. </Group>). \ref ParseHelper_Group_Begin.
|
|
||||||
void ParseHelper_Node_Exit();
|
|
||||||
|
|
||||||
/// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
|
|
||||||
/// must be converted to right form - "0.xxx".
|
|
||||||
/// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
|
|
||||||
/// \param [out[ pOutString - output string with right form of values.
|
|
||||||
void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
|
|
||||||
|
|
||||||
/// Check if current node has nodes of type X3DMetadataObject. Why we must do it? Because X3DMetadataObject can be in any non-empty X3DNode.
|
|
||||||
/// Meaning that X3DMetadataObject can be in any non-empty node in <Scene>.
|
|
||||||
/// \return true - if metadata node are found and parsed, false - metadata not found.
|
|
||||||
bool ParseHelper_CheckRead_X3DMetadataObject();
|
|
||||||
|
|
||||||
/// Check if current node has nodes of type X3DGeometricPropertyNode. X3DGeometricPropertyNode
|
|
||||||
/// X3DGeometricPropertyNode inheritors:
|
|
||||||
/// <FogCoordinate>, <HAnimDisplacer>, <Color>, <ColorRGBA>, <Coordinate>, <CoordinateDouble>, <GeoCoordinate>, <Normal>,
|
|
||||||
/// <MultiTextureCoordinate>, <TextureCoordinate>, <TextureCoordinate3D>, <TextureCoordinate4D>, <TextureCoordinateGenerator>,
|
|
||||||
/// <FloatVertexAttribute>, <Matrix3VertexAttribute>, <Matrix4VertexAttribute>.
|
|
||||||
/// \return true - if nodes are found and parsed, false - nodes not found.
|
|
||||||
bool ParseHelper_CheckRead_X3DGeometricPropertyNode();
|
|
||||||
|
|
||||||
/// Parse <X3D> node of the file.
|
|
||||||
void ParseNode_Root();
|
|
||||||
|
|
||||||
/// Parse <head> node of the file.
|
|
||||||
void ParseNode_Head();
|
|
||||||
|
|
||||||
/// Parse <Scene> node of the file.
|
|
||||||
void ParseNode_Scene();
|
|
||||||
|
|
||||||
/// Parse child nodes of <Metadata*> node.
|
|
||||||
/// \param [in] pNodeName - parsed node name. Must be set because that function is general and name needed for checking the end
|
|
||||||
/// and error reporing.
|
|
||||||
/// \param [in] pParentElement - parent metadata element.
|
|
||||||
void ParseNode_Metadata(X3DNodeElementBase* pParentElement, const std::string& pNodeName);
|
|
||||||
|
|
||||||
/// Parse <MetadataBoolean> node of the file.
|
|
||||||
void ParseNode_MetadataBoolean();
|
|
||||||
|
|
||||||
/// Parse <MetadataDouble> node of the file.
|
|
||||||
void ParseNode_MetadataDouble();
|
|
||||||
|
|
||||||
/// Parse <MetadataFloat> node of the file.
|
|
||||||
void ParseNode_MetadataFloat();
|
|
||||||
|
|
||||||
/// Parse <MetadataInteger> node of the file.
|
|
||||||
void ParseNode_MetadataInteger();
|
|
||||||
|
|
||||||
/// Parse <MetadataSet> node of the file.
|
|
||||||
void ParseNode_MetadataSet();
|
|
||||||
|
|
||||||
/// \fn void ParseNode_MetadataString()
|
|
||||||
/// Parse <MetadataString> node of the file.
|
|
||||||
void ParseNode_MetadataString();
|
|
||||||
|
|
||||||
/// Parse <Arc2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Arc2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <ArcClose2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_ArcClose2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Circle2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Circle2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Disk2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Disk2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Polyline2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Polyline2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Polypoint2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Polypoint2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Rectangle2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_Rectangle2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <TriangleSet2D> node of the file.
|
|
||||||
void ParseNode_Geometry2D_TriangleSet2D(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Box> node of the file.
|
|
||||||
void ParseNode_Geometry3D_Box(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Cone> node of the file.
|
|
||||||
void ParseNode_Geometry3D_Cone(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Cylinder> node of the file.
|
|
||||||
void ParseNode_Geometry3D_Cylinder(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <ElevationGrid> node of the file.
|
|
||||||
void ParseNode_Geometry3D_ElevationGrid(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Extrusion> node of the file.
|
|
||||||
void ParseNode_Geometry3D_Extrusion(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <IndexedFaceSet> node of the file.
|
|
||||||
void ParseNode_Geometry3D_IndexedFaceSet(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Sphere> node of the file.
|
|
||||||
void ParseNode_Geometry3D_Sphere(XmlNode &node);
|
|
||||||
|
|
||||||
/// Parse <Group> node of the file. And create new node in scene graph.
|
|
||||||
void ParseNode_Grouping_Group(XmlNode &node);
|
|
||||||
|
|
||||||
/// Doing actions at an exit from <Group>. Walk up in scene graph.
|
|
||||||
void ParseNode_Grouping_GroupEnd();
|
|
||||||
|
|
||||||
/// Parse <StaticGroup> node of the file. And create new node in scene graph.
|
|
||||||
void ParseNode_Grouping_StaticGroup(XmlNode &node);
|
|
||||||
|
|
||||||
/// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
|
|
||||||
void ParseNode_Grouping_StaticGroupEnd();
|
|
||||||
|
|
||||||
/// Parse <Switch> node of the file. And create new node in scene graph.
|
|
||||||
void ParseNode_Grouping_Switch(XmlNode &node);
|
|
||||||
|
|
||||||
/// Doing actions at an exit from <Switch>. Walk up in scene graph.
|
|
||||||
void ParseNode_Grouping_SwitchEnd();
|
|
||||||
|
|
||||||
/// Parse <Transform> node of the file. And create new node in scene graph.
|
|
||||||
void ParseNode_Grouping_Transform(XmlNode &node);
|
|
||||||
|
|
||||||
/// Doing actions at an exit from <Transform>. Walk up in scene graph.
|
|
||||||
void ParseNode_Grouping_TransformEnd();
|
|
||||||
|
|
||||||
/// Parse <Color> node of the file.
|
|
||||||
void ParseNode_Rendering_Color();
|
|
||||||
|
|
||||||
/// Parse <ColorRGBA> node of the file.
|
|
||||||
void ParseNode_Rendering_ColorRGBA();
|
|
||||||
|
|
||||||
/// Parse <Coordinate> node of the file.
|
|
||||||
void ParseNode_Rendering_Coordinate();
|
|
||||||
|
|
||||||
/// Parse <Normal> node of the file.
|
|
||||||
void ParseNode_Rendering_Normal();
|
|
||||||
|
|
||||||
/// Parse <IndexedLineSet> node of the file.
|
|
||||||
void ParseNode_Rendering_IndexedLineSet();
|
|
||||||
|
|
||||||
/// Parse <IndexedTriangleFanSet> node of the file.
|
|
||||||
void ParseNode_Rendering_IndexedTriangleFanSet();
|
|
||||||
|
|
||||||
/// Parse <IndexedTriangleSet> node of the file.
|
|
||||||
void ParseNode_Rendering_IndexedTriangleSet();
|
|
||||||
|
|
||||||
/// Parse <IndexedTriangleStripSet> node of the file.
|
|
||||||
void ParseNode_Rendering_IndexedTriangleStripSet();
|
|
||||||
|
|
||||||
/// Parse <LineSet> node of the file.
|
|
||||||
void ParseNode_Rendering_LineSet();
|
|
||||||
|
|
||||||
/// Parse <PointSet> node of the file.
|
|
||||||
void ParseNode_Rendering_PointSet();
|
|
||||||
|
|
||||||
/// Parse <TriangleFanSet> node of the file.
|
|
||||||
void ParseNode_Rendering_TriangleFanSet();
|
|
||||||
|
|
||||||
/// Parse <TriangleSet> node of the file.
|
|
||||||
void ParseNode_Rendering_TriangleSet();
|
|
||||||
|
|
||||||
/// Parse <TriangleStripSet> node of the file.
|
|
||||||
void ParseNode_Rendering_TriangleStripSet();
|
|
||||||
|
|
||||||
/// Parse <ImageTexture> node of the file.
|
|
||||||
void ParseNode_Texturing_ImageTexture();
|
|
||||||
|
|
||||||
/// Parse <TextureCoordinate> node of the file.
|
|
||||||
void ParseNode_Texturing_TextureCoordinate();
|
|
||||||
|
|
||||||
/// Parse <TextureTransform> node of the file.
|
|
||||||
void ParseNode_Texturing_TextureTransform();
|
|
||||||
|
|
||||||
/// Parse <Shape> node of the file.
|
|
||||||
void ParseNode_Shape_Shape();
|
|
||||||
|
|
||||||
/// Parse <Appearance> node of the file.
|
|
||||||
void ParseNode_Shape_Appearance();
|
|
||||||
|
|
||||||
/// Parse <Material> node of the file.
|
|
||||||
void ParseNode_Shape_Material();
|
|
||||||
|
|
||||||
/// Parse <Inline> node of the file.
|
|
||||||
void ParseNode_Networking_Inline();
|
|
||||||
|
|
||||||
/// Parse <DirectionalLight> node of the file.
|
|
||||||
void ParseNode_Lighting_DirectionalLight();
|
|
||||||
|
|
||||||
/// Parse <PointLight> node of the file.
|
|
||||||
void ParseNode_Lighting_PointLight();
|
|
||||||
|
|
||||||
/// Parse <SpotLight> node of the file.
|
|
||||||
void ParseNode_Lighting_SpotLight();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
/******************** Types ********************/
|
/******************** Types ********************/
|
||||||
|
@ -796,7 +337,7 @@ private:
|
||||||
/****************** Variables ******************/
|
/****************** Variables ******************/
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
X3DNodeElementBase* mNodeElementCur;///< Current element.
|
X3DNodeElementBase* mNodeElementCur;///< Current element.
|
||||||
std::unique_ptr<FIReader> mReader;///< Pointer to XML-reader object
|
XmlParser *mXmlParser;
|
||||||
IOSystem *mpIOHandler;
|
IOSystem *mpIOHandler;
|
||||||
};// class X3DImporter
|
};// class X3DImporter
|
||||||
|
|
||||||
|
|
|
@ -1,521 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Geometry2D.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Geometry2D" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Node.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
// <Arc2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// endAngle="1.570796" SFFloat [initializeOnly]
|
|
||||||
// radius="1" SFFloat [initializeOnly]
|
|
||||||
// startAngle="0" SFFloat [initializeOnly]
|
|
||||||
// />
|
|
||||||
// The Arc2D node specifies a linear circular arc whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
|
||||||
// towards the positive y-axis. The radius field specifies the radius of the circle of which the arc is a portion. The arc extends from the startAngle
|
|
||||||
// counterclockwise to the endAngle. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different
|
|
||||||
// angle base unit has been specified). If startAngle and endAngle have the same value, a circle is specified.
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Arc2D() {
|
|
||||||
std::string def, use;
|
|
||||||
float endAngle = AI_MATH_HALF_PI_F;
|
|
||||||
float radius = 1;
|
|
||||||
float startAngle = 0;
|
|
||||||
X3DNodeElementBase* ne = nullptr;
|
|
||||||
|
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Arc2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Arc2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// create point list of geometry object and convert it to line set.
|
|
||||||
std::list<aiVector3D> tlist;
|
|
||||||
|
|
||||||
GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
|
|
||||||
GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 2;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Arc2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <ArcClose2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// closureType="PIE" SFString [initializeOnly], {"PIE", "CHORD"}
|
|
||||||
// endAngle="1.570796" SFFloat [initializeOnly]
|
|
||||||
// radius="1" SFFloat [initializeOnly]
|
|
||||||
// solid="false" SFBool [initializeOnly]
|
|
||||||
// startAngle="0" SFFloat [initializeOnly]
|
|
||||||
// />
|
|
||||||
// The ArcClose node specifies a portion of a circle whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
|
||||||
// towards the positive y-axis. The end points of the arc specified are connected as defined by the closureType field. The radius field specifies the radius
|
|
||||||
// of the circle of which the arc is a portion. The arc extends from the startAngle counterclockwise to the endAngle. The value of radius shall be greater
|
|
||||||
// than zero. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different default angle base unit has
|
|
||||||
// been specified). If startAngle and endAngle have the same value, a circle is specified and closureType is ignored. If the absolute difference between
|
|
||||||
// startAngle and endAngle is greater than or equal to 2pi, a complete circle is produced with no chord or radial line(s) drawn from the center.
|
|
||||||
// A closureType of "PIE" connects the end point to the start point by defining two straight line segments first from the end point to the center and then
|
|
||||||
// the center to the start point. A closureType of "CHORD" connects the end point to the start point by defining a straight line segment from the end point
|
|
||||||
// to the start point. Textures are applied individually to each face of the ArcClose2D. On the front (+Z) and back (-Z) faces of the ArcClose2D, when
|
|
||||||
// viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_ArcClose2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string closureType("PIE");
|
|
||||||
float endAngle = AI_MATH_HALF_PI_F;
|
|
||||||
float radius = 1;
|
|
||||||
bool solid = false;
|
|
||||||
float startAngle = 0;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("closureType", closureType, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ArcClose2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_ArcClose2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->Solid = solid;
|
|
||||||
// create point list of geometry object.
|
|
||||||
GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, ((X3DGeometry2D*)ne)->Vertices);///TODO: IME - AI_CONFIG for NumSeg
|
|
||||||
// add chord or two radiuses only if not a circle was defined
|
|
||||||
if(!((std::fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle)))
|
|
||||||
{
|
|
||||||
std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
|
|
||||||
|
|
||||||
if((closureType == "PIE") || (closureType == "\"PIE\""))
|
|
||||||
vlist.push_back(aiVector3D(0, 0, 0));// center point - first radial line
|
|
||||||
else if((closureType != "CHORD") && (closureType != "\"CHORD\""))
|
|
||||||
Throw_IncorrectAttrValue("closureType");
|
|
||||||
|
|
||||||
vlist.push_back(*vlist.begin());// arc first point - chord from first to last point of arc(if CHORD) or second radial line(if PIE).
|
|
||||||
}
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = ((X3DGeometry2D*)ne)->Vertices.size();
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "ArcClose2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Circle2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// radius="1" SFFloat [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Circle2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
float radius = 1;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Circle2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Circle2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// create point list of geometry object and convert it to line set.
|
|
||||||
std::list<aiVector3D> tlist;
|
|
||||||
|
|
||||||
GeometryHelper_Make_Arc2D(0, 0, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
|
|
||||||
GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 2;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Circle2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Disk2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// innerRadius="0" SFFloat [initializeOnly]
|
|
||||||
// outerRadius="1" SFFloat [initializeOnly]
|
|
||||||
// solid="false" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
// The Disk2D node specifies a circular disk which is centred at (0, 0) in the local coordinate system. The outerRadius field specifies the radius of the
|
|
||||||
// outer dimension of the Disk2D. The innerRadius field specifies the inner dimension of the Disk2D. The value of outerRadius shall be greater than zero.
|
|
||||||
// The value of innerRadius shall be greater than or equal to zero and less than or equal to outerRadius. If innerRadius is zero, the Disk2D is completely
|
|
||||||
// filled. Otherwise, the area within the innerRadius forms a hole in the Disk2D. If innerRadius is equal to outerRadius, a solid circular line shall
|
|
||||||
// be drawn using the current line properties. Textures are applied individually to each face of the Disk2D. On the front (+Z) and back (-Z) faces of
|
|
||||||
// the Disk2D, when viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Disk2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
float innerRadius = 0;
|
|
||||||
float outerRadius = 1;
|
|
||||||
bool solid = false;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("innerRadius", innerRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("outerRadius", outerRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Disk2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::list<aiVector3D> tlist_o, tlist_i;
|
|
||||||
|
|
||||||
if(innerRadius > outerRadius) Throw_IncorrectAttrValue("innerRadius");
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Disk2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// create point list of geometry object.
|
|
||||||
///TODO: IME - AI_CONFIG for NumSeg
|
|
||||||
GeometryHelper_Make_Arc2D(0, 0, outerRadius, 10, tlist_o);// outer circle
|
|
||||||
if(innerRadius == 0.0f)
|
|
||||||
{// make filled disk
|
|
||||||
// in tlist_o we already have points of circle. just copy it and sign as polygon.
|
|
||||||
((X3DGeometry2D*)ne)->Vertices = tlist_o;
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = tlist_o.size();
|
|
||||||
}
|
|
||||||
else if(innerRadius == outerRadius)
|
|
||||||
{// make circle
|
|
||||||
// in tlist_o we already have points of circle. convert it to line set.
|
|
||||||
GeometryHelper_Extend_PointToLine(tlist_o, ((X3DGeometry2D*)ne)->Vertices);
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{// make disk
|
|
||||||
std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
|
|
||||||
|
|
||||||
GeometryHelper_Make_Arc2D(0, 0, innerRadius, 10, tlist_i);// inner circle
|
|
||||||
//
|
|
||||||
// create quad list from two point lists
|
|
||||||
//
|
|
||||||
if(tlist_i.size() < 2) throw DeadlyImportError("Disk2D. Not enough points for creating quad list.");// tlist_i and tlist_o has equal size.
|
|
||||||
|
|
||||||
// add all quads except last
|
|
||||||
for(std::list<aiVector3D>::iterator it_i = tlist_i.begin(), it_o = tlist_o.begin(); it_i != tlist_i.end();)
|
|
||||||
{
|
|
||||||
// do not forget - CCW direction
|
|
||||||
vlist.push_back(*it_i++);// 1st point
|
|
||||||
vlist.push_back(*it_o++);// 2nd point
|
|
||||||
vlist.push_back(*it_o);// 3rd point
|
|
||||||
vlist.push_back(*it_i);// 4th point
|
|
||||||
}
|
|
||||||
|
|
||||||
// add last quad
|
|
||||||
vlist.push_back(*tlist_i.end());// 1st point
|
|
||||||
vlist.push_back(*tlist_o.end());// 2nd point
|
|
||||||
vlist.push_back(*tlist_o.begin());// 3rd point
|
|
||||||
vlist.push_back(*tlist_o.begin());// 4th point
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->Solid = solid;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Disk2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Polyline2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// lineSegments="" MFVec2F [intializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Polyline2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::list<aiVector2D> lineSegments;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("lineSegments", lineSegments, XML_ReadNode_GetAttrVal_AsListVec2f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polyline2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Polyline2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
//
|
|
||||||
// convert read point list of geometry object to line set.
|
|
||||||
//
|
|
||||||
std::list<aiVector3D> tlist;
|
|
||||||
|
|
||||||
// convert vec2 to vec3
|
|
||||||
for(std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); ++it2) tlist.push_back(aiVector3D(it2->x, it2->y, 0));
|
|
||||||
|
|
||||||
// convert point set to line set
|
|
||||||
GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 2;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Polyline2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Polypoint2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// point="" MFVec2F [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Polypoint2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::list<aiVector2D> point;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polypoint2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Polypoint2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// convert vec2 to vec3
|
|
||||||
for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); ++it2)
|
|
||||||
{
|
|
||||||
((X3DGeometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 1;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Polypoint2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Rectangle2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// size="2 2" SFVec2f [initializeOnly]
|
|
||||||
// solid="false" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_Rectangle2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
aiVector2D size(2, 2);
|
|
||||||
bool solid = false;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Rectangle2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Rectangle2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
float x1 = -size.x / 2.0f;
|
|
||||||
float x2 = size.x / 2.0f;
|
|
||||||
float y1 = -size.y / 2.0f;
|
|
||||||
float y2 = size.y / 2.0f;
|
|
||||||
std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
|
|
||||||
|
|
||||||
vlist.push_back(aiVector3D(x2, y1, 0));// 1st point
|
|
||||||
vlist.push_back(aiVector3D(x2, y2, 0));// 2nd point
|
|
||||||
vlist.push_back(aiVector3D(x1, y2, 0));// 3rd point
|
|
||||||
vlist.push_back(aiVector3D(x1, y1, 0));// 4th point
|
|
||||||
((X3DGeometry2D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 4;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Rectangle2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <TriangleSet2D
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// solid="false" SFBool [initializeOnly]
|
|
||||||
// vertices="" MFVec2F [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry2D_TriangleSet2D()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
bool solid = false;
|
|
||||||
std::list<aiVector2D> vertices;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("vertices", vertices, XML_ReadNode_GetAttrVal_AsListVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet2D, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry2D(X3DNodeElementBase::ENET_TriangleSet2D, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// convert vec2 to vec3
|
|
||||||
for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2)
|
|
||||||
{
|
|
||||||
((X3DGeometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
((X3DGeometry2D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry2D*)ne)->NumIndices = 3;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "TriangleSet2D");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,999 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Geometry3D.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Geometry3D" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
// Header files, Assimp.
|
|
||||||
#include <assimp/StandardShapes.h>
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
// <Box
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// size="2 2 2" SFVec3f [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
|
|
||||||
// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
|
|
||||||
// respectively and each component value shall be greater than zero.
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_Box()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
bool solid = true;
|
|
||||||
aiVector3D size(2, 2, 2);
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Box, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Box, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
GeometryHelper_MakeQL_RectParallelepiped(size, ((X3DGeometry3D*)ne)->Vertices);// get quad list
|
|
||||||
((X3DGeometry3D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry3D*)ne)->NumIndices = 4;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Box");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Cone
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bottom="true" SFBool [initializeOnly]
|
|
||||||
// bottomRadius="1" SFloat [initializeOnly]
|
|
||||||
// height="2" SFloat [initializeOnly]
|
|
||||||
// side="true" SFBool [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_Cone()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool bottom = true;
|
|
||||||
float bottomRadius = 1;
|
|
||||||
float height = 2;
|
|
||||||
bool side = true;
|
|
||||||
bool solid = true;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("bottomRadius", bottomRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cone, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
|
|
||||||
|
|
||||||
std::vector<aiVector3D> tvec;// temp array for vertices.
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Cone, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// make cone or parts according to flags.
|
|
||||||
if(side)
|
|
||||||
{
|
|
||||||
StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
|
|
||||||
}
|
|
||||||
else if(bottom)
|
|
||||||
{
|
|
||||||
StandardShapes::MakeCircle(bottomRadius, tess, tvec);
|
|
||||||
height = -(height / 2);
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ.
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy data from temp array
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) ((X3DGeometry3D*)ne)->Vertices.push_back(*it);
|
|
||||||
|
|
||||||
((X3DGeometry3D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry3D*)ne)->NumIndices = 3;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Cone");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Cylinder
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bottom="true" SFBool [initializeOnly]
|
|
||||||
// height="2" SFloat [initializeOnly]
|
|
||||||
// radius="1" SFloat [initializeOnly]
|
|
||||||
// side="true" SFBool [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// top="true" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_Cylinder()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool bottom = true;
|
|
||||||
float height = 2;
|
|
||||||
float radius = 1;
|
|
||||||
bool side = true;
|
|
||||||
bool solid = true;
|
|
||||||
bool top = true;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("top", top, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cylinder, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
|
|
||||||
|
|
||||||
std::vector<aiVector3D> tside;// temp array for vertices of side.
|
|
||||||
std::vector<aiVector3D> tcir;// temp array for vertices of circle.
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Cylinder, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// make cilynder or parts according to flags.
|
|
||||||
if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);
|
|
||||||
|
|
||||||
height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
|
|
||||||
if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
|
|
||||||
// copy data from temp arrays
|
|
||||||
std::list<aiVector3D>& vlist = ((X3DGeometry3D*)ne)->Vertices;// just short alias.
|
|
||||||
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it) vlist.push_back(*it);
|
|
||||||
|
|
||||||
if(top)
|
|
||||||
{
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
|
|
||||||
{
|
|
||||||
(*it).y = height;// y - because circle made in oXZ.
|
|
||||||
vlist.push_back(*it);
|
|
||||||
}
|
|
||||||
}// if(top)
|
|
||||||
|
|
||||||
if(bottom)
|
|
||||||
{
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
|
|
||||||
{
|
|
||||||
(*it).y = -height;// y - because circle made in oXZ.
|
|
||||||
vlist.push_back(*it);
|
|
||||||
}
|
|
||||||
}// if(top)
|
|
||||||
|
|
||||||
((X3DGeometry3D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry3D*)ne)->NumIndices = 3;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Cylinder");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <ElevationGrid
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ccw="true" SFBool [initializeOnly]
|
|
||||||
// colorPerVertex="true" SFBool [initializeOnly]
|
|
||||||
// creaseAngle="0" SFloat [initializeOnly]
|
|
||||||
// height="" MFloat [initializeOnly]
|
|
||||||
// normalPerVertex="true" SFBool [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// xDimension="0" SFInt32 [initializeOnly]
|
|
||||||
// xSpacing="1.0" SFloat [initializeOnly]
|
|
||||||
// zDimension="0" SFInt32 [initializeOnly]
|
|
||||||
// zSpacing="1.0" SFloat [initializeOnly]
|
|
||||||
// >
|
|
||||||
// <!-- ColorNormalTexCoordContentModel -->
|
|
||||||
// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
|
|
||||||
// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </ElevationGrid>
|
|
||||||
// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
|
|
||||||
// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
|
|
||||||
// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
|
|
||||||
// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool ccw = true;
|
|
||||||
bool colorPerVertex = true;
|
|
||||||
float creaseAngle = 0;
|
|
||||||
std::vector<float> height;
|
|
||||||
bool normalPerVertex = true;
|
|
||||||
bool solid = true;
|
|
||||||
int32_t xDimension = 0;
|
|
||||||
float xSpacing = 1;
|
|
||||||
int32_t zDimension = 0;
|
|
||||||
float zSpacing = 1;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsArrF);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("zSpacing", zSpacing, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ElevationGrid, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
|
|
||||||
if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
|
|
||||||
if((size_t)(xDimension * zDimension) != height.size()) Throw_IncorrectAttrValue("Heights count must be equal to \"xDimension * zDimension\"");
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DElevationGrid(X3DNodeElementBase::ENET_ElevationGrid, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
X3DElevationGrid& grid_alias = *((X3DElevationGrid*)ne);// create alias for conveience
|
|
||||||
|
|
||||||
{// create grid vertices list
|
|
||||||
std::vector<float>::const_iterator he_it = height.begin();
|
|
||||||
|
|
||||||
for(int32_t zi = 0; zi < zDimension; zi++)// rows
|
|
||||||
{
|
|
||||||
for(int32_t xi = 0; xi < xDimension; xi++)// columns
|
|
||||||
{
|
|
||||||
aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
|
|
||||||
|
|
||||||
grid_alias.Vertices.push_back(tvec);
|
|
||||||
++he_it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// END: create grid vertices list
|
|
||||||
//
|
|
||||||
// create faces list. In "coordIdx" format
|
|
||||||
//
|
|
||||||
// check if we have quads
|
|
||||||
if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set.
|
|
||||||
{
|
|
||||||
((X3DElevationGrid*)ne)->NumIndices = 2;// will be holded as line set.
|
|
||||||
for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
|
|
||||||
{
|
|
||||||
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i));
|
|
||||||
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1));
|
|
||||||
grid_alias.CoordIdx.push_back(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else// two or more elements in every dimension is set. create quad set.
|
|
||||||
{
|
|
||||||
((X3DElevationGrid*)ne)->NumIndices = 4;
|
|
||||||
for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows
|
|
||||||
{
|
|
||||||
for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns
|
|
||||||
{
|
|
||||||
// points direction in face.
|
|
||||||
if(ccw)
|
|
||||||
{
|
|
||||||
// CCW:
|
|
||||||
// 3 2
|
|
||||||
// 0 1
|
|
||||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
|
||||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
|
||||||
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
|
||||||
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CW:
|
|
||||||
// 0 1
|
|
||||||
// 3 2
|
|
||||||
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
|
||||||
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
|
||||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
|
||||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
|
||||||
}// if(ccw) else
|
|
||||||
|
|
||||||
grid_alias.CoordIdx.push_back(-1);
|
|
||||||
}// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
|
|
||||||
}// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
|
|
||||||
}// if((xDimension < 2) || (zDimension < 2)) else
|
|
||||||
|
|
||||||
grid_alias.ColorPerVertex = colorPerVertex;
|
|
||||||
grid_alias.NormalPerVertex = normalPerVertex;
|
|
||||||
grid_alias.CreaseAngle = creaseAngle;
|
|
||||||
grid_alias.Solid = solid;
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("ElevationGrid");
|
|
||||||
// check for X3DComposedGeometryNodes
|
|
||||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
|
||||||
// check for X3DMetadataObject
|
|
||||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("ElevationGrid");
|
|
||||||
|
|
||||||
MACRO_NODECHECK_LOOPEND("ElevationGrid");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!mReader->isEmptyElement())
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
}// if(!mReader->isEmptyElement()) else
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TVector>
|
|
||||||
static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed)
|
|
||||||
{
|
|
||||||
size_t cur_sz = pCurve.size();
|
|
||||||
|
|
||||||
pCurveIsClosed = false;
|
|
||||||
// for curve with less than four points checking is have no sense,
|
|
||||||
if(cur_sz < 4) return;
|
|
||||||
|
|
||||||
for(size_t s = 3, s_e = cur_sz; s < s_e; s++)
|
|
||||||
{
|
|
||||||
// search for first point of duplicated part.
|
|
||||||
if(pCurve[0] == pCurve[s])
|
|
||||||
{
|
|
||||||
bool found = true;
|
|
||||||
|
|
||||||
// check if tail(indexed by b2) is duplicate of head(indexed by b1).
|
|
||||||
for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
|
|
||||||
{
|
|
||||||
if(pCurve[b1] != pCurve[b2])
|
|
||||||
{// points not match: clear flag and break loop.
|
|
||||||
found = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
|
|
||||||
|
|
||||||
// if duplicate tail is found then drop or not it depending on flags.
|
|
||||||
if(found)
|
|
||||||
{
|
|
||||||
pCurveIsClosed = true;
|
|
||||||
if(pDropTail)
|
|
||||||
{
|
|
||||||
if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics.
|
|
||||||
|
|
||||||
pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}// if(found)
|
|
||||||
}// if(pCurve[0] == pCurve[s])
|
|
||||||
}// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
|
|
||||||
}
|
|
||||||
|
|
||||||
static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed)
|
|
||||||
{
|
|
||||||
const size_t spine_idx_last = pSpine.size() - 1;
|
|
||||||
aiVector3D tvec;
|
|
||||||
|
|
||||||
if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases
|
|
||||||
{
|
|
||||||
if(pSpine_Closed)
|
|
||||||
{// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
|
|
||||||
// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
|
|
||||||
// in tail are removed.
|
|
||||||
// So, last point in pSpine is a spine[n - 2]
|
|
||||||
tvec = pSpine[1] - pSpine[spine_idx_last];
|
|
||||||
}
|
|
||||||
else if(pSpine_PointIdx == 0)
|
|
||||||
{// The Y-axis used for the first point is the vector from spine[0] to spine[1]
|
|
||||||
tvec = pSpine[1] - pSpine[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
|
|
||||||
// the spine[0].
|
|
||||||
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
|
|
||||||
}
|
|
||||||
}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
|
|
||||||
else
|
|
||||||
{// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
|
|
||||||
tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
|
|
||||||
}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
|
|
||||||
|
|
||||||
return tvec.Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed,
|
|
||||||
const aiVector3D pVecZ_Prev)
|
|
||||||
{
|
|
||||||
const aiVector3D zero_vec(0);
|
|
||||||
const size_t spine_idx_last = pSpine.size() - 1;
|
|
||||||
|
|
||||||
aiVector3D tvec;
|
|
||||||
|
|
||||||
// at first special cases
|
|
||||||
if(pSpine.size() < 3)// spine have not enough points for vector calculations.
|
|
||||||
{
|
|
||||||
tvec.Set(0, 0, 1);
|
|
||||||
}
|
|
||||||
else if(pSpine_PointIdx == 0)// special case: first point
|
|
||||||
{
|
|
||||||
if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
|
|
||||||
{
|
|
||||||
tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
|
|
||||||
}
|
|
||||||
else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
|
|
||||||
// then the Z-axis for the first spine point with a defined Z-axis is used."
|
|
||||||
// Walk through spine and find Z.
|
|
||||||
for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
|
|
||||||
{
|
|
||||||
// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
|
|
||||||
tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
|
|
||||||
found = !tvec.Equal(zero_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if entire spine are collinear then use OZ axis.
|
|
||||||
if(!found) tvec.Set(0, 0, 1);
|
|
||||||
}// if(pSpine_Closed) else
|
|
||||||
}// else if(pSpine_PointIdx == 0)
|
|
||||||
else if(pSpine_PointIdx == spine_idx_last)// special case: last point
|
|
||||||
{
|
|
||||||
if(pSpine_Closed)
|
|
||||||
{// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
|
|
||||||
tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
|
||||||
// if taken spine vectors are collinear then use previous vector Z.
|
|
||||||
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{// vector Z for last point of not closed curve is previous vector Z.
|
|
||||||
tvec = pVecZ_Prev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else// regular point
|
|
||||||
{
|
|
||||||
tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
|
||||||
// if taken spine vectors are collinear then use previous vector Z.
|
|
||||||
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
// After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
|
|
||||||
// is flipped (multiplied by -1).
|
|
||||||
if((tvec * pVecZ_Prev) < 0) tvec = -tvec;
|
|
||||||
|
|
||||||
return tvec.Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Extrusion
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// beginCap="true" SFBool [initializeOnly]
|
|
||||||
// ccw="true" SFBool [initializeOnly]
|
|
||||||
// convex="true" SFBool [initializeOnly]
|
|
||||||
// creaseAngle="0.0" SFloat [initializeOnly]
|
|
||||||
// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f [initializeOnly]
|
|
||||||
// endCap="true" SFBool [initializeOnly]
|
|
||||||
// orientation="0 0 1 0" MFRotation [initializeOnly]
|
|
||||||
// scale="1 1" MFVec2f [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// spine="0 0 0 0 1 0" MFVec3f [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_Extrusion()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool beginCap = true;
|
|
||||||
bool ccw = true;
|
|
||||||
bool convex = true;
|
|
||||||
float creaseAngle = 0;
|
|
||||||
std::vector<aiVector2D> crossSection;
|
|
||||||
bool endCap = true;
|
|
||||||
std::vector<float> orientation;
|
|
||||||
std::vector<aiVector2D> scale;
|
|
||||||
bool solid = true;
|
|
||||||
std::vector<aiVector3D> spine;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("beginCap", beginCap, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("crossSection", crossSection, XML_ReadNode_GetAttrVal_AsArrVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("endCap", endCap, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("orientation", orientation, XML_ReadNode_GetAttrVal_AsArrF);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsArrVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("spine", spine, XML_ReadNode_GetAttrVal_AsArrVec3f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Extrusion, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// check if default values must be assigned
|
|
||||||
//
|
|
||||||
if(spine.size() == 0)
|
|
||||||
{
|
|
||||||
spine.resize(2);
|
|
||||||
spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
|
|
||||||
}
|
|
||||||
else if(spine.size() == 1)
|
|
||||||
{
|
|
||||||
throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(crossSection.size() == 0)
|
|
||||||
{
|
|
||||||
crossSection.resize(5);
|
|
||||||
crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
{// orientation
|
|
||||||
size_t ori_size = orientation.size() / 4;
|
|
||||||
|
|
||||||
if(ori_size < spine.size())
|
|
||||||
{
|
|
||||||
float add_ori[4];// values that will be added
|
|
||||||
|
|
||||||
if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
|
|
||||||
{
|
|
||||||
add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
|
|
||||||
}
|
|
||||||
else// else - use default values
|
|
||||||
{
|
|
||||||
add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
orientation.reserve(spine.size() * 4);
|
|
||||||
for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
|
|
||||||
orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
|
|
||||||
}// END: orientation
|
|
||||||
|
|
||||||
{// scale
|
|
||||||
if(scale.size() < spine.size())
|
|
||||||
{
|
|
||||||
aiVector2D add_sc;
|
|
||||||
|
|
||||||
if(scale.size() == 1)// if "scale" has one element then use it value for all spine points.
|
|
||||||
add_sc = scale[0];
|
|
||||||
else// else - use default values
|
|
||||||
add_sc.Set(1, 1);
|
|
||||||
|
|
||||||
scale.reserve(spine.size());
|
|
||||||
for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
|
|
||||||
}
|
|
||||||
}// END: scale
|
|
||||||
//
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
//
|
|
||||||
ne = new X3DIndexedSet(X3DNodeElementBase::ENET_Extrusion, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
X3DIndexedSet& ext_alias = *((X3DIndexedSet*)ne);// create alias for conveience
|
|
||||||
// assign part of input data
|
|
||||||
ext_alias.CCW = ccw;
|
|
||||||
ext_alias.Convex = convex;
|
|
||||||
ext_alias.CreaseAngle = creaseAngle;
|
|
||||||
ext_alias.Solid = solid;
|
|
||||||
|
|
||||||
//
|
|
||||||
// How we done it at all?
|
|
||||||
// 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
|
|
||||||
// are applied vor every basis.
|
|
||||||
// 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position
|
|
||||||
// using relative spine point.
|
|
||||||
// 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
|
|
||||||
// needed. While createing CootdIdx is taking in account CCW flag.
|
|
||||||
// 4. The last step: create Vertices list.
|
|
||||||
//
|
|
||||||
bool spine_closed;// flag: true if spine curve is closed.
|
|
||||||
bool cross_closed;// flag: true if cross curve is closed.
|
|
||||||
std::vector<aiMatrix3x3> basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
|
|
||||||
std::vector<std::vector<aiVector3D> > pointset_arr;// array of point sets: cross curves.
|
|
||||||
|
|
||||||
// detect closed curves
|
|
||||||
GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end.
|
|
||||||
GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end.
|
|
||||||
// If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
|
|
||||||
if(spine_closed)
|
|
||||||
{
|
|
||||||
beginCap |= endCap;
|
|
||||||
endCap = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
{// 1. Calculate array of basises.
|
|
||||||
aiMatrix4x4 rotmat;
|
|
||||||
aiVector3D vecX(0), vecY(0), vecZ(0);
|
|
||||||
|
|
||||||
basis_arr.resize(spine.size());
|
|
||||||
for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
|
|
||||||
{
|
|
||||||
aiVector3D tvec;
|
|
||||||
|
|
||||||
// get axises of basis.
|
|
||||||
vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
|
|
||||||
vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
|
|
||||||
vecX = (vecY ^ vecZ).Normalize();
|
|
||||||
// get rotation matrix and apply "orientation" to basis
|
|
||||||
aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
|
|
||||||
tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
|
|
||||||
tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
|
|
||||||
tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
|
|
||||||
}// for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
|
|
||||||
}// END: 1. Calculate array of basises
|
|
||||||
|
|
||||||
{// 2. Create array of point sets.
|
|
||||||
aiMatrix4x4 scmat;
|
|
||||||
std::vector<aiVector3D> tcross(crossSection.size());
|
|
||||||
|
|
||||||
pointset_arr.resize(spine.size());
|
|
||||||
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
|
|
||||||
{
|
|
||||||
aiVector3D tc23vec;
|
|
||||||
|
|
||||||
tc23vec.Set(scale[spi].x, 0, scale[spi].y);
|
|
||||||
aiMatrix4x4::Scaling(tc23vec, scmat);
|
|
||||||
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
|
|
||||||
{
|
|
||||||
aiVector3D tvecX, tvecY, tvecZ;
|
|
||||||
|
|
||||||
tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
|
|
||||||
// apply scaling to point
|
|
||||||
tcross[cri] = scmat * tc23vec;
|
|
||||||
//
|
|
||||||
// transfer point to new basis
|
|
||||||
// calculate coordinate in new basis
|
|
||||||
tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
|
|
||||||
tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
|
|
||||||
tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
|
|
||||||
// apply new coordinates and translate it to spine point.
|
|
||||||
tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
|
|
||||||
}// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
|
|
||||||
|
|
||||||
pointset_arr[spi] = tcross;// store transferred point set
|
|
||||||
}// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
|
|
||||||
}// END: 2. Create array of point sets.
|
|
||||||
|
|
||||||
{// 3. Create CoordIdx.
|
|
||||||
// add caps if needed
|
|
||||||
if(beginCap)
|
|
||||||
{
|
|
||||||
// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
|
|
||||||
for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
|
|
||||||
|
|
||||||
// add delimiter
|
|
||||||
ext_alias.CoordIndex.push_back(-1);
|
|
||||||
}// if(beginCap)
|
|
||||||
|
|
||||||
if(endCap)
|
|
||||||
{
|
|
||||||
// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
|
|
||||||
size_t beg = (pointset_arr.size() - 1) * crossSection.size();
|
|
||||||
|
|
||||||
for(size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
|
|
||||||
|
|
||||||
// add delimiter
|
|
||||||
ext_alias.CoordIndex.push_back(-1);
|
|
||||||
}// if(beginCap)
|
|
||||||
|
|
||||||
// add quads
|
|
||||||
for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++)
|
|
||||||
{
|
|
||||||
const size_t cr_sz = crossSection.size();
|
|
||||||
const size_t cr_last = crossSection.size() - 1;
|
|
||||||
|
|
||||||
size_t right_col;// hold index basis for points of quad placed in right column;
|
|
||||||
|
|
||||||
if(spi != spi_e)
|
|
||||||
right_col = spi + 1;
|
|
||||||
else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve.
|
|
||||||
right_col = 0;
|
|
||||||
else
|
|
||||||
break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
|
|
||||||
|
|
||||||
for(size_t cri = 0; cri < cr_sz; cri++)
|
|
||||||
{
|
|
||||||
if(cri != cr_last)
|
|
||||||
{
|
|
||||||
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
|
|
||||||
static_cast<int32_t>(spi * cr_sz + cri),
|
|
||||||
static_cast<int32_t>(right_col * cr_sz + cri),
|
|
||||||
static_cast<int32_t>(right_col * cr_sz + cri + 1),
|
|
||||||
static_cast<int32_t>(spi * cr_sz + cri + 1));
|
|
||||||
// add delimiter
|
|
||||||
ext_alias.CoordIndex.push_back(-1);
|
|
||||||
}
|
|
||||||
else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve.
|
|
||||||
{
|
|
||||||
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
|
|
||||||
static_cast<int32_t>(spi * cr_sz + cri),
|
|
||||||
static_cast<int32_t>(right_col * cr_sz + cri),
|
|
||||||
static_cast<int32_t>(right_col * cr_sz + 0),
|
|
||||||
static_cast<int32_t>(spi * cr_sz + 0));
|
|
||||||
// add delimiter
|
|
||||||
ext_alias.CoordIndex.push_back(-1);
|
|
||||||
}
|
|
||||||
}// for(size_t cri = 0; cri < cr_sz; cri++)
|
|
||||||
}// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
|
|
||||||
}// END: 3. Create CoordIdx.
|
|
||||||
|
|
||||||
{// 4. Create vertices list.
|
|
||||||
// just copy all vertices
|
|
||||||
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
|
|
||||||
{
|
|
||||||
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
|
|
||||||
{
|
|
||||||
ext_alias.Vertices.push_back(pointset_arr[spi][cri]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// END: 4. Create vertices list.
|
|
||||||
//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
|
|
||||||
//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Extrusion");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <IndexedFaceSet
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ccw="true" SFBool [initializeOnly]
|
|
||||||
// colorIndex="" MFInt32 [initializeOnly]
|
|
||||||
// colorPerVertex="true" SFBool [initializeOnly]
|
|
||||||
// convex="true" SFBool [initializeOnly]
|
|
||||||
// coordIndex="" MFInt32 [initializeOnly]
|
|
||||||
// creaseAngle="0" SFFloat [initializeOnly]
|
|
||||||
// normalIndex="" MFInt32 [initializeOnly]
|
|
||||||
// normalPerVertex="true" SFBool [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// texCoordIndex="" MFInt32 [initializeOnly]
|
|
||||||
// >
|
|
||||||
// <!-- ComposedGeometryContentModel -->
|
|
||||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
|
||||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
|
||||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </IndexedFaceSet>
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool ccw = true;
|
|
||||||
std::vector<int32_t> colorIndex;
|
|
||||||
bool colorPerVertex = true;
|
|
||||||
bool convex = true;
|
|
||||||
std::vector<int32_t> coordIndex;
|
|
||||||
float creaseAngle = 0;
|
|
||||||
std::vector<int32_t> normalIndex;
|
|
||||||
bool normalPerVertex = true;
|
|
||||||
bool solid = true;
|
|
||||||
std::vector<int32_t> texCoordIndex;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsArrI32);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedFaceSet, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// check data
|
|
||||||
if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedFaceSet, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
|
|
||||||
|
|
||||||
ne_alias.CCW = ccw;
|
|
||||||
ne_alias.ColorIndex = colorIndex;
|
|
||||||
ne_alias.ColorPerVertex = colorPerVertex;
|
|
||||||
ne_alias.Convex = convex;
|
|
||||||
ne_alias.CoordIndex = coordIndex;
|
|
||||||
ne_alias.CreaseAngle = creaseAngle;
|
|
||||||
ne_alias.NormalIndex = normalIndex;
|
|
||||||
ne_alias.NormalPerVertex = normalPerVertex;
|
|
||||||
ne_alias.Solid = solid;
|
|
||||||
ne_alias.TexCoordIndex = texCoordIndex;
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("IndexedFaceSet");
|
|
||||||
// check for X3DComposedGeometryNodes
|
|
||||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
|
||||||
// check for X3DMetadataObject
|
|
||||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedFaceSet");
|
|
||||||
|
|
||||||
MACRO_NODECHECK_LOOPEND("IndexedFaceSet");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!mReader->isEmptyElement())
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Sphere
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// radius="1" SFloat [initializeOnly]
|
|
||||||
// solid="true" SFBool [initializeOnly]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Geometry3D_Sphere()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
ai_real radius = 1;
|
|
||||||
bool solid = true;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Sphere, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property
|
|
||||||
|
|
||||||
std::vector<aiVector3D> tlist;
|
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Sphere, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
StandardShapes::MakeSphere(tess, tlist);
|
|
||||||
// copy data from temp array and apply scale
|
|
||||||
for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it)
|
|
||||||
{
|
|
||||||
((X3DGeometry3D*)ne)->Vertices.push_back(*it * radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
((X3DGeometry3D*)ne)->Solid = solid;
|
|
||||||
((X3DGeometry3D*)ne)->NumIndices = 3;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Sphere");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,393 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Group.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Grouping" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
#include <assimp/ParsingUtils.h>
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
// <Group
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// >
|
|
||||||
// <!-- ChildContentModel -->
|
|
||||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
|
||||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
|
||||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </Group>
|
|
||||||
// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
|
|
||||||
void X3DImporter::ParseNode_Grouping_Group(XmlNode &node) {
|
|
||||||
//std::string def, use;
|
|
||||||
|
|
||||||
std::string def = node.attribute("DEF").as_string();
|
|
||||||
std::string use = node.attribute("USE").as_string();
|
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
X3DNodeElementBase *ne = nullptr;
|
|
||||||
if (def.empty()) {
|
|
||||||
Throw_DEF_And_USE(node.name());
|
|
||||||
}
|
|
||||||
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
|
||||||
Throw_USE_NotFound(node.name(), use);
|
|
||||||
}
|
|
||||||
mNodeElementCur->Child.push_back(ne);
|
|
||||||
//MACRO_USE_CHECKANDAPPLY(def, use, X3DNodeElementBase::ENET_Group, ne);
|
|
||||||
} else {
|
|
||||||
ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
|
|
||||||
|
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if (!def.empty()) {
|
|
||||||
mNodeElementCur->ID = def;
|
|
||||||
}
|
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
|
||||||
//if(mReader->isEmptyElement())
|
|
||||||
if (node.empty()) {
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Grouping_GroupEnd()
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Exit();// go up in scene graph
|
|
||||||
}
|
|
||||||
|
|
||||||
// <StaticGroup
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// >
|
|
||||||
// <!-- ChildContentModel -->
|
|
||||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
|
||||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
|
||||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </StaticGroup>
|
|
||||||
// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
|
|
||||||
// contain any USE references outside the StaticGroup.
|
|
||||||
void X3DImporter::ParseNode_Grouping_StaticGroup(XmlNode &node) {
|
|
||||||
// std::string def, use;
|
|
||||||
std::string def = node.attribute("DEF").as_string();
|
|
||||||
std::string use = node.attribute("USE").as_string();
|
|
||||||
|
|
||||||
/* MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
X3DNodeElementBase* ne = nullptr;
|
|
||||||
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
|
||||||
Throw_USE_NotFound(node.name(), use);
|
|
||||||
}
|
|
||||||
mNodeElementCur->Child.push_back(ne);
|
|
||||||
|
|
||||||
// MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
|
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if(!def.empty()) mNodeElementCur->ID = def;
|
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
|
||||||
if (node.empty()) {
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Exit();// go up in scene graph
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Switch
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// whichChoice="-1" SFInt32 [inputOutput]
|
|
||||||
// >
|
|
||||||
// <!-- ChildContentModel -->
|
|
||||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
|
||||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
|
||||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </Switch>
|
|
||||||
// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
|
|
||||||
// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
|
|
||||||
// is chosen.
|
|
||||||
void X3DImporter::ParseNode_Grouping_Switch(XmlNode &node) {
|
|
||||||
// std::string def, use;
|
|
||||||
int32_t whichChoice = -1;
|
|
||||||
std::string def = node.attribute("DEF").as_string();
|
|
||||||
std::string use = node.attribute("USE").as_string();
|
|
||||||
pugi::xml_attribute attr = node.attribute("whichChoise");
|
|
||||||
whichChoice = attr.as_int();
|
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
X3DNodeElementBase* ne = nullptr;
|
|
||||||
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
|
||||||
Throw_USE_NotFound(node.name(), use);
|
|
||||||
}
|
|
||||||
mNodeElementCur->Child.push_back(ne);
|
|
||||||
|
|
||||||
|
|
||||||
// MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
|
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if(!def.empty()) mNodeElementCur->ID = def;
|
|
||||||
|
|
||||||
// also set values specific to this type of group
|
|
||||||
((X3DGroup*)mNodeElementCur)->UseChoice = true;
|
|
||||||
((X3DGroup*)mNodeElementCur)->Choice = whichChoice;
|
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
|
||||||
// if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
|
||||||
if (node.empty()) {
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Grouping_SwitchEnd()
|
|
||||||
{
|
|
||||||
// just exit from node. Defined choice will be accepted at post-processing stage.
|
|
||||||
ParseHelper_Node_Exit();// go up in scene graph
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadAttrAsVec3f(pugi::xml_node &node, const std::string &attrName, aiVector3D &vec) {
|
|
||||||
const pugi::xml_attribute &attr = node.attribute(attrName.c_str());
|
|
||||||
if (attr.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string data = attr.as_string();
|
|
||||||
std::vector<std::string> token;
|
|
||||||
tokenize<std::string>(data, token, " ");
|
|
||||||
vec.x = (ai_real)std::atof(token[0].c_str());
|
|
||||||
vec.y = (ai_real)std::atof(token[1].c_str());
|
|
||||||
vec.z = (ai_real)std::atof(token[2].c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ReadAttrAsFloatArray(pugi::xml_node &node, const std::string &attrName, size_t numComponents, std::vector<float> &tvec) {
|
|
||||||
pugi::xml_attribute attr = node.attribute(attrName.c_str());
|
|
||||||
std::string data = attr.as_string();
|
|
||||||
std::vector<std::string> token;
|
|
||||||
tokenize<std::string>(data, token, " ");
|
|
||||||
if (token.size() != numComponents) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
|
||||||
for (size_t i = 0; i < numComponents; ++i) {
|
|
||||||
tvec.push_back((ai_real)std::atof(token[i].c_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Transform
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// center="0 0 0" SFVec3f [inputOutput]
|
|
||||||
// rotation="0 0 1 0" SFRotation [inputOutput]
|
|
||||||
// scale="1 1 1" SFVec3f [inputOutput]
|
|
||||||
// scaleOrientation="0 0 1 0" SFRotation [inputOutput]
|
|
||||||
// translation="0 0 0" SFVec3f [inputOutput]
|
|
||||||
// >
|
|
||||||
// <!-- ChildContentModel -->
|
|
||||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
|
||||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
|
||||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
|
||||||
// </Transform>
|
|
||||||
// The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
|
|
||||||
// Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
|
|
||||||
// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
|
|
||||||
// equivalent transformation matrices,
|
|
||||||
// P' = T * C * R * SR * S * -SR * -C * P
|
|
||||||
void X3DImporter::ParseNode_Grouping_Transform(XmlNode &node) {
|
|
||||||
aiVector3D center(0, 0, 0);
|
|
||||||
float rotation[4] = { 0, 0, 1, 0 };
|
|
||||||
aiVector3D scale(1, 1, 1); // A value of zero indicates that any child geometry shall not be displayed
|
|
||||||
float scale_orientation[4] = { 0, 0, 1, 0 };
|
|
||||||
aiVector3D translation(0, 0, 0);
|
|
||||||
aiMatrix4x4 matr, tmatr;
|
|
||||||
//std::string use, def;
|
|
||||||
|
|
||||||
//MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
std::string def = node.attribute("DEF").as_string();
|
|
||||||
std::string use = node.attribute("USE").as_string();
|
|
||||||
|
|
||||||
//MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
ReadAttrAsVec3f(node, "center", center);
|
|
||||||
ReadAttrAsVec3f(node, "scale", scale);
|
|
||||||
ReadAttrAsVec3f(node, "translation", translation);
|
|
||||||
/*MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);*/
|
|
||||||
if (hasAttribute(node, "rotation")) {
|
|
||||||
std::vector<float> tvec;
|
|
||||||
ReadAttrAsFloatArray(node, "rotation", 4, tvec);
|
|
||||||
memcpy(rotation, tvec.data(), sizeof(rotation));
|
|
||||||
}
|
|
||||||
if (hasAttribute(node, "scaleOrientation")) {
|
|
||||||
std::vector<float> tvec;
|
|
||||||
ReadAttrAsFloatArray(node, "rotation", 4, tvec);
|
|
||||||
::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
|
|
||||||
}
|
|
||||||
/*if(an == "rotation")
|
|
||||||
{
|
|
||||||
std::vector<float> tvec;
|
|
||||||
|
|
||||||
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
|
||||||
if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
|
||||||
|
|
||||||
memcpy(rotation, tvec.data(), sizeof(rotation));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(an == "scaleOrientation"){
|
|
||||||
|
|
||||||
std::vector<float> tvec;
|
|
||||||
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
|
||||||
if ( tvec.size() != 4 )
|
|
||||||
{
|
|
||||||
throw DeadlyImportError( "<Transform>: scaleOrientation vector must have 4 elements." );
|
|
||||||
}
|
|
||||||
|
|
||||||
::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation) );
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty()) {
|
|
||||||
X3DNodeElementBase* ne = nullptr;
|
|
||||||
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
|
||||||
Throw_USE_NotFound(node.name(), use);
|
|
||||||
}
|
|
||||||
mNodeElementCur->Child.push_back(ne);
|
|
||||||
|
|
||||||
//MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
|
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if ( !def.empty() )
|
|
||||||
{
|
|
||||||
mNodeElementCur->ID = def;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// also set values specific to this type of group
|
|
||||||
//
|
|
||||||
// calculate transformation matrix
|
|
||||||
aiMatrix4x4::Translation(translation, matr);// T
|
|
||||||
aiMatrix4x4::Translation(center, tmatr);// C
|
|
||||||
matr *= tmatr;
|
|
||||||
aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr);// R
|
|
||||||
matr *= tmatr;
|
|
||||||
aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// SR
|
|
||||||
matr *= tmatr;
|
|
||||||
aiMatrix4x4::Scaling(scale, tmatr);// S
|
|
||||||
matr *= tmatr;
|
|
||||||
aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// -SR
|
|
||||||
matr *= tmatr;
|
|
||||||
aiMatrix4x4::Translation(-center, tmatr);// -C
|
|
||||||
matr *= tmatr;
|
|
||||||
// and assign it
|
|
||||||
((X3DGroup*)mNodeElementCur)->Transformation = matr;
|
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
|
||||||
if ( node.empty() ) {
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Grouping_TransformEnd()
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Exit();// go up in scene graph
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,290 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Light.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Lighting" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
#include <assimp/StringUtils.h>
|
|
||||||
|
|
||||||
namespace Assimp {
|
|
||||||
|
|
||||||
// <DirectionalLight
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ambientIntensity="0" SFFloat [inputOutput]
|
|
||||||
// color="1 1 1" SFColor [inputOutput]
|
|
||||||
// direction="0 0 -1" SFVec3f [inputOutput]
|
|
||||||
// global="false" SFBool [inputOutput]
|
|
||||||
// intensity="1" SFFloat [inputOutput]
|
|
||||||
// on="true" SFBool [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Lighting_DirectionalLight()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
float ambientIntensity = 0;
|
|
||||||
aiColor3D color(1, 1, 1);
|
|
||||||
aiVector3D direction(0, 0, -1);
|
|
||||||
bool global = false;
|
|
||||||
float intensity = 1;
|
|
||||||
bool on = true;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_DirectionalLight, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(on)
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DLight(X3DNodeElementBase::ENET_DirectionalLight, mNodeElementCur);
|
|
||||||
if(!def.empty())
|
|
||||||
ne->ID = def;
|
|
||||||
else
|
|
||||||
ne->ID = "DirectionalLight_" + to_string((size_t)ne);// make random name
|
|
||||||
|
|
||||||
((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
|
|
||||||
((X3DLight*)ne)->Color = color;
|
|
||||||
((X3DLight*)ne)->Direction = direction;
|
|
||||||
((X3DLight*)ne)->Global = global;
|
|
||||||
((X3DLight*)ne)->Intensity = intensity;
|
|
||||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
|
||||||
ParseHelper_Group_Begin(false);
|
|
||||||
|
|
||||||
mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "DirectionalLight");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(on)
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <PointLight
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ambientIntensity="0" SFFloat [inputOutput]
|
|
||||||
// attenuation="1 0 0" SFVec3f [inputOutput]
|
|
||||||
// color="1 1 1" SFColor [inputOutput]
|
|
||||||
// global="true" SFBool [inputOutput]
|
|
||||||
// intensity="1" SFFloat [inputOutput]
|
|
||||||
// location="0 0 0" SFVec3f [inputOutput]
|
|
||||||
// on="true" SFBool [inputOutput]
|
|
||||||
// radius="100" SFFloat [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Lighting_PointLight()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
float ambientIntensity = 0;
|
|
||||||
aiVector3D attenuation( 1, 0, 0 );
|
|
||||||
aiColor3D color( 1, 1, 1 );
|
|
||||||
bool global = true;
|
|
||||||
float intensity = 1;
|
|
||||||
aiVector3D location( 0, 0, 0 );
|
|
||||||
bool on = true;
|
|
||||||
float radius = 100;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointLight, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(on)
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DLight(X3DNodeElementBase::ENET_PointLight, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
|
|
||||||
((X3DLight*)ne)->Attenuation = attenuation;
|
|
||||||
((X3DLight*)ne)->Color = color;
|
|
||||||
((X3DLight*)ne)->Global = global;
|
|
||||||
((X3DLight*)ne)->Intensity = intensity;
|
|
||||||
((X3DLight*)ne)->Location = location;
|
|
||||||
((X3DLight*)ne)->Radius = radius;
|
|
||||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
|
||||||
ParseHelper_Group_Begin(false);
|
|
||||||
// make random name
|
|
||||||
if(ne->ID.empty()) ne->ID = "PointLight_" + to_string((size_t)ne);
|
|
||||||
|
|
||||||
mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "PointLight");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(on)
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <SpotLight
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ambientIntensity="0" SFFloat [inputOutput]
|
|
||||||
// attenuation="1 0 0" SFVec3f [inputOutput]
|
|
||||||
// beamWidth="0.7854" SFFloat [inputOutput]
|
|
||||||
// color="1 1 1" SFColor [inputOutput]
|
|
||||||
// cutOffAngle="1.570796" SFFloat [inputOutput]
|
|
||||||
// direction="0 0 -1" SFVec3f [inputOutput]
|
|
||||||
// global="true" SFBool [inputOutput]
|
|
||||||
// intensity="1" SFFloat [inputOutput]
|
|
||||||
// location="0 0 0" SFVec3f [inputOutput]
|
|
||||||
// on="true" SFBool [inputOutput]
|
|
||||||
// radius="100" SFFloat [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Lighting_SpotLight()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
float ambientIntensity = 0;
|
|
||||||
aiVector3D attenuation( 1, 0, 0 );
|
|
||||||
float beamWidth = 0.7854f;
|
|
||||||
aiColor3D color( 1, 1, 1 );
|
|
||||||
float cutOffAngle = 1.570796f;
|
|
||||||
aiVector3D direction( 0, 0, -1 );
|
|
||||||
bool global = true;
|
|
||||||
float intensity = 1;
|
|
||||||
aiVector3D location( 0, 0, 0 );
|
|
||||||
bool on = true;
|
|
||||||
float radius = 100;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("beamWidth", beamWidth, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("cutOffAngle", cutOffAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_SpotLight, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(on)
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DLight(X3DNodeElementBase::ENET_SpotLight, mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
if(beamWidth > cutOffAngle) beamWidth = cutOffAngle;
|
|
||||||
|
|
||||||
((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
|
|
||||||
((X3DLight*)ne)->Attenuation = attenuation;
|
|
||||||
((X3DLight*)ne)->BeamWidth = beamWidth;
|
|
||||||
((X3DLight*)ne)->Color = color;
|
|
||||||
((X3DLight*)ne)->CutOffAngle = cutOffAngle;
|
|
||||||
((X3DLight*)ne)->Direction = direction;
|
|
||||||
((X3DLight*)ne)->Global = global;
|
|
||||||
((X3DLight*)ne)->Intensity = intensity;
|
|
||||||
((X3DLight*)ne)->Location = location;
|
|
||||||
((X3DLight*)ne)->Radius = radius;
|
|
||||||
|
|
||||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
|
||||||
ParseHelper_Group_Begin(false);
|
|
||||||
// make random name
|
|
||||||
if(ne->ID.empty()) ne->ID = "SpotLight_" + to_string((size_t)ne);
|
|
||||||
|
|
||||||
mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "SpotLight");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(on)
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,195 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Macro.hpp
|
|
||||||
/// \brief Useful macrodefines.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
|
|
||||||
#define X3DIMPORTER_MACRO_HPP_INCLUDED
|
|
||||||
|
|
||||||
/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE)
|
|
||||||
/// Used for regular checking while attribute "USE" is defined.
|
|
||||||
/// \param [in] pDEF - string holding "DEF" value.
|
|
||||||
/// \param [in] pUSE - string holding "USE" value.
|
|
||||||
/// \param [in] pType - type of element to find.
|
|
||||||
/// \param [out] pNE - pointer to found node element.
|
|
||||||
#define MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pType, pNE) \
|
|
||||||
do { \
|
|
||||||
XML_CheckNode_MustBeEmpty(); \
|
|
||||||
if(!pDEF.empty()) Throw_DEF_And_USE(); \
|
|
||||||
if(!FindNodeElement(pUSE, CX3DImporter_NodeElement::pType, &pNE)) Throw_USE_NotFound(pUSE); \
|
|
||||||
\
|
|
||||||
NodeElement_Cur->Child.push_back(pNE);/* add found object as child to current element */ \
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
/// \def MACRO_ATTRREAD_LOOPBEG
|
|
||||||
/// Begin of loop that read attributes values.
|
|
||||||
#define MACRO_ATTRREAD_LOOPBEG \
|
|
||||||
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
|
|
||||||
{ \
|
|
||||||
std::string an(mReader->getAttributeName(idx));
|
|
||||||
|
|
||||||
/// \def MACRO_ATTRREAD_LOOPEND
|
|
||||||
/// End of loop that read attributes values.
|
|
||||||
#define MACRO_ATTRREAD_LOOPEND \
|
|
||||||
Throw_IncorrectAttr(an); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \def MACRO_ATTRREAD_CHECK_REF
|
|
||||||
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
|
|
||||||
/// "continue" will called.
|
|
||||||
/// \param [in] pAttrName - attribute name.
|
|
||||||
/// \param [out] pVarName - output variable name.
|
|
||||||
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
|
|
||||||
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
|
|
||||||
if(an == pAttrName) \
|
|
||||||
{ \
|
|
||||||
pFunction(idx, pVarName); \
|
|
||||||
continue; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \def MACRO_ATTRREAD_CHECK_RET
|
|
||||||
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
|
|
||||||
/// If result was read then "continue" will called.
|
|
||||||
/// \param [in] pAttrName - attribute name.
|
|
||||||
/// \param [out] pVarName - output variable name.
|
|
||||||
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
|
|
||||||
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
|
|
||||||
if(an == pAttrName) \
|
|
||||||
{ \
|
|
||||||
pVarName = pFunction(idx); \
|
|
||||||
continue; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
|
|
||||||
/// Compact variant for checking "USE" and "DEF". Also skip bbox attributes: "bboxCenter", "bboxSize".
|
|
||||||
/// If result was read then "continue" will called.
|
|
||||||
/// \param [out] pDEF_Var - output variable name for "DEF" value.
|
|
||||||
/// \param [out] pUSE_Var - output variable name for "USE" value.
|
|
||||||
#define MACRO_ATTRREAD_CHECKUSEDEF_RET(pDEF_Var, pUSE_Var) \
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("DEF", pDEF_Var, mReader->getAttributeValue); \
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("USE", pUSE_Var, mReader->getAttributeValue); \
|
|
||||||
if(an == "bboxCenter") continue; \
|
|
||||||
if(an == "bboxSize") continue; \
|
|
||||||
if(an == "containerField") continue; \
|
|
||||||
do {} while(false)
|
|
||||||
|
|
||||||
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
|
|
||||||
/// Begin of loop of parsing child nodes. Do not add ';' at end.
|
|
||||||
/// \param [in] pNodeName - current node name.
|
|
||||||
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
|
|
||||||
do { \
|
|
||||||
bool close_found = false; \
|
|
||||||
\
|
|
||||||
while(mReader->read()) \
|
|
||||||
{ \
|
|
||||||
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
|
|
||||||
{
|
|
||||||
|
|
||||||
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
|
|
||||||
/// End of loop of parsing child nodes.
|
|
||||||
/// \param [in] pNodeName - current node name.
|
|
||||||
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
|
|
||||||
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
|
|
||||||
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
|
|
||||||
{ \
|
|
||||||
if(XML_CheckNode_NameEqual(pNodeName)) \
|
|
||||||
{ \
|
|
||||||
close_found = true; \
|
|
||||||
\
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
|
|
||||||
}/* while(mReader->read()) */ \
|
|
||||||
\
|
|
||||||
if(!close_found) Throw_CloseNotFound(pNodeName); \
|
|
||||||
\
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
#define MACRO_NODECHECK_METADATA(pNodeName) \
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
|
|
||||||
/* and childs must be metadata nodes */ \
|
|
||||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported(pNodeName); \
|
|
||||||
MACRO_NODECHECK_LOOPEND(pNodeName)
|
|
||||||
|
|
||||||
/// \def MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4)
|
|
||||||
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
|
||||||
#define MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4) \
|
|
||||||
do { \
|
|
||||||
if(pCCW) \
|
|
||||||
{ \
|
|
||||||
pOut.push_back(pIn[pP1]); \
|
|
||||||
pOut.push_back(pIn[pP2]); \
|
|
||||||
pOut.push_back(pIn[pP3]); \
|
|
||||||
pOut.push_back(pIn[pP4]); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
pOut.push_back(pIn[pP4]); \
|
|
||||||
pOut.push_back(pIn[pP3]); \
|
|
||||||
pOut.push_back(pIn[pP2]); \
|
|
||||||
pOut.push_back(pIn[pP1]); \
|
|
||||||
} \
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
/// \def MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4)
|
|
||||||
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
|
||||||
#define MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4) \
|
|
||||||
do { \
|
|
||||||
if(pCCW) \
|
|
||||||
{ \
|
|
||||||
pOut.push_back(pP1); \
|
|
||||||
pOut.push_back(pP2); \
|
|
||||||
pOut.push_back(pP3); \
|
|
||||||
pOut.push_back(pP4); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
pOut.push_back(pP4); \
|
|
||||||
pOut.push_back(pP3); \
|
|
||||||
pOut.push_back(pP2); \
|
|
||||||
pOut.push_back(pP1); \
|
|
||||||
} \
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
#endif // X3DIMPORTER_MACRO_HPP_INCLUDED
|
|
|
@ -1,277 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Metadata.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Metadata" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
|
|
||||||
/// Find element by "USE" or create new one.
|
|
||||||
/// \param [in] pDEF_Var - variable name with "DEF" value.
|
|
||||||
/// \param [in] pUSE_Var - variable name with "USE" value.
|
|
||||||
/// \param [in] pReference - variable name with "reference" value.
|
|
||||||
/// \param [in] pValue - variable name with "value" value.
|
|
||||||
/// \param [in, out] pNE - pointer to node element.
|
|
||||||
/// \param [in] pMetaClass - Class of node.
|
|
||||||
/// \param [in] pMetaName - Name of node.
|
|
||||||
/// \param [in] pType - type of element to find.
|
|
||||||
#define MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \
|
|
||||||
/* if "USE" defined then find already defined element. */ \
|
|
||||||
if(!pUSE_Var.empty()) \
|
|
||||||
{ \
|
|
||||||
MACRO_USE_CHECKANDAPPLY(pDEF_Var, pUSE_Var, pType, pNE); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
pNE = new pMetaClass(NodeElement_Cur); \
|
|
||||||
if(!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
|
|
||||||
\
|
|
||||||
((pMetaClass*)pNE)->Reference = pReference; \
|
|
||||||
((pMetaClass*)pNE)->Value = pValue; \
|
|
||||||
/* also metadata node can contain childs */ \
|
|
||||||
if(!mReader->isEmptyElement()) \
|
|
||||||
ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \
|
|
||||||
else \
|
|
||||||
NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manually */ \
|
|
||||||
\
|
|
||||||
NodeElement_List.push_back(pNE);/* add new element to elements list. */ \
|
|
||||||
}/* if(!pUSE_Var.empty()) else */ \
|
|
||||||
\
|
|
||||||
do {} while(false)
|
|
||||||
|
|
||||||
bool X3DImporter::ParseHelper_CheckRead_X3DMetadataObject()
|
|
||||||
{
|
|
||||||
if(XML_CheckNode_NameEqual("MetadataBoolean"))
|
|
||||||
ParseNode_MetadataBoolean();
|
|
||||||
else if(XML_CheckNode_NameEqual("MetadataDouble"))
|
|
||||||
ParseNode_MetadataDouble();
|
|
||||||
else if(XML_CheckNode_NameEqual("MetadataFloat"))
|
|
||||||
ParseNode_MetadataFloat();
|
|
||||||
else if(XML_CheckNode_NameEqual("MetadataInteger"))
|
|
||||||
ParseNode_MetadataInteger();
|
|
||||||
else if(XML_CheckNode_NameEqual("MetadataSet"))
|
|
||||||
ParseNode_MetadataSet();
|
|
||||||
else if(XML_CheckNode_NameEqual("MetadataString"))
|
|
||||||
ParseNode_MetadataString();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Metadata(X3DNodeElementBase* pParentElement, const std::string& /*pNodeName*/)
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Enter(pParentElement);
|
|
||||||
MACRO_NODECHECK_METADATA(mReader->getNodeName());
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataBoolean
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// value="" MFBool [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataBoolean()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
std::vector<bool> value;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrB);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataDouble
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// value="" MFDouble [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataDouble()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
std::vector<double> value;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrD);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaDouble, "MetadataDouble", ENET_MetaDouble);
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataFloat
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// value="" MFFloat [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataFloat()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
std::vector<float> value;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrF);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaFloat, "MetadataFloat", ENET_MetaFloat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataInteger
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// value="" MFInteger [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataInteger()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
std::vector<int32_t> value;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrI32);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaInteger, "MetadataInteger", ENET_MetaInteger);
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataSet
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataSet()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_MetaSet, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ne = new X3DMetaSet(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DMetaSet*)ne)->Reference = reference;
|
|
||||||
// also metadata node can contain childs
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "MetadataSet");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add new element to elements list.
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <MetadataString
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// name="" SFString [inputOutput]
|
|
||||||
// reference="" SFString [inputOutput]
|
|
||||||
// value="" MFString [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_MetadataString()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
std::string name, reference;
|
|
||||||
std::list<std::string> value;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListS);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaString, "MetadataString", ENET_MetaString);
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Networking.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Networking" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
// Header files, Assimp.
|
|
||||||
#include <assimp/DefaultIOSystem.h>
|
|
||||||
|
|
||||||
//#include <regex>
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
|
|
||||||
static std::string parentDir("/../");
|
|
||||||
|
|
||||||
// <Inline
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// load="true" SFBool [inputOutput]
|
|
||||||
// url="" MFString [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Networking_Inline()
|
|
||||||
{
|
|
||||||
std::string def, use;
|
|
||||||
bool load = true;
|
|
||||||
std::list<std::string> url;
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("load", load, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
X3DNodeElementBase* ne;
|
|
||||||
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
|
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if(!def.empty()) mNodeElementCur->ID = def;
|
|
||||||
|
|
||||||
if(load && !url.empty())
|
|
||||||
{
|
|
||||||
std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
|
|
||||||
|
|
||||||
//full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
|
|
||||||
for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
|
|
||||||
if (pos > 0) {
|
|
||||||
std::string::size_type pos2 = full_path.rfind('/', pos - 1);
|
|
||||||
if (pos2 != std::string::npos) {
|
|
||||||
full_path.erase(pos2, pos - pos2 + 3);
|
|
||||||
pos = pos2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
full_path.erase(0, pos + 4);
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
|
||||||
std::string::size_type slashPos = full_path.find_last_of("\\/");
|
|
||||||
mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
|
|
||||||
ParseFile(full_path, mpIOHandler);
|
|
||||||
mpIOHandler->PopDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement()) ParseNode_Metadata(mNodeElementCur, "Inline");
|
|
||||||
|
|
||||||
// exit from node in that place
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,507 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Node.hpp
|
|
||||||
/// \brief Elements of scene graph.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
|
|
||||||
#define INCLUDED_AI_X3D_IMPORTER_NODE_H
|
|
||||||
|
|
||||||
// Header files, Assimp.
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <assimp/types.h>
|
|
||||||
|
|
||||||
// Header files, stdlib.
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/// Base class for elements of nodes.
|
|
||||||
class X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
/// Define what data type contain node element.
|
|
||||||
enum EType {
|
|
||||||
ENET_Group, ///< Element has type "Group".
|
|
||||||
ENET_MetaBoolean, ///< Element has type "Metadata boolean".
|
|
||||||
ENET_MetaDouble, ///< Element has type "Metadata double".
|
|
||||||
ENET_MetaFloat, ///< Element has type "Metadata float".
|
|
||||||
ENET_MetaInteger, ///< Element has type "Metadata integer".
|
|
||||||
ENET_MetaSet, ///< Element has type "Metadata set".
|
|
||||||
ENET_MetaString, ///< Element has type "Metadata string".
|
|
||||||
ENET_Arc2D, ///< Element has type "Arc2D".
|
|
||||||
ENET_ArcClose2D, ///< Element has type "ArcClose2D".
|
|
||||||
ENET_Circle2D, ///< Element has type "Circle2D".
|
|
||||||
ENET_Disk2D, ///< Element has type "Disk2D".
|
|
||||||
ENET_Polyline2D, ///< Element has type "Polyline2D".
|
|
||||||
ENET_Polypoint2D, ///< Element has type "Polypoint2D".
|
|
||||||
ENET_Rectangle2D, ///< Element has type "Rectangle2D".
|
|
||||||
ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
|
|
||||||
ENET_Box, ///< Element has type "Box".
|
|
||||||
ENET_Cone, ///< Element has type "Cone".
|
|
||||||
ENET_Cylinder, ///< Element has type "Cylinder".
|
|
||||||
ENET_Sphere, ///< Element has type "Sphere".
|
|
||||||
ENET_ElevationGrid, ///< Element has type "ElevationGrid".
|
|
||||||
ENET_Extrusion, ///< Element has type "Extrusion".
|
|
||||||
ENET_Coordinate, ///< Element has type "Coordinate".
|
|
||||||
ENET_Normal, ///< Element has type "Normal".
|
|
||||||
ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
|
|
||||||
ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
|
|
||||||
ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
|
|
||||||
ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
|
|
||||||
ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
|
|
||||||
ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
|
|
||||||
ENET_LineSet, ///< Element has type "LineSet".
|
|
||||||
ENET_PointSet, ///< Element has type "PointSet".
|
|
||||||
ENET_TriangleSet, ///< Element has type "TriangleSet".
|
|
||||||
ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
|
|
||||||
ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
|
|
||||||
ENET_Color, ///< Element has type "Color".
|
|
||||||
ENET_ColorRGBA, ///< Element has type "ColorRGBA".
|
|
||||||
ENET_Shape, ///< Element has type "Shape".
|
|
||||||
ENET_Appearance, ///< Element has type "Appearance".
|
|
||||||
ENET_Material, ///< Element has type "Material".
|
|
||||||
ENET_ImageTexture, ///< Element has type "ImageTexture".
|
|
||||||
ENET_TextureTransform, ///< Element has type "TextureTransform".
|
|
||||||
ENET_DirectionalLight, ///< Element has type "DirectionalLight".
|
|
||||||
ENET_PointLight, ///< Element has type "PointLight".
|
|
||||||
ENET_SpotLight, ///< Element has type "SpotLight".
|
|
||||||
|
|
||||||
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
|
|
||||||
};
|
|
||||||
|
|
||||||
const EType Type;
|
|
||||||
|
|
||||||
std::string ID; ///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
|
|
||||||
X3DNodeElementBase *Parent; ///< Parent element. If nullptr then this node is root.
|
|
||||||
std::list<X3DNodeElementBase *> Child; ///< Child elements.
|
|
||||||
|
|
||||||
/// @brief The destructor, virtual.
|
|
||||||
virtual ~X3DNodeElementBase() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/// In constructor inheritor must set element type.
|
|
||||||
/// \param [in] pType - element type.
|
|
||||||
/// \param [in] pParent - parent element.
|
|
||||||
X3DNodeElementBase(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
Type(pType), Parent(pParent) {}
|
|
||||||
|
|
||||||
X3DNodeElementBase(const X3DNodeElementBase &pNodeElement) = delete;
|
|
||||||
X3DNodeElementBase &operator=(const X3DNodeElementBase &pNodeElement) = delete;
|
|
||||||
X3DNodeElementBase() = delete;
|
|
||||||
}; // class IX3DImporter_NodeElement
|
|
||||||
|
|
||||||
/// \class CX3DImporter_NodeElement_Group
|
|
||||||
/// Class that define grouping node. Define transformation matrix for children.
|
|
||||||
/// Also can select which child will be kept and others are removed.
|
|
||||||
class X3DGroup : public X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
aiMatrix4x4 Transformation; ///< Transformation matrix.
|
|
||||||
|
|
||||||
/// \var bool Static
|
|
||||||
/// As you know node elements can use already defined node elements when attribute "USE" is defined.
|
|
||||||
/// Standard search when looking for an element in the whole scene graph, existing at this moment.
|
|
||||||
/// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
|
|
||||||
bool Static;
|
|
||||||
|
|
||||||
bool UseChoice; ///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
|
|
||||||
int32_t Choice; ///< Number of the child which will be kept.
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pStatic - static node flag.
|
|
||||||
X3DGroup(X3DNodeElementBase *pParent, const bool pStatic = false) :
|
|
||||||
X3DNodeElementBase(ENET_Group, pParent),
|
|
||||||
Static(pStatic),
|
|
||||||
UseChoice(false) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}; // class CX3DImporter_NodeElement_Group
|
|
||||||
|
|
||||||
/// This struct describe meta-value.
|
|
||||||
class X3DMeta : public X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
std::string Name; ///< Name of metadata object.
|
|
||||||
|
|
||||||
/// If provided, it identifies the metadata standard or other specification that defines the name field. If the reference field is not provided or is
|
|
||||||
/// empty, the meaning of the name field is considered implicit to the characters in the string.
|
|
||||||
std::string Reference;
|
|
||||||
|
|
||||||
/// In constructor inheritor must set element type.
|
|
||||||
/// \param [in] pType - element type.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMeta(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pType, pParent) {}
|
|
||||||
}; // class CX3DImporter_NodeElement_Meta
|
|
||||||
|
|
||||||
/// \struct CX3DImporter_NodeElement_MetaBoolean
|
|
||||||
/// This struct describe metavalue of type boolean.
|
|
||||||
struct X3DMetaBoolean : public X3DMeta {
|
|
||||||
std::vector<bool> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaBoolean(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaBoolean, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaBoolean
|
|
||||||
|
|
||||||
/// \struct CX3DImporter_NodeElement_MetaDouble
|
|
||||||
/// This struct describe metavalue of type double.
|
|
||||||
struct X3DMetaDouble : public X3DMeta {
|
|
||||||
std::vector<double> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaDouble(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaDouble, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaDouble
|
|
||||||
|
|
||||||
/// This struct describe metavalue of type float.
|
|
||||||
struct X3DMetaFloat : public X3DMeta {
|
|
||||||
std::vector<float> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaFloat(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaFloat, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaFloat
|
|
||||||
|
|
||||||
/// This struct describe metavalue of type integer.
|
|
||||||
struct X3DMetaInteger : public X3DMeta {
|
|
||||||
std::vector<int32_t> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaInteger(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaInteger, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaInteger
|
|
||||||
|
|
||||||
/// This struct describe container for metaobjects.
|
|
||||||
struct X3DMetaSet : public X3DMeta {
|
|
||||||
std::list<X3DMeta> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaSet(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaSet, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaSet
|
|
||||||
|
|
||||||
/// This struct describe metavalue of type string.
|
|
||||||
struct X3DMetaString : public X3DMeta {
|
|
||||||
std::list<std::string> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DMetaString(X3DNodeElementBase *pParent) :
|
|
||||||
X3DMeta(ENET_MetaString, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_MetaString
|
|
||||||
|
|
||||||
/// This struct hold <Color> value.
|
|
||||||
struct X3DColor : public X3DNodeElementBase {
|
|
||||||
std::list<aiColor3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DColor(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Color, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Color
|
|
||||||
|
|
||||||
/// This struct hold <ColorRGBA> value.
|
|
||||||
struct X3DColorRGBA : public X3DNodeElementBase {
|
|
||||||
std::list<aiColor4D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DColorRGBA(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_ColorRGBA, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_ColorRGBA
|
|
||||||
|
|
||||||
/// This struct hold <Coordinate> value.
|
|
||||||
struct X3DCoordinate : public X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DCoordinate(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Coordinate, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Coordinate
|
|
||||||
|
|
||||||
/// This struct hold <Normal> value.
|
|
||||||
struct X3DNormal : public X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DNormal(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Normal, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Normal
|
|
||||||
|
|
||||||
/// This struct hold <TextureCoordinate> value.
|
|
||||||
struct X3DTextureCoordinate : public X3DNodeElementBase {
|
|
||||||
std::list<aiVector2D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DTextureCoordinate(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_TextureCoordinate, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_TextureCoordinate
|
|
||||||
|
|
||||||
/// Two-dimensional figure.
|
|
||||||
class X3DGeometry2D : public X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
|
||||||
size_t NumIndices; ///< Number of indices in one face.
|
|
||||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DGeometry2D(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pType, pParent), Solid(true) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_Geometry2D
|
|
||||||
|
|
||||||
/// Three-dimensional body.
|
|
||||||
class X3DGeometry3D : public X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
|
||||||
size_t NumIndices; ///< Number of indices in one face.
|
|
||||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DGeometry3D(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pType, pParent), Vertices(), NumIndices(0), Solid(true) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}; // class CX3DImporter_NodeElement_Geometry3D
|
|
||||||
|
|
||||||
/// \class CX3DImporter_NodeElement_ElevationGrid
|
|
||||||
/// Uniform rectangular grid of varying height.
|
|
||||||
class X3DElevationGrid : public X3DGeometry3D {
|
|
||||||
public:
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
|
||||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
|
||||||
float CreaseAngle;
|
|
||||||
std::vector<int32_t> CoordIdx; ///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DElevationGrid(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DGeometry3D(pType, pParent) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_IndexedSet
|
|
||||||
|
|
||||||
/// Shape with indexed vertices.
|
|
||||||
class X3DIndexedSet : public X3DGeometry3D {
|
|
||||||
public:
|
|
||||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
|
||||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
|
||||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
|
||||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
|
||||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
|
||||||
/// ccw field, results are undefined.
|
|
||||||
bool CCW;
|
|
||||||
std::vector<int32_t> ColorIndex; ///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
|
|
||||||
/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
|
|
||||||
/// even if the convex field is FALSE.
|
|
||||||
bool Convex;
|
|
||||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
|
||||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
|
||||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
|
||||||
float CreaseAngle;
|
|
||||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DIndexedSet(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DGeometry3D(pType, pParent) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_IndexedSet
|
|
||||||
|
|
||||||
/// Shape with set of vertices.
|
|
||||||
class X3DSet : public X3DGeometry3D {
|
|
||||||
public:
|
|
||||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
|
||||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
|
||||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
|
||||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
|
||||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
|
||||||
/// ccw field, results are undefined.
|
|
||||||
bool CCW;
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
|
||||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
|
||||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
|
||||||
std::vector<int32_t> VertexCount; ///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DSet(const EType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DGeometry3D(pType, pParent) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_Set
|
|
||||||
|
|
||||||
/// This struct hold <Shape> value.
|
|
||||||
struct X3DShape : public X3DNodeElementBase {
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DShape(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Shape, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Shape
|
|
||||||
|
|
||||||
/// This struct hold <Appearance> value.
|
|
||||||
struct X3DAppearance : public X3DNodeElementBase {
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DAppearance(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Appearance, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Appearance
|
|
||||||
|
|
||||||
/// Material.
|
|
||||||
class X3DMaterial : public X3DNodeElementBase {
|
|
||||||
public:
|
|
||||||
float AmbientIntensity; ///< Specifies how much ambient light from light sources this surface shall reflect.
|
|
||||||
aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
|
|
||||||
aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
|
|
||||||
float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
|
|
||||||
aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
|
|
||||||
float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
X3DMaterial(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_Material, pParent),
|
|
||||||
AmbientIntensity(0.0f),
|
|
||||||
DiffuseColor(),
|
|
||||||
EmissiveColor(),
|
|
||||||
Shininess(0.0f),
|
|
||||||
SpecularColor(),
|
|
||||||
Transparency(1.0f) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}; // class CX3DImporter_NodeElement_Material
|
|
||||||
|
|
||||||
/// This struct hold <ImageTexture> value.
|
|
||||||
struct X3DImageTexture : public X3DNodeElementBase {
|
|
||||||
/// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
|
|
||||||
/// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
|
|
||||||
/// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
|
|
||||||
bool RepeatS;
|
|
||||||
bool RepeatT; ///< See \ref RepeatS.
|
|
||||||
std::string URL; ///< URL of the texture.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DImageTexture(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_ImageTexture, pParent) {}
|
|
||||||
}; // struct CX3DImporter_NodeElement_ImageTexture
|
|
||||||
|
|
||||||
/// This struct hold <TextureTransform> value.
|
|
||||||
struct X3DTextureTransform : public X3DNodeElementBase {
|
|
||||||
aiVector2D Center; ///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
|
|
||||||
float Rotation; ///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
|
|
||||||
aiVector2D Scale; ///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
|
|
||||||
aiVector2D Translation; ///< Specifies a translation of the texture coordinates.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
X3DTextureTransform(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(ENET_TextureTransform, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_TextureTransform
|
|
||||||
|
|
||||||
/// This struct hold <TextureTransform> value.
|
|
||||||
struct X3DLight : public X3DNodeElementBase {
|
|
||||||
float AmbientIntensity; ///< Specifies the intensity of the ambient emission from the light.
|
|
||||||
aiColor3D Color; ///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
|
|
||||||
aiVector3D Direction; ///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
|
|
||||||
/// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
|
|
||||||
/// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
|
|
||||||
bool Global;
|
|
||||||
float Intensity; ///< Specifies the brightness of the direct emission from the light.
|
|
||||||
|
|
||||||
/// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
|
|
||||||
/// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
|
|
||||||
aiVector3D Attenuation;
|
|
||||||
aiVector3D Location; ///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
|
|
||||||
float Radius; ///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
|
|
||||||
float BeamWidth; ///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
|
|
||||||
float CutOffAngle; ///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pLightType - type of the light source.
|
|
||||||
X3DLight(EType pLightType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pLightType, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Light
|
|
||||||
|
|
||||||
#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H
|
|
|
@ -1,829 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Postprocess.cpp
|
|
||||||
/// \brief Convert built scenegraph and objects to Assimp scenegraph.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
|
|
||||||
// Header files, Assimp.
|
|
||||||
#include <assimp/ai_assert.h>
|
|
||||||
#include <assimp/StandardShapes.h>
|
|
||||||
#include <assimp/StringUtils.h>
|
|
||||||
|
|
||||||
// Header files, stdlib.
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
|
|
||||||
{
|
|
||||||
X3DNodeElementBase* cur_node;
|
|
||||||
std::list<aiMatrix4x4> matr;
|
|
||||||
aiMatrix4x4 out_matr;
|
|
||||||
|
|
||||||
// starting walk from current element to root
|
|
||||||
cur_node = mNodeElementCur;
|
|
||||||
if(cur_node != nullptr)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// if cur_node is group then store group transformation matrix in list.
|
|
||||||
if(cur_node->Type == X3DNodeElementBase::ENET_Group) matr.push_back(((X3DGroup*)cur_node)->Transformation);
|
|
||||||
|
|
||||||
cur_node = cur_node->Parent;
|
|
||||||
} while(cur_node != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// multiplicate all matrices in reverse order
|
|
||||||
for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit) out_matr = out_matr * (*rit);
|
|
||||||
|
|
||||||
return out_matr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::PostprocessHelper_CollectMetadata(const X3DNodeElementBase& pNodeElement, std::list<X3DNodeElementBase*>& pList) const
|
|
||||||
{
|
|
||||||
// walk through childs and find for metadata.
|
|
||||||
for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
|
|
||||||
{
|
|
||||||
if(((*el_it)->Type == X3DNodeElementBase::ENET_MetaBoolean) || ((*el_it)->Type == X3DNodeElementBase::ENET_MetaDouble) ||
|
|
||||||
((*el_it)->Type == X3DNodeElementBase::ENET_MetaFloat) || ((*el_it)->Type == X3DNodeElementBase::ENET_MetaInteger) ||
|
|
||||||
((*el_it)->Type == X3DNodeElementBase::ENET_MetaString))
|
|
||||||
{
|
|
||||||
pList.push_back(*el_it);
|
|
||||||
}
|
|
||||||
else if((*el_it)->Type == X3DNodeElementBase::ENET_MetaSet)
|
|
||||||
{
|
|
||||||
PostprocessHelper_CollectMetadata(**el_it, pList);
|
|
||||||
}
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
|
||||||
}
|
|
||||||
|
|
||||||
bool X3DImporter::PostprocessHelper_ElementIsMetadata(const X3DNodeElementBase::EType pType) const
|
|
||||||
{
|
|
||||||
if((pType == X3DNodeElementBase::ENET_MetaBoolean) || (pType == X3DNodeElementBase::ENET_MetaDouble) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_MetaFloat) || (pType == X3DNodeElementBase::ENET_MetaInteger) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_MetaString) || (pType == X3DNodeElementBase::ENET_MetaSet))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool X3DImporter::PostprocessHelper_ElementIsMesh(const X3DNodeElementBase::EType pType) const
|
|
||||||
{
|
|
||||||
if((pType == X3DNodeElementBase::ENET_Arc2D) || (pType == X3DNodeElementBase::ENET_ArcClose2D) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Box) || (pType == X3DNodeElementBase::ENET_Circle2D) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Cone) || (pType == X3DNodeElementBase::ENET_Cylinder) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Disk2D) || (pType == X3DNodeElementBase::ENET_ElevationGrid) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Extrusion) || (pType == X3DNodeElementBase::ENET_IndexedFaceSet) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_IndexedLineSet) || (pType == X3DNodeElementBase::ENET_IndexedTriangleFanSet) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_IndexedTriangleSet) || (pType == X3DNodeElementBase::ENET_IndexedTriangleStripSet) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_PointSet) || (pType == X3DNodeElementBase::ENET_LineSet) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Polyline2D) || (pType == X3DNodeElementBase::ENET_Polypoint2D) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_Rectangle2D) || (pType == X3DNodeElementBase::ENET_Sphere) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_TriangleFanSet) || (pType == X3DNodeElementBase::ENET_TriangleSet) ||
|
|
||||||
(pType == X3DNodeElementBase::ENET_TriangleSet2D) || (pType == X3DNodeElementBase::ENET_TriangleStripSet))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_BuildLight(const X3DNodeElementBase& pNodeElement, std::list<aiLight*>& pSceneLightList) const
|
|
||||||
{
|
|
||||||
const X3DLight& ne = *( ( X3DLight* ) &pNodeElement );
|
|
||||||
aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
|
|
||||||
aiLight* new_light = new aiLight;
|
|
||||||
|
|
||||||
new_light->mName = ne.ID;
|
|
||||||
new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
|
|
||||||
new_light->mColorDiffuse = ne.Color * ne.Intensity;
|
|
||||||
new_light->mColorSpecular = ne.Color * ne.Intensity;
|
|
||||||
switch(pNodeElement.Type)
|
|
||||||
{
|
|
||||||
case X3DNodeElementBase::ENET_DirectionalLight:
|
|
||||||
new_light->mType = aiLightSource_DIRECTIONAL;
|
|
||||||
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case X3DNodeElementBase::ENET_PointLight:
|
|
||||||
new_light->mType = aiLightSource_POINT;
|
|
||||||
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
|
||||||
new_light->mAttenuationConstant = ne.Attenuation.x;
|
|
||||||
new_light->mAttenuationLinear = ne.Attenuation.y;
|
|
||||||
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case X3DNodeElementBase::ENET_SpotLight:
|
|
||||||
new_light->mType = aiLightSource_SPOT;
|
|
||||||
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
|
||||||
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
|
||||||
new_light->mAttenuationConstant = ne.Attenuation.x;
|
|
||||||
new_light->mAttenuationLinear = ne.Attenuation.y;
|
|
||||||
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
|
||||||
new_light->mAngleInnerCone = ne.BeamWidth;
|
|
||||||
new_light->mAngleOuterCone = ne.CutOffAngle;
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + to_string(pNodeElement.Type) + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
pSceneLightList.push_back(new_light);
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_BuildMaterial(const X3DNodeElementBase& pNodeElement, aiMaterial** pMaterial) const
|
|
||||||
{
|
|
||||||
// check argument
|
|
||||||
if(pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
|
|
||||||
if(*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
|
|
||||||
|
|
||||||
*pMaterial = new aiMaterial;
|
|
||||||
aiMaterial& taimat = **pMaterial;// creating alias for convenience.
|
|
||||||
|
|
||||||
// at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
|
|
||||||
for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
|
|
||||||
{
|
|
||||||
if((*el_it)->Type == X3DNodeElementBase::ENET_Material)
|
|
||||||
{
|
|
||||||
aiColor3D tcol3;
|
|
||||||
float tvalf;
|
|
||||||
X3DMaterial& tnemat = *((X3DMaterial*)*el_it);
|
|
||||||
|
|
||||||
tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
|
|
||||||
taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
|
|
||||||
taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
|
|
||||||
taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
|
|
||||||
taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
|
|
||||||
tvalf = 1;
|
|
||||||
taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
|
|
||||||
taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
|
|
||||||
tvalf = 1.0f - tnemat.Transparency;
|
|
||||||
taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
|
|
||||||
}// if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
|
|
||||||
else if((*el_it)->Type == X3DNodeElementBase::ENET_ImageTexture)
|
|
||||||
{
|
|
||||||
X3DImageTexture& tnetex = *((X3DImageTexture*)*el_it);
|
|
||||||
aiString url_str(tnetex.URL.c_str());
|
|
||||||
int mode = aiTextureOp_Multiply;
|
|
||||||
|
|
||||||
taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
|
||||||
taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
|
|
||||||
taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
|
|
||||||
taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
|
|
||||||
}// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
|
|
||||||
else if((*el_it)->Type == X3DNodeElementBase::ENET_TextureTransform)
|
|
||||||
{
|
|
||||||
aiUVTransform trans;
|
|
||||||
X3DTextureTransform& tnetextr = *((X3DTextureTransform*)*el_it);
|
|
||||||
|
|
||||||
trans.mTranslation = tnetextr.Translation - tnetextr.Center;
|
|
||||||
trans.mScaling = tnetextr.Scale;
|
|
||||||
trans.mRotation = tnetextr.Rotation;
|
|
||||||
taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
|
|
||||||
}// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_BuildMesh(const X3DNodeElementBase& pNodeElement, aiMesh** pMesh) const
|
|
||||||
{
|
|
||||||
// check argument
|
|
||||||
if(pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
|
|
||||||
if(*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
|
|
||||||
|
|
||||||
/************************************************************************************************************************************/
|
|
||||||
/************************************************************ Geometry2D ************************************************************/
|
|
||||||
/************************************************************************************************************************************/
|
|
||||||
if((pNodeElement.Type == X3DNodeElementBase::ENET_Arc2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_ArcClose2D) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_Circle2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_Disk2D) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_Polyline2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_Polypoint2D) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_Rectangle2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_TriangleSet2D))
|
|
||||||
{
|
|
||||||
X3DGeometry2D& tnemesh = *((X3DGeometry2D*)&pNodeElement);// create alias for convenience
|
|
||||||
std::vector<aiVector3D> tarr;
|
|
||||||
|
|
||||||
tarr.reserve(tnemesh.Vertices.size());
|
|
||||||
for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it) tarr.push_back(*it);
|
|
||||||
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}
|
|
||||||
/************************************************************************************************************************************/
|
|
||||||
/************************************************************ Geometry3D ************************************************************/
|
|
||||||
/************************************************************************************************************************************/
|
|
||||||
//
|
|
||||||
// Predefined figures
|
|
||||||
//
|
|
||||||
if((pNodeElement.Type == X3DNodeElementBase::ENET_Box) || (pNodeElement.Type == X3DNodeElementBase::ENET_Cone) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_Cylinder) || (pNodeElement.Type == X3DNodeElementBase::ENET_Sphere))
|
|
||||||
{
|
|
||||||
X3DGeometry3D& tnemesh = *((X3DGeometry3D*)&pNodeElement);// create alias for convenience
|
|
||||||
std::vector<aiVector3D> tarr;
|
|
||||||
|
|
||||||
tarr.reserve(tnemesh.Vertices.size());
|
|
||||||
for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it) tarr.push_back(*it);
|
|
||||||
|
|
||||||
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Parametric figures
|
|
||||||
//
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_ElevationGrid)
|
|
||||||
{
|
|
||||||
X3DElevationGrid& tnemesh = *((X3DElevationGrid*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first create mesh from existing vertices.
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, ((X3DNormal*)*ch_it)->Value, tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
|
|
||||||
//
|
|
||||||
// Indexed primitives sets
|
|
||||||
//
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedFaceSet)
|
|
||||||
{
|
|
||||||
X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
|
|
||||||
tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
|
|
||||||
tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedLineSet)
|
|
||||||
{
|
|
||||||
X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
|
|
||||||
tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
|
|
||||||
|
|
||||||
if((pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleSet) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleFanSet) ||
|
|
||||||
(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleStripSet))
|
|
||||||
{
|
|
||||||
X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
|
|
||||||
tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
|
|
||||||
tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
|
|
||||||
IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_Extrusion)
|
|
||||||
{
|
|
||||||
X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices);
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Primitives sets
|
|
||||||
//
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_PointSet)
|
|
||||||
{
|
|
||||||
X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
std::vector<aiVector3D> vec_copy;
|
|
||||||
|
|
||||||
vec_copy.reserve(((X3DCoordinate*)*ch_it)->Value.size());
|
|
||||||
for(std::list<aiVector3D>::const_iterator it = ((X3DCoordinate*)*ch_it)->Value.begin();
|
|
||||||
it != ((X3DCoordinate*)*ch_it)->Value.end(); ++it)
|
|
||||||
{
|
|
||||||
vec_copy.push_back(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, true);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, true);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_LineSet)
|
|
||||||
{
|
|
||||||
X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, true);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, true);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleFanSet)
|
|
||||||
{
|
|
||||||
X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if ( nullptr == *pMesh ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value,tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
|
|
||||||
tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleSet)
|
|
||||||
{
|
|
||||||
X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
std::vector<aiVector3D> vec_copy;
|
|
||||||
|
|
||||||
vec_copy.reserve(((X3DCoordinate*)*ch_it)->Value.size());
|
|
||||||
for(std::list<aiVector3D>::const_iterator it = ((X3DCoordinate*)*ch_it)->Value.begin();
|
|
||||||
it != ((X3DCoordinate*)*ch_it)->Value.end(); ++it)
|
|
||||||
{
|
|
||||||
vec_copy.push_back(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
|
|
||||||
tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
|
|
||||||
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleStripSet)
|
|
||||||
{
|
|
||||||
X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
// at first search for <Coordinate> node and create mesh.
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{
|
|
||||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy additional information from children
|
|
||||||
for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
{
|
|
||||||
ai_assert(*pMesh);
|
|
||||||
if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
|
|
||||||
MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
|
|
||||||
{} // skip because already read when mesh created.
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
|
|
||||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
|
|
||||||
tnemesh.NormalPerVertex);
|
|
||||||
else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
|
|
||||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + ".");
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
|
|
||||||
|
|
||||||
return;// mesh is build, nothing to do anymore.
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
|
|
||||||
|
|
||||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + to_string(pNodeElement.Type) + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_BuildNode(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
|
|
||||||
std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const
|
|
||||||
{
|
|
||||||
std::list<X3DNodeElementBase*>::const_iterator chit_begin = pNodeElement.Child.begin();
|
|
||||||
std::list<X3DNodeElementBase*>::const_iterator chit_end = pNodeElement.Child.end();
|
|
||||||
std::list<aiNode*> SceneNode_Child;
|
|
||||||
std::list<unsigned int> SceneNode_Mesh;
|
|
||||||
|
|
||||||
// At first read all metadata
|
|
||||||
Postprocess_CollectMetadata(pNodeElement, pSceneNode);
|
|
||||||
// check if we have deal with grouping node. Which can contain transformation or switch
|
|
||||||
if(pNodeElement.Type == X3DNodeElementBase::ENET_Group)
|
|
||||||
{
|
|
||||||
const X3DGroup& tne_group = *((X3DGroup*)&pNodeElement);// create alias for convenience
|
|
||||||
|
|
||||||
pSceneNode.mTransformation = tne_group.Transformation;
|
|
||||||
if(tne_group.UseChoice)
|
|
||||||
{
|
|
||||||
// If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
|
|
||||||
if((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Child.size()))
|
|
||||||
{
|
|
||||||
chit_begin = pNodeElement.Child.end();
|
|
||||||
chit_end = pNodeElement.Child.end();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < (size_t)tne_group.Choice; i++) ++chit_begin;// forward iterator to chosen node.
|
|
||||||
|
|
||||||
chit_end = chit_begin;
|
|
||||||
++chit_end;// point end iterator to next element after chosen node.
|
|
||||||
}
|
|
||||||
}// if(tne_group.UseChoice)
|
|
||||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
|
|
||||||
|
|
||||||
// Reserve memory for fast access and check children.
|
|
||||||
for(std::list<X3DNodeElementBase*>::const_iterator it = chit_begin; it != chit_end; ++it)
|
|
||||||
{// in this loop we do not read metadata because it's already read at begin.
|
|
||||||
if((*it)->Type == X3DNodeElementBase::ENET_Group)
|
|
||||||
{
|
|
||||||
// if child is group then create new node and do recursive call.
|
|
||||||
aiNode* new_node = new aiNode;
|
|
||||||
|
|
||||||
new_node->mName = (*it)->ID;
|
|
||||||
new_node->mParent = &pSceneNode;
|
|
||||||
SceneNode_Child.push_back(new_node);
|
|
||||||
Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_Shape)
|
|
||||||
{
|
|
||||||
// shape can contain only one geometry and one appearance nodes.
|
|
||||||
Postprocess_BuildShape(*((X3DShape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
|
|
||||||
}
|
|
||||||
else if(((*it)->Type == X3DNodeElementBase::ENET_DirectionalLight) || ((*it)->Type == X3DNodeElementBase::ENET_PointLight) ||
|
|
||||||
((*it)->Type == X3DNodeElementBase::ENET_SpotLight))
|
|
||||||
{
|
|
||||||
Postprocess_BuildLight(*((X3DLight*)*it), pSceneLightList);
|
|
||||||
}
|
|
||||||
else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
|
|
||||||
{
|
|
||||||
throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + to_string((*it)->Type) + ".");
|
|
||||||
}
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
|
|
||||||
|
|
||||||
// copy data about children and meshes to aiNode.
|
|
||||||
if(!SceneNode_Child.empty())
|
|
||||||
{
|
|
||||||
std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
|
|
||||||
|
|
||||||
pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size());
|
|
||||||
pSceneNode.mChildren = new aiNode*[pSceneNode.mNumChildren];
|
|
||||||
for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!SceneNode_Mesh.empty())
|
|
||||||
{
|
|
||||||
std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
|
|
||||||
|
|
||||||
pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size());
|
|
||||||
pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
|
|
||||||
for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// that's all. return to previous deals
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_BuildShape(const X3DShape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
|
|
||||||
std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
|
|
||||||
{
|
|
||||||
aiMaterial* tmat = nullptr;
|
|
||||||
aiMesh* tmesh = nullptr;
|
|
||||||
X3DNodeElementBase::EType mesh_type = X3DNodeElementBase::ENET_Invalid;
|
|
||||||
unsigned int mat_ind = 0;
|
|
||||||
|
|
||||||
for(std::list<X3DNodeElementBase*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); ++it)
|
|
||||||
{
|
|
||||||
if(PostprocessHelper_ElementIsMesh((*it)->Type))
|
|
||||||
{
|
|
||||||
Postprocess_BuildMesh(**it, &tmesh);
|
|
||||||
if(tmesh != nullptr)
|
|
||||||
{
|
|
||||||
// if mesh successfully built then add data about it to arrays
|
|
||||||
pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size()));
|
|
||||||
pSceneMeshList.push_back(tmesh);
|
|
||||||
// keep mesh type. Need above for texture coordinate generation.
|
|
||||||
mesh_type = (*it)->Type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_Appearance)
|
|
||||||
{
|
|
||||||
Postprocess_BuildMaterial(**it, &tmat);
|
|
||||||
if(tmat != nullptr)
|
|
||||||
{
|
|
||||||
// if material successfully built then add data about it to array
|
|
||||||
mat_ind = static_cast<unsigned int>(pSceneMaterialList.size());
|
|
||||||
pSceneMaterialList.push_back(tmat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
|
|
||||||
|
|
||||||
// associate read material with read mesh.
|
|
||||||
if((tmesh != nullptr) && (tmat != nullptr))
|
|
||||||
{
|
|
||||||
tmesh->mMaterialIndex = mat_ind;
|
|
||||||
// Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
|
|
||||||
if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
|
|
||||||
{
|
|
||||||
int32_t tm;
|
|
||||||
aiVector3D tvec3;
|
|
||||||
|
|
||||||
switch(mesh_type)
|
|
||||||
{
|
|
||||||
case X3DNodeElementBase::ENET_Box:
|
|
||||||
tm = aiTextureMapping_BOX;
|
|
||||||
break;
|
|
||||||
case X3DNodeElementBase::ENET_Cone:
|
|
||||||
case X3DNodeElementBase::ENET_Cylinder:
|
|
||||||
tm = aiTextureMapping_CYLINDER;
|
|
||||||
break;
|
|
||||||
case X3DNodeElementBase::ENET_Sphere:
|
|
||||||
tm = aiTextureMapping_SPHERE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tm = aiTextureMapping_PLANE;
|
|
||||||
break;
|
|
||||||
}// switch(mesh_type)
|
|
||||||
|
|
||||||
tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
|
|
||||||
}// if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
|
|
||||||
}// if((tmesh != nullptr) && (tmat != nullptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
void X3DImporter::Postprocess_CollectMetadata(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode) const
|
|
||||||
{
|
|
||||||
std::list<X3DNodeElementBase*> meta_list;
|
|
||||||
size_t meta_idx;
|
|
||||||
|
|
||||||
PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
|
|
||||||
if ( !meta_list.empty() )
|
|
||||||
{
|
|
||||||
if ( pSceneNode.mMetaData != nullptr ) {
|
|
||||||
throw DeadlyImportError( "Postprocess. MetaData member in node are not nullptr. Something went wrong." );
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy collected metadata to output node.
|
|
||||||
pSceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(meta_list.size()) );
|
|
||||||
meta_idx = 0;
|
|
||||||
for(std::list<X3DNodeElementBase*>::const_iterator it = meta_list.begin(); it != meta_list.end(); ++it, ++meta_idx)
|
|
||||||
{
|
|
||||||
X3DMeta* cur_meta = (X3DMeta*)*it;
|
|
||||||
|
|
||||||
// due to limitations we can add only first element of value list.
|
|
||||||
// Add an element according to its type.
|
|
||||||
if((*it)->Type == X3DNodeElementBase::ENET_MetaBoolean)
|
|
||||||
{
|
|
||||||
if(((X3DMetaBoolean*)cur_meta)->Value.size() > 0) {
|
|
||||||
const bool v = (bool) *( ( (X3DMetaBoolean*) cur_meta )->Value.begin());
|
|
||||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_MetaDouble)
|
|
||||||
{
|
|
||||||
if(((X3DMetaDouble*)cur_meta)->Value.size() > 0)
|
|
||||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((X3DMetaDouble*)cur_meta)->Value.begin()));
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_MetaFloat)
|
|
||||||
{
|
|
||||||
if(((X3DMetaFloat*)cur_meta)->Value.size() > 0)
|
|
||||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DMetaFloat*)cur_meta)->Value.begin()));
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_MetaInteger)
|
|
||||||
{
|
|
||||||
if(((X3DMetaInteger*)cur_meta)->Value.size() > 0)
|
|
||||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DMetaInteger*)cur_meta)->Value.begin()));
|
|
||||||
}
|
|
||||||
else if((*it)->Type == X3DNodeElementBase::ENET_MetaString)
|
|
||||||
{
|
|
||||||
if(((X3DMetaString*)cur_meta)->Value.size() > 0)
|
|
||||||
{
|
|
||||||
aiString tstr(((X3DMetaString*)cur_meta)->Value.begin()->data());
|
|
||||||
|
|
||||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw DeadlyImportError("Postprocess. Unknown metadata type.");
|
|
||||||
}// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
|
|
||||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
|
|
||||||
}// if( !meta_list.empty() )
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,250 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Shape.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Shape" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
// <Shape
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
|
||||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
|
||||||
// >
|
|
||||||
// <!-- ShapeChildContentModel -->
|
|
||||||
// "ShapeChildContentModel is the child-node content model corresponding to X3DShapeNode. ShapeChildContentModel can contain a single Appearance node and a
|
|
||||||
// single geometry node, in any order.
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
|
|
||||||
// </Shape>
|
|
||||||
// A Shape node is unlit if either of the following is true:
|
|
||||||
// The shape's appearance field is nullptr (default).
|
|
||||||
// The material field in the Appearance node is nullptr (default).
|
|
||||||
// NOTE Geometry nodes that represent lines or points do not support lighting.
|
|
||||||
void X3DImporter::ParseNode_Shape_Shape()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Shape, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DShape(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("Shape");
|
|
||||||
// check for appearance node
|
|
||||||
if(XML_CheckNode_NameEqual("Appearance")) { ParseNode_Shape_Appearance(); continue; }
|
|
||||||
// check for X3DGeometryNodes
|
|
||||||
if(XML_CheckNode_NameEqual("Arc2D")) { ParseNode_Geometry2D_Arc2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("ArcClose2D")) { ParseNode_Geometry2D_ArcClose2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Circle2D")) { ParseNode_Geometry2D_Circle2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Disk2D")) { ParseNode_Geometry2D_Disk2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Polyline2D")) { ParseNode_Geometry2D_Polyline2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Polypoint2D")) { ParseNode_Geometry2D_Polypoint2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Rectangle2D")) { ParseNode_Geometry2D_Rectangle2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TriangleSet2D")) { ParseNode_Geometry2D_TriangleSet2D(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Box")) { ParseNode_Geometry3D_Box(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Cone")) { ParseNode_Geometry3D_Cone(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Cylinder")) { ParseNode_Geometry3D_Cylinder(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("ElevationGrid")) { ParseNode_Geometry3D_ElevationGrid(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Extrusion")) { ParseNode_Geometry3D_Extrusion(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("IndexedFaceSet")) { ParseNode_Geometry3D_IndexedFaceSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("Sphere")) { ParseNode_Geometry3D_Sphere(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("IndexedLineSet")) { ParseNode_Rendering_IndexedLineSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("LineSet")) { ParseNode_Rendering_LineSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("PointSet")) { ParseNode_Rendering_PointSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("IndexedTriangleFanSet")) { ParseNode_Rendering_IndexedTriangleFanSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("IndexedTriangleSet")) { ParseNode_Rendering_IndexedTriangleSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("IndexedTriangleStripSet")) { ParseNode_Rendering_IndexedTriangleStripSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TriangleFanSet")) { ParseNode_Rendering_TriangleFanSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TriangleSet")) { ParseNode_Rendering_TriangleSet(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TriangleStripSet")) { ParseNode_Rendering_TriangleStripSet(); continue; }
|
|
||||||
// check for X3DMetadataObject
|
|
||||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Shape");
|
|
||||||
|
|
||||||
MACRO_NODECHECK_LOOPEND("Shape");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!mReader->isEmptyElement())
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Appearance
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// >
|
|
||||||
// <!-- AppearanceChildContentModel -->
|
|
||||||
// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
|
|
||||||
// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
|
|
||||||
// PackagedShader, ProgramShader).
|
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
|
|
||||||
// </Appearance>
|
|
||||||
void X3DImporter::ParseNode_Shape_Appearance()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Appearance, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DAppearance(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
{
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("Appearance");
|
|
||||||
if(XML_CheckNode_NameEqual("Material")) { ParseNode_Shape_Material(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("ImageTexture")) { ParseNode_Texturing_ImageTexture(); continue; }
|
|
||||||
if(XML_CheckNode_NameEqual("TextureTransform")) { ParseNode_Texturing_TextureTransform(); continue; }
|
|
||||||
// check for X3DMetadataObject
|
|
||||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Appearance");
|
|
||||||
|
|
||||||
MACRO_NODECHECK_LOOPEND("Appearance");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!mReader->isEmptyElement())
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <Material
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// ambientIntensity="0.2" SFFloat [inputOutput]
|
|
||||||
// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
|
|
||||||
// emissiveColor="0 0 0" SFColor [inputOutput]
|
|
||||||
// shininess="0.2" SFFloat [inputOutput]
|
|
||||||
// specularColor="0 0 0" SFColor [inputOutput]
|
|
||||||
// transparency="0" SFFloat [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Shape_Material()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
float ambientIntensity = 0.2f;
|
|
||||||
float shininess = 0.2f;
|
|
||||||
float transparency = 0;
|
|
||||||
aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
|
|
||||||
aiColor3D emissiveColor(0, 0, 0);
|
|
||||||
aiColor3D specularColor(0, 0, 0);
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("shininess", shininess, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("transparency", transparency, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("diffuseColor", diffuseColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("emissiveColor", emissiveColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("specularColor", specularColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Material, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DMaterial(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DMaterial*)ne)->AmbientIntensity = ambientIntensity;
|
|
||||||
((X3DMaterial*)ne)->Shininess = shininess;
|
|
||||||
((X3DMaterial*)ne)->Transparency = transparency;
|
|
||||||
((X3DMaterial*)ne)->DiffuseColor = diffuseColor;
|
|
||||||
((X3DMaterial*)ne)->EmissiveColor = emissiveColor;
|
|
||||||
((X3DMaterial*)ne)->SpecularColor = specularColor;
|
|
||||||
// check for child nodes
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "Material");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
|
@ -1,197 +0,0 @@
|
||||||
/*
|
|
||||||
Open Asset Import Library (assimp)
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
|
||||||
with or without modification, are permitted provided that the
|
|
||||||
following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer in the documentation and/or other
|
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the assimp team, nor the names of its
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior
|
|
||||||
written permission of the assimp team.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/// \file X3DImporter_Texturing.cpp
|
|
||||||
/// \brief Parsing data from nodes of "Texturing" set of X3D.
|
|
||||||
/// \date 2015-2016
|
|
||||||
/// \author smal.root@gmail.com
|
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
||||||
|
|
||||||
#include "X3DImporter.hpp"
|
|
||||||
#include "X3DImporter_Macro.hpp"
|
|
||||||
|
|
||||||
namespace Assimp
|
|
||||||
{
|
|
||||||
|
|
||||||
// <ImageTexture
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// repeatS="true" SFBool
|
|
||||||
// repeatT="true" SFBool
|
|
||||||
// url="" MFString
|
|
||||||
// />
|
|
||||||
// When the url field contains no values ([]), texturing is disabled.
|
|
||||||
void X3DImporter::ParseNode_Texturing_ImageTexture()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
bool repeatS = true;
|
|
||||||
bool repeatT = true;
|
|
||||||
std::list<std::string> url;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("repeatS", repeatS, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("repeatT", repeatT, XML_ReadNode_GetAttrVal_AsBool);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ImageTexture, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DImageTexture(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DImageTexture*)ne)->RepeatS = repeatS;
|
|
||||||
((X3DImageTexture*)ne)->RepeatT = repeatT;
|
|
||||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
|
||||||
if(!url.empty())
|
|
||||||
((X3DImageTexture*)ne)->URL = url.front();
|
|
||||||
else
|
|
||||||
((X3DImageTexture*)ne)->URL = "";
|
|
||||||
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "ImageTexture");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <TextureCoordinate
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// point="" MFVec3f [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Texturing_TextureCoordinate()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
std::list<aiVector2D> point;
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureCoordinate, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DTextureCoordinate(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DTextureCoordinate*)ne)->Value = point;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "TextureCoordinate");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
// <TextureTransform
|
|
||||||
// DEF="" ID
|
|
||||||
// USE="" IDREF
|
|
||||||
// center="0 0" SFVec2f [inputOutput]
|
|
||||||
// rotation="0" SFFloat [inputOutput]
|
|
||||||
// scale="1 1" SFVec2f [inputOutput]
|
|
||||||
// translation="0 0" SFVec2f [inputOutput]
|
|
||||||
// />
|
|
||||||
void X3DImporter::ParseNode_Texturing_TextureTransform()
|
|
||||||
{
|
|
||||||
std::string use, def;
|
|
||||||
aiVector2D center(0, 0);
|
|
||||||
float rotation = 0;
|
|
||||||
aiVector2D scale(1, 1);
|
|
||||||
aiVector2D translation(0, 0);
|
|
||||||
X3DNodeElementBase* ne( nullptr );
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("rotation", rotation, XML_ReadNode_GetAttrVal_AsFloat);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec2f);
|
|
||||||
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec2f);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
|
||||||
if(!use.empty())
|
|
||||||
{
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureTransform, ne);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create and if needed - define new geometry object.
|
|
||||||
ne = new X3DTextureTransform(mNodeElementCur);
|
|
||||||
if(!def.empty()) ne->ID = def;
|
|
||||||
|
|
||||||
((X3DTextureTransform*)ne)->Center = center;
|
|
||||||
((X3DTextureTransform*)ne)->Rotation = rotation;
|
|
||||||
((X3DTextureTransform*)ne)->Scale = scale;
|
|
||||||
((X3DTextureTransform*)ne)->Translation = translation;
|
|
||||||
// check for X3DMetadataObject childs.
|
|
||||||
if(!mReader->isEmptyElement())
|
|
||||||
ParseNode_Metadata(ne, "TextureTransform");
|
|
||||||
else
|
|
||||||
mNodeElementCur->Child.push_back(ne);// add made object as child to current element
|
|
||||||
|
|
||||||
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
|
||||||
}// if(!use.empty()) else
|
|
||||||
}
|
|
||||||
|
|
||||||
}// namespace Assimp
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
File diff suppressed because it is too large
Load Diff
|
@ -249,7 +249,7 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void XGLImporter::ReadWorld(TempScope &scope) {
|
void XGLImporter::ReadWorld(TempScope &scope) {
|
||||||
XmlNode *root = m_xmlParser->getRootNode();
|
XmlNode *root = mXmlParser->getRootNode();
|
||||||
for (XmlNode &node : root->children()) {
|
for (XmlNode &node : root->children()) {
|
||||||
const std::string &s = node.name();
|
const std::string &s = node.name();
|
||||||
// XXX right now we'd skip <lighting> if it comes after
|
// XXX right now we'd skip <lighting> if it comes after
|
||||||
|
@ -261,7 +261,7 @@ void XGLImporter::ReadWorld(TempScope &scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aiNode *const nd = ReadObject(*root, scope, true, "world");
|
aiNode *const nd = ReadObject( *root, scope, true);
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
ThrowException("failure reading <world>");
|
ThrowException("failure reading <world>");
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ aiLight *XGLImporter::ReadDirectionalLight(XmlNode &node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope, bool skipFirst, const char *closetag) {
|
aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope, bool skipFirst/*, const char *closetag */) {
|
||||||
aiNode *nd = new aiNode;
|
aiNode *nd = new aiNode;
|
||||||
std::vector<aiNode *> children;
|
std::vector<aiNode *> children;
|
||||||
std::vector<unsigned int> meshes;
|
std::vector<unsigned int> meshes;
|
||||||
|
@ -546,22 +546,22 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
|
||||||
TempFace tf[3];
|
TempFace tf[3];
|
||||||
bool has[3] = { false };
|
bool has[3] = { false };
|
||||||
for (XmlNode &sub_child : child.children()) {
|
for (XmlNode &sub_child : child.children()) {
|
||||||
const std::string &s = sub_child.name();
|
const std::string &scn = sub_child.name();
|
||||||
if (s == "fv1" || s == "lv1" || s == "pv1") {
|
if (scn == "fv1" || scn == "lv1" || scn == "pv1") {
|
||||||
ReadFaceVertex(sub_child, t, tf[0]);
|
ReadFaceVertex(sub_child, t, tf[0]);
|
||||||
has[0] = true;
|
has[0] = true;
|
||||||
} else if (s == "fv2" || s == "lv2") {
|
} else if (scn == "fv2" || scn == "lv2") {
|
||||||
ReadFaceVertex(sub_child, t, tf[1]);
|
ReadFaceVertex(sub_child, t, tf[1]);
|
||||||
has[1] = true;
|
has[1] = true;
|
||||||
} else if (s == "fv3") {
|
} else if (scn == "fv3") {
|
||||||
ReadFaceVertex(sub_child, t, tf[2]);
|
ReadFaceVertex(sub_child, t, tf[2]);
|
||||||
has[2] = true;
|
has[2] = true;
|
||||||
} else if (s == "mat") {
|
} else if (scn == "mat") {
|
||||||
if (mid != ~0u) {
|
if (mid != ~0u) {
|
||||||
LogWarn("only one material tag allowed per <f>");
|
LogWarn("only one material tag allowed per <f>");
|
||||||
}
|
}
|
||||||
mid = ResolveMaterialRef(sub_child, scope);
|
mid = ResolveMaterialRef(sub_child, scope);
|
||||||
} else if (s == "matref") {
|
} else if (scn == "matref") {
|
||||||
if (mid != ~0u) {
|
if (mid != ~0u) {
|
||||||
LogWarn("only one material tag allowed per <f>");
|
LogWarn("only one material tag allowed per <f>");
|
||||||
}
|
}
|
||||||
|
@ -688,10 +688,7 @@ void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
void XGLImporter::ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out) {
|
void XGLImporter::ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out) {
|
||||||
const std::string &end = node.name();
|
|
||||||
|
|
||||||
bool havep = false;
|
bool havep = false;
|
||||||
//while (ReadElementUpToClosing(end.c_str())) {
|
|
||||||
for (XmlNode &child : node.children()) {
|
for (XmlNode &child : node.children()) {
|
||||||
const std::string &s = child.name();
|
const std::string &s = child.name();
|
||||||
if (s == "pref") {
|
if (s == "pref") {
|
||||||
|
|
|
@ -170,27 +170,26 @@ private:
|
||||||
bool ReadElement();
|
bool ReadElement();
|
||||||
bool ReadElementUpToClosing(const char *closetag);
|
bool ReadElementUpToClosing(const char *closetag);
|
||||||
bool SkipToText();
|
bool SkipToText();
|
||||||
unsigned int ReadIDAttr();
|
unsigned int ReadIDAttr(XmlNode &node);
|
||||||
|
|
||||||
void ReadWorld(TempScope &scope);
|
void ReadWorld(TempScope &scope);
|
||||||
void ReadLighting(TempScope &scope);
|
void ReadLighting(XmlNode &node, TempScope &scope);
|
||||||
aiLight *ReadDirectionalLight();
|
aiLight *ReadDirectionalLight(XmlNode &node);
|
||||||
aiNode *ReadObject(TempScope &scope, bool skipFirst = false, const char *closetag = "object");
|
aiNode *ReadObject(XmlNode &node, TempScope &scope, bool skipFirst = false/*, const char *closetag = "object"*/);
|
||||||
bool ReadMesh(TempScope &scope);
|
bool ReadMesh(XmlNode &node, TempScope &scope);
|
||||||
void ReadMaterial(TempScope &scope);
|
void ReadMaterial(XmlNode &node, TempScope &scope);
|
||||||
aiVector2D ReadVec2();
|
aiVector2D ReadVec2(XmlNode &node);
|
||||||
aiVector3D ReadVec3();
|
aiVector3D ReadVec3(XmlNode &node);
|
||||||
aiColor3D ReadCol3();
|
aiColor3D ReadCol3(XmlNode &node);
|
||||||
aiMatrix4x4 ReadTrafo();
|
aiMatrix4x4 ReadTrafo(XmlNode &node);
|
||||||
unsigned int ReadIndexFromText();
|
unsigned int ReadIndexFromText(XmlNode &node);
|
||||||
float ReadFloat();
|
float ReadFloat(XmlNode &node);
|
||||||
|
|
||||||
aiMesh *ToOutputMesh(const TempMaterialMesh &m);
|
aiMesh *ToOutputMesh(const TempMaterialMesh &m);
|
||||||
void ReadFaceVertex(const TempMesh &t, TempFace &out);
|
void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out);
|
||||||
unsigned int ResolveMaterialRef(TempScope &scope);
|
unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//std::shared_ptr<irr::io::IrrXMLReader> m_reader;
|
|
||||||
XmlParser *mXmlParser;
|
XmlParser *mXmlParser;
|
||||||
aiScene *m_scene;
|
aiScene *m_scene;
|
||||||
};
|
};
|
||||||
|
|
|
@ -800,21 +800,6 @@ ADD_ASSIMP_IMPORTER( X
|
||||||
ADD_ASSIMP_IMPORTER( X3D
|
ADD_ASSIMP_IMPORTER( X3D
|
||||||
AssetLib/X3D/X3DImporter.cpp
|
AssetLib/X3D/X3DImporter.cpp
|
||||||
AssetLib/X3D/X3DImporter.hpp
|
AssetLib/X3D/X3DImporter.hpp
|
||||||
AssetLib/X3D/X3DImporter_Geometry2D.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Geometry3D.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Group.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Light.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Macro.hpp
|
|
||||||
AssetLib/X3D/X3DImporter_Metadata.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Networking.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Node.hpp
|
|
||||||
AssetLib/X3D/X3DImporter_Postprocess.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Rendering.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Shape.cpp
|
|
||||||
AssetLib/X3D/X3DImporter_Texturing.cpp
|
|
||||||
#AssetLib/X3D/FIReader.hpp
|
|
||||||
#AssetLib/X3D/FIReader.cpp
|
|
||||||
#AssetLib/X3D/X3DVocabulary.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER( GLTF
|
ADD_ASSIMP_IMPORTER( GLTF
|
||||||
|
|
|
@ -47,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_PARSING_UTILS_H_INC
|
#define AI_PARSING_UTILS_H_INC
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# pragma GCC system_header
|
#pragma GCC system_header
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <assimp/StringComparison.h>
|
#include <assimp/StringComparison.h>
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
#include <assimp/defs.h>
|
#include <assimp/defs.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -72,57 +73,53 @@ static const unsigned int BufferSize = 4096;
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE
|
||||||
char_t ToLower( char_t in ) {
|
char_t
|
||||||
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
|
ToLower(char_t in) {
|
||||||
|
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in + 0x20) : in;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE
|
||||||
char_t ToUpper( char_t in) {
|
char_t
|
||||||
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
|
ToUpper(char_t in) {
|
||||||
|
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in - 0x20) : in;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool IsUpper(char_t in) {
|
||||||
bool IsUpper( char_t in) {
|
|
||||||
return (in >= (char_t)'A' && in <= (char_t)'Z');
|
return (in >= (char_t)'A' && in <= (char_t)'Z');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool IsLower(char_t in) {
|
||||||
bool IsLower( char_t in) {
|
|
||||||
return (in >= (char_t)'a' && in <= (char_t)'z');
|
return (in >= (char_t)'a' && in <= (char_t)'z');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool IsSpace(char_t in) {
|
||||||
bool IsSpace( char_t in) {
|
|
||||||
return (in == (char_t)' ' || in == (char_t)'\t');
|
return (in == (char_t)' ' || in == (char_t)'\t');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool IsLineEnd(char_t in) {
|
||||||
bool IsLineEnd( char_t in) {
|
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0' || in == (char_t)'\f');
|
||||||
return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool IsSpaceOrNewLine(char_t in) {
|
||||||
bool IsSpaceOrNewLine( char_t in) {
|
|
||||||
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
|
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipSpaces(const char_t *in, const char_t **out) {
|
||||||
bool SkipSpaces( const char_t* in, const char_t** out) {
|
while (*in == (char_t)' ' || *in == (char_t)'\t') {
|
||||||
while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
|
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
*out = in;
|
*out = in;
|
||||||
|
@ -131,21 +128,19 @@ bool SkipSpaces( const char_t* in, const char_t** out) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipSpaces(const char_t **inout) {
|
||||||
bool SkipSpaces( const char_t** inout) {
|
return SkipSpaces<char_t>(*inout, inout);
|
||||||
return SkipSpaces<char_t>(*inout,inout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipLine(const char_t *in, const char_t **out) {
|
||||||
bool SkipLine( const char_t* in, const char_t** out) {
|
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0') {
|
||||||
while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
|
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
|
|
||||||
// files are opened in binary mode. Ergo there are both NL and CR
|
// files are opened in binary mode. Ergo there are both NL and CR
|
||||||
while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
while (*in == (char_t)'\r' || *in == (char_t)'\n') {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
*out = in;
|
*out = in;
|
||||||
|
@ -154,16 +149,14 @@ bool SkipLine( const char_t* in, const char_t** out) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipLine(const char_t **inout) {
|
||||||
bool SkipLine( const char_t** inout) {
|
return SkipLine<char_t>(*inout, inout);
|
||||||
return SkipLine<char_t>(*inout,inout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t *in, const char_t **out) {
|
||||||
bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
|
while (*in == (char_t)' ' || *in == (char_t)'\t' || *in == (char_t)'\r' || *in == (char_t)'\n') {
|
||||||
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
*out = in;
|
*out = in;
|
||||||
|
@ -172,27 +165,25 @@ bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t **inout) {
|
||||||
bool SkipSpacesAndLineEnd( const char_t** inout) {
|
return SkipSpacesAndLineEnd<char_t>(*inout, inout);
|
||||||
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool GetNextLine(const char_t *&buffer, char_t out[BufferSize]) {
|
||||||
bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
|
if ((char_t)'\0' == *buffer) {
|
||||||
if( ( char_t )'\0' == *buffer ) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* _out = out;
|
char *_out = out;
|
||||||
char* const end = _out + BufferSize;
|
char *const end = _out + BufferSize;
|
||||||
while( !IsLineEnd( *buffer ) && _out < end ) {
|
while (!IsLineEnd(*buffer) && _out < end) {
|
||||||
*_out++ = *buffer++;
|
*_out++ = *buffer++;
|
||||||
}
|
}
|
||||||
*_out = (char_t)'\0';
|
*_out = (char_t)'\0';
|
||||||
|
|
||||||
while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
|
while (IsLineEnd(*buffer) && '\0' != *buffer) {
|
||||||
++buffer;
|
++buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,18 +192,16 @@ bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE bool IsNumeric( char_t in) {
|
AI_FORCE_INLINE bool IsNumeric(char_t in) {
|
||||||
return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
|
return (in >= '0' && in <= '9') || '-' == in || '+' == in;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
template <class char_t>
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE bool TokenMatch(char_t *&in, const char *token, unsigned int len) {
|
||||||
bool TokenMatch(char_t*& in, const char* token, unsigned int len)
|
if (!::strncmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
|
||||||
{
|
|
||||||
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
|
||||||
if (in[len] != '\0') {
|
if (in[len] != '\0') {
|
||||||
in += len+1;
|
in += len + 1;
|
||||||
} else {
|
} else {
|
||||||
// If EOF after the token make sure we don't go past end of buffer
|
// If EOF after the token make sure we don't go past end of buffer
|
||||||
in += len;
|
in += len;
|
||||||
|
@ -229,9 +218,9 @@ bool TokenMatch(char_t*& in, const char* token, unsigned int len)
|
||||||
* @param len Number of characters to check
|
* @param len Number of characters to check
|
||||||
*/
|
*/
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE
|
||||||
bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
|
bool TokenMatchI(const char *&in, const char *token, unsigned int len) {
|
||||||
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
if (!ASSIMP_strincmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
|
||||||
in += len+1;
|
in += len + 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -239,22 +228,22 @@ bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE
|
||||||
void SkipToken(const char*& in) {
|
void SkipToken(const char *&in) {
|
||||||
SkipSpaces(&in);
|
SkipSpaces(&in);
|
||||||
while ( !IsSpaceOrNewLine( *in ) ) {
|
while (!IsSpaceOrNewLine(*in)) {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE
|
AI_FORCE_INLINE
|
||||||
std::string GetNextToken(const char*& in) {
|
std::string GetNextToken(const char *&in) {
|
||||||
SkipSpacesAndLineEnd(&in);
|
SkipSpacesAndLineEnd(&in);
|
||||||
const char* cur = in;
|
const char *cur = in;
|
||||||
while ( !IsSpaceOrNewLine( *in ) ) {
|
while (!IsSpaceOrNewLine(*in)) {
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
return std::string(cur,(size_t)(in-cur));
|
return std::string(cur, (size_t)(in - cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -290,6 +279,6 @@ AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
} // ! namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
#endif // ! AI_PARSING_UTILS_H_INC
|
#endif // ! AI_PARSING_UTILS_H_INC
|
||||||
|
|
Loading…
Reference in New Issue