谷歌 draco学习 二 压缩点信息

  • Post author:
  • Post category:其他


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



版权声明:本文为u014572215原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。