谷歌 draco學習 二 壓縮點信息

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章