7 #include "imstkVisualObjectImporter.h" 8 #include "imstkAssimpMeshIO.h" 9 #include "imstkLineMesh.h" 10 #include "imstkLogger.h" 11 #include "imstkRenderMaterial.h" 12 #include "imstkSceneObject.h" 13 #include "imstkSurfaceMesh.h" 14 #include "imstkVecDataArray.h" 15 #include "imstkVisualModel.h" 17 #include <assimp/Importer.hpp> 18 #include <assimp/scene.h> 21 #include <unordered_map> 26 aiMatToMat4d(
const aiMatrix4x4& m)
29 for (
int i = 0; i < 4; i++)
31 for (
int j = 0; j < 4; j++)
33 results(i, j) =
static_cast<double>(m[i][j]);
40 mat4dToAiMat(
const Mat4d& m)
43 for (
int i = 0; i < 4; i++)
45 for (
int j = 0; j < 4; j++)
47 results[i][j] =
static_cast<float>(m(i, j));
53 std::shared_ptr<SceneObject>
55 const std::string& objName,
56 const std::string& modelFilePath,
57 const std::string& textureFolderPath,
58 const Mat4d& transform)
63 if (type != MeshFileType::_3DS
64 && type != MeshFileType::OBJ
65 && type != MeshFileType::FBX
66 && type != MeshFileType::DAE)
68 LOG(FATAL) <<
"Error: File type not supported! Input model file path: " << modelFilePath;
72 auto visualObject = std::make_shared<SceneObject>(objName);
75 Assimp::Importer importer;
79 CHECK(scene !=
nullptr && scene->HasMeshes()) <<
"Error: could not read model with Assimp reader! Input model file path: " 83 std::vector<std::shared_ptr<RenderMaterial>> materials(scene->mNumMaterials);
84 for (
unsigned int i = 0; i < scene->mNumMaterials; i++)
86 materials[i] = readMaterial(scene->mMaterials[i], textureFolderPath);
90 std::vector<std::shared_ptr<PointSet>> meshes(scene->mNumMeshes);
91 std::vector<std::shared_ptr<RenderMaterial>> meshMaterials(scene->mNumMeshes);
92 for (
unsigned int i = 0; i < scene->mNumMeshes; i++)
94 aiMesh* importedMesh = scene->mMeshes[i];
96 meshMaterials[i] = materials[importedMesh->mMaterialIndex];
100 std::stack<aiNode*> nodes;
101 nodes.push(scene->mRootNode);
102 scene->mRootNode->mTransformation = mat4dToAiMat(transform) * scene->mRootNode->mTransformation;
103 std::unordered_map<aiNode*, Mat4d> worldTransforms;
104 while (!nodes.empty())
106 aiNode* currNode = nodes.top();
109 Mat4d parentWorldTransform = Mat4d::Identity();
110 if (currNode->mParent !=
nullptr)
112 parentWorldTransform = worldTransforms[currNode->mParent];
114 Mat4d localTransform = aiMatToMat4d(currNode->mTransformation);
115 Mat4d currWorldTransform = parentWorldTransform * localTransform;
116 worldTransforms[currNode] = currWorldTransform;
118 for (
unsigned int i = 0; i < currNode->mNumMeshes; i++)
120 const unsigned int meshIndex = currNode->mMeshes[i];
123 std::shared_ptr<PointSet> copyMesh = meshes[meshIndex]->clone();
125 auto visualModel = visualObject->addComponent<
VisualModel>();
126 visualModel->setGeometry(copyMesh);
127 visualModel->setName(std::string(currNode->mName.C_Str()));
129 copyMesh->transform(currWorldTransform, Geometry::TransformType::ApplyToData);
130 visualModel->setRenderMaterial(meshMaterials[meshIndex]);
133 for (
unsigned int i = 0; i < currNode->mNumChildren; i++)
135 nodes.push(currNode->mChildren[i]);
142 std::shared_ptr<Texture>
143 ObjectIO::createTexture(std::string textureFolderPath, std::string textureFilePath,
Texture::Type textureType)
145 textureFilePath = getSubstringGivenString(textureFilePath,
"/",
true);
146 textureFilePath = getSubstringGivenString(textureFilePath,
"\\",
true);
148 std::string fileName = getSubstringGivenString(textureFilePath,
".",
false);
150 const std::string fileExt = getSubstringGivenString(textureFilePath,
".",
true);
152 const std::string filePath = textureFolderPath + fileName +
"." + fileExt;
155 std::ifstream file(filePath);
159 return std::make_shared<Texture>(filePath, textureType);
164 std::shared_ptr<RenderMaterial>
165 ObjectIO::readMaterial(aiMaterial* material, std::string textureFolderPath)
168 auto renderMaterial = std::make_shared<RenderMaterial>();
173 aiReturn ret = material->Get(AI_MATKEY_NAME, name);
174 if (ret == AI_SUCCESS)
176 renderMaterial->setName(std::string(name.C_Str()));
179 aiColor3D ambientColor;
180 ret = material->Get(AI_MATKEY_COLOR_AMBIENT, ambientColor);
181 if (ret == AI_SUCCESS)
183 renderMaterial->setAmbientColor(
Color(ambientColor.r, ambientColor.g, ambientColor.b));
186 aiColor3D diffuseColor;
187 ret = material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColor);
188 if (ret == AI_SUCCESS)
190 renderMaterial->setDiffuseColor(
Color(diffuseColor.r, diffuseColor.g, diffuseColor.b));
193 aiColor3D specularColor;
194 ret = material->Get(AI_MATKEY_COLOR_SPECULAR, specularColor);
195 if (ret == AI_SUCCESS)
197 renderMaterial->setSpecularColor(
Color(specularColor.r, specularColor.g, specularColor.b));
201 ret = material->Get(AI_MATKEY_ENABLE_WIREFRAME, useWireframe);
202 if (ret == AI_SUCCESS)
204 if (useWireframe == 1)
206 renderMaterial->setDisplayMode(RenderMaterial::DisplayMode::Wireframe);
210 int useBackfaceRendering;
211 ret = material->Get(AI_MATKEY_TWOSIDED, useBackfaceRendering);
212 if (ret == AI_SUCCESS)
214 renderMaterial->setBackFaceCulling(static_cast<bool>(useBackfaceRendering));
218 ret = material->Get(AI_MATKEY_OPACITY, opacity);
219 if (ret == AI_SUCCESS)
221 renderMaterial->setOpacity(opacity);
225 ret = material->Get(AI_MATKEY_SHININESS, shininess);
226 if (ret == AI_SUCCESS)
228 renderMaterial->setSpecular(shininess);
231 float shininessStrength;
232 ret = material->Get(AI_MATKEY_SHININESS_STRENGTH, shininessStrength);
233 if (ret == AI_SUCCESS)
235 renderMaterial->setSpecularPower(shininessStrength);
239 ret = material->Get(AI_MATKEY_REFLECTIVITY, reflectivity);
240 if (ret == AI_SUCCESS)
245 renderMaterial->setRecomputeVertexNormals(
false);
247 aiString texFilePath;
248 ret = material->GetTexture(aiTextureType::aiTextureType_AMBIENT, 0, &texFilePath);
249 if (ret == AI_SUCCESS)
251 std::shared_ptr<Texture> tex = createTexture(textureFolderPath, std::string(texFilePath.C_Str()), Texture::Type::AmbientOcclusion);
254 renderMaterial->addTexture(tex);
257 ret = material->GetTexture(aiTextureType::aiTextureType_DIFFUSE, 0, &texFilePath);
258 if (ret == AI_SUCCESS)
260 std::shared_ptr<Texture> tex = createTexture(textureFolderPath, std::string(texFilePath.C_Str()), Texture::Type::Diffuse);
263 renderMaterial->addTexture(tex);
266 ret = material->GetTexture(aiTextureType::aiTextureType_EMISSIVE, 0, &texFilePath);
267 if (ret == AI_SUCCESS)
269 std::shared_ptr<Texture> tex = createTexture(textureFolderPath, std::string(texFilePath.C_Str()), Texture::Type::Emissive);
272 renderMaterial->addTexture(tex);
275 ret = material->GetTexture(aiTextureType::aiTextureType_NORMALS, 0, &texFilePath);
276 if (ret == AI_SUCCESS)
278 std::shared_ptr<Texture> tex = createTexture(textureFolderPath, std::string(texFilePath.C_Str()), Texture::Type::Normal);
281 renderMaterial->addTexture(tex);
284 ret = material->GetTexture(aiTextureType::aiTextureType_SPECULAR, 0, &texFilePath);
285 if (ret == AI_SUCCESS)
287 std::shared_ptr<Texture> tex = createTexture(textureFolderPath, std::string(texFilePath.C_Str()), Texture::Type::Metalness);
290 renderMaterial->addTexture(tex);
293 return renderMaterial;
297 ObjectIO::getSubstringGivenString(
298 const std::string& input,
299 const std::string& delimiter,
300 const bool lastInstance )
302 unsigned long long index = 0;
303 unsigned long long tempIndex;
307 tempIndex = input.rfind(delimiter) + 1;
308 if (tempIndex >= input.length())
315 tempIndex = input.find(delimiter);
318 if (tempIndex == std::string::npos)
320 index = lastInstance ? 0 : input.length();
329 return input.substr(index);
332 return input.substr(0, index);
Phong shading model (default)
Type
Texture type - determines filtering.
static std::shared_ptr< SceneObject > importSceneObject(const std::string &objName, const std::string &modelFilePath, const std::string &textureFolderPath, const Mat4d &transform=Mat4d::Identity())
Import a scene object.
static const MeshFileType getFileType(const std::string &filePath)
Returns the type of the file.
static unsigned int getDefaultPostProcessSteps()
Helper function for getting default post processing flags.
static std::shared_ptr< PointSet > convertAssimpMesh(aiMesh *importedMesh)
Convert from Assimp mesh to iMSTK SurfaceMesh. May convert to LineMesh if no triangles & only lines a...
Contains geometric, material, and render information.