/src/assimp/code/AssetLib/OpenGEX/OpenGEXImporter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2025, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | #ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER |
42 | | |
43 | | #include "OpenGEXImporter.h" |
44 | | #include "PostProcessing/MakeVerboseFormat.h" |
45 | | |
46 | | #include <assimp/DefaultIOSystem.h> |
47 | | #include <assimp/StringComparison.h> |
48 | | #include <assimp/StringUtils.h> |
49 | | #include <assimp/DefaultLogger.hpp> |
50 | | #include <assimp/ai_assert.h> |
51 | | #include <assimp/importerdesc.h> |
52 | | #include <assimp/scene.h> |
53 | | #include <openddlparser/OpenDDLParser.h> |
54 | | |
55 | | static constexpr aiImporterDesc desc = { |
56 | | "Open Game Engine Exchange", |
57 | | "", |
58 | | "", |
59 | | "", |
60 | | aiImporterFlags_SupportTextFlavour, |
61 | | 0, |
62 | | 0, |
63 | | 0, |
64 | | 0, |
65 | | "ogex" |
66 | | }; |
67 | | |
68 | | namespace Grammar { |
69 | | static constexpr char MetricType[] = "Metric"; |
70 | | static constexpr char Metric_DistanceType[] = "distance"; |
71 | | static constexpr char Metric_AngleType[] = "angle"; |
72 | | static constexpr char Metric_TimeType[] = "time"; |
73 | | static constexpr char Metric_UpType[] = "up"; |
74 | | static constexpr char NameType[] = "Name"; |
75 | | static constexpr char ObjectRefType[] = "ObjectRef"; |
76 | | static constexpr char MaterialRefType[] = "MaterialRef"; |
77 | | static constexpr char MetricKeyType[] = "key"; |
78 | | static constexpr char GeometryNodeType[] = "GeometryNode"; |
79 | | static constexpr char CameraNodeType[] = "CameraNode"; |
80 | | static constexpr char LightNodeType[] = "LightNode"; |
81 | | static constexpr char GeometryObjectType[] = "GeometryObject"; |
82 | | static constexpr char CameraObjectType[] = "CameraObject"; |
83 | | static constexpr char LightObjectType[] = "LightObject"; |
84 | | static constexpr char TransformType[] = "Transform"; |
85 | | static constexpr char MeshType[] = "Mesh"; |
86 | | static constexpr char VertexArrayType[] = "VertexArray"; |
87 | | static constexpr char IndexArrayType[] = "IndexArray"; |
88 | | static constexpr char MaterialType[] = "Material"; |
89 | | static constexpr char ColorType[] = "Color"; |
90 | | static constexpr char ParamType[] = "Param"; |
91 | | static constexpr char TextureType[] = "Texture"; |
92 | | static constexpr char AttenType[] = "Atten"; |
93 | | |
94 | | static constexpr char DiffuseColorToken[] = "diffuse"; |
95 | | static constexpr char SpecularColorToken[] = "specular"; |
96 | | static constexpr char EmissionColorToken[] = "emission"; |
97 | | |
98 | | static constexpr char DiffuseTextureToken[] = "diffuse"; |
99 | | static constexpr char DiffuseSpecularTextureToken[] = "specular"; |
100 | | static constexpr char SpecularPowerTextureToken[] = "specular_power"; |
101 | | static constexpr char EmissionTextureToken[] = "emission"; |
102 | | static constexpr char OpacyTextureToken[] = "opacity"; |
103 | | static constexpr char TransparencyTextureToken[] = "transparency"; |
104 | | static constexpr char NormalTextureToken[] = "normal"; |
105 | | |
106 | | enum TokenType { |
107 | | NoneType = -1, |
108 | | MetricToken, |
109 | | NameToken, |
110 | | ObjectRefToken, |
111 | | MaterialRefToken, |
112 | | MetricKeyToken, |
113 | | GeometryNodeToken, |
114 | | CameraNodeToken, |
115 | | LightNodeToken, |
116 | | GeometryObjectToken, |
117 | | CameraObjectToken, |
118 | | LightObjectToken, |
119 | | TransformToken, |
120 | | MeshToken, |
121 | | VertexArrayToken, |
122 | | IndexArrayToken, |
123 | | MaterialToken, |
124 | | ColorToken, |
125 | | ParamToken, |
126 | | TextureToken, |
127 | | AttenToken |
128 | | }; |
129 | | |
130 | | static const std::string ValidMetricToken[4] = { |
131 | | Metric_DistanceType, |
132 | | Metric_AngleType, |
133 | | Metric_TimeType, |
134 | | Metric_UpType |
135 | | }; |
136 | | |
137 | 0 | static int isValidMetricType(const char *token) { |
138 | 0 | if (nullptr == token) { |
139 | 0 | return false; |
140 | 0 | } |
141 | | |
142 | 0 | int idx = -1; |
143 | 0 | for (size_t i = 0; i < 4; i++) { |
144 | 0 | if (ValidMetricToken[i] == token) { |
145 | 0 | idx = (int)i; |
146 | 0 | break; |
147 | 0 | } |
148 | 0 | } |
149 | |
|
150 | 0 | return idx; |
151 | 0 | } |
152 | | |
153 | 0 | static TokenType matchTokenType(const char *tokenType) { |
154 | 0 | const size_t len = std::strlen(tokenType); |
155 | 0 | if (0 == strncmp(MetricType, tokenType, len)) { |
156 | 0 | return MetricToken; |
157 | 0 | } else if (0 == strncmp(NameType, tokenType, len)) { |
158 | 0 | return NameToken; |
159 | 0 | } else if (0 == strncmp(ObjectRefType, tokenType, len)) { |
160 | 0 | return ObjectRefToken; |
161 | 0 | } else if (0 == strncmp(MaterialRefType, tokenType, len)) { |
162 | 0 | return MaterialRefToken; |
163 | 0 | } else if (0 == strncmp(MetricKeyType, tokenType, len)) { |
164 | 0 | return MetricKeyToken; |
165 | 0 | } else if (0 == strncmp(GeometryNodeType, tokenType, len)) { |
166 | 0 | return GeometryNodeToken; |
167 | 0 | } else if (0 == strncmp(CameraNodeType, tokenType, len)) { |
168 | 0 | return CameraNodeToken; |
169 | 0 | } else if (0 == strncmp(LightNodeType, tokenType, len)) { |
170 | 0 | return LightNodeToken; |
171 | 0 | } else if (0 == strncmp(GeometryObjectType, tokenType, len)) { |
172 | 0 | return GeometryObjectToken; |
173 | 0 | } else if (0 == strncmp(CameraObjectType, tokenType, len)) { |
174 | 0 | return CameraObjectToken; |
175 | 0 | } else if (0 == strncmp(LightObjectType, tokenType, len)) { |
176 | 0 | return LightObjectToken; |
177 | 0 | } else if (0 == strncmp(TransformType, tokenType, len)) { |
178 | 0 | return TransformToken; |
179 | 0 | } else if (0 == strncmp(MeshType, tokenType, len)) { |
180 | 0 | return MeshToken; |
181 | 0 | } else if (0 == strncmp(VertexArrayType, tokenType, len)) { |
182 | 0 | return VertexArrayToken; |
183 | 0 | } else if (0 == strncmp(IndexArrayType, tokenType, len)) { |
184 | 0 | return IndexArrayToken; |
185 | 0 | } else if (0 == strncmp(MaterialType, tokenType, len)) { |
186 | 0 | return MaterialToken; |
187 | 0 | } else if (0 == strncmp(ColorType, tokenType, len)) { |
188 | 0 | return ColorToken; |
189 | 0 | } else if (0 == strncmp(ParamType, tokenType, len)) { |
190 | 0 | return ParamToken; |
191 | 0 | } else if (0 == strncmp(TextureType, tokenType, len)) { |
192 | 0 | return TextureToken; |
193 | 0 | } else if (0 == strncmp(AttenType, tokenType, len)) { |
194 | 0 | return AttenToken; |
195 | 0 | } |
196 | | |
197 | 0 | return NoneType; |
198 | 0 | } |
199 | | } // Namespace Grammar |
200 | | |
201 | | namespace Assimp { |
202 | | namespace OpenGEX { |
203 | | |
204 | | USE_ODDLPARSER_NS |
205 | | |
206 | | //------------------------------------------------------------------------------------------------ |
207 | 0 | static void propId2StdString(Property *prop, std::string &name, std::string &key) { |
208 | 0 | name = key = std::string(); |
209 | 0 | if (nullptr == prop) { |
210 | 0 | return; |
211 | 0 | } |
212 | | |
213 | 0 | if (nullptr != prop->m_key) { |
214 | | #ifdef ASSIMP_USE_HUNTER |
215 | | name = prop->m_key->m_text.m_buffer; |
216 | | #else |
217 | 0 | name = prop->m_key->m_buffer; |
218 | 0 | #endif |
219 | 0 | if (Value::ValueType::ddl_string == prop->m_value->m_type) { |
220 | 0 | key = prop->m_value->getString(); |
221 | 0 | } |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | | //------------------------------------------------------------------------------------------------ |
226 | 5 | static void logDDLParserMessage (LogSeverity severity, const std::string &rawmsg) { |
227 | 5 | std::string msg = ai_str_toprintable(rawmsg); |
228 | 5 | switch (severity) { |
229 | 0 | case ddl_debug_msg: ASSIMP_LOG_DEBUG(msg); break; |
230 | 0 | case ddl_info_msg: ASSIMP_LOG_INFO(msg); break; |
231 | 0 | case ddl_warn_msg: ASSIMP_LOG_WARN(msg); break; |
232 | 5 | case ddl_error_msg: ASSIMP_LOG_ERROR(msg); break; |
233 | 0 | default: ASSIMP_LOG_VERBOSE_DEBUG(msg); break; |
234 | 5 | } |
235 | 5 | } |
236 | | |
237 | | //------------------------------------------------------------------------------------------------ |
238 | | OpenGEXImporter::VertexContainer::VertexContainer() : |
239 | 220 | m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() { |
240 | | // empty |
241 | 220 | } |
242 | | |
243 | | //------------------------------------------------------------------------------------------------ |
244 | 220 | OpenGEXImporter::VertexContainer::~VertexContainer() { |
245 | 220 | delete[] m_colors; |
246 | | |
247 | 1.76k | for (auto &texcoords : m_textureCoords) { |
248 | 1.76k | delete[] texcoords; |
249 | 1.76k | } |
250 | 220 | } |
251 | | |
252 | | //------------------------------------------------------------------------------------------------ |
253 | | OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::string> &names) : |
254 | 0 | m_node(node), |
255 | 0 | m_type(type), |
256 | 0 | m_Names(names) { |
257 | | // empty |
258 | 0 | } |
259 | | |
260 | | //------------------------------------------------------------------------------------------------ |
261 | | OpenGEXImporter::OpenGEXImporter() : |
262 | 220 | m_root(nullptr), |
263 | 220 | m_nodeChildMap(), |
264 | 220 | m_mesh2refMap(), |
265 | 220 | m_material2refMap(), |
266 | 220 | m_ctx(nullptr), |
267 | 220 | m_metrics(), |
268 | 220 | m_currentNode(nullptr), |
269 | 220 | m_currentVertices(), |
270 | 220 | m_currentMesh(nullptr), |
271 | 220 | m_currentMaterial(nullptr), |
272 | 220 | m_currentLight(nullptr), |
273 | 220 | m_currentCamera(nullptr), |
274 | 220 | m_tokenType(Grammar::NoneType), |
275 | 220 | m_materialCache(), |
276 | 220 | m_cameraCache(), |
277 | 220 | m_lightCache(), |
278 | 220 | m_nodeStack(), |
279 | 220 | m_unresolvedRefStack() { |
280 | | // empty |
281 | 220 | } |
282 | | |
283 | | //------------------------------------------------------------------------------------------------ |
284 | 60 | bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const { |
285 | 60 | static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" }; |
286 | 60 | return SearchFileHeaderForToken(pIOHandler, file, tokens, AI_COUNT_OF(tokens)); |
287 | 60 | } |
288 | | |
289 | | //------------------------------------------------------------------------------------------------ |
290 | 8 | void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) { |
291 | | // open source file |
292 | 8 | std::unique_ptr<IOStream> file(pIOHandler->Open(filename, "rb")); |
293 | 8 | if (!file) { |
294 | 0 | throw DeadlyImportError("Failed to open file ", filename); |
295 | 0 | } |
296 | | |
297 | 8 | std::vector<char> buffer; |
298 | 8 | TextFileToBuffer(file.get(), buffer); |
299 | | |
300 | 8 | OpenDDLParser myParser; |
301 | 8 | myParser.setLogCallback(&logDDLParserMessage); |
302 | 8 | myParser.setBuffer(&buffer[0], buffer.size()); |
303 | 8 | bool success(myParser.parse()); |
304 | 8 | if (success) { |
305 | 0 | m_ctx = myParser.getContext(); |
306 | 0 | pScene->mRootNode = new aiNode; |
307 | 0 | pScene->mRootNode->mName.Set(filename); |
308 | 0 | handleNodes(m_ctx->m_root, pScene); |
309 | 0 | } |
310 | | |
311 | 8 | copyMeshes(pScene); |
312 | 8 | copyCameras(pScene); |
313 | | // TODO: lights only partially implemented and breaking model import |
314 | | // copyLights(pScene); |
315 | 8 | copyMaterials(pScene); |
316 | 8 | resolveReferences(); |
317 | 8 | createNodeTree(pScene); |
318 | 8 | } |
319 | | |
320 | | //------------------------------------------------------------------------------------------------ |
321 | 218 | const aiImporterDesc *OpenGEXImporter::GetInfo() const { |
322 | 218 | return &desc; |
323 | 218 | } |
324 | | |
325 | | //------------------------------------------------------------------------------------------------ |
326 | 8 | void OpenGEXImporter::SetupProperties(const Importer *pImp) { |
327 | 8 | if (nullptr == pImp) { |
328 | 0 | return; |
329 | 0 | } |
330 | 8 | } |
331 | | |
332 | | //------------------------------------------------------------------------------------------------ |
333 | 0 | void OpenGEXImporter::handleNodes(DDLNode *node, aiScene *pScene) { |
334 | 0 | if (nullptr == node) { |
335 | 0 | return; |
336 | 0 | } |
337 | | |
338 | 0 | DDLNode::DllNodeList children = node->getChildNodeList(); |
339 | 0 | for (DDLNode::DllNodeList::iterator it = children.begin(); it != children.end(); ++it) { |
340 | 0 | Grammar::TokenType tokenType(Grammar::matchTokenType((*it)->getType().c_str())); |
341 | 0 | switch (tokenType) { |
342 | 0 | case Grammar::MetricToken: |
343 | 0 | handleMetricNode(*it, pScene); |
344 | 0 | break; |
345 | | |
346 | 0 | case Grammar::NameToken: |
347 | 0 | handleNameNode(*it, pScene); |
348 | 0 | break; |
349 | | |
350 | 0 | case Grammar::ObjectRefToken: |
351 | 0 | handleObjectRefNode(*it, pScene); |
352 | 0 | break; |
353 | | |
354 | 0 | case Grammar::MaterialRefToken: |
355 | 0 | handleMaterialRefNode(*it, pScene); |
356 | 0 | break; |
357 | | |
358 | 0 | case Grammar::MetricKeyToken: |
359 | 0 | break; |
360 | | |
361 | 0 | case Grammar::GeometryNodeToken: |
362 | 0 | handleGeometryNode(*it, pScene); |
363 | 0 | break; |
364 | | |
365 | 0 | case Grammar::CameraNodeToken: |
366 | 0 | handleCameraNode(*it, pScene); |
367 | 0 | break; |
368 | | |
369 | 0 | case Grammar::LightNodeToken: |
370 | | // TODO: lights only partially implemented and breaking model import |
371 | | // handleLightNode(*it, pScene); |
372 | 0 | break; |
373 | | |
374 | 0 | case Grammar::GeometryObjectToken: |
375 | 0 | handleGeometryObject(*it, pScene); |
376 | 0 | break; |
377 | | |
378 | 0 | case Grammar::CameraObjectToken: |
379 | 0 | handleCameraObject(*it, pScene); |
380 | 0 | break; |
381 | | |
382 | 0 | case Grammar::LightObjectToken: |
383 | | // TODO: lights only partially implemented and breaking model import |
384 | | // handleLightObject(*it, pScene); |
385 | 0 | break; |
386 | | |
387 | 0 | case Grammar::TransformToken: |
388 | 0 | handleTransformNode(*it, pScene); |
389 | 0 | break; |
390 | | |
391 | 0 | case Grammar::MeshToken: |
392 | 0 | handleMeshNode(*it, pScene); |
393 | 0 | break; |
394 | | |
395 | 0 | case Grammar::VertexArrayToken: |
396 | 0 | handleVertexArrayNode(*it, pScene); |
397 | 0 | break; |
398 | | |
399 | 0 | case Grammar::IndexArrayToken: |
400 | 0 | handleIndexArrayNode(*it, pScene); |
401 | 0 | break; |
402 | | |
403 | 0 | case Grammar::MaterialToken: |
404 | 0 | handleMaterialNode(*it, pScene); |
405 | 0 | break; |
406 | | |
407 | 0 | case Grammar::ColorToken: |
408 | 0 | handleColorNode(*it, pScene); |
409 | 0 | break; |
410 | | |
411 | 0 | case Grammar::ParamToken: |
412 | 0 | handleParamNode(*it, pScene); |
413 | 0 | break; |
414 | | |
415 | 0 | case Grammar::TextureToken: |
416 | 0 | handleTextureNode(*it, pScene); |
417 | 0 | break; |
418 | | |
419 | 0 | default: |
420 | 0 | break; |
421 | 0 | } |
422 | 0 | } |
423 | 0 | } |
424 | | |
425 | | //------------------------------------------------------------------------------------------------ |
426 | 0 | void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) { |
427 | 0 | if (nullptr == node || nullptr == m_ctx) { |
428 | 0 | return; |
429 | 0 | } |
430 | | |
431 | 0 | if (m_ctx->m_root != node->getParent()) { |
432 | 0 | return; |
433 | 0 | } |
434 | | |
435 | 0 | Property *prop(node->getProperties()); |
436 | 0 | while (nullptr != prop) { |
437 | 0 | if (nullptr != prop->m_key) { |
438 | 0 | if (Value::ValueType::ddl_string == prop->m_value->m_type) { |
439 | 0 | std::string valName((char *)prop->m_value->m_data); |
440 | 0 | int type(Grammar::isValidMetricType(valName.c_str())); |
441 | 0 | if (Grammar::NoneType != type) { |
442 | 0 | Value *val(node->getValue()); |
443 | 0 | if (nullptr != val) { |
444 | 0 | if (Value::ValueType::ddl_float == val->m_type) { |
445 | 0 | m_metrics[type].m_floatValue = val->getFloat(); |
446 | 0 | } else if (Value::ValueType::ddl_int32 == val->m_type) { |
447 | 0 | m_metrics[type].m_intValue = val->getInt32(); |
448 | 0 | } else if (Value::ValueType::ddl_string == val->m_type) { |
449 | 0 | m_metrics[type].m_stringValue = std::string(val->getString()); |
450 | 0 | } else { |
451 | 0 | throw DeadlyImportError("OpenGEX: invalid data type for Metric node."); |
452 | 0 | } |
453 | 0 | } |
454 | 0 | } |
455 | 0 | } |
456 | 0 | } |
457 | 0 | prop = prop->m_next; |
458 | 0 | } |
459 | 0 | } |
460 | | |
461 | | //------------------------------------------------------------------------------------------------ |
462 | 0 | void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) { |
463 | 0 | if (nullptr == m_currentNode) { |
464 | 0 | throw DeadlyImportError("No current node for name."); |
465 | 0 | } |
466 | | |
467 | 0 | Value *val(node->getValue()); |
468 | 0 | if (nullptr != val) { |
469 | 0 | if (Value::ValueType::ddl_string != val->m_type) { |
470 | 0 | throw DeadlyImportError("OpenGEX: invalid data type for value in node name."); |
471 | 0 | } |
472 | | |
473 | 0 | const std::string name(val->getString()); |
474 | 0 | if (m_tokenType == Grammar::GeometryNodeToken || |
475 | | // TODO: lights only partially implemented and breaking model import |
476 | | // m_tokenType == Grammar::LightNodeToken || |
477 | 0 | m_tokenType == Grammar::CameraNodeToken) { |
478 | 0 | m_currentNode->mName.Set(name.c_str()); |
479 | 0 | } else if (m_tokenType == Grammar::MaterialToken) { |
480 | 0 | aiString aiName; |
481 | 0 | aiName.Set(name); |
482 | 0 | m_currentMaterial->AddProperty(&aiName, AI_MATKEY_NAME); |
483 | 0 | m_material2refMap[name] = m_materialCache.size() - 1; |
484 | 0 | } |
485 | 0 | } |
486 | 0 | } |
487 | | |
488 | | //------------------------------------------------------------------------------------------------ |
489 | 0 | static void getRefNames(DDLNode *node, std::vector<std::string> &names) { |
490 | 0 | ai_assert(nullptr != node); |
491 | |
|
492 | 0 | Reference *ref = node->getReferences(); |
493 | 0 | if (nullptr != ref) { |
494 | 0 | for (size_t i = 0; i < ref->m_numRefs; i++) { |
495 | 0 | Name *currentName(ref->m_referencedName[i]); |
496 | 0 | if (nullptr != currentName && nullptr != currentName->m_id) { |
497 | | #ifdef ASSIMP_USE_HUNTER |
498 | | const std::string name(currentName->m_id->m_text.m_buffer); |
499 | | #else |
500 | 0 | const std::string name(currentName->m_id->m_buffer); |
501 | 0 | #endif |
502 | 0 | if (!name.empty()) { |
503 | 0 | names.push_back(name); |
504 | 0 | } |
505 | 0 | } |
506 | 0 | } |
507 | 0 | } |
508 | 0 | } |
509 | | |
510 | | //------------------------------------------------------------------------------------------------ |
511 | 0 | void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) { |
512 | 0 | if (nullptr == m_currentNode) { |
513 | 0 | throw DeadlyImportError("No parent node for name."); |
514 | 0 | } |
515 | | |
516 | 0 | std::vector<std::string> objRefNames; |
517 | 0 | getRefNames(node, objRefNames); |
518 | | |
519 | | // when we are dealing with a geometry node prepare the mesh cache |
520 | 0 | if (m_tokenType == Grammar::GeometryNodeToken) { |
521 | 0 | m_currentNode->mNumMeshes = static_cast<unsigned int>(objRefNames.size()); |
522 | 0 | m_currentNode->mMeshes = new unsigned int[objRefNames.size()]; |
523 | 0 | if (!objRefNames.empty()) { |
524 | 0 | m_unresolvedRefStack.push_back(std::unique_ptr<RefInfo>(new RefInfo(m_currentNode, RefInfo::MeshRef, objRefNames))); |
525 | 0 | } |
526 | 0 | } else if (m_tokenType == Grammar::LightNodeToken) { |
527 | | // TODO! |
528 | 0 | } else if (m_tokenType == Grammar::CameraNodeToken) { |
529 | | // TODO! |
530 | 0 | } |
531 | 0 | } |
532 | | |
533 | | //------------------------------------------------------------------------------------------------ |
534 | 0 | void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
535 | 0 | if (nullptr == m_currentNode) { |
536 | 0 | throw DeadlyImportError("No parent node for name."); |
537 | 0 | } |
538 | | |
539 | 0 | std::vector<std::string> matRefNames; |
540 | 0 | getRefNames(node, matRefNames); |
541 | 0 | if (!matRefNames.empty()) { |
542 | 0 | m_unresolvedRefStack.push_back(std::unique_ptr<RefInfo>(new RefInfo(m_currentNode, RefInfo::MaterialRef, matRefNames))); |
543 | 0 | } |
544 | 0 | } |
545 | | |
546 | | //------------------------------------------------------------------------------------------------ |
547 | 0 | void OpenGEXImporter::handleGeometryNode(DDLNode *node, aiScene *pScene) { |
548 | 0 | aiNode *newNode = new aiNode; |
549 | 0 | pushNode(newNode, pScene); |
550 | 0 | m_tokenType = Grammar::GeometryNodeToken; |
551 | 0 | m_currentNode = newNode; |
552 | 0 | handleNodes(node, pScene); |
553 | |
|
554 | 0 | popNode(); |
555 | 0 | } |
556 | | |
557 | | //------------------------------------------------------------------------------------------------ |
558 | 0 | void OpenGEXImporter::handleCameraNode(DDLNode *node, aiScene *pScene) { |
559 | 0 | aiCamera *camera(new aiCamera); |
560 | 0 | m_cameraCache.push_back(camera); |
561 | 0 | m_currentCamera = camera; |
562 | |
|
563 | 0 | aiNode *newNode = new aiNode; |
564 | 0 | pushNode(newNode, pScene); |
565 | 0 | m_tokenType = Grammar::CameraNodeToken; |
566 | 0 | m_currentNode = newNode; |
567 | |
|
568 | 0 | handleNodes(node, pScene); |
569 | |
|
570 | 0 | popNode(); |
571 | |
|
572 | 0 | m_currentCamera->mName.Set(newNode->mName.C_Str()); |
573 | 0 | } |
574 | | |
575 | | //------------------------------------------------------------------------------------------------ |
576 | 0 | void OpenGEXImporter::handleLightNode(ODDLParser::DDLNode *node, aiScene *pScene) { |
577 | 0 | aiLight *light(new aiLight); |
578 | 0 | m_lightCache.push_back(light); |
579 | 0 | m_currentLight = light; |
580 | |
|
581 | 0 | aiNode *newNode = new aiNode; |
582 | 0 | m_tokenType = Grammar::LightNodeToken; |
583 | 0 | m_currentNode = newNode; |
584 | 0 | pushNode(newNode, pScene); |
585 | |
|
586 | 0 | handleNodes(node, pScene); |
587 | |
|
588 | 0 | popNode(); |
589 | |
|
590 | 0 | m_currentLight->mName.Set(newNode->mName.C_Str()); |
591 | 0 | } |
592 | | |
593 | | //------------------------------------------------------------------------------------------------ |
594 | 0 | void OpenGEXImporter::handleGeometryObject(DDLNode *node, aiScene *pScene) { |
595 | | // parameters will be parsed normally in the tree, so just go for it |
596 | 0 | handleNodes(node, pScene); |
597 | 0 | } |
598 | | |
599 | | //------------------------------------------------------------------------------------------------ |
600 | 0 | void OpenGEXImporter::handleCameraObject(ODDLParser::DDLNode *node, aiScene *pScene) { |
601 | | // parameters will be parsed normally in the tree, so just go for it |
602 | |
|
603 | 0 | handleNodes(node, pScene); |
604 | 0 | } |
605 | | |
606 | | //------------------------------------------------------------------------------------------------ |
607 | 0 | void OpenGEXImporter::handleLightObject(ODDLParser::DDLNode *node, aiScene *pScene) { |
608 | 0 | aiLight *light(new aiLight); |
609 | 0 | m_lightCache.push_back(light); |
610 | 0 | std::string objName = node->getName(); |
611 | 0 | if (!objName.empty()) { |
612 | 0 | light->mName.Set(objName); |
613 | 0 | } |
614 | 0 | m_currentLight = light; |
615 | |
|
616 | 0 | Property *prop(node->findPropertyByName("type")); |
617 | 0 | if (nullptr != prop) { |
618 | 0 | if (nullptr != prop->m_value) { |
619 | 0 | std::string typeStr(prop->m_value->getString()); |
620 | 0 | if ("point" == typeStr) { |
621 | 0 | m_currentLight->mType = aiLightSource_POINT; |
622 | 0 | } else if ("spot" == typeStr) { |
623 | 0 | m_currentLight->mType = aiLightSource_SPOT; |
624 | 0 | } else if ("infinite" == typeStr) { |
625 | 0 | m_currentLight->mType = aiLightSource_DIRECTIONAL; |
626 | 0 | } |
627 | 0 | } |
628 | 0 | } |
629 | | |
630 | | // parameters will be parsed normally in the tree, so just go for it |
631 | 0 | handleNodes(node, pScene); |
632 | 0 | } |
633 | | |
634 | | //------------------------------------------------------------------------------------------------ |
635 | 0 | static void setMatrix(aiNode *node, DataArrayList *transformData) { |
636 | 0 | ai_assert(nullptr != node); |
637 | 0 | ai_assert(nullptr != transformData); |
638 | |
|
639 | 0 | float m[16]; |
640 | 0 | size_t i(1); |
641 | 0 | Value *next(transformData->m_dataList->m_next); |
642 | 0 | m[0] = transformData->m_dataList->getFloat(); |
643 | 0 | while (next != nullptr) { |
644 | 0 | m[i] = next->getFloat(); |
645 | 0 | next = next->m_next; |
646 | 0 | i++; |
647 | 0 | } |
648 | |
|
649 | 0 | ai_assert(i == 16); |
650 | |
|
651 | 0 | node->mTransformation.a1 = m[0]; |
652 | 0 | node->mTransformation.a2 = m[4]; |
653 | 0 | node->mTransformation.a3 = m[8]; |
654 | 0 | node->mTransformation.a4 = m[12]; |
655 | |
|
656 | 0 | node->mTransformation.b1 = m[1]; |
657 | 0 | node->mTransformation.b2 = m[5]; |
658 | 0 | node->mTransformation.b3 = m[9]; |
659 | 0 | node->mTransformation.b4 = m[13]; |
660 | |
|
661 | 0 | node->mTransformation.c1 = m[2]; |
662 | 0 | node->mTransformation.c2 = m[6]; |
663 | 0 | node->mTransformation.c3 = m[10]; |
664 | 0 | node->mTransformation.c4 = m[14]; |
665 | |
|
666 | 0 | node->mTransformation.d1 = m[3]; |
667 | 0 | node->mTransformation.d2 = m[7]; |
668 | 0 | node->mTransformation.d3 = m[11]; |
669 | 0 | node->mTransformation.d4 = m[15]; |
670 | 0 | } |
671 | | |
672 | | //------------------------------------------------------------------------------------------------ |
673 | 0 | void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
674 | 0 | if (nullptr == m_currentNode) { |
675 | 0 | throw DeadlyImportError("No parent node for name."); |
676 | 0 | } |
677 | | |
678 | 0 | DataArrayList *transformData(node->getDataArrayList()); |
679 | 0 | if (nullptr != transformData) { |
680 | 0 | if (transformData->m_numItems != 16) { |
681 | 0 | throw DeadlyImportError("Invalid number of data for transform matrix."); |
682 | 0 | } |
683 | 0 | setMatrix(m_currentNode, transformData); |
684 | 0 | } |
685 | 0 | } |
686 | | |
687 | | //------------------------------------------------------------------------------------------------ |
688 | 0 | void OpenGEXImporter::handleMeshNode(ODDLParser::DDLNode *node, aiScene *pScene) { |
689 | 0 | m_currentMesh = new aiMesh; |
690 | 0 | const size_t meshidx(m_meshCache.size()); |
691 | | // ownership is transferred but a reference remains in m_currentMesh |
692 | 0 | m_meshCache.emplace_back(m_currentMesh); |
693 | |
|
694 | 0 | Property *prop = node->getProperties(); |
695 | 0 | if (nullptr != prop) { |
696 | 0 | std::string propName, propKey; |
697 | 0 | propId2StdString(prop, propName, propKey); |
698 | 0 | if ("primitive" == propName) { |
699 | 0 | if ("points" == propKey) { |
700 | 0 | m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; |
701 | 0 | } else if ("lines" == propKey) { |
702 | 0 | m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; |
703 | 0 | } else if ("triangles" == propKey) { |
704 | 0 | m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; |
705 | 0 | } else if ("quads" == propKey) { |
706 | 0 | m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; |
707 | 0 | } else { |
708 | 0 | ASSIMP_LOG_WARN(propKey, " is not supported primitive type."); |
709 | 0 | } |
710 | 0 | } |
711 | 0 | } |
712 | |
|
713 | 0 | handleNodes(node, pScene); |
714 | |
|
715 | 0 | DDLNode *parent(node->getParent()); |
716 | 0 | if (nullptr != parent) { |
717 | 0 | const std::string &name = parent->getName(); |
718 | 0 | m_mesh2refMap[name] = meshidx; |
719 | 0 | } |
720 | 0 | } |
721 | | |
722 | | //------------------------------------------------------------------------------------------------ |
723 | | enum MeshAttribute { |
724 | | None, |
725 | | Position, |
726 | | Color, |
727 | | Normal, |
728 | | TexCoord |
729 | | }; |
730 | | |
731 | | constexpr auto PosToken = "position"; |
732 | | constexpr auto ColToken = "color"; |
733 | | constexpr auto NormalToken = "normal"; |
734 | | constexpr auto TexCoordToken = "texcoord"; |
735 | | |
736 | | //------------------------------------------------------------------------------------------------ |
737 | 0 | static MeshAttribute getAttributeByName(const char *attribName) { |
738 | 0 | ai_assert(nullptr != attribName); |
739 | |
|
740 | 0 | if (0 == strcmp(PosToken, attribName)) { |
741 | 0 | return Position; |
742 | 0 | } else if (0 == strcmp(ColToken, attribName)) { |
743 | 0 | return Color; |
744 | 0 | } else if (0 == strcmp(NormalToken, attribName)) { |
745 | 0 | return Normal; |
746 | 0 | } else if (0 == strcmp(TexCoordToken, attribName)) { |
747 | 0 | return TexCoord; |
748 | 0 | } |
749 | | |
750 | 0 | return None; |
751 | 0 | } |
752 | | |
753 | | //------------------------------------------------------------------------------------------------ |
754 | 0 | static void fillVector3(aiVector3D *vec3, Value *vals) { |
755 | 0 | ai_assert(nullptr != vec3); |
756 | 0 | ai_assert(nullptr != vals); |
757 | |
|
758 | 0 | float x(0.0f), y(0.0f), z(0.0f); |
759 | 0 | Value *next(vals); |
760 | 0 | x = next->getFloat(); |
761 | 0 | next = next->m_next; |
762 | 0 | y = next->getFloat(); |
763 | 0 | next = next->m_next; |
764 | 0 | if (nullptr != next) { |
765 | 0 | z = next->getFloat(); |
766 | 0 | } |
767 | |
|
768 | 0 | vec3->Set(x, y, z); |
769 | 0 | } |
770 | | |
771 | | //------------------------------------------------------------------------------------------------ |
772 | 0 | static void fillColor4(aiColor4D *col4, Value *vals) { |
773 | 0 | ai_assert(nullptr != col4); |
774 | 0 | ai_assert(nullptr != vals); |
775 | |
|
776 | 0 | Value *next(vals); |
777 | 0 | col4->r = next->getFloat(); |
778 | 0 | next = next->m_next; |
779 | 0 | if (!next) { |
780 | 0 | throw DeadlyImportError("OpenGEX: Not enough values to fill 4-element color, only 1"); |
781 | 0 | } |
782 | | |
783 | 0 | col4->g = next->getFloat(); |
784 | 0 | next = next->m_next; |
785 | 0 | if (!next) { |
786 | 0 | throw DeadlyImportError("OpenGEX: Not enough values to fill 4-element color, only 2"); |
787 | 0 | } |
788 | | |
789 | 0 | col4->b = next->getFloat(); |
790 | 0 | next = next->m_next; |
791 | 0 | if (!next) { |
792 | 0 | col4->a = 1.0f; |
793 | 0 | } else { |
794 | 0 | col4->a = next->getFloat(); |
795 | 0 | } |
796 | 0 | } |
797 | | |
798 | | //------------------------------------------------------------------------------------------------ |
799 | 0 | static size_t countDataArrayListItems(DataArrayList *vaList) { |
800 | 0 | size_t numItems(0); |
801 | 0 | if (nullptr == vaList) { |
802 | 0 | return numItems; |
803 | 0 | } |
804 | | |
805 | 0 | DataArrayList *next(vaList); |
806 | 0 | while (nullptr != next) { |
807 | 0 | if (nullptr != vaList->m_dataList) { |
808 | 0 | numItems++; |
809 | 0 | } |
810 | 0 | next = next->m_next; |
811 | 0 | } |
812 | |
|
813 | 0 | return numItems; |
814 | 0 | } |
815 | | |
816 | | //------------------------------------------------------------------------------------------------ |
817 | 0 | static void copyVectorArray(size_t numItems, DataArrayList *vaList, aiVector3D *vectorArray) { |
818 | 0 | for (size_t i = 0; i < numItems; i++) { |
819 | 0 | Value *next(vaList->m_dataList); |
820 | 0 | fillVector3(&vectorArray[i], next); |
821 | 0 | vaList = vaList->m_next; |
822 | 0 | } |
823 | 0 | } |
824 | | |
825 | | //------------------------------------------------------------------------------------------------ |
826 | 0 | static void copyColor4DArray(size_t numItems, DataArrayList *vaList, aiColor4D *colArray) { |
827 | 0 | for (size_t i = 0; i < numItems; i++) { |
828 | 0 | Value *next(vaList->m_dataList); |
829 | 0 | fillColor4(&colArray[i], next); |
830 | 0 | } |
831 | 0 | } |
832 | | |
833 | | //------------------------------------------------------------------------------------------------ |
834 | 0 | void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
835 | 0 | if (nullptr == node) { |
836 | 0 | throw DeadlyImportError("No parent node for name."); |
837 | 0 | } |
838 | | |
839 | 0 | Property *prop = node->getProperties(); |
840 | 0 | if (nullptr != prop) { |
841 | 0 | std::string propName, propKey; |
842 | 0 | propId2StdString(prop, propName, propKey); |
843 | 0 | MeshAttribute attribType(getAttributeByName(propKey.c_str())); |
844 | 0 | if (None == attribType) { |
845 | 0 | return; |
846 | 0 | } |
847 | | |
848 | 0 | DataArrayList *vaList = node->getDataArrayList(); |
849 | 0 | if (nullptr == vaList) { |
850 | 0 | return; |
851 | 0 | } |
852 | | |
853 | 0 | const size_t numItems(countDataArrayListItems(vaList)); |
854 | |
|
855 | 0 | if (Position == attribType) { |
856 | 0 | m_currentVertices.m_vertices.resize(numItems); |
857 | 0 | copyVectorArray(numItems, vaList, m_currentVertices.m_vertices.data()); |
858 | 0 | } else if (Color == attribType) { |
859 | 0 | m_currentVertices.m_numColors = numItems; |
860 | 0 | m_currentVertices.m_colors = new aiColor4D[numItems]; |
861 | 0 | copyColor4DArray(numItems, vaList, m_currentVertices.m_colors); |
862 | 0 | } else if (Normal == attribType) { |
863 | 0 | m_currentVertices.m_normals.resize(numItems); |
864 | 0 | copyVectorArray(numItems, vaList, m_currentVertices.m_normals.data()); |
865 | 0 | } else if (TexCoord == attribType) { |
866 | 0 | m_currentVertices.m_numUVComps[0] = numItems; |
867 | 0 | m_currentVertices.m_textureCoords[0] = new aiVector3D[numItems]; |
868 | 0 | copyVectorArray(numItems, vaList, m_currentVertices.m_textureCoords[0]); |
869 | 0 | } |
870 | 0 | } |
871 | 0 | } |
872 | | |
873 | | //------------------------------------------------------------------------------------------------ |
874 | 0 | void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
875 | 0 | if (nullptr == node) { |
876 | 0 | throw DeadlyImportError("No parent node for name."); |
877 | 0 | } |
878 | | |
879 | 0 | if (nullptr == m_currentMesh) { |
880 | 0 | throw DeadlyImportError("No current mesh for index data found."); |
881 | 0 | } |
882 | | |
883 | 0 | DataArrayList *vaList = node->getDataArrayList(); |
884 | 0 | if (nullptr == vaList) { |
885 | 0 | return; |
886 | 0 | } |
887 | | |
888 | 0 | const size_t numItems(countDataArrayListItems(vaList)); |
889 | 0 | m_currentMesh->mNumFaces = static_cast<unsigned int>(numItems); |
890 | 0 | m_currentMesh->mFaces = new aiFace[numItems]; |
891 | 0 | m_currentMesh->mNumVertices = static_cast<unsigned int>(numItems * 3); |
892 | 0 | m_currentMesh->mVertices = new aiVector3D[m_currentMesh->mNumVertices]; |
893 | 0 | bool hasColors(false); |
894 | 0 | if (m_currentVertices.m_numColors > 0) { |
895 | 0 | m_currentMesh->mColors[0] = new aiColor4D[m_currentVertices.m_numColors]; |
896 | 0 | hasColors = true; |
897 | 0 | } |
898 | 0 | bool hasNormalCoords(false); |
899 | 0 | if (!m_currentVertices.m_normals.empty()) { |
900 | 0 | m_currentMesh->mNormals = new aiVector3D[m_currentMesh->mNumVertices]; |
901 | 0 | hasNormalCoords = true; |
902 | 0 | } |
903 | 0 | bool hasTexCoords(false); |
904 | 0 | if (m_currentVertices.m_numUVComps[0] > 0) { |
905 | 0 | m_currentMesh->mTextureCoords[0] = new aiVector3D[m_currentMesh->mNumVertices]; |
906 | 0 | hasTexCoords = true; |
907 | 0 | } |
908 | |
|
909 | 0 | unsigned int index(0); |
910 | 0 | for (size_t i = 0; i < m_currentMesh->mNumFaces; i++) { |
911 | 0 | aiFace ¤t(m_currentMesh->mFaces[i]); |
912 | 0 | current.mNumIndices = 3; |
913 | 0 | current.mIndices = new unsigned int[current.mNumIndices]; |
914 | 0 | Value *next(vaList->m_dataList); |
915 | 0 | for (size_t indices = 0; indices < current.mNumIndices; indices++) { |
916 | 0 | int idx = -1; |
917 | 0 | if (next->m_type == Value::ValueType::ddl_unsigned_int16) { |
918 | 0 | idx = next->getUnsignedInt16(); |
919 | 0 | } else if (next->m_type == Value::ValueType::ddl_unsigned_int32) { |
920 | 0 | idx = next->getUnsignedInt32(); |
921 | 0 | } |
922 | | |
923 | 0 | ai_assert(static_cast<size_t>(idx) <= m_currentVertices.m_vertices.size()); |
924 | 0 | ai_assert(index < m_currentMesh->mNumVertices); |
925 | 0 | aiVector3D &pos = (m_currentVertices.m_vertices[idx]); |
926 | 0 | m_currentMesh->mVertices[index].Set(pos.x, pos.y, pos.z); |
927 | 0 | if (hasColors) { |
928 | 0 | aiColor4D &col = m_currentVertices.m_colors[idx]; |
929 | 0 | m_currentMesh->mColors[0][index] = col; |
930 | 0 | } |
931 | 0 | if (hasNormalCoords) { |
932 | 0 | aiVector3D &normal = (m_currentVertices.m_normals[idx]); |
933 | 0 | m_currentMesh->mNormals[index].Set(normal.x, normal.y, normal.z); |
934 | 0 | } |
935 | 0 | if (hasTexCoords) { |
936 | 0 | aiVector3D &tex = (m_currentVertices.m_textureCoords[0][idx]); |
937 | 0 | m_currentMesh->mTextureCoords[0][index].Set(tex.x, tex.y, tex.z); |
938 | 0 | } |
939 | 0 | current.mIndices[indices] = index; |
940 | 0 | index++; |
941 | |
|
942 | 0 | next = next->m_next; |
943 | 0 | } |
944 | 0 | vaList = vaList->m_next; |
945 | 0 | } |
946 | 0 | } |
947 | | |
948 | | //------------------------------------------------------------------------------------------------ |
949 | 0 | static void getColorRGB3(aiColor3D *pColor, DataArrayList *colList) { |
950 | 0 | if (nullptr == pColor || nullptr == colList) { |
951 | 0 | return; |
952 | 0 | } |
953 | | |
954 | 0 | ai_assert(3 == colList->m_numItems); |
955 | 0 | Value *val(colList->m_dataList); |
956 | 0 | pColor->r = val->getFloat(); |
957 | 0 | val = val->getNext(); |
958 | 0 | pColor->g = val->getFloat(); |
959 | 0 | val = val->getNext(); |
960 | 0 | pColor->b = val->getFloat(); |
961 | 0 | } |
962 | | |
963 | | //------------------------------------------------------------------------------------------------ |
964 | 0 | static void getColorRGB4(aiColor4D *pColor, DataArrayList *colList) { |
965 | 0 | if (nullptr == pColor || nullptr == colList) { |
966 | 0 | return; |
967 | 0 | } |
968 | | |
969 | 0 | ai_assert(4 == colList->m_numItems); |
970 | 0 | Value *val(colList->m_dataList); |
971 | 0 | pColor->r = val->getFloat(); |
972 | 0 | val = val->getNext(); |
973 | 0 | pColor->g = val->getFloat(); |
974 | 0 | val = val->getNext(); |
975 | 0 | pColor->b = val->getFloat(); |
976 | 0 | val = val->getNext(); |
977 | 0 | pColor->a = val->getFloat(); |
978 | 0 | } |
979 | | |
980 | | //------------------------------------------------------------------------------------------------ |
981 | | enum ColorType { |
982 | | NoneColor = 0, |
983 | | DiffuseColor, |
984 | | SpecularColor, |
985 | | EmissionColor, |
986 | | LightColor |
987 | | }; |
988 | | |
989 | | //------------------------------------------------------------------------------------------------ |
990 | 0 | static ColorType getColorType(Text *id) { |
991 | 0 | if (nullptr == id) { |
992 | 0 | return NoneColor; |
993 | 0 | } |
994 | | |
995 | 0 | if (*id == Grammar::DiffuseColorToken) { |
996 | 0 | return DiffuseColor; |
997 | 0 | } else if (*id == Grammar::SpecularColorToken) { |
998 | 0 | return SpecularColor; |
999 | 0 | } else if (*id == Grammar::EmissionColorToken) { |
1000 | 0 | return EmissionColor; |
1001 | 0 | } else if (*id == "light") { |
1002 | 0 | return LightColor; |
1003 | 0 | } |
1004 | | |
1005 | 0 | return NoneColor; |
1006 | 0 | } |
1007 | | |
1008 | | //------------------------------------------------------------------------------------------------ |
1009 | 0 | void OpenGEXImporter::handleMaterialNode(ODDLParser::DDLNode *node, aiScene *pScene) { |
1010 | 0 | m_currentMaterial = new aiMaterial; |
1011 | 0 | m_materialCache.push_back(m_currentMaterial); |
1012 | 0 | m_tokenType = Grammar::MaterialToken; |
1013 | 0 | handleNodes(node, pScene); |
1014 | 0 | } |
1015 | | |
1016 | | //------------------------------------------------------------------------------------------------ |
1017 | 0 | void OpenGEXImporter::handleColorNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
1018 | 0 | if (nullptr == node) { |
1019 | 0 | return; |
1020 | 0 | } |
1021 | | |
1022 | 0 | Property *prop = node->findPropertyByName("attrib"); |
1023 | 0 | if (nullptr != prop) { |
1024 | 0 | if (nullptr != prop->m_value) { |
1025 | 0 | DataArrayList *colList(node->getDataArrayList()); |
1026 | 0 | if (nullptr == colList) { |
1027 | 0 | return; |
1028 | 0 | } |
1029 | 0 | aiColor3D col; |
1030 | 0 | if (3 == colList->m_numItems) { |
1031 | 0 | aiColor3D col3; |
1032 | 0 | getColorRGB3(&col3, colList); |
1033 | 0 | col = col3; |
1034 | 0 | } else { |
1035 | 0 | aiColor4D col4; |
1036 | 0 | getColorRGB4(&col4, colList); |
1037 | 0 | col.r = col4.r; |
1038 | 0 | col.g = col4.g; |
1039 | 0 | col.b = col4.b; |
1040 | 0 | } |
1041 | | #ifdef ASSIMP_USE_HUNTER |
1042 | | const ColorType colType(getColorType(&prop->m_key->m_text)); |
1043 | | #else |
1044 | 0 | const ColorType colType(getColorType(prop->m_key)); |
1045 | 0 | #endif |
1046 | 0 | if (DiffuseColor == colType) { |
1047 | 0 | m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_DIFFUSE); |
1048 | 0 | } else if (SpecularColor == colType) { |
1049 | 0 | m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_SPECULAR); |
1050 | 0 | } else if (EmissionColor == colType) { |
1051 | 0 | m_currentMaterial->AddProperty(&col, 1, AI_MATKEY_COLOR_EMISSIVE); |
1052 | 0 | } else if (LightColor == colType) { |
1053 | 0 | m_currentLight->mColorDiffuse = col; |
1054 | 0 | } |
1055 | 0 | } |
1056 | 0 | } |
1057 | 0 | } |
1058 | | |
1059 | | //------------------------------------------------------------------------------------------------ |
1060 | 0 | void OpenGEXImporter::handleTextureNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
1061 | 0 | if (nullptr == node) { |
1062 | 0 | return; |
1063 | 0 | } |
1064 | | |
1065 | 0 | Property *prop = node->findPropertyByName("attrib"); |
1066 | 0 | if (nullptr != prop) { |
1067 | 0 | if (nullptr != prop->m_value) { |
1068 | 0 | Value *val(node->getValue()); |
1069 | 0 | if (nullptr != val) { |
1070 | 0 | aiString tex; |
1071 | 0 | tex.Set(val->getString()); |
1072 | 0 | if (prop->m_value->getString() == Grammar::DiffuseTextureToken) { |
1073 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); |
1074 | 0 | } else if (prop->m_value->getString() == Grammar::DiffuseSpecularTextureToken) { |
1075 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(0)); |
1076 | 0 | } else if (prop->m_value->getString() == Grammar::SpecularPowerTextureToken) { |
1077 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(0)); |
1078 | 0 | } else if (prop->m_value->getString() == Grammar::EmissionTextureToken) { |
1079 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(0)); |
1080 | 0 | } else if (prop->m_value->getString() == Grammar::OpacyTextureToken) { |
1081 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_OPACITY(0)); |
1082 | 0 | } else if (prop->m_value->getString() == Grammar::TransparencyTextureToken) { |
1083 | | // ToDo! |
1084 | | // m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); |
1085 | 0 | } else if (prop->m_value->getString() == Grammar::NormalTextureToken) { |
1086 | 0 | m_currentMaterial->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0)); |
1087 | 0 | } else { |
1088 | 0 | ai_assert(false); |
1089 | 0 | } |
1090 | 0 | } |
1091 | 0 | } |
1092 | 0 | } |
1093 | 0 | } |
1094 | | |
1095 | | //------------------------------------------------------------------------------------------------ |
1096 | 0 | void OpenGEXImporter::handleParamNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
1097 | 0 | if (nullptr == node) { |
1098 | 0 | return; |
1099 | 0 | } |
1100 | | |
1101 | 0 | Property *prop = node->findPropertyByName("attrib"); |
1102 | 0 | if (nullptr == prop) { |
1103 | 0 | return; |
1104 | 0 | } |
1105 | | |
1106 | 0 | if (nullptr != prop->m_value) { |
1107 | 0 | Value *val(node->getValue()); |
1108 | 0 | if (nullptr == val) { |
1109 | 0 | return; |
1110 | 0 | } |
1111 | 0 | const float floatVal(val->getFloat()); |
1112 | 0 | if (0 == ASSIMP_strincmp("fov", prop->m_value->getString(), 3)) { |
1113 | 0 | m_currentCamera->mHorizontalFOV = floatVal; |
1114 | 0 | } else if (0 == ASSIMP_strincmp("near", prop->m_value->getString(), 4)) { |
1115 | 0 | m_currentCamera->mClipPlaneNear = floatVal; |
1116 | 0 | } else if (0 == ASSIMP_strincmp("far", prop->m_value->getString(), 3)) { |
1117 | 0 | m_currentCamera->mClipPlaneFar = floatVal; |
1118 | 0 | } |
1119 | 0 | } |
1120 | 0 | } |
1121 | | |
1122 | | //------------------------------------------------------------------------------------------------ |
1123 | 0 | void OpenGEXImporter::handleAttenNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) { |
1124 | 0 | if (nullptr == node) { |
1125 | 0 | return; |
1126 | 0 | } |
1127 | | |
1128 | 0 | Property *prop = node->findPropertyByName("curve"); |
1129 | 0 | if (nullptr != prop) { |
1130 | 0 | if (nullptr != prop->m_value) { |
1131 | 0 | Value *val(node->getValue()); |
1132 | 0 | const float floatVal(val->getFloat()); |
1133 | 0 | if (0 == strncmp("scale", prop->m_value->getString(), strlen("scale"))) { |
1134 | 0 | m_currentLight->mAttenuationQuadratic = floatVal; |
1135 | 0 | } |
1136 | 0 | } |
1137 | 0 | } |
1138 | 0 | } |
1139 | | |
1140 | | //------------------------------------------------------------------------------------------------ |
1141 | 8 | void OpenGEXImporter::copyMeshes(aiScene *pScene) { |
1142 | 8 | ai_assert(nullptr != pScene); |
1143 | | |
1144 | 8 | if (m_meshCache.empty()) { |
1145 | 8 | return; |
1146 | 8 | } |
1147 | | |
1148 | 0 | pScene->mNumMeshes = static_cast<unsigned int>(m_meshCache.size()); |
1149 | 0 | pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; |
1150 | 0 | for (unsigned int i = 0; i < pScene->mNumMeshes; i++) { |
1151 | 0 | pScene->mMeshes[i] = m_meshCache[i].release(); |
1152 | 0 | } |
1153 | 0 | } |
1154 | | |
1155 | | //------------------------------------------------------------------------------------------------ |
1156 | 8 | void OpenGEXImporter::copyCameras(aiScene *pScene) { |
1157 | 8 | ai_assert(nullptr != pScene); |
1158 | | |
1159 | 8 | if (m_cameraCache.empty()) { |
1160 | 8 | return; |
1161 | 8 | } |
1162 | | |
1163 | 0 | pScene->mNumCameras = static_cast<unsigned int>(m_cameraCache.size()); |
1164 | 0 | pScene->mCameras = new aiCamera *[pScene->mNumCameras]; |
1165 | 0 | std::copy(m_cameraCache.begin(), m_cameraCache.end(), pScene->mCameras); |
1166 | 0 | } |
1167 | | |
1168 | | //------------------------------------------------------------------------------------------------ |
1169 | 0 | void OpenGEXImporter::copyLights(aiScene *pScene) { |
1170 | 0 | ai_assert(nullptr != pScene); |
1171 | |
|
1172 | 0 | if (m_lightCache.empty()) { |
1173 | 0 | return; |
1174 | 0 | } |
1175 | | |
1176 | 0 | pScene->mNumLights = static_cast<unsigned int>(m_lightCache.size()); |
1177 | 0 | pScene->mLights = new aiLight *[pScene->mNumLights]; |
1178 | 0 | std::copy(m_lightCache.begin(), m_lightCache.end(), pScene->mLights); |
1179 | 0 | } |
1180 | | |
1181 | | //------------------------------------------------------------------------------------------------ |
1182 | 8 | void OpenGEXImporter::copyMaterials(aiScene *pScene) { |
1183 | 8 | ai_assert(nullptr != pScene); |
1184 | | |
1185 | 8 | if (m_materialCache.empty()) { |
1186 | 8 | return; |
1187 | 8 | } |
1188 | | |
1189 | 0 | pScene->mNumMaterials = static_cast<unsigned int>(m_materialCache.size()); |
1190 | 0 | pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; |
1191 | 0 | std::copy(m_materialCache.begin(), m_materialCache.end(), pScene->mMaterials); |
1192 | 0 | } |
1193 | | |
1194 | | //------------------------------------------------------------------------------------------------ |
1195 | 8 | void OpenGEXImporter::resolveReferences() { |
1196 | 8 | if (m_unresolvedRefStack.empty()) { |
1197 | 8 | return; |
1198 | 8 | } |
1199 | | |
1200 | 0 | RefInfo *currentRefInfo(nullptr); |
1201 | 0 | for (auto it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it) { |
1202 | 0 | currentRefInfo = it->get(); |
1203 | 0 | if (nullptr != currentRefInfo) { |
1204 | 0 | aiNode *node(currentRefInfo->m_node); |
1205 | 0 | if (RefInfo::MeshRef == currentRefInfo->m_type) { |
1206 | 0 | for (size_t i = 0; i < currentRefInfo->m_Names.size(); ++i) { |
1207 | 0 | const std::string &name(currentRefInfo->m_Names[i]); |
1208 | 0 | ReferenceMap::const_iterator curIt(m_mesh2refMap.find(name)); |
1209 | 0 | if (m_mesh2refMap.end() != curIt) { |
1210 | 0 | unsigned int meshIdx = static_cast<unsigned int>(m_mesh2refMap[name]); |
1211 | 0 | node->mMeshes[i] = meshIdx; |
1212 | 0 | } |
1213 | 0 | } |
1214 | 0 | } else if (RefInfo::MaterialRef == currentRefInfo->m_type) { |
1215 | 0 | for (size_t i = 0; i < currentRefInfo->m_Names.size(); ++i) { |
1216 | 0 | const std::string name(currentRefInfo->m_Names[i]); |
1217 | 0 | ReferenceMap::const_iterator curIt(m_material2refMap.find(name)); |
1218 | 0 | if (m_material2refMap.end() != curIt) { |
1219 | 0 | if (nullptr != m_currentMesh) { |
1220 | 0 | unsigned int matIdx = static_cast<unsigned int>(m_material2refMap[name]); |
1221 | 0 | if (m_currentMesh->mMaterialIndex != 0) { |
1222 | 0 | ASSIMP_LOG_WARN("Override of material reference in current mesh by material reference."); |
1223 | 0 | } |
1224 | 0 | m_currentMesh->mMaterialIndex = matIdx; |
1225 | 0 | } else { |
1226 | 0 | ASSIMP_LOG_WARN("Cannot resolve material reference, because no current mesh is there."); |
1227 | 0 | } |
1228 | 0 | } |
1229 | 0 | } |
1230 | 0 | } else { |
1231 | 0 | throw DeadlyImportError("Unknown reference info to resolve."); |
1232 | 0 | } |
1233 | 0 | } |
1234 | 0 | } |
1235 | 0 | } |
1236 | | |
1237 | | //------------------------------------------------------------------------------------------------ |
1238 | 8 | void OpenGEXImporter::createNodeTree(aiScene *pScene) { |
1239 | 8 | if (nullptr == m_root) { |
1240 | 8 | return; |
1241 | 8 | } |
1242 | | |
1243 | 0 | if (m_root->m_children.empty()) { |
1244 | 0 | return; |
1245 | 0 | } |
1246 | | |
1247 | 0 | pScene->mRootNode->mNumChildren = static_cast<unsigned int>(m_root->m_children.size()); |
1248 | 0 | pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; |
1249 | 0 | std::copy(m_root->m_children.begin(), m_root->m_children.end(), pScene->mRootNode->mChildren); |
1250 | 0 | } |
1251 | | |
1252 | | //------------------------------------------------------------------------------------------------ |
1253 | 0 | void OpenGEXImporter::pushNode(aiNode *node, aiScene *pScene) { |
1254 | 0 | ai_assert(nullptr != pScene); |
1255 | |
|
1256 | 0 | if (nullptr == node) { |
1257 | 0 | return; |
1258 | 0 | } |
1259 | | |
1260 | 0 | ChildInfo *info(nullptr); |
1261 | 0 | if (m_nodeStack.empty()) { |
1262 | 0 | node->mParent = pScene->mRootNode; |
1263 | 0 | NodeChildMap::iterator it(m_nodeChildMap.find(node->mParent)); |
1264 | 0 | if (m_nodeChildMap.end() == it) { |
1265 | 0 | info = new ChildInfo; |
1266 | 0 | m_root = info; |
1267 | 0 | m_nodeChildMap[node->mParent] = std::unique_ptr<ChildInfo>(info); |
1268 | 0 | } else { |
1269 | 0 | info = it->second.get(); |
1270 | 0 | } |
1271 | 0 | info->m_children.push_back(node); |
1272 | 0 | } else { |
1273 | 0 | aiNode *parent(m_nodeStack.back()); |
1274 | 0 | ai_assert(nullptr != parent); |
1275 | 0 | node->mParent = parent; |
1276 | 0 | NodeChildMap::iterator it(m_nodeChildMap.find(node->mParent)); |
1277 | 0 | if (m_nodeChildMap.end() == it) { |
1278 | 0 | info = new ChildInfo; |
1279 | 0 | m_nodeChildMap[node->mParent] = std::unique_ptr<ChildInfo>(info); |
1280 | 0 | } else { |
1281 | 0 | info = it->second.get(); |
1282 | 0 | } |
1283 | 0 | info->m_children.push_back(node); |
1284 | 0 | } |
1285 | 0 | m_nodeStack.push_back(node); |
1286 | 0 | } |
1287 | | |
1288 | | //------------------------------------------------------------------------------------------------ |
1289 | 0 | aiNode *OpenGEXImporter::popNode() { |
1290 | 0 | if (m_nodeStack.empty()) { |
1291 | 0 | return nullptr; |
1292 | 0 | } |
1293 | | |
1294 | 0 | aiNode *node(top()); |
1295 | 0 | m_nodeStack.pop_back(); |
1296 | |
|
1297 | 0 | return node; |
1298 | 0 | } |
1299 | | |
1300 | | //------------------------------------------------------------------------------------------------ |
1301 | 0 | aiNode *OpenGEXImporter::top() const { |
1302 | 0 | if (m_nodeStack.empty()) { |
1303 | 0 | return nullptr; |
1304 | 0 | } |
1305 | | |
1306 | 0 | return m_nodeStack.back(); |
1307 | 0 | } |
1308 | | |
1309 | | //------------------------------------------------------------------------------------------------ |
1310 | 0 | void OpenGEXImporter::clearNodeStack() { |
1311 | 0 | m_nodeStack.clear(); |
1312 | 0 | } |
1313 | | |
1314 | | //------------------------------------------------------------------------------------------------ |
1315 | | |
1316 | | } // Namespace OpenGEX |
1317 | | } // Namespace Assimp |
1318 | | |
1319 | | #endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER |