Skip to content

Commit 4db3059

Browse files
gregoire-dlcbentejac
authored andcommitted
[mesh] Texturing: Fix .gltf and add .glb mesh export
1 parent ff4ee78 commit 4db3059

File tree

1 file changed

+70
-21
lines changed

1 file changed

+70
-21
lines changed

src/aliceVision/mesh/Texturing.cpp

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,23 +1304,30 @@ void Texturing::saveAs(const fs::path& dir, const std::string& basename, EFileTy
13041304
const std::string meshFileTypeStr = EFileType_enumToString(meshFileType);
13051305
const std::string filepath = (dir / (basename + "." + meshFileTypeStr)).string();
13061306

1307-
ALICEVISION_LOG_INFO("Save " << filepath << " mesh file");
1307+
ALICEVISION_LOG_INFO("Saving " << meshFileTypeStr << " mesh file using Assimp.");
13081308

13091309
if (_atlases.empty())
13101310
{
1311+
ALICEVISION_LOG_ERROR("No texture atlases available. Cannot save mesh.");
13111312
return;
13121313
}
13131314

1315+
// Assimp scene setup
1316+
// create scene and root node
13141317
aiScene scene;
1318+
scene.mRootNode = new aiNode();
13151319

1316-
scene.mRootNode = new aiNode;
1320+
// create material array
1321+
scene.mMaterials = new aiMaterial*[_atlases.size()];
1322+
scene.mNumMaterials = _atlases.size();
13171323

1324+
// create mesh array
13181325
scene.mMeshes = new aiMesh*[_atlases.size()];
13191326
scene.mNumMeshes = _atlases.size();
1327+
1328+
// link mesh array to root node
13201329
scene.mRootNode->mMeshes = new unsigned int[_atlases.size()];
13211330
scene.mRootNode->mNumMeshes = _atlases.size();
1322-
scene.mMaterials = new aiMaterial*[_atlases.size()];
1323-
scene.mNumMaterials = _atlases.size();
13241331

13251332
// define shared material properties
13261333
const aiVector3D valcolor = {material.diffuse.r, material.diffuse.g, material.diffuse.b};
@@ -1340,7 +1347,7 @@ void Texturing::saveAs(const fs::path& dir, const std::string& basename, EFileTy
13401347
// Set material for this atlas
13411348
const aiString texName("material_" + Material::textureId(atlasId));
13421349

1343-
scene.mMaterials[atlasId] = new aiMaterial;
1350+
scene.mMaterials[atlasId] = new aiMaterial();
13441351
scene.mMaterials[atlasId]->AddProperty(&valcolor, 1, AI_MATKEY_COLOR_DIFFUSE);
13451352
scene.mMaterials[atlasId]->AddProperty(&valambient, 1, AI_MATKEY_COLOR_AMBIENT);
13461353
scene.mMaterials[atlasId]->AddProperty(&valspecular, 1, AI_MATKEY_COLOR_SPECULAR);
@@ -1376,11 +1383,18 @@ void Texturing::saveAs(const fs::path& dir, const std::string& basename, EFileTy
13761383
}
13771384

13781385
scene.mRootNode->mMeshes[atlasId] = atlasId;
1379-
scene.mMeshes[atlasId] = new aiMesh;
1386+
scene.mMeshes[atlasId] = new aiMesh();
13801387
aiMesh* aimesh = scene.mMeshes[atlasId];
13811388
aimesh->mMaterialIndex = atlasId;
13821389
aimesh->mNumUVComponents[0] = 2;
13831390

1391+
if (meshFileType == EFileType::GLTF || meshFileType == EFileType::GLB)
1392+
{
1393+
// set primitive types to triangles, required for gltf and glb export
1394+
// for other file types, primitive types is unspecified to avoid normal generation
1395+
aimesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
1396+
}
1397+
13841398
// Assimp does not allow vertex indices different from uv indices
13851399
// So we need to group and duplicate
13861400
std::map<std::pair<int, int>, int> unique_pairs;
@@ -1398,24 +1412,31 @@ void Texturing::saveAs(const fs::path& dir, const std::string& basename, EFileTy
13981412

13991413
aimesh->mNumVertices = unique_pairs.size();
14001414
aimesh->mVertices = new aiVector3D[unique_pairs.size()];
1401-
aimesh->mTextureCoords[0] = new aiVector3D[unique_pairs.size()];
1415+
1416+
if (hasUVs())
1417+
{
1418+
aimesh->mTextureCoords[0] = new aiVector3D[unique_pairs.size()];
1419+
}
14021420

14031421
int index = 0;
14041422
for (auto& p : unique_pairs)
14051423
{
1406-
int vertexId = p.first.first;
1407-
int uvId = p.first.second;
1424+
const int vertexId = p.first.first;
14081425

14091426
aimesh->mVertices[index].x = mesh->pts[vertexId].x;
14101427
aimesh->mVertices[index].y = -mesh->pts[vertexId].y;
14111428
aimesh->mVertices[index].z = -mesh->pts[vertexId].z;
14121429

1413-
aimesh->mTextureCoords[0][index].x = mesh->uvCoords[uvId].x;
1414-
aimesh->mTextureCoords[0][index].y = mesh->uvCoords[uvId].y;
1415-
aimesh->mTextureCoords[0][index].z = 0.0;
1430+
if (hasUVs())
1431+
{
1432+
const int uvId = p.first.second;
14161433

1417-
p.second = index;
1434+
aimesh->mTextureCoords[0][index].x = mesh->uvCoords[uvId].x;
1435+
aimesh->mTextureCoords[0][index].y = mesh->uvCoords[uvId].y;
1436+
aimesh->mTextureCoords[0][index].z = 0.0;
1437+
}
14181438

1439+
p.second = index;
14191440
++index;
14201441
}
14211442

@@ -1440,21 +1461,49 @@ void Texturing::saveAs(const fs::path& dir, const std::string& basename, EFileTy
14401461
}
14411462
}
14421463

1443-
std::string formatId = meshFileTypeStr;
1464+
// exporter setup
1465+
std::string pFormatId = meshFileTypeStr;
14441466
unsigned int pPreprocessing = 0u;
1445-
// If gltf, use gltf 2.0
1446-
if (meshFileType == EFileType::GLTF)
1467+
1468+
if (meshFileType == EFileType::GLTF || meshFileType == EFileType::GLB)
14471469
{
1448-
formatId = "gltf2";
1449-
// Flip UVs when exporting (issue with UV origin for gltf2)
1470+
if (meshFileType == EFileType::GLTF)
1471+
{
1472+
// gltf file, use gltf 2.0
1473+
pFormatId = "gltf2";
1474+
}
1475+
else
1476+
{
1477+
// glb file, use glb 2.0
1478+
pFormatId = "glb2";
1479+
}
1480+
1481+
// flip UVs when exporting (issue with UV origin for gltf2)
14501482
// https://github.com/around-media/ue4-custom-prompto/commit/044dbad90fc2172f4c5a8b67c779b80ceace5e1e
1451-
pPreprocessing |= aiPostProcessSteps::aiProcess_FlipUVs | aiProcess_GenNormals;
1483+
// pPreprocessing |= aiProcess_FlipUVs;
1484+
1485+
// gen normals in order to have correct shading in Qt 3D Scene
1486+
// but cause problems with assimp importer
1487+
pPreprocessing |= aiProcess_GenNormals;
14521488
}
14531489

1490+
// export mesh
14541491
Assimp::Exporter exporter;
1455-
exporter.Export(&scene, formatId, filepath, pPreprocessing);
1492+
const aiReturn ret = exporter.Export(&scene, pFormatId, filepath, pPreprocessing);
1493+
1494+
// check for errors
1495+
if (ret != AI_SUCCESS)
1496+
{
1497+
if (ret == AI_OUTOFMEMORY)
1498+
{
1499+
ALICEVISION_LOG_ERROR("Assimp exporter ran out of memory while exporting mesh to " << filepath);
1500+
}
1501+
1502+
ALICEVISION_THROW_ERROR("Assimp exporter failed to export mesh to " << filepath << ", error: " << exporter.GetErrorString());
1503+
return;
1504+
}
14561505

1457-
ALICEVISION_LOG_INFO("Save mesh to " << meshFileTypeStr << " done.");
1506+
ALICEVISION_LOG_INFO("Mesh saved.");
14581507
}
14591508

14601509
void Texturing::_generateNormalAndHeightMaps(const mvsUtils::MultiViewParams& mp,

0 commit comments

Comments
 (0)