void copy_face_attributes(Mesh::Ptr mesh, std::unique_ptr<draco::Mesh>& draco_mesh) { const auto num_faces = mesh->get_num_faces(); const auto& attribute_names = mesh->get_attribute_names(); for (const auto& name : attribute_names) { const auto& values = mesh->get_attribute(name); if (values.size() % num_faces != 0) continue; const auto num_rows = num_faces; const auto num_cols = values.size() / num_faces; draco::GeometryAttribute attr; if (name == "face_normal") { attr.Init(draco::GeometryAttribute::NORMAL, nullptr, num_cols, draco::DT_FLOAT64, false, sizeof(Float) * num_cols, 0); } else if (name.substr(0, 4) == "face"){ attr.Init(draco::GeometryAttribute::GENERIC, nullptr, num_cols, draco::DT_FLOAT64, false, sizeof(Float) * num_cols, 0); } else { // Not a face attribute. continue; } const auto id = draco_mesh->AddAttribute(attr, true, num_rows); draco_mesh->SetAttributeElementType(id, draco::MESH_FACE_ATTRIBUTE); for (size_t i=0; i<num_rows; i++) { draco_mesh->attribute(id)->SetAttributeValue( draco::AttributeValueIndex(i), values.data() + i*num_cols); } std::unique_ptr<draco::AttributeMetadata> metadata = std::make_unique<draco::AttributeMetadata>(); metadata->AddEntryString("name", name); draco_mesh->AddAttributeMetadata(id, std::move(metadata)); } }
GeoMeshPtr GeogramMeshUtils::mesh_to_geomesh(const Mesh::Ptr mesh) { const size_t dim = mesh->get_dim(); const size_t vertex_per_face = mesh->get_vertex_per_face(); const size_t num_vertices = mesh->get_num_vertices(); const size_t num_faces = mesh->get_num_faces(); const auto& vertices = mesh->get_vertices(); const auto& faces = mesh->get_faces(); if (vertex_per_face != 3) { throw NotImplementedError("Converting non-triangle mesh to " "Geogram mesh is not yet implemented"); } auto geo_mesh = std::make_shared<GeoMesh>(dim, false); geo_mesh->vertices.clear(); geo_mesh->vertices.create_vertices(num_vertices); geo_mesh->facets.clear(); geo_mesh->facets.create_triangles(num_faces); for (size_t i=0; i<num_vertices; i++) { auto& p = geo_mesh->vertices.point(i); for (size_t j=0; j<dim; j++) { p[j] = vertices[i*dim+j]; } } for (size_t i=0; i<num_faces; i++) { geo_mesh->facets.set_vertex(i, 0, faces[i*3]); geo_mesh->facets.set_vertex(i, 1, faces[i*3+1]); geo_mesh->facets.set_vertex(i, 2, faces[i*3+2]); } return geo_mesh; }
CellPartition::Ptr CellPartition::create(const Mesh::Ptr& mesh) { const MatrixFr vertices = MatrixUtils::reshape<MatrixFr>( mesh->get_vertices(), mesh->get_num_vertices(), mesh->get_dim()); const MatrixIr faces = MatrixUtils::reshape<MatrixIr>( mesh->get_faces(), mesh->get_num_faces(), mesh->get_vertex_per_face()); return CellPartition::Ptr(new CellPartition(vertices, faces)); }
void copy_faces(Mesh::Ptr mesh, std::unique_ptr<DracoMesh>& draco_mesh) { const auto num_faces = mesh->get_num_faces(); const auto& faces = mesh->get_faces(); for (int i = 0; i < num_faces; ++i) { draco_mesh->AddFace({{ draco::PointIndex(faces[i*3]), draco::PointIndex(faces[i*3+1]), draco::PointIndex(faces[i*3+2]) }}); } }
std::unique_ptr<draco::PointCloud> to_draco_point_cloud(Mesh::Ptr mesh, bool with_attributes=true) { std::unique_ptr<draco::PointCloud> draco_mesh(new draco::PointCloud()); assert(mesh->get_num_faces() == 0); copy_vertices(mesh, draco_mesh); if (with_attributes) { copy_vertex_attributes(mesh, draco_mesh); } return draco_mesh; }
std::string DracoCompressionEngine::compress(Mesh::Ptr mesh) const { const size_t num_faces = mesh->get_num_faces(); draco::EncoderBuffer buffer; draco::Encoder encoder; if (num_faces > 0) { auto draco_mesh = DracoCompressionEngineHelper::to_draco_mesh(mesh); const auto status = encoder.EncodeMeshToBuffer(*draco_mesh, &buffer); if (!status.ok()) { throw RuntimeError("Draco encoding error!"); } return std::string(buffer.data(), buffer.size()); } else { auto draco_mesh = DracoCompressionEngineHelper::to_draco_point_cloud(mesh); const auto status = encoder.EncodePointCloudToBuffer(*draco_mesh, &buffer); if (!status.ok()) { throw RuntimeError("Draco encoding error!"); } return std::string(buffer.data(), buffer.size()); } }