当前位置: 首页 > 工具软件 > Draco > 使用案例 >

谷歌 draco学习 一 压缩格网信息

司徒嘉祥
2023-12-01

draco版本是Version 1.3.6

地址:https://github.com/google/draco

压缩三角网,包括点的位置meshPositions、法线meshnormals、纹理坐标meshUv

示例使用c++完成。

具体步骤

1、初始化变量和数据。

初始化一个四边形,两个三角网

//顶点信息
float meshPositions[12] = {0, 0, 0,
                           100, 0, 0,
                           100, 100, 0,
                           0, 100, 0};
//法线信息
float meshnormals[12] = {0, 1, 0,
                         0, 1, 0,
                         0, 1, 0,
                         0, 1, 0};
//纹理信息
float meshUv[8] = {0, 0,
                   0, 1,
                   1, 1,
                   1, 0};
//索引信息,两个三角形
unsigned short primitiveIndices[6] = {3, 1, 0,
                                      3, 2, 1};

2、将数据初始化到draco中

创建draco对象

// Add faces to Draco mesh.  向Draco网格添加面。
std::unique_ptr<draco::Mesh> dracoMesh(new draco::Mesh());
//写入面索引
const int numTriangles = sizeof(primitiveIndices) / sizeof(primitiveIndices[0]) / 3;//面个数
dracoMesh->SetNumFaces(numTriangles);//设置面个数
for (draco::FaceIndex i(0); i < numTriangles; ++i) {
    draco::Mesh::Face face;
    face[0] = primitiveIndices[i.value() * 3];
    face[1] = primitiveIndices[i.value() * 3 + 1];
    face[2] = primitiveIndices[i.value() * 3 + 2];
    dracoMesh->SetFace(i, face);
}

压缩顶点

//顶点位置
//为Draco网格创建属性。
draco::GeometryAttribute::Type att_type = draco::GeometryAttribute::POSITION;
const int componentCount = 3;//每个顶点有xyz三个值
//顶点
const int vertexCount = sizeof(meshPositions) / sizeof(meshPositions[0]) / componentCount;
draco::PointAttribute att;
int byte_stride = sizeof(float) * componentCount;//每个顶点的步长,xyz坐标和数据大小,3*4  xyz是3每个是浮点型
att.Init(att_type, componentCount, draco::DT_FLOAT32, false, byte_stride);
int att_id = dracoMesh->AddAttribute(att, /* identity_mapping */ true, vertexCount);
draco::PointAttribute *att_ptr = dracoMesh->attribute(att_id);
//要注意压缩网格后属性id不必与唯一ID相同,但unqiue id不会改变。添加顶点
for (draco::PointIndex i(0); i < vertexCount; i++) {
    std::vector<float> vertex_data(componentCount);
    memcpy(&vertex_data[0], &meshPositions[i.value() * componentCount], sizeof(float) * componentCount);
    att_ptr->SetAttributeValue(att_ptr->mapped_index(i), &vertex_data[0]);
}

法线

//法线
const int normalCount = sizeof(meshnormals) / sizeof(meshnormals[0]) / componentCount;
att_type = draco::GeometryAttribute::NORMAL;
draco::PointAttribute attnormal;
attnormal.Init(att_type, componentCount, draco::DT_FLOAT32, false, sizeof(float) * componentCount);
int normalatt_id = dracoMesh->AddAttribute(attnormal, /* identity_mapping */ true, normalCount);
draco::PointAttribute *normalatt_ptr = dracoMesh->attribute(normalatt_id);
//要注意压缩网格后属性id不必与唯一ID相同,但unqiue id不会改变。添加法线
for (draco::PointIndex i(0); i < normalCount; i++) {
    std::vector<float> vertex_data(componentCount);
    memcpy(&vertex_data[0], &meshnormals[i.value() * componentCount], sizeof(float) * componentCount);
    normalatt_ptr->SetAttributeValue(normalatt_ptr->mapped_index(i), &vertex_data[0]);
}

纹理

//纹理
int uvCounts=2;
const int uvCount = sizeof(meshUv) / sizeof(meshUv[0]) / uvCounts;
att_type = draco::GeometryAttribute::TEX_COORD;
draco::PointAttribute attUv;
attnormal.Init(att_type, 2, draco::DT_FLOAT32, false, sizeof(float) * uvCounts);
int uvatt_id = dracoMesh->AddAttribute(attnormal,  true, normalCount);
draco::PointAttribute *uvatt_ptr = dracoMesh->attribute(uvatt_id);
for (draco::PointIndex i(0); i < uvCount; i++) {
    std::vector<float> vertex_data(uvCounts);
    memcpy(&vertex_data[0], &meshUv[i.value() * uvCounts], sizeof(float) * uvCounts);
    uvatt_ptr->SetAttributeValue(uvatt_ptr->mapped_index(i), &vertex_data[0]);
}

3、创建draco压缩对象

//压缩draco
draco::Encoder encoder;
const int posQuantizationBits = 14;
const int texcoordsQuantizationBits = 10;
const int normalsQuantizationBits = 10;
const int colorQuantizationBits = 8;
const int genericQuantizationBits = 8;

//设置压缩参数
encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, posQuantizationBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, texcoordsQuantizationBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, normalsQuantizationBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, colorQuantizationBits);
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, genericQuantizationBits);
draco::EncoderBuffer dracoBuffer;//压缩后存储的对象
const draco::Status status = encoder.EncodeMeshToBuffer(*dracoMesh, &dracoBuffer);//压缩数据

4、获取压缩的数据

if (!status.ok()) {
    std::cerr << "Error: Encode mesh.\n";
} else {
    std::cout << "success" << std::endl;
    std::cout << dracoBuffer.size() << std::endl;//压缩后的数据大小
    std::cout << dracoBuffer.data() << std::endl;//压缩后的数据
}

