/* QGLView Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "loader_assimp.h" #include "glscene.h" #include "glmesh.h" #include "glmaterial.h" #include "globject.h" #include #include #include #include #include QVector3D fromAiVector3D(const aiVector3D & v) {return QVector3D(v.x, v.y, v.z);} Vector3i fromAiFace (const aiFace & v) {return Vector3i(v.mIndices[0], v.mIndices[1], v.mIndices[2]);} QMatrix4x4 fromAiMatrix4D(const aiMatrix4x4 & v) {return QMatrix4x4(v.a1, v.a2, v.a3, v.a4, v.b1, v.b2, v.b3, v.b4, v.c1, v.c2, v.c3, v.c4, v.d1, v.d2, v.d3, v.d4);} bool isAiMeshTriangles(const aiMesh * m) {return (m->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) == aiPrimitiveType_TRIANGLE;} Mesh * assimpMesh(const aiMesh * m) { if (!m) return 0; if (!isAiMeshTriangles(m)) return 0; Mesh * ret = new Mesh(); int vcnt = m->mNumVertices, tcnt = m->mNumFaces; QVector & v(ret->vertices()); v.resize(vcnt); QVector & t(ret->texcoords()); t.resize(vcnt); QVector< Vector3i> & ind(ret->indices()); for (int i = 0; i < vcnt; ++i) v[i] = fromAiVector3D(m->mVertices[i]); if (m->HasNormals()) { QVector & n(ret->normals()); n.resize(vcnt); for (int i = 0; i < vcnt; ++i) n[i] = fromAiVector3D(m->mNormals[i]); } if (m->HasTextureCoords(0)) { for (int i = 0; i < vcnt; ++i) t[i] = fromAiVector3D(m->mTextureCoords[0][i]).toVector2D(); } if (m->HasFaces()) { ind.resize(tcnt); for (int i = 0; i < tcnt; ++i) ind[i] = fromAiFace(m->mFaces[i]); } else { tcnt = vcnt / 3; ind.resize(tcnt); int si = 0; for (int i = 0; i < tcnt; ++i) { si = i+i+i; ind[i] = Vector3i(si, si+1, si+2); } } //qDebug() << "add mesh" << v.size() << ret->normals().size() << ret->texcoords().size() << ret->indices().size(); return ret; } ObjectBase * assimpObject(const aiNode * n, const QVector & meshes) { if (!n) return 0; ObjectBase * ret = new ObjectBase(); ret->setName(n->mName.C_Str()); ret->setTransform(fromAiMatrix4D(n->mTransformation)); //qDebug() << "add object" << ret << ret->name(); for (uint i = 0; i < n->mNumMeshes; ++i) { int mi = n->mMeshes[i]; if (meshes[mi]) { ret->setMesh(meshes[mi]); //qDebug() << "set mesh" << mi << ret->mesh(); break; } } for (uint i = 0; i < n->mNumChildren; ++i) { ObjectBase * co = assimpObject(n->mChildren[i], meshes); if (co) ret->addChild(co); } return ret; } Scene * loadScene(const QString & filepath) { if (filepath.isEmpty()) return 0; qDebug() << "[Loader Assimp] Import" << filepath << "..."; Assimp::Importer importer; const aiScene * ais = importer.ReadFile(filepath.toUtf8(), aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_GenUVCoords | aiProcess_TransformUVCoords); if (!ais) { qDebug() << "[Loader Assimp] Error: \"" + QString(importer.GetErrorString()) + "\""; return 0; } qDebug() << "[Loader Assimp] Imported" << ais->mNumMeshes << "meshes"; QVector meshes; for (uint i = 0; i < ais->mNumMeshes; ++i) meshes << assimpMesh(ais->mMeshes[i]); ObjectBase * root = assimpObject(ais->mRootNode, meshes); if (!root) return 0; Scene * scene = new Scene(); scene->setName(root->name()); foreach (ObjectBase * o, root->children()) scene->addObject(o); return scene; }