Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write directly to GLB from TGeometries #6404

Merged
merged 23 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion 3rdparty/assimp/assimp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ ExternalProject_Add(
-DCMAKE_CXX_FLAGS:STRING=${assimp_cmake_cxx_flags}
-DBUILD_SHARED_LIBS=OFF
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DASSIMP_NO_EXPORT=ON
-DASSIMP_BUILD_ASSIMP_TOOLS=OFF
-DASSIMP_BUILD_TESTS=OFF
-DASSIMP_INSTALL_PDB=OFF
Expand Down
1 change: 1 addition & 0 deletions cpp/open3d/t/io/TriangleMeshIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ static const std::unordered_map<
const bool)>>
file_extension_to_trianglemesh_write_function{
{"npz", WriteTriangleMeshToNPZ},
{"glb", WriteTriangleMeshUsingASSIMP},
};

std::shared_ptr<geometry::TriangleMesh> CreateMeshFromFile(
Expand Down
9 changes: 9 additions & 0 deletions cpp/open3d/t/io/TriangleMeshIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ bool ReadTriangleMeshFromNPZ(const std::string &filename,
geometry::TriangleMesh &mesh,
const open3d::io::ReadTriangleMeshOptions &params);

bool WriteTriangleMeshUsingASSIMP(const std::string &filename,
const geometry::TriangleMesh &mesh,
const bool write_ascii,
const bool compressed,
const bool write_vertex_normals,
const bool write_vertex_colors,
const bool write_triangle_uvs,
const bool print_progress);

bool WriteTriangleMeshToNPZ(const std::string &filename,
const geometry::TriangleMesh &mesh,
const bool write_ascii,
Expand Down
126 changes: 126 additions & 0 deletions cpp/open3d/t/io/file_format/FileASSIMP.cpp
errissa marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <assimp/postprocess.h>
#include <assimp/scene.h>

#include <assimp/Exporter.hpp>
#include <assimp/Importer.hpp>
#include <assimp/ProgressHandler.hpp>
#include <fstream>
Expand Down Expand Up @@ -174,6 +175,131 @@ bool ReadTriangleMeshUsingASSIMP(
return true;
}

bool WriteTriangleMeshUsingASSIMP(const std::string& filename,
const geometry::TriangleMesh& mesh,
const bool write_ascii,
const bool compressed,
const bool write_vertex_normals,
const bool write_vertex_colors,
const bool write_triangle_uvs,
const bool print_progress) {
errissa marked this conversation as resolved.
Show resolved Hide resolved
// Sanity checks...
if (write_ascii) {
utility::LogWarning(
"TriangleMesh can't be saved in ASCII fromat as .glb");
return false;
}
if (compressed) {
utility::LogWarning(
"TriangleMesh can't be saved in compressed format as .glb");
return false;
errissa marked this conversation as resolved.
Show resolved Hide resolved
}
if (!mesh.HasVertexPositions()) {
utility::LogWarning(
"TriangleMesh has no vertex positions and can't be saved as "
".glb");
return false;
}

Assimp::Exporter exporter;
auto ai_scene = new aiScene;
errissa marked this conversation as resolved.
Show resolved Hide resolved

// Fill mesh data...
ai_scene->mNumMeshes = 1;
ai_scene->mMeshes = new aiMesh*[1];
auto ai_mesh = new aiMesh;
ai_mesh->mName.Set("Object1");
ai_mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// Guaranteed to have both vertex positions and triangle indices
auto vertices = mesh.GetVertexPositions();
auto indices = mesh.GetTriangleIndices().To(core::Dtype::UInt32);
ai_mesh->mNumVertices = vertices.GetShape(0);
ai_mesh->mVertices = new aiVector3D[ai_mesh->mNumVertices];
memcpy(&ai_mesh->mVertices->x, vertices.GetDataPtr(),
sizeof(float) * ai_mesh->mNumVertices * 3);
ai_mesh->mNumFaces = indices.GetShape(0);
ai_mesh->mFaces = new aiFace[ai_mesh->mNumFaces];
for (unsigned int i = 0; i < ai_mesh->mNumFaces; ++i) {
ai_mesh->mFaces[i].mNumIndices = 3;
ai_mesh->mFaces[i].mIndices = new unsigned int[3]; // triangles
errissa marked this conversation as resolved.
Show resolved Hide resolved
ai_mesh->mFaces[i].mIndices[0] = indices[i][0].Item<unsigned int>();
ai_mesh->mFaces[i].mIndices[1] = indices[i][1].Item<unsigned int>();
ai_mesh->mFaces[i].mIndices[2] = indices[i][2].Item<unsigned int>();
}

// Add normals if present...
if (mesh.HasVertexNormals()) {
auto normals = mesh.GetVertexNormals();
auto m_normals = normals.GetShape(0);
ai_mesh->mNormals = new aiVector3D[m_normals];
memcpy(&ai_mesh->mNormals->x, normals.GetDataPtr(),
sizeof(float) * m_normals * 3);
}

// Add colors if present...
if (mesh.HasVertexColors()) {
auto colors = mesh.GetVertexColors();
auto m_colors = colors.GetShape(0);
ai_mesh->mColors[0] = new aiColor4D[m_colors];
if (colors.GetShape(1) == 4) {
memcpy(&ai_mesh->mColors[0][0].r, colors.GetDataPtr(),
sizeof(float) * m_colors * 4);
} else { // must be 3 components
auto color_ptr = reinterpret_cast<float*>(colors.GetDataPtr());
for (unsigned int i = 0; i < m_colors; ++i) {
ai_mesh->mColors[0][i].r = *color_ptr++;
ai_mesh->mColors[0][i].g = *color_ptr++;
ai_mesh->mColors[0][i].b = *color_ptr++;
ai_mesh->mColors[0][i].a = 1.0f;
ssheorey marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

// Add UVs if present...
if (mesh.HasTriangleAttr("texture_uvs")) {
auto triangle_uvs = mesh.GetTriangleAttr("texture_uvs");
auto vertex_uvs = core::Tensor::Empty({ai_mesh->mNumVertices, 2},
core::Dtype::Float32);
auto n_uvs = ai_mesh->mNumVertices;
for (int64_t i = 0; i < indices.GetShape(0); i++) {
vertex_uvs[indices[i][0].Item<uint32_t>()] = triangle_uvs[i][0];
vertex_uvs[indices[i][1].Item<uint32_t>()] = triangle_uvs[i][1];
vertex_uvs[indices[i][2].Item<uint32_t>()] = triangle_uvs[i][2];
}
ai_mesh->mTextureCoords[0] = new aiVector3D[n_uvs];
auto uv_ptr = reinterpret_cast<float*>(vertex_uvs.GetDataPtr());
for (unsigned int i = 0; i < n_uvs; ++i) {
ai_mesh->mTextureCoords[0][i].x = *uv_ptr++;
ai_mesh->mTextureCoords[0][i].y = *uv_ptr++;
}
ai_mesh->mNumUVComponents[0] = 2;
}
ai_scene->mMeshes[0] = ai_mesh;

// Fill material data...
ai_scene->mNumMaterials = 1;
ai_scene->mMaterials = new aiMaterial*[ai_scene->mNumMaterials];
auto ai_mat = new aiMaterial;
if (mesh.HasMaterial()) {
}
ai_scene->mMaterials[0] = ai_mat;

auto root_node = new aiNode;
root_node->mName.Set("root");
root_node->mNumMeshes = 1;
root_node->mMeshes = new unsigned int[root_node->mNumMeshes];
root_node->mMeshes[0] = 0;
ai_scene->mRootNode = root_node;

// Export
if (exporter.Export(ai_scene, "glb2", filename.c_str()) == AI_FAILURE) {
utility::LogWarning("Got error: {}", exporter.GetErrorString());
return false;
}

return true;
}

} // namespace io
} // namespace t
} // namespace open3d
Loading