完整代码如下

int main(int argc, char **argv) {
    std::cout << "Hello, World!" << std::endl;
    //顶点信息
    float meshPositions[12] = {0, 0, 0,
                               100, 0, 0,
                               100, 100, 0,
                               0, 100, 0};
    //法线信息
    float meshnormals[12] = {0, 1, 0,
                             0, 1, 0,
                             0, 1, 0,
                             0, 1, 0};
    //纹理信息
    float meshUv[8] = {0, 0,
                       0, 1,
                       1, 1,
                       1, 0};
    //索引信息,两个三角形
    unsigned short primitiveIndices[6] = {3, 1, 0,
                                          3, 2, 1};
    // Add faces to Draco mesh.  向Draco网格添加面。
    std::unique_ptr<draco::Mesh> dracoMesh(new draco::Mesh());
    //写入面索引
    const int numTriangles = sizeof(primitiveIndices) / sizeof(primitiveIndices[0]) / 3;//面个数
    dracoMesh->SetNumFaces(numTriangles);//设置面个数
    for (draco::FaceIndex i(0); i < numTriangles; ++i) {
        draco::Mesh::Face face;
        face[0] = primitiveIndices[i.value() * 3];
        face[1] = primitiveIndices[i.value() * 3 + 1];
        face[2] = primitiveIndices[i.value() * 3 + 2];
        dracoMesh->SetFace(i, face);
    }

    //顶点位置
    //为Draco网格创建属性。
    draco::GeometryAttribute::Type att_type = draco::GeometryAttribute::POSITION;
    const int componentCount = 3;//每个顶点有xyz三个值
    //顶点
    const int vertexCount = sizeof(meshPositions) / sizeof(meshPositions[0]) / componentCount;
    draco::PointAttribute att;
    int byte_stride = sizeof(float) * componentCount;//每个顶点的步长,xyz坐标和数据大小,3*4  xyz是3每个是浮点型
    att.Init(att_type, componentCount, draco::DT_FLOAT32, false, byte_stride);
    int att_id = dracoMesh->AddAttribute(att, /* identity_mapping */ true, vertexCount);
    draco::PointAttribute *att_ptr = dracoMesh->attribute(att_id);
    //要注意压缩网格后属性id不必与唯一ID相同,但unqiue id不会改变。添加顶点
    for (draco::PointIndex i(0); i < vertexCount; i++) {
        std::vector<float> vertex_data(componentCount);
        memcpy(&vertex_data[0], &meshPositions[i.value() * componentCount], sizeof(float) * componentCount);
        att_ptr->SetAttributeValue(att_ptr->mapped_index(i), &vertex_data[0]);
    }
    //法线
    const int normalCount = sizeof(meshnormals) / sizeof(meshnormals[0]) / componentCount;
    att_type = draco::GeometryAttribute::NORMAL;
    draco::PointAttribute attnormal;
    attnormal.Init(att_type, componentCount, draco::DT_FLOAT32, false, sizeof(float) * componentCount);
    int normalatt_id = dracoMesh->AddAttribute(attnormal, /* identity_mapping */ true, normalCount);
    draco::PointAttribute *normalatt_ptr = dracoMesh->attribute(normalatt_id);
    //要注意压缩网格后属性id不必与唯一ID相同,但unqiue id不会改变。添加法线
    for (draco::PointIndex i(0); i < normalCount; i++) {
        std::vector<float> vertex_data(componentCount);
        memcpy(&vertex_data[0], &meshnormals[i.value() * componentCount], sizeof(float) * componentCount);
        normalatt_ptr->SetAttributeValue(normalatt_ptr->mapped_index(i), &vertex_data[0]);
    }

    //纹理
    int uvCounts=2;
    const int uvCount = sizeof(meshUv) / sizeof(meshUv[0]) / uvCounts;
    att_type = draco::GeometryAttribute::TEX_COORD;
    draco::PointAttribute attUv;
    attnormal.Init(att_type, 2, draco::DT_FLOAT32, false, sizeof(float) * uvCounts);
    int uvatt_id = dracoMesh->AddAttribute(attnormal,  true, normalCount);
    draco::PointAttribute *uvatt_ptr = dracoMesh->attribute(uvatt_id);
    for (draco::PointIndex i(0); i < uvCount; i++) {
        std::vector<float> vertex_data(uvCounts);
        memcpy(&vertex_data[0], &meshUv[i.value() * uvCounts], sizeof(float) * uvCounts);
        uvatt_ptr->SetAttributeValue(uvatt_ptr->mapped_index(i), &vertex_data[0]);
    }


    //压缩draco
    draco::Encoder encoder;
    const int posQuantizationBits = 14;
    const int texcoordsQuantizationBits = 10;
    const int normalsQuantizationBits = 10;
    const int colorQuantizationBits = 8;
    const int genericQuantizationBits = 8;

    //设置压缩参数
    encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, posQuantizationBits);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, texcoordsQuantizationBits);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, normalsQuantizationBits);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, colorQuantizationBits);
    encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, genericQuantizationBits);
    draco::EncoderBuffer dracoBuffer;//压缩后存储的对象
    const draco::Status status = encoder.EncodeMeshToBuffer(*dracoMesh, &dracoBuffer);//压缩数据
    if (!status.ok()) {
        std::cerr << "Error: Encode mesh.\n";
    } else {
        std::cout << "success" << std::endl;
        std::cout << dracoBuffer.size() << std::endl;//压缩后的数据大小
        std::cout << dracoBuffer.data() << std::endl;//压缩后的数据
    }
    system("pause");
    return 0;
}

 

 类似资料: