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());
      }
    }
  }
}

需要注意的就是兩點:

  1. 傳入draco::Decoder進行解壓縮的需要二進制流,這個在從文件讀取時一定要注意,很容易讀成了文本流導致不能正常解壓縮。
  2. 對draco::Mesh的解析。draco::Mesh的頂點屬性中的buffer並不是頂點索引中存儲的數據。這個時壓縮算法決定的,解析Mesh時一定要按照實例中解析。直接解析頂點屬性中的buffer會得不到正確的頂點順序。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章