6 #include <unordered_set>
46 #define AVOID_NULLPTR_STRING(arg) (arg == nullptr?"":arg)
49 using std::make_unique;
53 using std::unordered_set;
94 const Color4 DAEReader::BLENDER_AMBIENT_NONE(0.0f, 0.0f, 0.0f, 1.0f);
96 Model* DAEReader::read(
const string& pathName,
const string& fileName,
bool useBC7TextureCompression)
99 auto xmlContent = FileSystem::getInstance()->getContentAsString(pathName, fileName);
101 xmlDocument.
Parse(xmlContent.c_str());
102 if (xmlDocument.
Error() ==
true) {
104 string(
"Could not parse XML. Error='") +
string(xmlDocument.
ErrorDesc()) +
string(
"'")
115 if (upVector == UpVector::Y_UP) {
116 rotationOrder = RotationOrder::ZYX;
118 if (upVector == UpVector::Z_UP) {
119 rotationOrder = RotationOrder::XYZ;
123 auto model = make_unique<Model>(
140 xmlSceneId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceVisualscene->Attribute(
"url"))), 1);
145 for (
auto xmlLibraryVisualScene:
getChildrenByTagName(xmlLibraryVisualScenes,
"visual_scene")) {
147 if (xmlVisualSceneId == xmlSceneId) {
152 if (xmlExtraNodes.empty() ==
false) {
153 auto xmlExtraNode = xmlExtraNodes.at(0);
156 if (xmlFrameRateNodes.empty() ==
false) {
166 auto node =
readVisualSceneNode(pathName, model.get(),
nullptr, xmlRoot, xmlNode, fps, useBC7TextureCompression);
167 if (node !=
nullptr) {
168 model->getSubNodes()[node->getId()] = node;
169 model->getNodes()[node->getId()] = node;
174 if (ModelTools::hasDefaultAnimation(model.get()) ==
false) ModelTools::createDefaultAnimation(model.get(), 0);
176 ModelTools::setupJoints(model.get());
178 ModelTools::fixAnimationLength(model.get());
180 ModelTools::prepareForIndexedRendering(model.get());
182 return model.release();
191 return Model::AUTHORINGTOOL_BLENDER;
196 return Model::AUTHORINGTOOL_UNKNOWN;
205 if (StringTools::equalsIgnoreCase(upAxis,
"Y_UP") ==
true) {
206 return UpVector::Y_UP;
208 if (StringTools::equalsIgnoreCase(upAxis,
"Z_UP") ==
true) {
209 return UpVector::Z_UP;
211 if (StringTools::equalsIgnoreCase(upAxis,
"X_UP") ==
true) {
227 if (StringTools::equalsIgnoreCase(upAxis,
"Y_UP") ==
true) {
229 if (StringTools::equalsIgnoreCase(upAxis,
"Z_UP") ==
true) {
232 if (StringTools::equalsIgnoreCase(upAxis,
"X_UP") ==
true) {
235 Console::println(
string(
"Warning: Unknown up axis: " + upAxis));
248 float scaleFactor = Float::parse(tmp);
258 if (xmlInstanceControllers.empty() ==
false) {
261 return readNode(pathName, model, parentNode, xmlRoot, xmlNode, fps, useBC7TextureCompression);
269 if (xmlNodeId.length() == 0) xmlNodeId = xmlNodeName;
272 auto node = make_unique<Node>(model, parentNode, xmlNodeId, xmlNodeName);
276 if (xmlMatrixElements.empty() ==
false) {
281 array<float, 16> transformMatrixArray;
282 for (
auto i = 0; i < transformMatrixArray.size(); i++) {
283 transformMatrixArray[i] = Float::parse(t.
nextToken());
286 node->setTransformMatrix(transformMatrix);
291 if (xmlAnimationsLibrary.empty() ==
false) {
295 if (_xmlAnimation.empty() ==
false) {
296 xmlAnimation = _xmlAnimation.at(0);
299 string xmlSamplerSource;
301 if (StringTools::startsWith(
string(
AVOID_NULLPTR_STRING(xmlChannel->Attribute(
"target"))), xmlNodeId +
"/") ==
true) {
302 xmlSamplerSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlChannel->Attribute(
"source"))), 1);
305 if (xmlSamplerSource.length() == 0) {
309 string xmlSamplerOutputSource;
310 string xmlSamplerInputSource;
314 xmlSamplerOutputSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlSamplerInput->Attribute(
"source"))), 1);
317 xmlSamplerInputSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlSamplerInput->Attribute(
"source"))), 1);
321 if (xmlSamplerOutputSource.length() == 0) {
323 "Could not find xml sampler output source for animation for '" + xmlNodeId +
"'"
328 vector<float> keyFrameTimes;
330 if (
string(
AVOID_NULLPTR_STRING(xmlAnimationSource->Attribute(
"id"))) == xmlSamplerInputSource) {
334 auto keyFrameIdx = 0;
335 keyFrameTimes.resize(frames);
339 keyFrameTimes[keyFrameIdx++] = Float::parse(t.
nextToken());
345 if (keyFrameTimes.size() > 0) {
347 if (
string(
AVOID_NULLPTR_STRING(xmlAnimationSource->Attribute(
"id"))) == xmlSamplerOutputSource) {
349 auto keyFrames = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlFloatArray->Attribute(
"count")))) / 16;
356 int32_t keyFrameIdx = 0;
357 vector<Matrix4x4> keyFrameMatrices;
358 keyFrameMatrices.resize(keyFrames);
361 array<float, 16> keyFrameMatricesArray;
362 for (
auto i = 0; i < keyFrameMatricesArray.size() ;i++) {
363 keyFrameMatricesArray[i] = Float::parse(t.
nextToken());
365 keyFrameMatrices[keyFrameIdx].set(keyFrameMatricesArray);
366 keyFrameMatrices[keyFrameIdx].transpose();
370 auto frames =
static_cast<int32_t
>(Math::ceil(keyFrameTimes[keyFrameTimes.size() - 1] * fps));
372 ModelTools::createDefaultAnimation(model, frames);
373 auto animation = make_unique<Animation>();
374 vector<Matrix4x4> transformMatrices;
375 transformMatrices.resize(frames);
376 auto tansformationsMatrixLast = &keyFrameMatrices[0];
379 auto timeStampLast = 0.0f;
380 for (
auto keyFrameTime : keyFrameTimes) {
381 auto transformMatrixCurrent = &keyFrameMatrices[(keyFrameIdx) % keyFrameMatrices.size()];
383 for (timeStamp = timeStampLast; timeStamp < keyFrameTime; timeStamp += 1.0f / fps) {
384 if (frameIdx >= frames) {
390 transformMatrices[frameIdx] = Matrix4x4::interpolateLinear(*tansformationsMatrixLast, *transformMatrixCurrent, (timeStamp - timeStampLast) / (keyFrameTime - timeStampLast));
393 timeStampLast = timeStamp;
394 tansformationsMatrixLast = transformMatrixCurrent;
397 animation->setTransformMatrices(transformMatrices);
398 node->setAnimation(animation.release());
409 auto _node =
readVisualSceneNode(pathName, model, node.get(), xmlRoot, _xmlNode, fps, useBC7TextureCompression);
410 if (_node !=
nullptr) {
411 node->getSubNodes()[_node->getId()] = _node;
412 model->
getNodes()[_node->getId()] = _node;
417 string xmlInstanceGeometryId;
419 if (xmlInstanceGeometryElements.empty() ==
false) {
420 auto xmlInstanceGeometryElement = xmlInstanceGeometryElements.at(0);
422 xmlInstanceGeometryId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceGeometryElement->Attribute(
"url"))), 1);
424 map<string, string> materialSymbols;
432 readGeometry(pathName, model, node.get(), xmlRoot, xmlInstanceGeometryId, materialSymbols, useBC7TextureCompression);
434 return node.release();
438 string xmlInstanceNodeId;
440 xmlInstanceNodeId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceNodeElement->Attribute(
"url"))), 1);
443 if (xmlInstanceNodeId.length() > 0) {
449 auto _node =
readVisualSceneNode(pathName, model, parentNode, xmlRoot, _xmlNode, fps, useBC7TextureCompression);
450 if (_node !=
nullptr) {
451 node->getSubNodes()[_node->getId()] = _node;
452 model->
getNodes()[_node->getId()] = _node;
457 auto xmlGeometryId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceGeometry->Attribute(
"url"))), 1);
459 map<string, string> materialSymbols;
467 readGeometry(pathName, model, node.get(), xmlRoot, xmlGeometryId, materialSymbols, useBC7TextureCompression);
472 return node.release();
479 map<string, string> materialSymbols;
481 string xmlGeometryId;
485 auto xmlInstanceController = xmlInstanceControllers.at(0);
495 auto xmlInstanceControllerId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceController->Attribute(
"url"))), 1);
499 if (
string(
AVOID_NULLPTR_STRING(xmlLibraryController->Attribute(
"id"))) == xmlInstanceControllerId) {
502 if (xmlSkins.empty() ==
false) {
503 xmlSkin = xmlSkins.at(0);
509 if (xmlSkin ==
nullptr) {
511 "skin not found for instance controller '" + xmlNodeId +
"'"
522 array<float, 16> bindShapeMatrixArray;
523 for (
auto i = 0; i < bindShapeMatrixArray.size(); i++) {
524 bindShapeMatrixArray[i] = Float::parse(t.
nextToken());
530 auto node = make_unique<Node>(model, parentNode, xmlNodeId, xmlNodeName);
533 auto skinning = make_unique<Skinning>();
536 readGeometry(pathName, model, node.get(), xmlRoot, xmlGeometryId, materialSymbols, useBC7TextureCompression);
539 string xmlJointsSource;
540 string xmlJointsInverseBindMatricesSource;
544 xmlJointsSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlJointsInput->Attribute(
"source"))), 1);
547 xmlJointsInverseBindMatricesSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlJointsInput->Attribute(
"source"))), 1);
552 if (xmlJointsSource.length() == 0) {
554 "joint source not found for instance controller '" + xmlNodeId +
"'"
559 vector<Joint> joints;
570 if (xmlJointsInverseBindMatricesSource.length() == 0) {
572 "inverse bind matrices source not found for instance controller '" + xmlNodeId +
"'"
578 if (
string(
AVOID_NULLPTR_STRING(xmlSkinSource->Attribute(
"id"))) == xmlJointsInverseBindMatricesSource) {
580 for (
auto i = 0; i < joints.size(); i++) {
583 array<float, 16> bindMatrixArray;
584 for (
auto i = 0; i < bindMatrixArray.size(); i++) {
585 bindMatrixArray[i] = Float::parse(t.
nextToken());
588 bindMatrix.
set(bindShapeMatrix);
590 joints[i].setBindMatrix(bindMatrix);
595 skinning->setJoints(joints);
598 vector<float> weights;
599 auto xmlJointOffset = -1;
600 auto xmlWeightOffset = -1;
601 string xmlWeightsSource;
604 for (
auto xmlVertexWeightInput: xmlVertexWeightInputs) {
606 if ((StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlVertexWeightInput->Attribute(
"source"))), 1) == xmlJointsSource) ==
false) {
609 xmlJointOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlVertexWeightInput->Attribute(
"offset"))));
612 xmlWeightOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlVertexWeightInput->Attribute(
"offset"))));
613 xmlWeightsSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlVertexWeightInput->Attribute(
"source"))), 1);
618 if (xmlJointOffset == -1) {
620 "xml vertex weight joint offset missing for node '" + xmlNodeId +
"'"
623 if (xmlWeightOffset == -1) {
625 "xml vertex weight weight offset missing for node " + xmlNodeId +
"'"
628 if (xmlWeightsSource.length() == 0) {
630 "xml vertex weight weight source missing for node '" + xmlNodeId +
"'"
639 weights.push_back(Float::parse(t.
nextToken()));
643 skinning->setWeights(weights);
646 auto xmlVertexWeightInputCount = xmlVertexWeightInputs.size();
649 t.
tokenize(vertexJointsInfluenceCountString,
" \n\r");
651 t2.
tokenize(vertexJointsInfluencesString,
" \n\r");
653 vector<vector<JointWeight>> verticesJointsWeights;
656 auto vertexJointsInfluencesCount = Integer::parse(t.
nextToken());
657 vector<JointWeight>vertexJointsWeights;
658 for (
auto i = 0; i < vertexJointsInfluencesCount; i++) {
659 auto vertexJoint = -1;
660 auto vertexWeight = -1;
661 while (vertexJoint == -1 || vertexWeight == -1) {
662 auto value = Integer::parse(t2.
nextToken());
663 if (offset % xmlVertexWeightInputCount == xmlJointOffset) {
665 }
else if (offset % xmlVertexWeightInputCount == xmlWeightOffset) {
666 vertexWeight = value;
670 vertexJointsWeights.emplace_back(vertexJoint, vertexWeight);
672 verticesJointsWeights.push_back(vertexJointsWeights);
674 skinning->setVerticesJointsWeights(verticesJointsWeights);
675 node->setSkinning(skinning.release());
677 return node.release();
683 auto verticesOffset =
static_cast<int32_t
>(node->
getVertices().size());
685 auto normalsOffset =
static_cast<int32_t
>(node->
getNormals().size());
686 vector<Vector3> normals = node->
getNormals();;
693 vector<TiXmlElement*> xmlPolygonsList;
696 xmlPolygonsList.push_back(xmlTriangesElement);
700 xmlPolygonsList.push_back(xmlPolyListElement);
704 xmlPolygonsList.push_back(xmlPolygonsElement);
707 for (
auto xmlPolygons: xmlPolygonsList) {
710 if (StringTools::toLowerCase((xmlPolygons->Value())) ==
"polylist") {
714 auto vertexCount = Integer::parse(t.
nextToken());
715 if (vertexCount != 3) {
717 "we only support triangles in '" + xmlNodeId +
"'"
723 auto xmlVerticesOffset = -1;
724 string xmlVerticesSource;
725 auto xmlNormalsOffset = -1;
726 string xmlNormalsSource;
727 auto xmlTexCoordOffset = -1;
728 string xmlTexCoordSource;
729 auto xmlColorOffset = -1;
730 string xmlColorSource;
732 auto materialSymbolIt = materialSymbols.find(xmlMaterialId);
733 if (materialSymbolIt != materialSymbols.end()) {
734 xmlMaterialId = materialSymbolIt->second;
735 xmlMaterialId = StringTools::substring(xmlMaterialId, 1);
738 if (xmlMaterialId.length() > 0) {
740 auto materialIt = model->
getMaterials().find(xmlMaterialId);
742 material = materialIt->second;
745 material =
readMaterial(pathName, model, xmlRoot, xmlMaterialId, useBC7TextureCompression);
750 unordered_set<int32_t> xmlInputSet;
754 xmlVerticesOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"offset"))));
755 xmlVerticesSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"source"))), 1);
756 xmlInputSet.insert(xmlVerticesOffset);
760 xmlNormalsOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"offset"))));
761 xmlNormalsSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"source"))), 1);
762 xmlInputSet.insert(xmlNormalsOffset);
766 xmlTexCoordOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"offset"))));
767 xmlTexCoordSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"source"))), 1);
768 xmlInputSet.insert(xmlTexCoordOffset);
772 xmlColorOffset = Integer::parse(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"offset"))));
773 xmlColorSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlTrianglesInput->Attribute(
"source"))), 1);
774 xmlInputSet.insert(xmlColorOffset);
777 xmlInputs = xmlInputSet.size();
782 if (StringTools::equalsIgnoreCase(
string(
AVOID_NULLPTR_STRING(xmlVerticesInput->Attribute(
"semantic"))),
"position") ==
true) {
783 xmlVerticesSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlVerticesInput->Attribute(
"source"))), 1);
785 if (StringTools::equalsIgnoreCase(
string(
AVOID_NULLPTR_STRING(xmlVerticesInput->Attribute(
"semantic"))),
"normal") ==
true) {
786 xmlNormalsSource = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlVerticesInput->Attribute(
"source"))), 1);
792 if (xmlVerticesSource.length() == 0) {
794 "Could not determine triangles vertices source for '" + xmlNodeId +
"'"
798 if (xmlNormalsSource.length() == 0) {
800 "Could not determine triangles normal source for '" + xmlNodeId +
"'"
815 vertices.emplace_back(x, y, z);
828 normals.emplace_back(x, y, z);
832 if (xmlTexCoordSource.length() > 0) {
841 textureCoordinates.emplace_back(u, 1.0f - v);
851 array<int32_t, 3> vi;
853 array<int32_t, 3> ni;
855 array<int32_t, 3> ti;
860 auto value = Integer::parse(t.
nextToken());
861 if (valueIdx % xmlInputs == xmlVerticesOffset) {
864 if (value < 0 || value >= vertices.size() - verticesOffset) {
868 if (xmlNormalsSource.length() > 0 && xmlNormalsOffset == -1) {
870 if (value < 0 || value >= normals.size() - normalsOffset) {
875 if (xmlNormalsOffset != -1 && valueIdx % xmlInputs == xmlNormalsOffset) {
878 if (value < 0 || value >= normals.size() - normalsOffset) {
882 if (xmlTexCoordOffset != -1 && valueIdx % xmlInputs == xmlTexCoordOffset) {
885 if (value < 0 || value >= textureCoordinates.size() - textureCoordinatesOffset) {
889 if (viIdx == 3 && niIdx == 3 && (xmlTexCoordSource.length() == 0 || tiIdx == 3)) {
893 if (xmlTexCoordSource.empty() ==
false) {
896 vi[0] + verticesOffset,
897 vi[1] + verticesOffset,
898 vi[2] + verticesOffset,
899 ni[0] + normalsOffset,
900 ni[1] + normalsOffset,
901 ni[2] + normalsOffset,
902 ti[0] + textureCoordinatesOffset,
903 ti[1] + textureCoordinatesOffset,
904 ti[2] + textureCoordinatesOffset
909 vi[0] + verticesOffset,
910 vi[1] + verticesOffset,
911 vi[2] + verticesOffset,
912 ni[0] + normalsOffset,
913 ni[1] + normalsOffset,
914 ni[2] + normalsOffset
927 if (faces.empty() ==
false) {
929 facesEntities.push_back(facesEntity);
950 xmlEffectId = StringTools::substring(
string(
AVOID_NULLPTR_STRING(xmlInstanceEffect->Attribute(
"url"))), 1);
953 if (xmlEffectId.length() == 0) {
956 "Could not determine effect id for '" +
964 auto material = make_unique<Material>(xmlNodeId);
965 auto specularMaterialProperties = make_unique<SpecularMaterialProperties>();
966 string xmlDiffuseTextureId;
967 string xmlTransparencyTextureId;
968 string xmlSpecularTextureId;
969 string xmlBumpTextureId;
975 map<string, string> samplerSurfaceMapping;
976 map<string, string> surfaceImageMapping;
981 surfaceImageMapping[xmlNewParamSID] =
986 samplerSurfaceMapping[xmlNewParamSID] =
991 for (
auto xmlTechniqueNode:
getChildren(xmlTechnique)) {
996 auto sample2SurfaceIt = samplerSurfaceMapping.find(xmlTransparencyTextureId);
997 string sample2Surface;
998 if (sample2SurfaceIt != samplerSurfaceMapping.end()) {
999 sample2Surface = sample2SurfaceIt->second;
1001 if (sample2Surface.length() == 0)
continue;
1003 string surface2Image;
1004 auto surface2ImageIt = surfaceImageMapping.find(sample2Surface);
1005 if (surface2ImageIt != surfaceImageMapping.end()) {
1006 surface2Image = surface2ImageIt->second;
1008 if (surface2Image.length() > 0) {
1009 xmlTransparencyTextureId = surface2Image;
1019 array<float, 4> colorArray;
1020 for (
auto i = 0; i < colorArray.size(); i++) {
1021 colorArray[i] = Float::parse(t.
nextToken());
1023 specularMaterialProperties->setDiffuseColor(
Color4(colorArray));
1029 auto sample2SurfaceIt = samplerSurfaceMapping.find(xmlDiffuseTextureId);
1030 string sample2Surface;
1031 if (sample2SurfaceIt != samplerSurfaceMapping.end()) {
1032 sample2Surface = sample2SurfaceIt->second;
1034 if (sample2Surface.length() == 0)
continue;
1036 string surface2Image;
1037 auto surface2ImageIt = surfaceImageMapping.find(sample2Surface);
1038 if (surface2ImageIt != surfaceImageMapping.end()) {
1039 surface2Image = surface2ImageIt->second;
1041 if (surface2Image.length() > 0) {
1042 xmlDiffuseTextureId = surface2Image;
1052 array<float, 4> colorArray;
1053 for (
auto i = 0; i < colorArray.size(); i++) {
1054 colorArray[i] = Float::parse(t.
nextToken());
1056 specularMaterialProperties->setAmbientColor(
Color4(colorArray));
1065 array<float, 4> colorArray;
1066 for (
auto i = 0; i < colorArray.size(); i++) {
1067 colorArray[i] = Float::parse(t.
nextToken());
1069 specularMaterialProperties->setEmissionColor(
Color4(colorArray));
1073 auto hasSpecularMap =
false;
1074 auto hasSpecularColor =
false;
1080 auto sample2SurfaceIt = samplerSurfaceMapping.find(xmlSpecularTextureId);
1081 string sample2Surface;
1082 if (sample2SurfaceIt != samplerSurfaceMapping.end()) {
1083 sample2Surface = sample2SurfaceIt->second;
1085 if (sample2Surface.length() == 0)
continue;
1087 string surface2Image;
1088 auto surface2ImageIt = surfaceImageMapping.find(sample2Surface);
1089 if (surface2ImageIt != surfaceImageMapping.end()) {
1090 surface2Image = surface2ImageIt->second;
1093 if (surface2Image.length() > 0) {
1094 xmlSpecularTextureId = surface2Image;
1095 hasSpecularMap =
true;
1102 array<float, 4> colorArray;
1103 for (
auto i = 0; i < colorArray.size(); i++) {
1104 colorArray[i] = Float::parse(t.
nextToken());
1106 specularMaterialProperties->setSpecularColor(
Color4(colorArray));
1107 hasSpecularColor =
true;
1110 if (hasSpecularMap ==
true && hasSpecularColor ==
false) {
1111 specularMaterialProperties->setSpecularColor(
Color4(1.0f, 1.0f, 1.0f, 1.0f));
1116 specularMaterialProperties->setShininess(Float::parse(
string(
AVOID_NULLPTR_STRING(xmlFloat->GetText()))));
1126 auto sample2SurfaceIt = samplerSurfaceMapping.find(xmlBumpTextureId);
1127 string sample2Surface;
1128 if (sample2SurfaceIt != samplerSurfaceMapping.end()) {
1129 sample2Surface = sample2SurfaceIt->second;
1131 if (sample2Surface.length() == 0)
continue;
1133 string surface2Image;
1134 auto surface2ImageIt = surfaceImageMapping.find(sample2Surface);
1135 if (surface2ImageIt != surfaceImageMapping.end()) {
1136 surface2Image = surface2ImageIt->second;
1139 if (surface2Image.length() > 0) xmlBumpTextureId = surface2Image;
1146 string xmlTransparencyTextureFilename;
1147 if (xmlDiffuseTextureId.length() > 0) {
1150 if (xmlTransparencyTextureFilename.length() > 0) {
1157 string xmlDiffuseTextureFilename;
1158 if (xmlDiffuseTextureId.length() > 0) {
1161 if (xmlDiffuseTextureFilename.length() > 0) {
1164 specularMaterialProperties->setDiffuseTexture(pathName, xmlDiffuseTextureFilename, pathName, xmlTransparencyTextureFilename);
1165 if (specularMaterialProperties->getDiffuseTexture() !=
nullptr) specularMaterialProperties->getDiffuseTexture()->setUseCompression(useBC7TextureCompression);
1166 if (specularMaterialProperties->hasDiffuseTextureTransparency() ==
true) specularMaterialProperties->setDiffuseTextureMaskedTransparency(
true);
1171 string xmlSpecularTextureFilename;
1172 if (xmlSpecularTextureId.length() > 0) {
1175 if (xmlSpecularTextureFilename.length() > 0) {
1178 specularMaterialProperties->setSpecularTexture(pathName, xmlSpecularTextureFilename);
1179 if (specularMaterialProperties->getSpecularTexture() !=
nullptr) specularMaterialProperties->getSpecularTexture()->setUseCompression(useBC7TextureCompression);
1184 string xmlBumpTextureFilename;
1185 if (xmlBumpTextureId.length() > 0) {
1188 if (xmlBumpTextureFilename.length() > 0) {
1191 specularMaterialProperties->setNormalTexture(pathName, xmlBumpTextureFilename);
1192 if (specularMaterialProperties->getNormalTexture() !=
nullptr) specularMaterialProperties->getNormalTexture()->setUseCompression(useBC7TextureCompression);
1207 specularMaterialProperties->setAmbientColor(
1215 specularMaterialProperties->setDiffuseColor(
1220 specularMaterialProperties->getDiffuseColor().getAlpha()
1226 material->setSpecularMaterialProperties(specularMaterialProperties.release());
1229 model->
getMaterials()[material->getId()] = material.get();
1232 return material.release();
1238 if (StringTools::startsWith(fileName,
"/") ==
true ||
1239 StringTools::regexMatch(fileName,
"^[A-Z]\\:\\\\.*$") ==
true) {
1240 int indexSlash = fileName.find_last_of(L
'/');
1241 int indexBackslash = fileName.find_last_of(L
'\\');
1242 if (indexSlash != -1 || indexBackslash != -1) {
1243 if (indexSlash > indexBackslash) {
1244 return StringTools::substring(fileName, indexSlash + 1);
1246 return StringTools::substring(fileName, indexBackslash + 1);
1255 string xmlTextureFilename;
1260 if (StringTools::startsWith(xmlTextureFilename,
"file://") ==
true) {
1261 xmlTextureFilename = StringTools::substring(xmlTextureFilename, 7);
1266 return xmlTextureFilename;
1271 vector<TiXmlElement*> elementList;
1273 elementList.push_back(child);
1280 vector<TiXmlElement*> elementList;
1282 elementList.push_back(child);
#define AVOID_NULLPTR_STRING(arg)
Color 4 definition class.
Collada DAE model reader.
static Node * readVisualSceneNode(const string &pathName, Model *model, Node *parentNode, TiXmlElement *xmlRoot, TiXmlElement *xmlNode, float fps, bool useBC7TextureCompression)
Read a DAE visual scene node.
static void readGeometry(const string &pathName, Model *model, Node *node, TiXmlElement *xmlRoot, const string &xmlNodeId, const map< string, string > &materialSymbols, bool useBC7TextureCompression)
Reads a geometry.
static Node * readNode(const string &pathName, Model *model, Node *parentNode, TiXmlElement *xmlRoot, TiXmlElement *xmlNode, float fps, bool useBC7TextureCompression)
Reads a DAE visual scene node node.
static const vector< TiXmlElement * > getChildren(TiXmlElement *parent)
Returns immediate children tags.
static constexpr float BLENDER_AMBIENT_FROM_DIFFUSE_SCALE
static Node * readVisualSceneInstanceController(const string &pathName, Model *model, Node *parentNode, TiXmlElement *xmlRoot, TiXmlElement *xmlNode, bool useBC7TextureCompression)
Reads a instance controller.
static constexpr float BLENDER_DIFFUSE_SCALE
static UpVector * getUpVector(TiXmlElement *xmlRoot)
Get Up vector.
static void setupModelImportRotationMatrix(TiXmlElement *xmlRoot, Model *model)
Set up model import rotation matrix.
static const string makeFileNameRelative(const string &fileName)
Make file name relative.
static const string getTextureFileNameById(TiXmlElement *xmlRoot, const string &xmlTextureId)
Get texture file name by id.
static STATIC_DLL_IMPEXT const Color4 BLENDER_AMBIENT_NONE
static void setupModelImportScaleMatrix(TiXmlElement *xmlRoot, Model *model)
Set up model import scale matrix.
static Material * readMaterial(const string &pathName, Model *model, TiXmlElement *xmlRoot, const string &xmlNodeId, bool useBC7TextureCompression)
Reads a material.
static const vector< TiXmlElement * > getChildrenByTagName(TiXmlElement *parent, const char *name)
Returns immediate children tags by tag name.
static Model::AuthoringTool getAuthoringTool(TiXmlElement *xmlRoot)
Get authoring tool.
Represents a model face, consisting of vertex, normal, tangent and bitangent vectors,...
Node faces entity A node can have multiple entities containing faces and a applied material.
void setMaterial(Material *material)
Set up the entity's material.
void setFaces(const vector< Face > &faces)
Set up entity's faces.
Representation of a 3D model.
unordered_map< string, Material * > & getMaterials()
Returns all object materials.
void setImportTransformMatrix(const Matrix4x4 &importTransformMatrix)
Set import transform matrix.
AuthoringTool getAuthoringTool()
const Matrix4x4 & getImportTransformMatrix()
unordered_map< string, Node * > & getNodes()
Returns all object's nodes.
void setVertices(const vector< Vector3 > &vertices)
Set vertices.
void setFacesEntities(const vector< FacesEntity > &facesEntities)
Set up faces entities.
void setTextureCoordinates(const vector< Vector2 > &textureCoordinates)
Set texture coordinates.
const vector< Vector3 > & getVertices() const
const vector< Vector3 > & getNormals() const
const vector< Vector2 > & getTextureCoordinates() const
void setNormals(const vector< Vector3 > &normals)
Set normals.
const vector< FacesEntity > & getFacesEntities() const
Represents rotation orders of a model.
Skinning definition for nodes.
Represents specular material properties.
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Matrix4x4 clone() const
Clones this matrix.
Matrix4x4 & scale(float scalar)
Scales by scalar.
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Matrix4x4 & set(float r0c0, float r0c1, float r0c2, float r0c3, float r1c0, float r1c1, float r1c2, float r1c3, float r2c0, float r2c1, float r2c2, float r2c3, float r3c0, float r3c1, float r3c2, float r3c3)
Sets this matrix by its components.
Matrix4x4 & transpose()
Transposes this matrix.
Matrix4x4 & setAxes(const Vector3 &xAxis, const Vector3 &yAxis, const Vector3 &zAxis)
Set coordinate system axes.
Vector3 class representing vector3 mathematical structure and operations with x, y,...
File system singleton class.
const string & nextToken()
void tokenize(const string &str, const string &delimiters, bool emptyTokens=false)
Tokenize.
An attribute is a name-value pair.
Always the top level node.
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Parse the given null terminated block of xml data.
const char * ErrorDesc() const
Contains a textual (english) description of the error if one occurs.
const TiXmlElement * RootElement() const
Get the root element – the only top level element – of the document.
bool Error() const
If an error occurs, Error will be set to true.
The element is a container class.
const char * Attribute(const char *name) const
Given an attribute name, Attribute() returns the value for the attribute of that name,...
const TiXmlElement * NextSiblingElement() const
Convenience function to get through elements.
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
std::exception Exception
Exception base class.