12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- Copyright (c) 2006-2025, 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 "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>
- static constexpr aiImporterDesc desc = {
- "Open Game Engine Exchange",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "ogex"
- };
- namespace Grammar {
- static constexpr char MetricType[] = "Metric";
- static constexpr char Metric_DistanceType[] = "distance";
- static constexpr char Metric_AngleType[] = "angle";
- static constexpr char Metric_TimeType[] = "time";
- static constexpr char Metric_UpType[] = "up";
- static constexpr char NameType[] = "Name";
- static constexpr char ObjectRefType[] = "ObjectRef";
- static constexpr char MaterialRefType[] = "MaterialRef";
- static constexpr char MetricKeyType[] = "key";
- static constexpr char GeometryNodeType[] = "GeometryNode";
- static constexpr char CameraNodeType[] = "CameraNode";
- static constexpr char LightNodeType[] = "LightNode";
- static constexpr char GeometryObjectType[] = "GeometryObject";
- static constexpr char CameraObjectType[] = "CameraObject";
- static constexpr char LightObjectType[] = "LightObject";
- static constexpr char TransformType[] = "Transform";
- static constexpr char MeshType[] = "Mesh";
- static constexpr char VertexArrayType[] = "VertexArray";
- static constexpr char IndexArrayType[] = "IndexArray";
- static constexpr char MaterialType[] = "Material";
- static constexpr char ColorType[] = "Color";
- static constexpr char ParamType[] = "Param";
- static constexpr char TextureType[] = "Texture";
- static constexpr char AttenType[] = "Atten";
- static constexpr char DiffuseColorToken[] = "diffuse";
- static constexpr char SpecularColorToken[] = "specular";
- static constexpr char EmissionColorToken[] = "emission";
- static constexpr char DiffuseTextureToken[] = "diffuse";
- static constexpr char DiffuseSpecularTextureToken[] = "specular";
- static constexpr char SpecularPowerTextureToken[] = "specular_power";
- static constexpr char EmissionTextureToken[] = "emission";
- static constexpr char OpacyTextureToken[] = "opacity";
- static constexpr char TransparencyTextureToken[] = "transparency";
- static constexpr char 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) {
- const size_t len = std::strlen(tokenType);
- if (0 == strncmp(MetricType, tokenType, len)) {
- return MetricToken;
- } else if (0 == strncmp(NameType, tokenType, len)) {
- return NameToken;
- } else if (0 == strncmp(ObjectRefType, tokenType, len)) {
- return ObjectRefToken;
- } else if (0 == strncmp(MaterialRefType, tokenType, len)) {
- return MaterialRefToken;
- } else if (0 == strncmp(MetricKeyType, tokenType, len)) {
- return MetricKeyToken;
- } else if (0 == strncmp(GeometryNodeType, tokenType, len)) {
- return GeometryNodeToken;
- } else if (0 == strncmp(CameraNodeType, tokenType, len)) {
- return CameraNodeToken;
- } else if (0 == strncmp(LightNodeType, tokenType, len)) {
- return LightNodeToken;
- } else if (0 == strncmp(GeometryObjectType, tokenType, len)) {
- return GeometryObjectToken;
- } else if (0 == strncmp(CameraObjectType, tokenType, len)) {
- return CameraObjectToken;
- } else if (0 == strncmp(LightObjectType, tokenType, len)) {
- return LightObjectToken;
- } else if (0 == strncmp(TransformType, tokenType, len)) {
- return TransformToken;
- } else if (0 == strncmp(MeshType, tokenType, len)) {
- return MeshToken;
- } else if (0 == strncmp(VertexArrayType, tokenType, len)) {
- return VertexArrayToken;
- } else if (0 == strncmp(IndexArrayType, tokenType, len)) {
- return IndexArrayToken;
- } else if (0 == strncmp(MaterialType, tokenType, len)) {
- return MaterialToken;
- } else if (0 == strncmp(ColorType, tokenType, len)) {
- return ColorToken;
- } else if (0 == strncmp(ParamType, tokenType, len)) {
- return ParamToken;
- } else if (0 == strncmp(TextureType, tokenType, len)) {
- return TextureToken;
- } else if (0 == strncmp(AttenType, tokenType, len)) {
- 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::OpenGEXImporter() :
- m_root(nullptr),
- m_nodeChildMap(),
- 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
- }
- //------------------------------------------------------------------------------------------------
- bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
- static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
- return SearchFileHeaderForToken(pIOHandler, file, tokens, AI_COUNT_OF(tokens));
- }
- //------------------------------------------------------------------------------------------------
- void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
- // open source file
- std::unique_ptr<IOStream> file(pIOHandler->Open(filename, "rb"));
- if (!file) {
- throw DeadlyImportError("Failed to open file ", filename);
- }
- std::vector<char> buffer;
- TextFileToBuffer(file.get(), buffer);
- 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);
- // TODO: lights only partially implemented and breaking model import
- // 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 children = node->getChildNodeList();
- for (DDLNode::DllNodeList::iterator it = children.begin(); it != children.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:
- // TODO: lights only partially implemented and breaking model import
- // handleLightNode(*it, pScene);
- break;
- case Grammar::GeometryObjectToken:
- handleGeometryObject(*it, pScene);
- break;
- case Grammar::CameraObjectToken:
- handleCameraObject(*it, pScene);
- break;
- case Grammar::LightObjectToken:
- // TODO: lights only partially implemented and breaking model import
- // 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.");
- }
- 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.");
- }
- const std::string name(val->getString());
- if (m_tokenType == Grammar::GeometryNodeToken ||
- // TODO: lights only partially implemented and breaking model import
- // 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.");
- }
- 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.");
- }
- 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.");
- }
- DataArrayList *transformData(node->getDataArrayList());
- if (nullptr != transformData) {
- if (transformData->m_numItems != 16) {
- throw DeadlyImportError("Invalid number of data for transform matrix.");
- }
- 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
- };
- constexpr auto PosToken = "position";
- constexpr auto ColToken = "color";
- constexpr auto NormalToken = "normal";
- constexpr auto TexCoordToken = "texcoord";
- //------------------------------------------------------------------------------------------------
- static MeshAttribute getAttributeByName(const char *attribName) {
- ai_assert(nullptr != attribName);
- if (0 == strcmp(PosToken, attribName)) {
- return Position;
- } else if (0 == strcmp(ColToken, attribName)) {
- return Color;
- } else if (0 == strcmp(NormalToken, attribName)) {
- return Normal;
- } else if (0 == strcmp(TexCoordToken, attribName)) {
- 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) {
- col4->a = 1.0f;
- } else {
- 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.");
- }
- 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.");
- }
- if (nullptr == m_currentMesh) {
- throw DeadlyImportError("No current mesh for index data found.");
- }
- 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++) {
- int idx = -1;
- if (next->m_type == Value::ValueType::ddl_unsigned_int16) {
- idx = next->getUnsignedInt16();
- } else if (next->m_type == Value::ValueType::ddl_unsigned_int32) {
- 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::DiffuseSpecularTextureToken) {
- m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(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
|