Draco使用笔记(1)——图形解压缩
目录
1. 概述
Draco是Google开发的图形压缩库,用于压缩和解压缩3D几何网格(geometric mesh)和点云(point cloud)。Draco还可以直接对obj或者ply格式的三维数据进行压缩和解压缩,甚至编译成wasm在浏览器端对glTF压缩和解压缩。
2. 详论
2.1. 工具
Draco编译完成后直接提供了压缩和解压缩的工具draco_decoder.exe和draco_encoder.exe。通过命令行,我们对某个已经压缩好的文件进行解压缩:
draco_decoder -i "D:/1.bin" -o "D:/1.ply"
2.2. 代码
如果需要用代码的方式实现,可以参考draco_decoder.exe中的源码,具体实现如下:
#include <core/decoder_buffer.h> #include <io/mesh_io.h> #include <fstream> #include <iostream> using namespace draco; using namespace std; int main() { string filePath = "D:/1.bin"; ifstream infile(filePath, ios::binary); infile.seekg(0, std::ios::end); size_t data_size = infile.tellg(); infile.seekg(0, std::ios::beg); vector<char> data(data_size, 0); infile.read(data.data(), data_size); DecoderBuffer buffer; buffer.Init(data.data(), data_size); //解压缩 std::unique_ptr<draco::PointCloud> pc; auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer); if (!type_statusor.ok()) { return 1; } //解析数据 const draco::EncodedGeometryType geom_type = type_statusor.value(); if (geom_type == draco::TRIANGULAR_MESH) { draco::Decoder decoder; auto statusor = decoder.DecodeMeshFromBuffer(&buffer); if (!statusor.ok()) { return 1; } std::unique_ptr<draco::Mesh> mesh = std::move(statusor).value(); if (mesh) { const int pos_att_id = mesh->GetNamedAttributeId(GeometryAttribute::POSITION); //解析顶点属性 for (PointIndex v(0); v < mesh->num_points(); ++v) { const auto *const pos_att = mesh->attribute(pos_att_id); const uint8_t *pos = pos_att->GetAddress(pos_att->mapped_index(v)); int64_t length = pos_att->byte_stride(); float temp[3]; memcpy(temp, pos, length); printf("%f,%f,%f\t", temp[0], temp[1], temp[2]); } //解析顶点索引 for (FaceIndex f(0); f < mesh->num_faces(); ++f) { printf("%d,%d,%d\t", mesh->face(f)[0].value(), mesh->face(f)[1].value(), mesh->face(f)[2].value()); } } } }
需要注意的就是两点:
- 传入draco::Decoder进行解压缩的需要二进制流,这个在从文件读取时一定要注意,很容易读成了文本流导致不能正常解压缩。
- 对draco::Mesh的解析。draco::Mesh的顶点属性中的buffer并不是顶点索引中存储的数据。这个时压缩算法决定的,解析Mesh时一定要按照实例中解析。直接解析顶点属性中的buffer会得不到正确的顶点顺序。
分类: 基础组件