8 #include <QImageReader>
9 #include <QRegularExpression>
17 #include "assimp/material.h"
18 #include "assimp/mesh.h"
19 #include "assimp/metadata.h"
20 #include "assimp/scene.h"
27 QImage _getEmbeddedTexture(
unsigned int inTextureIndex,
28 const aiScene *inScene) {
31 if (inScene->mNumTextures == 0) {
33 QStringLiteral(
"[qMeshIO] Scene requests embedded texture, but "
38 auto texture = inScene->mTextures[inTextureIndex];
41 bool isCompressed = (texture->mHeight == 0);
45 QStringLiteral(
"[qMeshIO] Uncompressed embedded textures not "
52 auto dataSize =
static_cast<const int32_t
>(texture->mWidth);
54 const QByteArray imageDataByteArray(
55 reinterpret_cast<const char *
>(texture->pcData), dataSize);
57 return QImage::fromData(imageDataByteArray);
60 QImage _getTextureFromFile(
const QString &inPath,
61 const QString &inTexturePath) {
62 QString cPath = QStringLiteral(
"%1/%2").arg(inPath, inTexturePath);
66 if (!QFile::exists(cPath)) {
67 CVLog::Warning(QStringLiteral(
"[qMeshIO] Material not found: '%1'")
72 QImageReader reader(cPath);
74 QImage
image = reader.read();
77 QString(
"[_getTextureFromFile] failed to read image %1, %2")
79 .arg(reader.errorString()));
89 void _assignMaterialProperties(aiMaterial *inAIMaterial,
93 if (inAIMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, colour) == AI_SUCCESS) {
94 inCCMaterial->setDiffuse(_convertColour(colour));
97 if (inAIMaterial->Get(AI_MATKEY_COLOR_AMBIENT, colour) == AI_SUCCESS) {
98 inCCMaterial->setAmbient(_convertColour(colour));
101 if (inAIMaterial->Get(AI_MATKEY_COLOR_SPECULAR, colour) == AI_SUCCESS) {
102 inCCMaterial->setSpecular(_convertColour(colour));
105 if (inAIMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, colour) == AI_SUCCESS) {
106 inCCMaterial->setEmission(_convertColour(colour));
111 if (inAIMaterial->Get(AI_MATKEY_SHININESS, property) == AI_SUCCESS) {
112 inCCMaterial->setShininess(property);
115 if (inAIMaterial->Get(AI_MATKEY_OPACITY, property) == AI_SUCCESS) {
116 inCCMaterial->setTransparency(property);
123 const QString &inPath,
124 const aiScene *inScene) {
125 if (inScene->mNumMaterials == 0) {
129 unsigned int index = inMesh->mMaterialIndex;
130 const auto aiMaterial = inScene->mMaterials[index];
132 const aiString cName = aiMaterial->GetName();
137 .arg(newMaterial->getName()));
144 auto loadTexture = [&](aiTextureType aiType,
146 const char *typeName) {
147 if (aiMaterial->GetTextureCount(aiType) > 0) {
148 aiString texturePath;
150 if (aiMaterial->GetTexture(aiType, 0, &texturePath) == AI_SUCCESS) {
151 static QRegularExpression sRegExp(
"^\\*(?<index>[0-9]+)$");
152 auto match = sRegExp.match(texturePath.C_Str());
157 inPath, texturePath.C_Str()));
160 if (match.hasMatch()) {
162 const QString cIndex = match.captured(
"index");
163 image = _getEmbeddedTexture(cIndex.toUInt(), inScene);
164 }
else if (!QFile::exists(
path) && inScene->HasTextures()) {
166 unsigned int cIndex = 0;
167 for (
unsigned int i = 0; i < inScene->mNumTextures; ++i) {
168 aiString textureName = inScene->mTextures[i]->mFilename;
169 if (textureName == texturePath) {
174 image = _getEmbeddedTexture(cIndex, inScene);
177 image = _getTextureFromFile(inPath, texturePath.C_Str());
180 if (!
image.isNull()) {
182 if (newMaterial->loadAndSetTextureMap(ccType,
path)) {
185 "[qMeshIO] Loaded %1 texture: %2")
186 .arg(typeName,
path));
192 newMaterial->setTexture(
image,
path,
false);
197 "[qMeshIO] Failed to load %1 texture: %2")
198 .arg(typeName,
path));
219 loadTexture(aiTextureType_DISPLACEMENT,
221 loadTexture(aiTextureType_REFLECTION,
227 loadTexture(aiTextureType_DIFFUSE_ROUGHNESS,
230 _assignMaterialProperties(aiMaterial, newMaterial);
241 auto newMesh =
new ccMesh(newPC);
243 QString
name(inMesh->mName.C_Str());
245 if (
name.isEmpty()) {
246 name = QStringLiteral(
"Mesh");
249 CVLog::Print(QStringLiteral(
"[qMeshIO] Mesh '%1' has %2 verts & %3 faces")
251 QLocale::system().
toString(inMesh->mNumVertices),
252 QLocale::system().toString(inMesh->mNumFaces)));
254 if (!inMesh->HasPositions() || !inMesh->HasFaces()) {
257 "[qMeshIO] Mesh '%1' does not have vertices or faces")
268 newPC->reserveThePointsTable(inMesh->mNumVertices);
270 if (inMesh->HasFaces()) {
271 newMesh->reserve(inMesh->mNumFaces);
275 bool hasVertexColors = inMesh->HasVertexColors(0);
276 if (hasVertexColors) {
277 bool allocated = newPC->reserveTheRGBTable();
281 "[qMeshIO] Cannot allocate colors for mesh '%1'")
287 if (inMesh->HasNormals()) {
288 bool allocated = newPC->reserveTheNormsTable();
293 "[qMeshIO] Cannot allocate normals for mesh '%1'")
299 bool hasTextureCoordinates = inMesh->HasTextureCoords(0);
303 if (hasTextureCoordinates) {
306 texCoords->reserve(inMesh->mNumVertices);
310 allocated &= newMesh->reservePerTriangleTexCoordIndexes();
311 allocated &= newMesh->reservePerTriangleMtlIndexes();
315 hasTextureCoordinates =
false;
316 CVLog::Warning(QStringLiteral(
"[qMeshIO] Cannot allocate texture "
317 "coordinates for mesh '%1'")
320 newMesh->setTexCoordinatesTable(texCoords);
325 for (
unsigned int i = 0; i < inMesh->mNumVertices; ++i) {
326 const aiVector3D &
point = inMesh->mVertices[i];
332 newPC->addPoint(point2);
335 if (newPC->hasColors()) {
336 const aiColor4D &
colors = inMesh->mColors[0][i];
342 newPC->addRGBColor(
color);
346 if (newPC->hasNormals()) {
347 const aiVector3D &
normal = inMesh->mNormals[i];
353 newPC->addNorm(normal2);
357 if (hasTextureCoordinates) {
358 const aiVector3D &texCoord = inMesh->mTextureCoords[0][i];
366 newPC->setEnabled(
false);
369 if (inMesh->HasFaces()) {
370 newMesh->reserve(inMesh->mNumFaces);
372 for (
unsigned int i = 0; i < inMesh->mNumFaces; ++i) {
373 const aiFace &
face = inMesh->mFaces[i];
375 if (
face.mNumIndices != 3) {
379 newMesh->addTriangle(
face.mIndices[0],
face.mIndices[1],
383 if (hasTextureCoordinates) {
384 newMesh->addTriangleMtlIndex(0);
386 newMesh->addTriangleTexCoordIndexes(
387 static_cast<int>(
face.mIndices[0]),
388 static_cast<int>(
face.mIndices[1]),
389 static_cast<int>(
face.mIndices[2]));
394 if (newMesh->size() == 0) {
396 QStringLiteral(
"[qMeshIO] Mesh '%1' does not have any faces")
405 newMesh->setName(
name);
406 newMesh->setVisible(
true);
408 if (!newPC->hasNormals()) {
410 QStringLiteral(
"[qMeshIO] Mesh '%1' does not have normals - "
411 "will compute them per vertex automatically!")
414 newMesh->computeNormals(
true);
417 newMesh->showNormals(
true);
418 newMesh->showColors(hasVertexColors);
419 newMesh->addChild(newPC);
425 const int cWidth = 4;
426 const int cHeight = 4;
430 for (
unsigned int i = 0; i < cWidth; ++i) {
431 for (
unsigned int j = 0; j < cHeight; ++j) {
432 data[j * cHeight + i] =
441 unsigned int inValueIndex) {
444 switch (inData->mValues[inValueIndex].mType) {
448 inData->Get<
bool>(inValueIndex, value);
457 inData->Get<int32_t>(inValueIndex, value);
466 inData->Get<uint64_t>(inValueIndex, value);
468 metaValue =
static_cast<qulonglong
>(value);
475 inData->Get<
float>(inValueIndex, value);
484 inData->Get<
double>(inValueIndex, value);
493 inData->Get<aiString>(inValueIndex, value);
495 metaValue = value.C_Str();
499 case AI_AIVECTOR3D: {
502 inData->Get<aiVector3D>(inValueIndex, value);
504 metaValue = QVector3D(value.x, value.y, value.z);
float PointCoordinateType
Type of the coordinates of a (N-D) point.
std::shared_ptr< core::Tensor > image
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
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.
Array of 2D texture coordinates.
bool isAllocated() const
Returns whether some memory has been allocated or not.
void addElement(const Type &value)
Float version of ccGLMatrixTpl.
Mesh (triangle) material.
int addMaterial(ccMaterial::CShared mat, bool allowDuplicateNames=false)
Adds a material.
Mesh (triangle) material.
TextureMapType
Texture map types for PBR materials.
QSharedPointer< ccMaterial > Shared
Shared type.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
std::vector< unsigned int > face
unsigned char ColorCompType
Default color components type (R,G and B)
static const unsigned OPENGL_MATRIX_SIZE
Model view matrix size (OpenGL)
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)
static const std::string path
std::string toString(T x)