From cbd4b24bf5930641e05c15bb36cf953848ad15ca Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Sun, 28 Feb 2021 22:16:47 +0100 Subject: [PATCH] support point clouds --- CMakeLists.txt | 1 + include/c_api.h | 60 ++++++++++++++--------- src/c_api_test.cc | 16 +++---- src/decoder.cc | 19 ++++++-- src/mesh.cc | 108 ----------------------------------------- src/point_cloud.cc | 117 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 143 deletions(-) create mode 100644 src/point_cloud.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 67088d7..1a4ca39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ endif() list(APPEND draco_c_sources "${CMAKE_CURRENT_SOURCE_DIR}/src/decoder.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/mesh.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/src/point_cloud.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/point_attribute.cc" ) diff --git a/include/c_api.h b/include/c_api.h index ba58ca2..67b9778 100644 --- a/include/c_api.h +++ b/include/c_api.h @@ -101,9 +101,33 @@ EXPORT_API int64_t dracoPointAttrByteOffset(const draco_point_attr* pa); EXPORT_API uint32_t dracoPointAttrUniqueId(const draco_point_attr* pa); +// draco::PointCloud + +typedef struct draco_point_cloud draco_point_cloud; + +EXPORT_API draco_point_cloud* dracoNewPointCloud(); + +EXPORT_API void dracoPointCloudRelease(draco_point_cloud *pc); + +EXPORT_API uint32_t dracoPointCloudNumPoints(const draco_point_cloud *pc); + +EXPORT_API int32_t dracoPointCloudNumAttrs(const draco_point_cloud *pc); + +EXPORT_API const draco_point_attr* dracoPointCloudGetAttribute(const draco_point_cloud *pc, int32_t att_id); + +EXPORT_API int32_t dracoPointCloudGetNamedAttributeId(const draco_point_cloud *pc, draco_geometry_type geo_type); + +EXPORT_API const draco_point_attr* dracoPointCloudGetAttributeByUniqueId(const draco_point_cloud *pc, uint32_t unique_id); + +EXPORT_API bool dracoPointCloudGetAttributeData(const draco_point_cloud *pc, + const draco_point_attr *pa, + draco_data_type data_type, + const size_t out_size, + void *out_values); + // draco::Mesh -typedef struct draco_mesh draco_mesh; +typedef struct draco_point_cloud draco_mesh; EXPORT_API draco_mesh* dracoNewMesh(); @@ -111,14 +135,10 @@ EXPORT_API void dracoMeshRelease(draco_mesh *mesh); EXPORT_API uint32_t dracoMeshNumFaces(const draco_mesh *mesh); -EXPORT_API uint32_t dracoMeshNumPoints(const draco_mesh *mesh); - -EXPORT_API int32_t dracoMeshNumAttrs(const draco_mesh *mesh); - // Queries an array of 3*face_count elements containing the triangle indices. // out_values must be allocated to contain at least 3*face_count uint16_t elements. // out_size must be exactly 3*face_count*sizeof(uint16_t), else out_values -// won´t be filled and returns false. +// won't be filled and returns false. EXPORT_API bool dracoMeshGetTrianglesUint16(const draco_mesh *mesh, const size_t out_size, uint16_t *out_values); @@ -126,23 +146,11 @@ EXPORT_API bool dracoMeshGetTrianglesUint16(const draco_mesh *mesh, // Queries an array of 3*face_count elements containing the triangle indices. // out_values must be allocated to contain at least 3*face_count uint32_t elements. // out_size must be exactly 3*face_count*sizeof(uint32_t), else out_values -// won´t be filled and returns false. +// won't be filled and returns false. EXPORT_API bool dracoMeshGetTrianglesUint32(const draco_mesh *mesh, const size_t out_size, uint32_t *out_values); -EXPORT_API const draco_point_attr* dracoMeshGetAttribute(const draco_mesh *mesh, int32_t att_id); - -EXPORT_API int32_t dracoMeshGetNamedAttributeId(const draco_mesh *mesh, draco_geometry_type geo_type); - -EXPORT_API const draco_point_attr* dracoMeshGetAttributeByUniqueId(const draco_mesh *mesh, uint32_t unique_id); - -EXPORT_API bool dracoMeshGetAttributeData(const draco_mesh *mesh, - const draco_point_attr *pa, - draco_data_type data_type, - const size_t out_size, - void *out_values); - // draco::Decoder typedef struct draco_decoder draco_decoder; @@ -151,10 +159,16 @@ EXPORT_API draco_decoder* dracoNewDecoder(); EXPORT_API void dracoDecoderRelease(draco_decoder *decoder); -EXPORT_API draco_status* dracoDecoderArrayToMesh(draco_decoder *decoder, - const char *data, - size_t data_size, - draco_mesh *out_mesh); +EXPORT_API draco_status* dracoDecoderDecodeMesh(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_mesh *out_mesh); + + +EXPORT_API draco_status* dracoDecoderDecodePointCloud(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_point_cloud *out_pc); #ifdef __cplusplus } diff --git a/src/c_api_test.cc b/src/c_api_test.cc index 0ca9cbb..1173ff5 100644 --- a/src/c_api_test.cc +++ b/src/c_api_test.cc @@ -35,7 +35,7 @@ draco_mesh *DecodeToDracoMesh(const std::string &file_name) { auto mesh = dracoNewMesh(); auto decoder = dracoNewDecoder(); - dracoDecoderArrayToMesh(decoder, data.data(), data.size(), mesh); + dracoDecoderDecodeMesh(decoder, data.data(), data.size(), mesh); dracoDecoderRelease(decoder); return mesh; } @@ -45,8 +45,8 @@ TEST(DracoCAPITest, TestDecode) { ASSERT_NE(mesh, nullptr); auto num_faces = dracoMeshNumFaces(mesh); ASSERT_EQ(num_faces, 170); - ASSERT_EQ(dracoMeshNumPoints(mesh), 99); - auto num_attrs = dracoMeshNumAttrs(mesh); + ASSERT_EQ(dracoPointCloudNumPoints(mesh), 99); + auto num_attrs = dracoPointCloudNumAttrs(mesh); ASSERT_EQ(num_attrs, 2); auto indices_size = 3 * num_faces * sizeof(uint32_t); @@ -54,7 +54,7 @@ TEST(DracoCAPITest, TestDecode) { ASSERT_TRUE(dracoMeshGetTrianglesUint32(mesh, indices_size, indices)); free(indices); - auto pa1 = dracoMeshGetAttribute(mesh, 0); + auto pa1 = dracoPointCloudGetAttribute(mesh, 0); ASSERT_EQ(dracoPointAttrType(pa1), GT_POSITION); ASSERT_EQ(dracoPointAttrDataType(pa1), DT_FLOAT32); ASSERT_EQ(dracoPointAttrNumComponents(pa1), 3); @@ -62,7 +62,7 @@ TEST(DracoCAPITest, TestDecode) { ASSERT_EQ(dracoPointAttrByteStride(pa1), 12); ASSERT_EQ(dracoPointAttrUniqueId(pa1), 0); - auto pa2 = dracoMeshGetAttribute(mesh, 1); + auto pa2 = dracoPointCloudGetAttribute(mesh, 1); ASSERT_EQ(dracoPointAttrType(pa2), GT_NORMAL); ASSERT_EQ(dracoPointAttrDataType(pa2), DT_FLOAT32); ASSERT_EQ(dracoPointAttrNumComponents(pa2), 3); @@ -72,9 +72,9 @@ TEST(DracoCAPITest, TestDecode) { auto arr_size = 3*99*sizeof(float); auto arr = (float *)malloc(arr_size); - ASSERT_TRUE(dracoMeshGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size, arr)); - ASSERT_FALSE(dracoMeshGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size+1, arr)); - ASSERT_FALSE(dracoMeshGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size-1, arr)); + ASSERT_TRUE(dracoPointCloudGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size, arr)); + ASSERT_FALSE(dracoPointCloudGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size+1, arr)); + ASSERT_FALSE(dracoPointCloudGetAttributeData(mesh, pa2, DT_FLOAT32, arr_size-1, arr)); dracoMeshRelease(mesh); } diff --git a/src/decoder.cc b/src/decoder.cc index 5cad755..364ab93 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -40,13 +40,24 @@ void dracoDecoderRelease(draco_decoder *decoder) { free(decoder); } -draco_status* dracoDecoderArrayToMesh(draco_decoder *decoder, - const char *data, - size_t data_size, - draco_mesh *out_mesh) { +draco_status* dracoDecoderDecodeMesh(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_mesh *out_mesh) { draco::DecoderBuffer buffer; buffer.Init(data, data_size); auto m = reinterpret_cast(out_mesh); const auto &last_status_ = reinterpret_cast(decoder)->DecodeBufferToGeometry(&buffer, m); return reinterpret_cast(new draco::Status(last_status_)); } + +draco_status* dracoDecoderDecodePointCloud(draco_decoder *decoder, + const char *data, + size_t data_size, + draco_point_cloud *out_pc) { + draco::DecoderBuffer buffer; + buffer.Init(data, data_size); + auto m = reinterpret_cast(out_pc); + const auto &last_status_ = reinterpret_cast(decoder)->DecodeBufferToGeometry(&buffer, m); + return reinterpret_cast(new draco::Status(last_status_)); +} diff --git a/src/mesh.cc b/src/mesh.cc index 4517a34..3215106 100644 --- a/src/mesh.cc +++ b/src/mesh.cc @@ -13,15 +13,6 @@ uint32_t dracoMeshNumFaces(const draco_mesh *mesh) { return reinterpret_cast(mesh)->num_faces(); } - -uint32_t dracoMeshNumPoints(const draco_mesh *mesh) { - return reinterpret_cast(mesh)->num_points(); -} - -int32_t dracoMeshNumAttrs(const draco_mesh *mesh) { - return reinterpret_cast(mesh)->num_attributes(); -} - template bool GetTrianglesArray(const draco::Mesh *m, const size_t out_size, T *out_values) { @@ -58,102 +49,3 @@ bool dracoMeshGetTrianglesUint32(const draco_mesh *mesh, const size_t out_size, return GetTrianglesArray(m, out_size, out_values); } - -const draco_point_attr* dracoMeshGetAttribute(const draco_mesh *mesh, int32_t att_id) { - auto m = reinterpret_cast(mesh); - if (att_id < 0 || att_id > m->num_attributes()) { - return nullptr; - } - auto attr = m->attribute(att_id); - return reinterpret_cast(attr); -} - -const draco_point_attr* dracoMeshGetAttributeByUniqueId(const draco_mesh *mesh, uint32_t unique_id) { - auto m = reinterpret_cast(mesh); - auto attr = m->GetAttributeByUniqueId(unique_id); - return reinterpret_cast(attr); -} - - -int32_t dracoMeshGetNamedAttributeId(const draco_mesh *mesh, draco_geometry_type geo_type) { - auto type = static_cast(geo_type); - return reinterpret_cast(mesh)->GetNamedAttributeId(type); -} - -template -static bool GetAttributeDataArrayForAllPoints(const draco::PointCloud *pc, - const draco::PointAttribute *pa, - draco::DataType type, - size_t out_size, - void *out_values) { - const int components = pa->num_components(); - const int num_points = pc->num_points(); - const int data_size = num_points * components * sizeof(T); - if (data_size != out_size) { - return false; - } - const bool requested_type_matches = pa->data_type() == type; - if (requested_type_matches && pa->is_mapping_identity()) { - // Copy values directly to the output vector. - const auto ptr = pa->GetAddress(draco::AttributeValueIndex(0)); - ::memcpy(out_values, ptr, data_size); - return true; - } - - // Copy values one by one. - std::vector values(components); - int entry_id = 0; - - T *const typed_output = reinterpret_cast(out_values); - for (draco::PointIndex i(0); i < num_points; ++i) { - const draco::AttributeValueIndex val_index = pa->mapped_index(i); - if (requested_type_matches) { - pa->GetValue(val_index, values.data()); - } else { - if (!pa->ConvertValue(val_index, values.data())) { - return false; - } - } - for (int j = 0; j < components; ++j) { - typed_output[entry_id++] = values[j]; - } - } - return true; -} - -bool dracoMeshGetAttributeData(const draco_mesh *pc, - const draco_point_attr *pa, - draco_data_type data_type, - const size_t out_size, - void *out_values) { - auto pcc = reinterpret_cast(pc); - auto pac = reinterpret_cast(pa); - switch (data_type) { - case DT_INT8: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT8, - out_size, out_values); - case DT_INT16: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT16, - out_size, out_values); - case DT_INT32: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT32, - out_size, out_values); - case DT_UINT8: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT8, - out_size, out_values); - case DT_UINT16: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT16, - out_size, out_values); - case DT_UINT32: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT32, - out_size, out_values); - case DT_FLOAT32: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_FLOAT32, - out_size, out_values); - case DT_FLOAT64: - return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_FLOAT64, - out_size, out_values); - default: - return false; - } -} diff --git a/src/point_cloud.cc b/src/point_cloud.cc new file mode 100644 index 0000000..eb88077 --- /dev/null +++ b/src/point_cloud.cc @@ -0,0 +1,117 @@ +#include "c_api.h" +#include "draco/point_cloud/point_cloud.h" + +draco_point_cloud* dracoNewPointCloud() { + return reinterpret_cast(new draco::PointCloud()); +} + +void dracoPointCloudRelease(draco_point_cloud *pc) { + free(pc); +} + +uint32_t dracoPointCloudNumPoints(const draco_point_cloud *pc) { + return reinterpret_cast(pc)->num_points(); +} + +int32_t dracoPointCloudNumAttrs(const draco_point_cloud *pc) { + return reinterpret_cast(pc)->num_attributes(); +} + +const draco_point_attr* dracoPointCloudGetAttribute(const draco_point_cloud *pc, int32_t att_id) { + auto m = reinterpret_cast(pc); + if (att_id < 0 || att_id > m->num_attributes()) { + return nullptr; + } + auto attr = m->attribute(att_id); + return reinterpret_cast(attr); +} + +int32_t dracoPointCloudGetNamedAttributeId(const draco_point_cloud *pc, draco_geometry_type geo_type) { + auto type = static_cast(geo_type); + return reinterpret_cast(pc)->GetNamedAttributeId(type); +} + +const draco_point_attr* dracoPointCloudGetAttributeByUniqueId(const draco_point_cloud *pc, uint32_t unique_id) { + auto m = reinterpret_cast(pc); + auto attr = m->GetAttributeByUniqueId(unique_id); + return reinterpret_cast(attr); +} + + +template +static bool GetAttributeDataArrayForAllPoints(const draco::PointCloud *pc, + const draco::PointAttribute *pa, + draco::DataType type, + size_t out_size, + void *out_values) { + const int components = pa->num_components(); + const int num_points = pc->num_points(); + const int data_size = num_points * components * sizeof(T); + if (data_size != out_size) { + return false; + } + const bool requested_type_matches = pa->data_type() == type; + if (requested_type_matches && pa->is_mapping_identity()) { + // Copy values directly to the output vector. + const auto ptr = pa->GetAddress(draco::AttributeValueIndex(0)); + ::memcpy(out_values, ptr, data_size); + return true; + } + + // Copy values one by one. + std::vector values(components); + int entry_id = 0; + + T *const typed_output = reinterpret_cast(out_values); + for (draco::PointIndex i(0); i < num_points; ++i) { + const draco::AttributeValueIndex val_index = pa->mapped_index(i); + if (requested_type_matches) { + pa->GetValue(val_index, values.data()); + } else { + if (!pa->ConvertValue(val_index, values.data())) { + return false; + } + } + for (int j = 0; j < components; ++j) { + typed_output[entry_id++] = values[j]; + } + } + return true; +} + +bool dracoPointCloudGetAttributeData(const draco_point_cloud *pc, + const draco_point_attr *pa, + draco_data_type data_type, + const size_t out_size, + void *out_values) { + auto pcc = reinterpret_cast(pc); + auto pac = reinterpret_cast(pa); + switch (data_type) { + case DT_INT8: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT8, + out_size, out_values); + case DT_INT16: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT16, + out_size, out_values); + case DT_INT32: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_INT32, + out_size, out_values); + case DT_UINT8: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT8, + out_size, out_values); + case DT_UINT16: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT16, + out_size, out_values); + case DT_UINT32: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_UINT32, + out_size, out_values); + case DT_FLOAT32: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_FLOAT32, + out_size, out_values); + case DT_FLOAT64: + return GetAttributeDataArrayForAllPoints(pcc, pac, draco::DT_FLOAT64, + out_size, out_values); + default: + return false; + } +} \ No newline at end of file