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