1336 lines
46 KiB
C++
1336 lines
46 KiB
C++
/*
|
|
Open Asset Import Library (assimp)
|
|
----------------------------------------------------------------------
|
|
|
|
Copyright (c) 2006-2021, 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.
|
|
|
|
----------------------------------------------------------------------
|
|
*/
|
|
#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
|
|
|
|
#include "AssetLib/OpenGEX/OpenGEXImporter.h"
|
|
#include "PostProcessing/MakeVerboseFormat.h"
|
|
|
|
#include <assimp/DefaultIOSystem.h>
|
|
#include <assimp/StringComparison.h>
|
|
#include <assimp/StringUtils.h>
|
|
#include <assimp/DefaultLogger.hpp>
|
|
|
|
#include <assimp/ai_assert.h>
|
|
#include <assimp/importerdesc.h>
|
|
#include <assimp/scene.h>
|
|
#include <openddlparser/OpenDDLParser.h>
|
|
|
|
#include <vector>
|
|
|
|
static const aiImporterDesc desc = {
|
|
"Open Game Engine Exchange",
|
|
"",
|
|
"",
|
|
"",
|
|
aiImporterFlags_SupportTextFlavour,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"ogex"
|
|
};
|
|
|
|
namespace Grammar {
|
|
static const std::string MetricType = "Metric";
|
|
static const std::string Metric_DistanceType = "distance";
|
|
static const std::string Metric_AngleType = "angle";
|
|
static const std::string Metric_TimeType = "time";
|
|
static const std::string Metric_UpType = "up";
|
|
static const std::string NameType = "Name";
|
|
static const std::string ObjectRefType = "ObjectRef";
|
|
static const std::string MaterialRefType = "MaterialRef";
|
|
static const std::string MetricKeyType = "key";
|
|
static const std::string GeometryNodeType = "GeometryNode";
|
|
static const std::string CameraNodeType = "CameraNode";
|
|
static const std::string LightNodeType = "LightNode";
|
|
static const std::string GeometryObjectType = "GeometryObject";
|
|
static const std::string CameraObjectType = "CameraObject";
|
|
static const std::string LightObjectType = "LightObject";
|
|
static const std::string TransformType = "Transform";
|
|
static const std::string MeshType = "Mesh";
|
|
static const std::string VertexArrayType = "VertexArray";
|
|
static const std::string IndexArrayType = "IndexArray";
|
|
static const std::string MaterialType = "Material";
|
|
static const std::string ColorType = "Color";
|
|
static const std::string ParamType = "Param";
|
|
static const std::string TextureType = "Texture";
|
|
static const std::string AttenType = "Atten";
|
|
|
|
static const std::string DiffuseColorToken = "diffuse";
|
|
static const std::string SpecularColorToken = "specular";
|
|
static const std::string EmissionColorToken = "emission";
|
|
|
|
static const std::string DiffuseTextureToken = "diffuse";
|
|
static const std::string DiffuseSpecularTextureToken = "specular";
|
|
static const std::string SpecularPowerTextureToken = "specular_power";
|
|
static const std::string EmissionTextureToken = "emission";
|
|
static const std::string OpacyTextureToken = "opacity";
|
|
static const std::string TransparencyTextureToken = "transparency";
|
|
static const std::string NormalTextureToken = "normal";
|
|
|
|
enum TokenType {
|
|
NoneType = -1,
|
|
MetricToken,
|
|
NameToken,
|
|
ObjectRefToken,
|
|
MaterialRefToken,
|
|
MetricKeyToken,
|
|
GeometryNodeToken,
|
|
CameraNodeToken,
|
|
LightNodeToken,
|
|
GeometryObjectToken,
|
|
CameraObjectToken,
|
|
LightObjectToken,
|
|
TransformToken,
|
|
MeshToken,
|
|
VertexArrayToken,
|
|
IndexArrayToken,
|
|
MaterialToken,
|
|
ColorToken,
|
|
ParamToken,
|
|
TextureToken,
|
|
AttenToken
|
|
};
|
|
|
|
static const std::string ValidMetricToken[4] = {
|
|
Metric_DistanceType,
|
|
Metric_AngleType,
|
|
Metric_TimeType,
|
|
Metric_UpType
|
|
};
|
|
|
|
static int isValidMetricType(const char *token) {
|
|
if (nullptr == token) {
|
|
return false;
|
|
}
|
|
|
|
int idx(-1);
|
|
for (size_t i = 0; i < 4; i++) {
|
|
if (ValidMetricToken[i] == token) {
|
|
idx = (int)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return idx;
|
|
}
|
|
|
|
static TokenType matchTokenType(const char *tokenType) {
|
|
if (MetricType == tokenType) {
|
|
return MetricToken;
|
|
} else if (NameType == tokenType) {
|
|
return NameToken;
|
|
} else if (ObjectRefType == tokenType) {
|
|
return ObjectRefToken;
|
|
} else if (MaterialRefType == tokenType) {
|
|
return MaterialRefToken;
|
|
} else if (MetricKeyType == tokenType) {
|
|
return MetricKeyToken;
|
|
} else if (GeometryNodeType == tokenType) {
|
|
return GeometryNodeToken;
|
|
} else if (CameraNodeType == tokenType) {
|
|
return CameraNodeToken;
|
|
} else if (LightNodeType == tokenType) {
|
|
return LightNodeToken;
|
|
} else if (GeometryObjectType == tokenType) {
|
|
return GeometryObjectToken;
|
|
} else if (CameraObjectType == tokenType) {
|
|
return CameraObjectToken;
|
|
} else if (LightObjectType == tokenType) {
|
|
return LightObjectToken;
|
|
} else if (TransformType == tokenType) {
|
|
return TransformToken;
|
|
} else if (MeshType == tokenType) {
|
|
return MeshToken;
|
|
} else if (VertexArrayType == tokenType) {
|
|
return VertexArrayToken;
|
|
} else if (IndexArrayType == tokenType) {
|
|
return IndexArrayToken;
|
|
} else if (MaterialType == tokenType) {
|
|
return MaterialToken;
|
|
} else if (ColorType == tokenType) {
|
|
return ColorToken;
|
|
} else if (ParamType == tokenType) {
|
|
return ParamToken;
|
|
} else if (TextureType == tokenType) {
|
|
return TextureToken;
|
|
} else if (AttenType == tokenType) {
|
|
return AttenToken;
|
|
}
|
|
|
|
return NoneType;
|
|
}
|
|
} // Namespace Grammar
|
|
|
|
namespace Assimp {
|
|
namespace OpenGEX {
|
|
|
|
USE_ODDLPARSER_NS
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void propId2StdString(Property *prop, std::string &name, std::string &key) {
|
|
name = key = std::string();
|
|
if (nullptr == prop) {
|
|
return;
|
|
}
|
|
|
|
if (nullptr != prop->m_key) {
|
|
#ifdef ASSIMP_USE_HUNTER
|
|
name = prop->m_key->m_text.m_buffer;
|
|
#else
|
|
name = prop->m_key->m_buffer;
|
|
#endif
|
|
if (Value::ValueType::ddl_string == prop->m_value->m_type) {
|
|
key = prop->m_value->getString();
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void logDDLParserMessage (LogSeverity severity, const std::string &rawmsg) {
|
|
std::string msg = ai_str_toprintable(rawmsg);
|
|
switch (severity) {
|
|
case ddl_debug_msg: ASSIMP_LOG_DEBUG(msg); break;
|
|
case ddl_info_msg: ASSIMP_LOG_INFO(msg); break;
|
|
case ddl_warn_msg: ASSIMP_LOG_WARN(msg); break;
|
|
case ddl_error_msg: ASSIMP_LOG_ERROR(msg); break;
|
|
default: ASSIMP_LOG_VERBOSE_DEBUG(msg); break;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::VertexContainer::VertexContainer() :
|
|
m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() {
|
|
// empty
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::VertexContainer::~VertexContainer() {
|
|
delete[] m_colors;
|
|
|
|
for (auto &texcoords : m_textureCoords) {
|
|
delete[] texcoords;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::string> &names) :
|
|
m_node(node),
|
|
m_type(type),
|
|
m_Names(names) {
|
|
// empty
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::RefInfo::~RefInfo() {
|
|
// empty
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::OpenGEXImporter() :
|
|
m_root(nullptr),
|
|
m_nodeChildMap(),
|
|
m_meshCache(),
|
|
m_mesh2refMap(),
|
|
m_material2refMap(),
|
|
m_ctx(nullptr),
|
|
m_metrics(),
|
|
m_currentNode(nullptr),
|
|
m_currentVertices(),
|
|
m_currentMesh(nullptr),
|
|
m_currentMaterial(nullptr),
|
|
m_currentLight(nullptr),
|
|
m_currentCamera(nullptr),
|
|
m_tokenType(Grammar::NoneType),
|
|
m_materialCache(),
|
|
m_cameraCache(),
|
|
m_lightCache(),
|
|
m_nodeStack(),
|
|
m_unresolvedRefStack() {
|
|
// empty
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
OpenGEXImporter::~OpenGEXImporter() {
|
|
m_ctx = nullptr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const {
|
|
bool canRead(false);
|
|
if (!checkSig) {
|
|
canRead = SimpleExtensionCheck(file, "ogex");
|
|
} else {
|
|
static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
|
|
canRead = BaseImporter::SearchFileHeaderForToken(pIOHandler, file, token, 4);
|
|
}
|
|
|
|
return canRead;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
|
|
// open source file
|
|
IOStream *file = pIOHandler->Open(filename, "rb");
|
|
if (!file) {
|
|
throw DeadlyImportError("Failed to open file ", filename);
|
|
}
|
|
|
|
std::vector<char> buffer;
|
|
TextFileToBuffer(file, buffer);
|
|
pIOHandler->Close(file);
|
|
|
|
OpenDDLParser myParser;
|
|
myParser.setLogCallback(&logDDLParserMessage);
|
|
myParser.setBuffer(&buffer[0], buffer.size());
|
|
bool success(myParser.parse());
|
|
if (success) {
|
|
m_ctx = myParser.getContext();
|
|
pScene->mRootNode = new aiNode;
|
|
pScene->mRootNode->mName.Set(filename);
|
|
handleNodes(m_ctx->m_root, pScene);
|
|
}
|
|
|
|
copyMeshes(pScene);
|
|
copyCameras(pScene);
|
|
copyLights(pScene);
|
|
copyMaterials(pScene);
|
|
resolveReferences();
|
|
createNodeTree(pScene);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
const aiImporterDesc *OpenGEXImporter::GetInfo() const {
|
|
return &desc;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::SetupProperties(const Importer *pImp) {
|
|
if (nullptr == pImp) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleNodes(DDLNode *node, aiScene *pScene) {
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
DDLNode::DllNodeList childs = node->getChildNodeList();
|
|
for (DDLNode::DllNodeList::iterator it = childs.begin(); it != childs.end(); ++it) {
|
|
Grammar::TokenType tokenType(Grammar::matchTokenType((*it)->getType().c_str()));
|
|
switch (tokenType) {
|
|
case Grammar::MetricToken:
|
|
handleMetricNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::NameToken:
|
|
handleNameNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::ObjectRefToken:
|
|
handleObjectRefNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::MaterialRefToken:
|
|
handleMaterialRefNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::MetricKeyToken:
|
|
break;
|
|
|
|
case Grammar::GeometryNodeToken:
|
|
handleGeometryNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::CameraNodeToken:
|
|
handleCameraNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::LightNodeToken:
|
|
handleLightNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::GeometryObjectToken:
|
|
handleGeometryObject(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::CameraObjectToken:
|
|
handleCameraObject(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::LightObjectToken:
|
|
handleLightObject(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::TransformToken:
|
|
handleTransformNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::MeshToken:
|
|
handleMeshNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::VertexArrayToken:
|
|
handleVertexArrayNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::IndexArrayToken:
|
|
handleIndexArrayNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::MaterialToken:
|
|
handleMaterialNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::ColorToken:
|
|
handleColorNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::ParamToken:
|
|
handleParamNode(*it, pScene);
|
|
break;
|
|
|
|
case Grammar::TextureToken:
|
|
handleTextureNode(*it, pScene);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node || nullptr == m_ctx) {
|
|
return;
|
|
}
|
|
|
|
if (m_ctx->m_root != node->getParent()) {
|
|
return;
|
|
}
|
|
|
|
Property *prop(node->getProperties());
|
|
while (nullptr != prop) {
|
|
if (nullptr != prop->m_key) {
|
|
if (Value::ValueType::ddl_string == prop->m_value->m_type) {
|
|
std::string valName((char *)prop->m_value->m_data);
|
|
int type(Grammar::isValidMetricType(valName.c_str()));
|
|
if (Grammar::NoneType != type) {
|
|
Value *val(node->getValue());
|
|
if (nullptr != val) {
|
|
if (Value::ValueType::ddl_float == val->m_type) {
|
|
m_metrics[type].m_floatValue = val->getFloat();
|
|
} else if (Value::ValueType::ddl_int32 == val->m_type) {
|
|
m_metrics[type].m_intValue = val->getInt32();
|
|
} else if (Value::ValueType::ddl_string == val->m_type) {
|
|
m_metrics[type].m_stringValue = std::string(val->getString());
|
|
} else {
|
|
throw DeadlyImportError("OpenGEX: invalid data type for Metric node.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
prop = prop->m_next;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == m_currentNode) {
|
|
throw DeadlyImportError("No current node for name.");
|
|
return;
|
|
}
|
|
|
|
Value *val(node->getValue());
|
|
if (nullptr != val) {
|
|
if (Value::ValueType::ddl_string != val->m_type) {
|
|
throw DeadlyImportError("OpenGEX: invalid data type for value in node name.");
|
|
return;
|
|
}
|
|
|
|
const std::string name(val->getString());
|
|
if (m_tokenType == Grammar::GeometryNodeToken || m_tokenType == Grammar::LightNodeToken || m_tokenType == Grammar::CameraNodeToken) {
|
|
m_currentNode->mName.Set(name.c_str());
|
|
} else if (m_tokenType == Grammar::MaterialToken) {
|
|
aiString aiName;
|
|
aiName.Set(name);
|
|
m_currentMaterial->AddProperty(&aiName, AI_MATKEY_NAME);
|
|
m_material2refMap[name] = m_materialCache.size() - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void getRefNames(DDLNode *node, std::vector<std::string> &names) {
|
|
ai_assert(nullptr != node);
|
|
|
|
Reference *ref = node->getReferences();
|
|
if (nullptr != ref) {
|
|
for (size_t i = 0; i < ref->m_numRefs; i++) {
|
|
Name *currentName(ref->m_referencedName[i]);
|
|
if (nullptr != currentName && nullptr != currentName->m_id) {
|
|
#ifdef ASSIMP_USE_HUNTER
|
|
const std::string name(currentName->m_id->m_text.m_buffer);
|
|
#else
|
|
const std::string name(currentName->m_id->m_buffer);
|
|
#endif
|
|
if (!name.empty()) {
|
|
names.push_back(name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == m_currentNode) {
|
|
throw DeadlyImportError("No parent node for name.");
|
|
return;
|
|
}
|
|
|
|
std::vector<std::string> objRefNames;
|
|
getRefNames(node, objRefNames);
|
|
|
|
// when we are dealing with a geometry node prepare the mesh cache
|
|
if (m_tokenType == Grammar::GeometryNodeToken) {
|
|
m_currentNode->mNumMeshes = static_cast<unsigned int>(objRefNames.size());
|
|
m_currentNode->mMeshes = new unsigned int[objRefNames.size()];
|
|
if (!objRefNames.empty()) {
|
|
m_unresolvedRefStack.push_back(std::unique_ptr<RefInfo>(new RefInfo(m_currentNode, RefInfo::MeshRef, objRefNames)));
|
|
}
|
|
} else if (m_tokenType == Grammar::LightNodeToken) {
|
|
// TODO!
|
|
} else if (m_tokenType == Grammar::CameraNodeToken) {
|
|
// TODO!
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == m_currentNode) {
|
|
throw DeadlyImportError("No parent node for name.");
|
|
return;
|
|
}
|
|
|
|
std::vector<std::string> matRefNames;
|
|
getRefNames(node, matRefNames);
|
|
if (!matRefNames.empty()) {
|
|
m_unresolvedRefStack.push_back(std::unique_ptr<RefInfo>(new RefInfo(m_currentNode, RefInfo::MaterialRef, matRefNames)));
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleGeometryNode(DDLNode *node, aiScene *pScene) {
|
|
aiNode *newNode = new aiNode;
|
|
pushNode(newNode, pScene);
|
|
m_tokenType = Grammar::GeometryNodeToken;
|
|
m_currentNode = newNode;
|
|
handleNodes(node, pScene);
|
|
|
|
popNode();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleCameraNode(DDLNode *node, aiScene *pScene) {
|
|
aiCamera *camera(new aiCamera);
|
|
m_cameraCache.push_back(camera);
|
|
m_currentCamera = camera;
|
|
|
|
aiNode *newNode = new aiNode;
|
|
pushNode(newNode, pScene);
|
|
m_tokenType = Grammar::CameraNodeToken;
|
|
m_currentNode = newNode;
|
|
|
|
handleNodes(node, pScene);
|
|
|
|
popNode();
|
|
|
|
m_currentCamera->mName.Set(newNode->mName.C_Str());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleLightNode(ODDLParser::DDLNode *node, aiScene *pScene) {
|
|
aiLight *light(new aiLight);
|
|
m_lightCache.push_back(light);
|
|
m_currentLight = light;
|
|
|
|
aiNode *newNode = new aiNode;
|
|
m_tokenType = Grammar::LightNodeToken;
|
|
m_currentNode = newNode;
|
|
pushNode(newNode, pScene);
|
|
|
|
handleNodes(node, pScene);
|
|
|
|
popNode();
|
|
|
|
m_currentLight->mName.Set(newNode->mName.C_Str());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleGeometryObject(DDLNode *node, aiScene *pScene) {
|
|
// parameters will be parsed normally in the tree, so just go for it
|
|
handleNodes(node, pScene);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleCameraObject(ODDLParser::DDLNode *node, aiScene *pScene) {
|
|
// parameters will be parsed normally in the tree, so just go for it
|
|
|
|
handleNodes(node, pScene);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleLightObject(ODDLParser::DDLNode *node, aiScene *pScene) {
|
|
aiLight *light(new aiLight);
|
|
m_lightCache.push_back(light);
|
|
std::string objName = node->getName();
|
|
if (!objName.empty()) {
|
|
light->mName.Set(objName);
|
|
}
|
|
m_currentLight = light;
|
|
|
|
Property *prop(node->findPropertyByName("type"));
|
|
if (nullptr != prop) {
|
|
if (nullptr != prop->m_value) {
|
|
std::string typeStr(prop->m_value->getString());
|
|
if ("point" == typeStr) {
|
|
m_currentLight->mType = aiLightSource_POINT;
|
|
} else if ("spot" == typeStr) {
|
|
m_currentLight->mType = aiLightSource_SPOT;
|
|
} else if ("infinite" == typeStr) {
|
|
m_currentLight->mType = aiLightSource_DIRECTIONAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// parameters will be parsed normally in the tree, so just go for it
|
|
handleNodes(node, pScene);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void setMatrix(aiNode *node, DataArrayList *transformData) {
|
|
ai_assert(nullptr != node);
|
|
ai_assert(nullptr != transformData);
|
|
|
|
float m[16];
|
|
size_t i(1);
|
|
Value *next(transformData->m_dataList->m_next);
|
|
m[0] = transformData->m_dataList->getFloat();
|
|
while (next != nullptr) {
|
|
m[i] = next->getFloat();
|
|
next = next->m_next;
|
|
i++;
|
|
}
|
|
|
|
ai_assert(i == 16);
|
|
|
|
node->mTransformation.a1 = m[0];
|
|
node->mTransformation.a2 = m[4];
|
|
node->mTransformation.a3 = m[8];
|
|
node->mTransformation.a4 = m[12];
|
|
|
|
node->mTransformation.b1 = m[1];
|
|
node->mTransformation.b2 = m[5];
|
|
node->mTransformation.b3 = m[9];
|
|
node->mTransformation.b4 = m[13];
|
|
|
|
node->mTransformation.c1 = m[2];
|
|
node->mTransformation.c2 = m[6];
|
|
node->mTransformation.c3 = m[10];
|
|
node->mTransformation.c4 = m[14];
|
|
|
|
node->mTransformation.d1 = m[3];
|
|
node->mTransformation.d2 = m[7];
|
|
node->mTransformation.d3 = m[11];
|
|
node->mTransformation.d4 = m[15];
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == m_currentNode) {
|
|
throw DeadlyImportError("No parent node for name.");
|
|
return;
|
|
}
|
|
|
|
DataArrayList *transformData(node->getDataArrayList());
|
|
if (nullptr != transformData) {
|
|
if (transformData->m_numItems != 16) {
|
|
throw DeadlyImportError("Invalid number of data for transform matrix.");
|
|
return;
|
|
}
|
|
setMatrix(m_currentNode, transformData);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleMeshNode(ODDLParser::DDLNode *node, aiScene *pScene) {
|
|
m_currentMesh = new aiMesh;
|
|
const size_t meshidx(m_meshCache.size());
|
|
// ownership is transferred but a reference remains in m_currentMesh
|
|
m_meshCache.emplace_back(m_currentMesh);
|
|
|
|
Property *prop = node->getProperties();
|
|
if (nullptr != prop) {
|
|
std::string propName, propKey;
|
|
propId2StdString(prop, propName, propKey);
|
|
if ("primitive" == propName) {
|
|
if ("points" == propKey) {
|
|
m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
|
} else if ("lines" == propKey) {
|
|
m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
|
} else if ("triangles" == propKey) {
|
|
m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
|
} else if ("quads" == propKey) {
|
|
m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
|
} else {
|
|
ASSIMP_LOG_WARN(propKey, " is not supported primitive type.");
|
|
}
|
|
}
|
|
}
|
|
|
|
handleNodes(node, pScene);
|
|
|
|
DDLNode *parent(node->getParent());
|
|
if (nullptr != parent) {
|
|
const std::string &name = parent->getName();
|
|
m_mesh2refMap[name] = meshidx;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
enum MeshAttribute {
|
|
None,
|
|
Position,
|
|
Color,
|
|
Normal,
|
|
TexCoord
|
|
};
|
|
|
|
static const std::string PosToken = "position";
|
|
static const std::string ColToken = "color";
|
|
static const std::string NormalToken = "normal";
|
|
static const std::string TexCoordToken = "texcoord";
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static MeshAttribute getAttributeByName(const char *attribName) {
|
|
ai_assert(nullptr != attribName);
|
|
|
|
if (0 == strncmp(PosToken.c_str(), attribName, PosToken.size())) {
|
|
return Position;
|
|
} else if (0 == strncmp(ColToken.c_str(), attribName, ColToken.size())) {
|
|
return Color;
|
|
} else if (0 == strncmp(NormalToken.c_str(), attribName, NormalToken.size())) {
|
|
return Normal;
|
|
} else if (0 == strncmp(TexCoordToken.c_str(), attribName, TexCoordToken.size())) {
|
|
return TexCoord;
|
|
}
|
|
|
|
return None;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void fillVector3(aiVector3D *vec3, Value *vals) {
|
|
ai_assert(nullptr != vec3);
|
|
ai_assert(nullptr != vals);
|
|
|
|
float x(0.0f), y(0.0f), z(0.0f);
|
|
Value *next(vals);
|
|
x = next->getFloat();
|
|
next = next->m_next;
|
|
y = next->getFloat();
|
|
next = next->m_next;
|
|
if (nullptr != next) {
|
|
z = next->getFloat();
|
|
}
|
|
|
|
vec3->Set(x, y, z);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void fillColor4(aiColor4D *col4, Value *vals) {
|
|
ai_assert(nullptr != col4);
|
|
ai_assert(nullptr != vals);
|
|
|
|
Value *next(vals);
|
|
col4->r = next->getFloat();
|
|
next = next->m_next;
|
|
if (!next) {
|
|
throw DeadlyImportError("OpenGEX: Not enough values to fill 4-element color, only 1");
|
|
}
|
|
|
|
col4->g = next->getFloat();
|
|
next = next->m_next;
|
|
if (!next) {
|
|
throw DeadlyImportError("OpenGEX: Not enough values to fill 4-element color, only 2");
|
|
}
|
|
|
|
col4->b = next->getFloat();
|
|
next = next->m_next;
|
|
if (!next) {
|
|
throw DeadlyImportError("OpenGEX: Not enough values to fill 4-element color, only 3");
|
|
}
|
|
|
|
col4->a = next->getFloat();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static size_t countDataArrayListItems(DataArrayList *vaList) {
|
|
size_t numItems(0);
|
|
if (nullptr == vaList) {
|
|
return numItems;
|
|
}
|
|
|
|
DataArrayList *next(vaList);
|
|
while (nullptr != next) {
|
|
if (nullptr != vaList->m_dataList) {
|
|
numItems++;
|
|
}
|
|
next = next->m_next;
|
|
}
|
|
|
|
return numItems;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void copyVectorArray(size_t numItems, DataArrayList *vaList, aiVector3D *vectorArray) {
|
|
for (size_t i = 0; i < numItems; i++) {
|
|
Value *next(vaList->m_dataList);
|
|
fillVector3(&vectorArray[i], next);
|
|
vaList = vaList->m_next;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void copyColor4DArray(size_t numItems, DataArrayList *vaList, aiColor4D *colArray) {
|
|
for (size_t i = 0; i < numItems; i++) {
|
|
Value *next(vaList->m_dataList);
|
|
fillColor4(&colArray[i], next);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
throw DeadlyImportError("No parent node for name.");
|
|
return;
|
|
}
|
|
|
|
Property *prop(node->getProperties());
|
|
if (nullptr != prop) {
|
|
std::string propName, propKey;
|
|
propId2StdString(prop, propName, propKey);
|
|
MeshAttribute attribType(getAttributeByName(propKey.c_str()));
|
|
if (None == attribType) {
|
|
return;
|
|
}
|
|
|
|
DataArrayList *vaList = node->getDataArrayList();
|
|
if (nullptr == vaList) {
|
|
return;
|
|
}
|
|
|
|
const size_t numItems(countDataArrayListItems(vaList));
|
|
|
|
if (Position == attribType) {
|
|
m_currentVertices.m_vertices.resize(numItems);
|
|
copyVectorArray(numItems, vaList, m_currentVertices.m_vertices.data());
|
|
} else if (Color == attribType) {
|
|
m_currentVertices.m_numColors = numItems;
|
|
m_currentVertices.m_colors = new aiColor4D[numItems];
|
|
copyColor4DArray(numItems, vaList, m_currentVertices.m_colors);
|
|
} else if (Normal == attribType) {
|
|
m_currentVertices.m_normals.resize(numItems);
|
|
copyVectorArray(numItems, vaList, m_currentVertices.m_normals.data());
|
|
} else if (TexCoord == attribType) {
|
|
m_currentVertices.m_numUVComps[0] = numItems;
|
|
m_currentVertices.m_textureCoords[0] = new aiVector3D[numItems];
|
|
copyVectorArray(numItems, vaList, m_currentVertices.m_textureCoords[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
throw DeadlyImportError("No parent node for name.");
|
|
return;
|
|
}
|
|
|
|
if (nullptr == m_currentMesh) {
|
|
throw DeadlyImportError("No current mesh for index data found.");
|
|
return;
|
|
}
|
|
|
|
DataArrayList *vaList = node->getDataArrayList();
|
|
if (nullptr == vaList) {
|
|
return;
|
|
}
|
|
|
|
const size_t numItems(countDataArrayListItems(vaList));
|
|
m_currentMesh->mNumFaces = static_cast<unsigned int>(numItems);
|
|
m_currentMesh->mFaces = new aiFace[numItems];
|
|
m_currentMesh->mNumVertices = static_cast<unsigned int>(numItems * 3);
|
|
m_currentMesh->mVertices = new aiVector3D[m_currentMesh->mNumVertices];
|
|
bool hasColors(false);
|
|
if (m_currentVertices.m_numColors > 0) {
|
|
m_currentMesh->mColors[0] = new aiColor4D[m_currentVertices.m_numColors];
|
|
hasColors = true;
|
|
}
|
|
bool hasNormalCoords(false);
|
|
if (!m_currentVertices.m_normals.empty()) {
|
|
m_currentMesh->mNormals = new aiVector3D[m_currentMesh->mNumVertices];
|
|
hasNormalCoords = true;
|
|
}
|
|
bool hasTexCoords(false);
|
|
if (m_currentVertices.m_numUVComps[0] > 0) {
|
|
m_currentMesh->mTextureCoords[0] = new aiVector3D[m_currentMesh->mNumVertices];
|
|
hasTexCoords = true;
|
|
}
|
|
|
|
unsigned int index(0);
|
|
for (size_t i = 0; i < m_currentMesh->mNumFaces; i++) {
|
|
aiFace ¤t(m_currentMesh->mFaces[i]);
|
|
current.mNumIndices = 3;
|
|
current.mIndices = new unsigned int[current.mNumIndices];
|
|
Value *next(vaList->m_dataList);
|
|
for (size_t indices = 0; indices < current.mNumIndices; indices++) {
|
|
const int idx(next->getUnsignedInt32());
|
|
ai_assert(static_cast<size_t>(idx) <= m_currentVertices.m_vertices.size());
|
|
ai_assert(index < m_currentMesh->mNumVertices);
|
|
aiVector3D &pos = (m_currentVertices.m_vertices[idx]);
|
|
m_currentMesh->mVertices[index].Set(pos.x, pos.y, pos.z);
|
|
if (hasColors) {
|
|
aiColor4D &col = m_currentVertices.m_colors[idx];
|
|
m_currentMesh->mColors[0][index] = col;
|
|
}
|
|
if (hasNormalCoords) {
|
|
aiVector3D &normal = (m_currentVertices.m_normals[idx]);
|
|
m_currentMesh->mNormals[index].Set(normal.x, normal.y, normal.z);
|
|
}
|
|
if (hasTexCoords) {
|
|
aiVector3D &tex = (m_currentVertices.m_textureCoords[0][idx]);
|
|
m_currentMesh->mTextureCoords[0][index].Set(tex.x, tex.y, tex.z);
|
|
}
|
|
current.mIndices[indices] = index;
|
|
index++;
|
|
|
|
next = next->m_next;
|
|
}
|
|
vaList = vaList->m_next;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void getColorRGB3(aiColor3D *pColor, DataArrayList *colList) {
|
|
if (nullptr == pColor || nullptr == colList) {
|
|
return;
|
|
}
|
|
|
|
ai_assert(3 == colList->m_numItems);
|
|
Value *val(colList->m_dataList);
|
|
pColor->r = val->getFloat();
|
|
val = val->getNext();
|
|
pColor->g = val->getFloat();
|
|
val = val->getNext();
|
|
pColor->b = val->getFloat();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static void getColorRGB4(aiColor4D *pColor, DataArrayList *colList) {
|
|
if (nullptr == pColor || nullptr == colList) {
|
|
return;
|
|
}
|
|
|
|
ai_assert(4 == colList->m_numItems);
|
|
Value *val(colList->m_dataList);
|
|
pColor->r = val->getFloat();
|
|
val = val->getNext();
|
|
pColor->g = val->getFloat();
|
|
val = val->getNext();
|
|
pColor->b = val->getFloat();
|
|
val = val->getNext();
|
|
pColor->a = val->getFloat();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
enum ColorType {
|
|
NoneColor = 0,
|
|
DiffuseColor,
|
|
SpecularColor,
|
|
EmissionColor,
|
|
LightColor
|
|
};
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
static ColorType getColorType(Text *id) {
|
|
if (nullptr == id) {
|
|
return NoneColor;
|
|
}
|
|
|
|
if (*id == Grammar::DiffuseColorToken) {
|
|
return DiffuseColor;
|
|
} else if (*id == Grammar::SpecularColorToken) {
|
|
return SpecularColor;
|
|
} else if (*id == Grammar::EmissionColorToken) {
|
|
return EmissionColor;
|
|
} else if (*id == "light") {
|
|
return LightColor;
|
|
}
|
|
|
|
return NoneColor;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleMaterialNode(ODDLParser::DDLNode *node, aiScene *pScene) {
|
|
m_currentMaterial = new aiMaterial;
|
|
m_materialCache.push_back(m_currentMaterial);
|
|
m_tokenType = Grammar::MaterialToken;
|
|
handleNodes(node, pScene);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleColorNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
Property *prop = node->findPropertyByName("attrib");
|
|
if (nullptr != prop) {
|
|
if (nullptr != prop->m_value) {
|
|
DataArrayList *colList(node->getDataArrayList());
|
|
if (nullptr == colList) {
|
|
return;
|
|
}
|
|
aiColor3D col;
|
|
if (3 == colList->m_numItems) {
|
|
aiColor3D col3;
|
|
getColorRGB3(&col3, colList);
|
|
col = col3;
|
|
} else {
|
|
aiColor4D col4;
|
|
getColorRGB4(&col4, colList);
|
|
col.r = col4.r;
|
|
col.g = col4.g;
|
|
col.b = col4.b;
|
|
}
|
|
#ifdef ASSIMP_USE_HUNTER
|
|
const ColorType colType(getColorType(&prop->m_key->m_text));
|
|
#else
|
|
const ColorType colType(getColorType(prop->m_key));
|
|
#endif
|
|
if (DiffuseColor == colType) {
|
|
m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_DIFFUSE);
|
|
} else if (SpecularColor == colType) {
|
|
m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_SPECULAR);
|
|
} else if (EmissionColor == colType) {
|
|
m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_EMISSIVE);
|
|
} else if (LightColor == colType) {
|
|
m_currentLight->mColorDiffuse = col;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleTextureNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
Property *prop = node->findPropertyByName("attrib");
|
|
if (nullptr != prop) {
|
|
if (nullptr != prop->m_value) {
|
|
Value *val(node->getValue());
|
|
if (nullptr != val) {
|
|
aiString tex;
|
|
tex.Set(val->getString());
|
|
if (prop->m_value->getString() == Grammar::DiffuseTextureToken) {
|
|
m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
|
} else if (prop->m_value->getString() == Grammar::SpecularPowerTextureToken) {
|
|
m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(0));
|
|
} else if (prop->m_value->getString() == Grammar::EmissionTextureToken) {
|
|
m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
|
|
} else if (prop->m_value->getString() == Grammar::OpacyTextureToken) {
|
|
m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_OPACITY(0));
|
|
} else if (prop->m_value->getString() == Grammar::TransparencyTextureToken) {
|
|
// ToDo!
|
|
// m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
|
|
} else if (prop->m_value->getString() == Grammar::NormalTextureToken) {
|
|
m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0));
|
|
} else {
|
|
ai_assert(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleParamNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
Property *prop = node->findPropertyByName("attrib");
|
|
if (nullptr == prop) {
|
|
return;
|
|
}
|
|
|
|
if (nullptr != prop->m_value) {
|
|
Value *val(node->getValue());
|
|
if (nullptr == val) {
|
|
return;
|
|
}
|
|
const float floatVal(val->getFloat());
|
|
if (0 == ASSIMP_strincmp("fov", prop->m_value->getString(), 3)) {
|
|
m_currentCamera->mHorizontalFOV = floatVal;
|
|
} else if (0 == ASSIMP_strincmp("near", prop->m_value->getString(), 4)) {
|
|
m_currentCamera->mClipPlaneNear = floatVal;
|
|
} else if (0 == ASSIMP_strincmp("far", prop->m_value->getString(), 3)) {
|
|
m_currentCamera->mClipPlaneFar = floatVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::handleAttenNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
Property *prop = node->findPropertyByName("curve");
|
|
if (nullptr != prop) {
|
|
if (nullptr != prop->m_value) {
|
|
Value *val(node->getValue());
|
|
const float floatVal(val->getFloat());
|
|
if (0 == strncmp("scale", prop->m_value->getString(), strlen("scale"))) {
|
|
m_currentLight->mAttenuationQuadratic = floatVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::copyMeshes(aiScene *pScene) {
|
|
ai_assert(nullptr != pScene);
|
|
|
|
if (m_meshCache.empty()) {
|
|
return;
|
|
}
|
|
|
|
pScene->mNumMeshes = static_cast<unsigned int>(m_meshCache.size());
|
|
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
|
for (unsigned int i = 0; i < pScene->mNumMeshes; i++) {
|
|
pScene->mMeshes[i] = m_meshCache[i].release();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::copyCameras(aiScene *pScene) {
|
|
ai_assert(nullptr != pScene);
|
|
|
|
if (m_cameraCache.empty()) {
|
|
return;
|
|
}
|
|
|
|
pScene->mNumCameras = static_cast<unsigned int>(m_cameraCache.size());
|
|
pScene->mCameras = new aiCamera *[pScene->mNumCameras];
|
|
std::copy(m_cameraCache.begin(), m_cameraCache.end(), pScene->mCameras);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::copyLights(aiScene *pScene) {
|
|
ai_assert(nullptr != pScene);
|
|
|
|
if (m_lightCache.empty()) {
|
|
return;
|
|
}
|
|
|
|
pScene->mNumLights = static_cast<unsigned int>(m_lightCache.size());
|
|
pScene->mLights = new aiLight *[pScene->mNumLights];
|
|
std::copy(m_lightCache.begin(), m_lightCache.end(), pScene->mLights);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::copyMaterials(aiScene *pScene) {
|
|
ai_assert(nullptr != pScene);
|
|
|
|
if (m_materialCache.empty()) {
|
|
return;
|
|
}
|
|
|
|
pScene->mNumMaterials = static_cast<unsigned int>(m_materialCache.size());
|
|
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
|
|
std::copy(m_materialCache.begin(), m_materialCache.end(), pScene->mMaterials);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::resolveReferences() {
|
|
if (m_unresolvedRefStack.empty()) {
|
|
return;
|
|
}
|
|
|
|
RefInfo *currentRefInfo(nullptr);
|
|
for (auto it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it) {
|
|
currentRefInfo = it->get();
|
|
if (nullptr != currentRefInfo) {
|
|
aiNode *node(currentRefInfo->m_node);
|
|
if (RefInfo::MeshRef == currentRefInfo->m_type) {
|
|
for (size_t i = 0; i < currentRefInfo->m_Names.size(); ++i) {
|
|
const std::string &name(currentRefInfo->m_Names[i]);
|
|
ReferenceMap::const_iterator curIt(m_mesh2refMap.find(name));
|
|
if (m_mesh2refMap.end() != curIt) {
|
|
unsigned int meshIdx = static_cast<unsigned int>(m_mesh2refMap[name]);
|
|
node->mMeshes[i] = meshIdx;
|
|
}
|
|
}
|
|
} else if (RefInfo::MaterialRef == currentRefInfo->m_type) {
|
|
for (size_t i = 0; i < currentRefInfo->m_Names.size(); ++i) {
|
|
const std::string name(currentRefInfo->m_Names[i]);
|
|
ReferenceMap::const_iterator curIt(m_material2refMap.find(name));
|
|
if (m_material2refMap.end() != curIt) {
|
|
if (nullptr != m_currentMesh) {
|
|
unsigned int matIdx = static_cast<unsigned int>(m_material2refMap[name]);
|
|
if (m_currentMesh->mMaterialIndex != 0) {
|
|
ASSIMP_LOG_WARN("Override of material reference in current mesh by material reference.");
|
|
}
|
|
m_currentMesh->mMaterialIndex = matIdx;
|
|
} else {
|
|
ASSIMP_LOG_WARN("Cannot resolve material reference, because no current mesh is there.");
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
throw DeadlyImportError("Unknown reference info to resolve.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::createNodeTree(aiScene *pScene) {
|
|
if (nullptr == m_root) {
|
|
return;
|
|
}
|
|
|
|
if (m_root->m_children.empty()) {
|
|
return;
|
|
}
|
|
|
|
pScene->mRootNode->mNumChildren = static_cast<unsigned int>(m_root->m_children.size());
|
|
pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren];
|
|
std::copy(m_root->m_children.begin(), m_root->m_children.end(), pScene->mRootNode->mChildren);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::pushNode(aiNode *node, aiScene *pScene) {
|
|
ai_assert(nullptr != pScene);
|
|
|
|
if (nullptr == node) {
|
|
return;
|
|
}
|
|
|
|
ChildInfo *info(nullptr);
|
|
if (m_nodeStack.empty()) {
|
|
node->mParent = pScene->mRootNode;
|
|
NodeChildMap::iterator it(m_nodeChildMap.find(node->mParent));
|
|
if (m_nodeChildMap.end() == it) {
|
|
info = new ChildInfo;
|
|
m_root = info;
|
|
m_nodeChildMap[node->mParent] = std::unique_ptr<ChildInfo>(info);
|
|
} else {
|
|
info = it->second.get();
|
|
}
|
|
info->m_children.push_back(node);
|
|
} else {
|
|
aiNode *parent(m_nodeStack.back());
|
|
ai_assert(nullptr != parent);
|
|
node->mParent = parent;
|
|
NodeChildMap::iterator it(m_nodeChildMap.find(node->mParent));
|
|
if (m_nodeChildMap.end() == it) {
|
|
info = new ChildInfo;
|
|
m_nodeChildMap[node->mParent] = std::unique_ptr<ChildInfo>(info);
|
|
} else {
|
|
info = it->second.get();
|
|
}
|
|
info->m_children.push_back(node);
|
|
}
|
|
m_nodeStack.push_back(node);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
aiNode *OpenGEXImporter::popNode() {
|
|
if (m_nodeStack.empty()) {
|
|
return nullptr;
|
|
}
|
|
|
|
aiNode *node(top());
|
|
m_nodeStack.pop_back();
|
|
|
|
return node;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
aiNode *OpenGEXImporter::top() const {
|
|
if (m_nodeStack.empty()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return m_nodeStack.back();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
void OpenGEXImporter::clearNodeStack() {
|
|
m_nodeStack.clear();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
} // Namespace OpenGEX
|
|
} // Namespace Assimp
|
|
|
|
#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER
|