draco版本是Version 1.3.6
地址:https://github.com/google/draco
壓縮點信息,包括點的位置position、法線normal、顏色color和點雲中的一個噪聲noise
示例使用c++完成。
具體步驟
1、初始化變量和數據。
聲明位置position、法線normal、顏色color和點雲中的噪聲noise的變量
std::vector<std::array<float, 3>> normals;//頂點
std::vector<std::array<float, 3>> positions;//法線
std::vector<std::array<unsigned char, 3>> colors;//顏色
std::vector<int> noises;//噪聲
初始化數據,循環生成位置position、法線normal、顏色color和噪聲noise
float x;
x = 0;
// create 30 points and normals
for (int i = 0; i < 30; i++) {
x = x + 0.01 * i;
x = x + 0.01 * i;
x = x + 0.01 * i;
positions.push_back({x, x, x});
normals.push_back({0, 1, 0});
colors.push_back({220, 132, 220});
noises.push_back(i);//噪聲
}
2、將數據初始化到draco中
創建draco對象
std::unique_ptr<draco::PointCloud> dracoPointCloud(new draco::PointCloud());
dracoPointCloud->set_num_points(30);//設置要壓縮的點個數
壓縮頂點
int j;
int vertexCount = 30; // num
int componentCount = 3;
int byte_stride = sizeof(float) * componentCount;
draco::GeometryAttribute::Type att_type = draco::GeometryAttribute::POSITION;//設置壓縮類型
draco::PointAttribute att;//創建壓縮屬性
att.Init(att_type, componentCount, draco::DT_FLOAT32, false, byte_stride);//初始化對象
int att_id = dracoPointCloud->AddAttribute(att, true, vertexCount);//添加到dracoPointCloud中
draco::PointAttribute *att_ptr = dracoPointCloud->attribute(att_id);//獲取添加的對象
draco::PointIndex pointIndex(0);//一個計數
//將頂點數據添加到壓縮屬性att中
for (j = 0; j < 30; j++) {
std::array<float, 3> vIndex = positions[j];//頂點
std::vector<float> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(float) * componentCount);//將頂點xyz保存到vertex_data中
att_ptr->SetAttributeValue(att_ptr->mapped_index(pointIndex), &vertex_data[0]);//頂點數據添加到壓縮屬性att中
pointIndex++;
}
添加法線數據
// NORMAL
vertexCount = 30; // num
componentCount = 3;
byte_stride = sizeof(float) * componentCount;
draco::GeometryAttribute::Type att_normal_type =
draco::GeometryAttribute::NORMAL;
draco::PointAttribute attNormal;
attNormal.Init(att_normal_type, componentCount, draco::DT_FLOAT32, false, byte_stride);
int att_normal_id =
dracoPointCloud->AddAttribute(attNormal, true, vertexCount);
draco::PointAttribute *att_normal_ptr =
dracoPointCloud->attribute(att_normal_id);
draco::PointIndex pointNormal(0);
for (j = 0; j < 30; j++) {
std::array<float, 3> vIndex = normals[j];
std::vector<float> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(float) * componentCount);
att_normal_ptr->SetAttributeValue(att_normal_ptr->mapped_index(pointNormal),
&vertex_data[0]);
pointNormal++;
}
添加顏色數據
// color
vertexCount = 30; // num
componentCount = 3;
byte_stride = sizeof(unsigned char) * componentCount;
draco::GeometryAttribute::Type att_color_type =
draco::GeometryAttribute::COLOR;
draco::PointAttribute attColor;
attColor.Init(att_color_type, componentCount, draco::DT_INT8, false, byte_stride);
int att_color_id = dracoPointCloud->AddAttribute(attColor, true, vertexCount);
draco::PointAttribute *att_color_ptr = dracoPointCloud->attribute(att_color_id);
draco::PointIndex pointColor(0);
for (j = 0; j < 30; j++) {
std::array<unsigned char, 3> vIndex = colors[j];
std::vector<unsigned char> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(unsigned char) * componentCount);
att_color_ptr->SetAttributeValue(att_color_ptr->mapped_index(pointColor),
&vertex_data[0]);
pointColor++;
}
添加噪聲
// noises
vertexCount = 30; // num
componentCount = 1;
byte_stride = sizeof(int) * componentCount;
draco::GeometryAttribute::Type att_noise_type =
draco::GeometryAttribute::GENERIC;
draco::PointAttribute attNoise;
attNoise.Init(att_noise_type, componentCount, draco::DT_INT32, false, byte_stride);
int att_noise_id = dracoPointCloud->AddAttribute(attNoise, true, vertexCount);
draco::PointAttribute *att_noise_ptr = dracoPointCloud->attribute(att_noise_id);
draco::PointIndex noiseColor(0);
for (j = 0; j < 30; j++) {
int vIndex = noises[j];
std::vector<int> vertex_data;
vertex_data.push_back(vIndex);
att_noise_ptr->SetAttributeValue(att_noise_ptr->mapped_index(noiseColor),
&vertex_data[0]);
noiseColor++;
}
3、創建draco壓縮對象
//設置壓縮參數
const int dracoCompressionSpeed = 7;
const int dracoPositionBits = 14;
const int dracoNormalBits = 8;
const int dracoColorBits = 8;
const int dracoGenericBits = 12;
draco::EncoderBuffer dracoBuffer;//壓縮後的數據存儲到draco的緩衝區中
draco::Encoder encoder;//壓縮對象
//設置壓縮參數
encoder.SetSpeedOptions(dracoCompressionSpeed, dracoCompressionSpeed);
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION,
dracoPositionBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL,
dracoNormalBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR,
dracoColorBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC,
dracoGenericBits);
//設置壓縮方法
encoder.SetEncodingMethod(draco::PointCloudEncodingMethod::POINT_CLOUD_KD_TREE_ENCODING);
// draco::EncoderBuffer dracoBuffer1;
//壓縮點、法線、顏色、噪聲
const draco::Status status = encoder.EncodePointCloudToBuffer(*dracoPointCloud, &dracoBuffer);
4、獲取壓縮的數據
// dracoBuffer
if (!status.ok()) {
std::cout << "Error: Encode mesh.\n";
}
std::cout << "success\n";
std::cout << dracoBuffer.size() << std::endl;//壓縮後的數據大小
std::cout << dracoBuffer.data() << std::endl;//壓縮後的數據
//輸出到文件中
if (!draco::WriteBufferToFile(dracoBuffer.data(), dracoBuffer.size(), "1.drc")) {
printf("Failed to write the output file.\n");
system("pause");
return -1;
}
運行結果如圖
完整的代碼:
//
// Created by asus on 2020/4/28.
//
#include <iostream>
#include <draco/core/status.h>
#include <draco/unity/draco_unity_plugin.h>
#include <draco/compression/encode.h>
#include <draco/io/file_utils.h>
#include <vector>
int main(int argc, char **argv) {
std::cout << "Hello, World!" << std::endl;
std::vector<std::array<float, 3>> normals;//頂點
std::vector<std::array<float, 3>> positions;//法線
std::vector<std::array<unsigned char, 3>> colors;//顏色
std::vector<int> noises;//噪聲
float x;
x = 0;
// create 30 points and normals
for (int i = 0; i < 30; i++) {
x = x + 0.01 * i;
x = x + 0.01 * i;
x = x + 0.01 * i;
positions.push_back({x, x, x});
normals.push_back({0, 1, 0});
colors.push_back({220, 132, 220});
noises.push_back(i);//噪聲
}
std::unique_ptr<draco::PointCloud> dracoPointCloud(new draco::PointCloud());
dracoPointCloud->set_num_points(30);//設置要壓縮的點個數
// POSITION
int j;
int vertexCount = 30; // num
int componentCount = 3;
int byte_stride = sizeof(float) * componentCount;//每個頂點的步長,xyz座標和數據大小,3*4 xyz是3每個是浮點型
draco::GeometryAttribute::Type att_type = draco::GeometryAttribute::POSITION;//設置壓縮類型
draco::PointAttribute att;//創建壓縮屬性
att.Init(att_type, componentCount, draco::DT_FLOAT32, false, byte_stride);//初始化對象
int att_id = dracoPointCloud->AddAttribute(att, true, vertexCount);//添加到dracoPointCloud中
draco::PointAttribute *att_ptr = dracoPointCloud->attribute(att_id);//獲取添加的對象
draco::PointIndex pointIndex(0);//一個計數
//將頂點數據添加到壓縮屬性att中
for (j = 0; j < 30; j++) {
std::array<float, 3> vIndex = positions[j];//頂點
std::vector<float> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(float) * componentCount);//將頂點xyz保存到vertex_data中
att_ptr->SetAttributeValue(att_ptr->mapped_index(pointIndex), &vertex_data[0]);//頂點數據添加到壓縮屬性att中
pointIndex++;
}
// NORMAL
vertexCount = 30; // num
componentCount = 3;
byte_stride = sizeof(float) * componentCount;
draco::GeometryAttribute::Type att_normal_type =
draco::GeometryAttribute::NORMAL;
draco::PointAttribute attNormal;
attNormal.Init(att_normal_type, componentCount, draco::DT_FLOAT32, false, byte_stride);
int att_normal_id =
dracoPointCloud->AddAttribute(attNormal, true, vertexCount);
draco::PointAttribute *att_normal_ptr =
dracoPointCloud->attribute(att_normal_id);
draco::PointIndex pointNormal(0);
for (j = 0; j < 30; j++) {
std::array<float, 3> vIndex = normals[j];
std::vector<float> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(float) * componentCount);
att_normal_ptr->SetAttributeValue(att_normal_ptr->mapped_index(pointNormal),
&vertex_data[0]);
pointNormal++;
}
// color
vertexCount = 30; // num
componentCount = 3;
byte_stride = sizeof(unsigned char) * componentCount;
draco::GeometryAttribute::Type att_color_type =
draco::GeometryAttribute::COLOR;
draco::PointAttribute attColor;
attColor.Init(att_color_type, componentCount, draco::DT_INT8, false, byte_stride);
int att_color_id = dracoPointCloud->AddAttribute(attColor, true, vertexCount);
draco::PointAttribute *att_color_ptr = dracoPointCloud->attribute(att_color_id);
draco::PointIndex pointColor(0);
for (j = 0; j < 30; j++) {
std::array<unsigned char, 3> vIndex = colors[j];
std::vector<unsigned char> vertex_data(componentCount);
memcpy(&vertex_data[0], &(vIndex[0]), sizeof(unsigned char) * componentCount);
att_color_ptr->SetAttributeValue(att_color_ptr->mapped_index(pointColor),
&vertex_data[0]);
pointColor++;
}
// noises
vertexCount = 30; // num
componentCount = 1;
byte_stride = sizeof(int) * componentCount;
draco::GeometryAttribute::Type att_noise_type =
draco::GeometryAttribute::GENERIC;
draco::PointAttribute attNoise;
attNoise.Init(att_noise_type, componentCount, draco::DT_INT32, false, byte_stride);
int att_noise_id = dracoPointCloud->AddAttribute(attNoise, true, vertexCount);
draco::PointAttribute *att_noise_ptr = dracoPointCloud->attribute(att_noise_id);
draco::PointIndex noiseColor(0);
for (j = 0; j < 30; j++) {
int vIndex = noises[j];
std::vector<int> vertex_data;
vertex_data.push_back(vIndex);
att_noise_ptr->SetAttributeValue(att_noise_ptr->mapped_index(noiseColor),
&vertex_data[0]);
noiseColor++;
}
//設置壓縮參數
const int dracoCompressionSpeed = 7;
const int dracoPositionBits = 14;
const int dracoNormalBits = 8;
const int dracoColorBits = 8;
const int dracoGenericBits = 12;
draco::EncoderBuffer dracoBuffer;//壓縮後的數據存儲到draco的緩存區中
draco::Encoder encoder;//壓縮對象
//設置壓縮參數
encoder.SetSpeedOptions(dracoCompressionSpeed, dracoCompressionSpeed);
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION,
dracoPositionBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL,
dracoNormalBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR,
dracoColorBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC,
dracoGenericBits);
//設置壓縮方法
encoder.SetEncodingMethod(draco::PointCloudEncodingMethod::POINT_CLOUD_KD_TREE_ENCODING);
// draco::EncoderBuffer dracoBuffer1;
//壓縮點法線顏色噪聲
const draco::Status status = encoder.EncodePointCloudToBuffer(*dracoPointCloud, &dracoBuffer);
// dracoBuffer
if (!status.ok()) {
std::cout << "Error: Encode mesh.\n";
}
std::cout << "success\n";
std::cout << dracoBuffer.size() << std::endl;//壓縮後的數據大小
std::cout << dracoBuffer.data() << std::endl;//壓縮後的數據
//輸出到文件中
if (!draco::WriteBufferToFile(dracoBuffer.data(), dracoBuffer.size(), "1.drc")) {
printf("Failed to write the output file.\n");
system("pause");
return -1;
}
system("pause");
return 0;
}