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