谷歌 draco學習 一 壓縮格網信息

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章