11 #include <QProgressDialog>
19 #include "assimp/DefaultLogger.hpp"
20 #include "assimp/Importer.hpp"
21 #include "assimp/ProgressHandler.hpp"
22 #include "assimp/postprocess.h"
23 #include "assimp/scene.h"
28 class _LogStream :
public Assimp::LogStream {
29 void write(
const char *inMessage)
override {
30 QString message = QString(inMessage).trimmed();
33 if (message.startsWith(
"Warn")) {
35 }
else if (message.startsWith(
"Error")) {
37 }
else if (message.startsWith(
"Info")) {
41 message.prepend(
"[qMeshIO] ai - ");
47 class _ProgressHandler :
public QProgressDialog,
48 public Assimp::ProgressHandler {
50 _ProgressHandler(
const QString &inText) : cText(inText) {
51 setWindowModality(Qt::WindowModal);
52 setWindowTitle(tr(
"Import Mesh"));
54 setMinimumDuration(0);
56 setMinimumSize(400, 100);
59 bool Update(
float inPercent)
override {
60 int value = qRound(inPercent * 100.0f);
62 setLabelText(QStringLiteral(
"Loading %1: %2%")
63 .arg(cText, QString::number(value)));
76 _Loader(
const aiScene *inScene,
77 const QString &inFileName,
78 const QString &inPath)
79 : cScene(inScene), cFileName(inFileName), cPath(inPath) {
84 if (cScene->HasMeshes()) {
85 CVLog::Print(QStringLiteral(
"[qMeshIO] The file '%1' has %2 meshes")
86 .arg(cFileName, QLocale::system().
toString(
87 cScene->mNumMeshes)));
90 if (cScene->HasCameras()) {
92 QStringLiteral(
"[qMeshIO] The file '%1' has %2 cameras")
93 .arg(cFileName, QLocale::system().
toString(
94 cScene->mNumCameras)));
97 _recursiveAddNode(cScene->mRootNode, cScene, &ioContainer);
102 _pruneTree(&ioContainer);
106 void _initCameraNames() {
107 for (
unsigned int i = 0; i < cScene->mNumCameras; ++i) {
108 const auto cCamera = cScene->mCameras[i];
109 const QString cCameraName(cCamera->mName.C_Str());
111 mCameraMap[cCameraName] = cCamera;
115 void _recursiveAddNode(
const aiNode *inNode,
116 const aiScene *inScene,
119 std::cout <<
"Process node: " << inNode->mName.C_Str() <<
std::endl;
120 std::cout <<
" num children: " << inNode->mNumChildren <<
std::endl;
121 std::cout <<
" num meshes: " << inNode->mNumMeshes <<
std::endl;
124 auto currentObject =
new ccHObject(inNode->mName.C_Str());
126 ioParentObject->
addChild(currentObject);
128 const bool cNodeHasTransform = !inNode->mTransformation.IsIdentity();
130 if (cNodeHasTransform) {
134 currentObject->setGLTransformation(transform);
138 for (
unsigned int j = 0; j < inNode->mNumMeshes; ++j) {
139 const auto cMeshIndex = inNode->mMeshes[j];
140 const auto mesh = inScene->mMeshes[cMeshIndex];
144 if (newMesh ==
nullptr) {
151 if (materialSet !=
nullptr) {
156 currentObject->addChild(newMesh);
160 if (inNode->mMetaData !=
nullptr) {
161 const auto data = inNode->mMetaData;
163 for (
unsigned int i = 0; i < data->mNumProperties; ++i) {
164 const auto cMetaKey = data->mKeys[i].C_Str();
169 std::cout <<
"Setting meta: " << cMetaKey <<
" = "
170 << metaValue.toString().toLatin1().constData()
174 currentObject->setMetaData(cMetaKey, metaValue);
178 for (
unsigned int i = 0; i < inNode->mNumChildren; ++i) {
179 const auto cChild = inNode->mChildren[i];
181 _recursiveAddNode(cChild, inScene, currentObject);
185 void _pruneTree(
ccHObject *ioCurrentObject) {
188 std::vector<ccHObject *> children;
192 for (
unsigned int i = 0; i < childCount; ++i) {
193 children.push_back(ioCurrentObject->
getChild(i));
196 for (
auto child : children) {
207 auto parent = ioCurrentObject->
getParent();
209 if (parent ==
nullptr) {
218 if (childCount == 0) {
220 std::cout <<
"pruning: "
221 << ioCurrentObject->
getName().toLatin1().constData()
223 << parent->getName().toLatin1().constData() <<
std::endl;
226 parent->detachChild(ioCurrentObject);
228 delete ioCurrentObject;
229 }
else if ((childCount == 1) && ioCurrentObject->
metaData().empty()) {
233 auto child = ioCurrentObject->
getChild(0);
235 if (child !=
nullptr) {
237 std::cout <<
"reparenting: "
238 << child->
getName().toLatin1().constData() <<
" from "
239 << ioCurrentObject->
getName().toLatin1().constData()
240 <<
" to " << parent->getName().toLatin1().constData()
245 child->setName(ioCurrentObject->
getName());
247 parent->addChild(child);
249 delete ioCurrentObject;
254 const aiScene *cScene;
255 const QString cFileName;
258 QMap<QString, const aiCamera *> mCameraMap;
267 bool &exclusive)
const {
276 const QString &inFileName,
279 Q_UNUSED(inParameters)
281 const auto cFileName = QFileInfo(inFileName).fileName();
282 const auto cPath = QFileInfo(inFileName).absoluteDir().path();
284 CVLog::Print(QStringLiteral(
"[qMeshIO] Loading file '%1'").arg(inFileName));
286 Assimp::DefaultLogger::create(
"", Assimp::Logger::NORMAL,
287 aiDefaultLogStream_STDOUT);
289 unsigned int loggingSeverity = Assimp::Logger::Err | Assimp::Logger::Warn;
292 loggingSeverity |= Assimp::Logger::Info;
293 loggingSeverity |= Assimp::Logger::Debugging;
296 Assimp::DefaultLogger::get()->attachStream(
new _LogStream, loggingSeverity);
298 Assimp::Importer importer;
300 importer.SetProgressHandler(
new _ProgressHandler(cFileName));
303 importer.SetPropertyInteger(
304 AI_CONFIG_PP_RVC_FLAGS,
305 aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS |
306 aiComponent_CAMERAS | aiComponent_LIGHTS);
308 importer.SetPropertyBool(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,
true);
309 importer.SetPropertyBool(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,
true);
310 importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE,
true);
311 importer.SetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS,
true);
313 const aiScene *cScene = importer.ReadFile(
314 inFileName.toStdString(),
315 aiProcess_FindInvalidData | aiProcess_JoinIdenticalVertices |
316 aiProcess_RemoveComponent | aiProcess_Triangulate |
317 aiProcess_ValidateDataStructure);
319 if (cScene ==
nullptr) {
320 CVLog::Warning(QStringLiteral(
"[qMeshIO] The file '%1' has errors: %2")
321 .arg(cFileName, importer.GetErrorString()));
323 Assimp::DefaultLogger::kill();
328 _Loader loader(cScene, cFileName, cPath);
330 loader.load(ioContainer);
332 Assimp::DefaultLogger::kill();
341 Q_UNUSED(ioContainer);
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
CC_FILE_ERROR
Typical I/O filter errors.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static void LogMessage(const QString &message, int level)
Static shortcut to CVLog::logMessage.
virtual void _postProcess(ccHObject &ioContainer)
bool canSave(CV_CLASS_ENUM inType, bool &outMultiple, bool &outExclusive) const override
Returns whether this I/O filter can save the specified type of entity.
IoAbstractLoader(const FileIOFilter::FilterInfo &info)
CC_FILE_ERROR loadFile(const QString &inFileName, ccHObject &ioContainer, LoadParameters &inParameters) override
Loads one or more entities from a file.
Float version of ccGLMatrixTpl.
virtual void showMaterials(bool state)
Sets whether textures should be displayed or not.
Hierarchical CLOUDVIEWER Object.
void detachChild(ccHObject *child)
Detaches a specific child.
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
unsigned getChildrenNumber() const
Returns the number of children.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getParent() const
Returns parent object.
virtual void resetGLTransformationHistory()
Resets the transformation 'history' matrix.
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
CV_CLASS_ENUM getClassID() const override
Returns class ID.
void setMaterialSet(ccMaterialSet *materialSet, bool autoReleaseOldMaterialSet=true)
Sets associated material set (may be shared)
const QVariantMap & metaData() const
Returns meta-data map (const only)
virtual QString getName() const
Returns object name.
ccMaterialSet * createMaterialSetForMesh(const aiMesh *inMesh, const QString &inPath, const aiScene *inScene)
ccMesh * newCCMeshFromAIMesh(const aiMesh *inMesh)
QVariant convertMetaValueToVariant(aiMetadata *inData, unsigned int inValueIndex)
ccGLMatrix convertMatrix(const aiMatrix4x4 &inAssimpMatrix)
QTextStream & endl(QTextStream &stream)
std::string toString(T x)
Generic loading parameters.