Skip to content

Commit ff4ee78

Browse files
gregoire-dlcbentejac
authored andcommitted
[mesh] Mesh: Fix .gltf and add.glb mesh export
1 parent 48c8f8f commit ff4ee78

File tree

2 files changed

+81
-27
lines changed

2 files changed

+81
-27
lines changed

src/aliceVision/mesh/Mesh.cpp

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,14 @@ std::string EFileType_enumToString(const EFileType meshFileType)
4444
return "obj";
4545
case EFileType::FBX:
4646
return "fbx";
47-
case EFileType::STL:
48-
return "stl";
4947
case EFileType::GLTF:
5048
return "gltf";
49+
case EFileType::GLB:
50+
return "glb";
51+
case EFileType::STL:
52+
return "stl";
53+
case EFileType::PLY:
54+
return "ply";
5155
}
5256
throw std::out_of_range("Unrecognized EMeshFileType");
5357
}
@@ -61,10 +65,15 @@ EFileType EFileType_stringToEnum(const std::string& meshFileType)
6165
return EFileType::OBJ;
6266
if (m == "fbx")
6367
return EFileType::FBX;
64-
if (m == "stl")
65-
return EFileType::STL;
6668
if (m == "gltf")
6769
return EFileType::GLTF;
70+
if (m == "glb")
71+
return EFileType::GLB;
72+
if (m == "stl")
73+
return EFileType::STL;
74+
if (m == "ply")
75+
return EFileType::PLY;
76+
6877
throw std::out_of_range("Invalid mesh file type " + meshFileType);
6978
}
7079

@@ -81,26 +90,42 @@ void Mesh::save(const std::string& filepath)
8190
const std::string fileTypeStr = std::filesystem::path(filepath).extension().string().substr(1);
8291
const EFileType fileType = mesh::EFileType_stringToEnum(fileTypeStr);
8392

84-
ALICEVISION_LOG_INFO("Save " << fileTypeStr << " mesh file");
93+
ALICEVISION_LOG_INFO("Saving " << fileTypeStr << " mesh file using Assimp.");
8594

95+
// Assimp scene setup
96+
// create scene and root node
8697
aiScene scene;
98+
scene.mRootNode = new aiNode();
8799

88-
scene.mRootNode = new aiNode;
89-
100+
// create default material
101+
scene.mMaterials = new aiMaterial*[1];
102+
scene.mMaterials[0] = new aiMaterial();
103+
scene.mNumMaterials = 1;
104+
105+
// create mesh
90106
scene.mMeshes = new aiMesh*[1];
107+
scene.mMeshes[0] = new aiMesh();
91108
scene.mNumMeshes = 1;
109+
110+
// link mesh to root node
92111
scene.mRootNode->mMeshes = new unsigned int[1];
112+
scene.mRootNode->mMeshes[0] = 0;
93113
scene.mRootNode->mNumMeshes = 1;
114+
115+
// fill mesh data
116+
aiMesh* aimesh = scene.mMeshes[0];
94117

95-
scene.mMaterials = new aiMaterial*[1];
96-
scene.mNumMaterials = 1;
97-
scene.mMaterials[0] = new aiMaterial;
118+
// set default material index
119+
aimesh->mMaterialIndex = 0;
98120

99-
scene.mRootNode->mMeshes[0] = 0;
100-
scene.mMeshes[0] = new aiMesh;
101-
aiMesh* aimesh = scene.mMeshes[0];
102-
aimesh->mMaterialIndex = 0;
121+
if (fileType == EFileType::GLTF || fileType == EFileType::GLB)
122+
{
123+
// set primitive types to triangles, required for gltf and glb export
124+
// for other file types, primitive types is unspecified to avoid normal generation
125+
aimesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
126+
}
103127

128+
// fill mesh vertices
104129
aimesh->mNumVertices = pts.size();
105130
aimesh->mVertices = new aiVector3D[pts.size()];
106131

@@ -114,6 +139,7 @@ void Mesh::save(const std::string& filepath)
114139
++index;
115140
}
116141

142+
// fill mesh faces
117143
aimesh->mNumFaces = tris.size();
118144
aimesh->mFaces = new aiFace[tris.size()];
119145

@@ -128,31 +154,57 @@ void Mesh::save(const std::string& filepath)
128154
}
129155
}
130156

131-
std::string formatId = fileTypeStr;
157+
// exporter setup
158+
std::string pFormatId = fileTypeStr;
132159
unsigned int pPreprocessing = 0u;
133-
// If gltf, use gltf 2.0
134-
if (fileType == EFileType::GLTF)
160+
161+
if (fileType == EFileType::GLTF || fileType == EFileType::GLB)
135162
{
136-
formatId = "gltf2";
163+
if (fileType == EFileType::GLTF)
164+
{
165+
// gltf file, use gltf 2.0
166+
pFormatId = "gltf2";
167+
}
168+
else
169+
{
170+
// glb file, use glb 2.0
171+
pFormatId = "glb2";
172+
}
173+
137174
// gen normals in order to have correct shading in Qt 3D Scene
138175
// but cause problems with assimp importer
139176
pPreprocessing |= aiProcess_GenNormals;
140177
}
141-
// If obj, do not use material
142178
else if (fileType == EFileType::OBJ)
143179
{
144-
formatId = "objnomtl";
180+
// obj file, do not use material
181+
pFormatId = "objnomtl";
145182
}
146183

184+
// export mesh
147185
Assimp::Exporter exporter;
148-
exporter.Export(&scene, formatId, filepath, pPreprocessing);
186+
const aiReturn ret = exporter.Export(&scene, pFormatId, filepath, pPreprocessing);
149187

150-
ALICEVISION_LOG_INFO("Save mesh to " << fileTypeStr << " done.");
188+
// log mesh information
189+
ALICEVISION_LOG_DEBUG("Mesh information:" << std::endl
190+
<< "\t- # vertices: " << pts.size() << std::endl
191+
<< "\t- # triangles: " << tris.size() << std::endl
192+
<< "\t- # UVs: " << uvCoords.size() << std::endl
193+
<< "\t- # normals: " << normals.size());
151194

152-
ALICEVISION_LOG_DEBUG("Vertices: " << pts.size());
153-
ALICEVISION_LOG_DEBUG("Triangles: " << tris.size());
154-
ALICEVISION_LOG_DEBUG("UVs: " << uvCoords.size());
155-
ALICEVISION_LOG_DEBUG("Normals: " << normals.size());
195+
// check for errors
196+
if (ret != AI_SUCCESS)
197+
{
198+
if (ret == AI_OUTOFMEMORY)
199+
{
200+
ALICEVISION_LOG_ERROR("Assimp exporter ran out of memory while exporting mesh to " << filepath);
201+
}
202+
203+
ALICEVISION_THROW_ERROR("Assimp exporter failed to export mesh to " << filepath << ", error: " << exporter.GetErrorString());
204+
return;
205+
}
206+
207+
ALICEVISION_LOG_INFO("Mesh saved.");
156208
}
157209

158210
bool Mesh::loadFromBin(const std::string& binFilepath)

src/aliceVision/mesh/Mesh.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ enum class EFileType
5050
OBJ = 0,
5151
FBX,
5252
GLTF,
53-
STL
53+
GLB,
54+
STL,
55+
PLY
5456
};
5557

5658
EFileType EFileType_stringToEnum(const std::string& filetype);

0 commit comments

Comments
 (0)