55#include < cmath>
66#include < vector>
77#include < cstddef>
8+ #include < sstream>
89#include " draco/compression/decode.h"
910#include " draco/compression/encode.h"
1011#include " draco/compression/config/compression_shared.h"
@@ -291,6 +292,17 @@ namespace DracoFunctions {
291292 // manually.
292293 draco::Mesh mesh; // Initialize a draco mesh
293294
295+ // Ensure unique ids for native attributes don't conflict with generic attributes
296+ uint32_t next_unique_id = 0 ;
297+ auto min_unique_id = std::min_element (unique_ids.begin (), unique_ids.end ());
298+ if (min_unique_id != unique_ids.end () && *min_unique_id < -1 ) {
299+ throw std::invalid_argument (" Should never be reached; all unique_ids should be >= -1." );
300+ }
301+ auto max_unique_id = std::max_element (unique_ids.begin (), unique_ids.end ());
302+ if (max_unique_id != unique_ids.end ()) {
303+ next_unique_id = *max_unique_id + 1 ;
304+ }
305+
294306 // Process vertices
295307 const size_t num_pts = points.size () / 3 ;
296308 mesh.set_num_points (num_pts);
@@ -331,6 +343,8 @@ namespace DracoFunctions {
331343 sizeof (uint8_t ) * colors_channel, // byte stride
332344 0 ); // byte offset
333345 color_att_id = mesh.AddAttribute (colors_attr, true , num_pts);
346+ mesh.attribute (color_att_id)->set_unique_id (next_unique_id);
347+ next_unique_id++;
334348 }
335349 int tex_coord_att_id = -1 ;
336350 if (tex_coord_channel) {
@@ -343,6 +357,8 @@ namespace DracoFunctions {
343357 sizeof (float ) * tex_coord_channel, // byte stride
344358 0 ); // byte offset
345359 tex_coord_att_id = mesh.AddAttribute (tex_coord_attr, true , num_pts);
360+ mesh.attribute (tex_coord_att_id)->set_unique_id (next_unique_id);
361+ next_unique_id++;
346362 }
347363
348364 int normal_att_id = -1 ;
@@ -356,6 +372,8 @@ namespace DracoFunctions {
356372 sizeof (float ) * 3 , // byte stride
357373 0 ); // byte offset
358374 normal_att_id = mesh.AddAttribute (normal_attr, true , num_pts);
375+ mesh.attribute (normal_att_id)->set_unique_id (next_unique_id);
376+ next_unique_id++;
359377 }
360378
361379
@@ -369,21 +387,22 @@ namespace DracoFunctions {
369387 draco::DataType dtype = static_cast <draco::DataType>(attr_data_types[i]);
370388 int num_components = attr_num_components[i];
371389 if (dtype != draco::DT_FLOAT32 && dtype != draco::DT_UINT8 && dtype != draco::DT_UINT16 && dtype != draco::DT_UINT32) {
372- // Unsupported data type, skip
373- // std::cout << "DEBUG: Unsupported attribute data type for " << unique_ids[i] << std::endl;
374- generic_attr_ids.push_back (-1 );
375- continue ;
390+ std::ostringstream oss;
391+ oss << " Unsupported attribute data type for attribute with unique id " << int (unique_ids[i]);
392+ throw std::invalid_argument (oss.str ());
376393 }
377394 generic_attr.Init (draco::GeometryAttribute::GENERIC, nullptr , num_components, dtype, false , 0 , 0 );
378395 int att_id = mesh.AddAttribute (generic_attr, true , num_pts);
379396 if (att_id == -1 ) {
380- // Failed to add attribute, skip
381- // std::cout << "DEBUG: Failed to add attribute " << unique_ids[i] << std::endl;
382- generic_attr_ids.push_back (-1 );
383- continue ;
397+ std::ostringstream oss;
398+ oss << " Failed to add attribute with unique id " << int (unique_ids[i]);
399+ throw std::runtime_error (oss.str ());
384400 }
385401 if (unique_ids[i] >= 0 ) {
386402 mesh.attribute (att_id)->set_unique_id (unique_ids[i]);
403+ } else {
404+ mesh.attribute (att_id)->set_unique_id (next_unique_id);
405+ next_unique_id++;
387406 }
388407 if (!attr_names[i].empty ()) {
389408 auto attribute_metadata = std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata ());
@@ -396,6 +415,8 @@ namespace DracoFunctions {
396415
397416
398417 const int pos_att_id = mesh.AddAttribute (positions_attr, true , num_pts);
418+ mesh.attribute (pos_att_id)->set_unique_id (next_unique_id);
419+ next_unique_id++;
399420 std::vector<int32_t > pts_int32;
400421 std::vector<uint32_t > pts_uint32;
401422 if (integer_mark == 1 ) {
@@ -439,8 +460,7 @@ namespace DracoFunctions {
439460 const auto &uint32_data = attr_uint32_data[j];
440461
441462 if (generic_attr_ids[j] == -1 ) {
442- // Skip if attribute was not added
443- continue ;
463+ throw std::runtime_error (" Should never be reached; all successfully added attributes should have nonnegative att_id." );
444464 }
445465
446466 if (attr_data_types[j] == draco::DT_FLOAT32) {
@@ -500,12 +520,31 @@ namespace DracoFunctions {
500520 const float *quantization_origin, const bool preserve_order,
501521 const bool create_metadata, const int integer_mark,
502522 const std::vector<uint8_t > &colors,
503- const uint8_t colors_channel
523+ const uint8_t colors_channel,
524+ std::vector<int8_t >& unique_ids,
525+ std::vector<std::vector<float >>& attr_float_data,
526+ std::vector<std::vector<uint8_t >>& attr_uint8_data,
527+ std::vector<std::vector<uint16_t >>& attr_uint16_data,
528+ std::vector<std::vector<uint32_t >>& attr_uint32_data,
529+ std::vector<int >& attr_data_types,
530+ std::vector<int >& attr_num_components,
531+ std::vector<std::string>& attr_names
504532 ) {
505533 int num_points = points.size () / 3 ;
506534 draco::PointCloudBuilder pcb;
507535 pcb.Start (num_points);
508536
537+ // Ensure unique ids for native attributes don't conflict with generic attributes
538+ uint32_t next_unique_id = 0 ;
539+ auto min_unique_id = std::min_element (unique_ids.begin (), unique_ids.end ());
540+ if (min_unique_id != unique_ids.end () && *min_unique_id < -1 ) {
541+ throw std::invalid_argument (" Should never be reached; all unique_ids should be >= -1." );
542+ }
543+ auto max_unique_id = std::max_element (unique_ids.begin (), unique_ids.end ());
544+ if (max_unique_id != unique_ids.end ()) {
545+ next_unique_id = *max_unique_id + 1 ;
546+ }
547+
509548 auto dtype = (integer_mark == 1 )
510549 ? draco::DataType::DT_INT32
511550 : (
@@ -517,11 +556,15 @@ namespace DracoFunctions {
517556 const int pos_att_id = pcb.AddAttribute (
518557 draco::GeometryAttribute::POSITION, 3 , dtype
519558 );
559+ pcb.SetAttributeUniqueId (pos_att_id, next_unique_id);
560+ next_unique_id++;
520561
521562 if (colors_channel){
522563 const int color_att_id = pcb.AddAttribute (
523564 draco::GeometryAttribute::COLOR, colors_channel, draco::DataType::DT_UINT8
524565 );
566+ pcb.SetAttributeUniqueId (color_att_id, next_unique_id);
567+ next_unique_id++;
525568 for (draco::PointIndex i (0 ); i < num_points; i++) {
526569 pcb.SetAttributeValueForPoint (pos_att_id, i, points.data () + 3 * i.value ());
527570 pcb.SetAttributeValueForPoint (color_att_id, i, colors.data () + colors_channel * i.value ());
@@ -532,6 +575,44 @@ namespace DracoFunctions {
532575 }
533576 }
534577
578+ // GENERIC ATTRIBUTES
579+ for (size_t j = 0 ; j < unique_ids.size (); ++j) {
580+ draco::DataType dtype = static_cast <draco::DataType>(attr_data_types[j]);
581+ int num_components = attr_num_components[j];
582+ if (dtype != draco::DT_FLOAT32 && dtype != draco::DT_UINT8 && dtype != draco::DT_UINT16 && dtype != draco::DT_UINT32) {
583+ std::ostringstream oss;
584+ oss << " Unsupported attribute data type for attribute with unique id " << int (unique_ids[j]);
585+ throw std::invalid_argument (oss.str ());
586+ }
587+ int att_id = pcb.AddAttribute (draco::GeometryAttribute::GENERIC, num_components, dtype);
588+ if (att_id == -1 ) {
589+ std::ostringstream oss;
590+ oss << " Failed to add attribute with unique id " << int (unique_ids[j]);
591+ throw std::runtime_error (oss.str ());
592+ }
593+ if (unique_ids[j] >= 0 ) {
594+ pcb.SetAttributeUniqueId (att_id, unique_ids[j]);
595+ } else {
596+ pcb.SetAttributeUniqueId (att_id, next_unique_id);
597+ next_unique_id++;
598+ }
599+ if (!attr_names[j].empty ()) {
600+ auto attribute_metadata = std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata ());
601+ attribute_metadata->AddEntryString (" name" , attr_names[j]);
602+ pcb.AddAttributeMetadata (att_id, std::move (attribute_metadata));
603+ }
604+
605+ if (dtype == draco::DT_FLOAT32) {
606+ pcb.SetAttributeValuesForAllPoints (att_id, attr_float_data[j].data (), 0 );
607+ } else if (dtype == draco::DT_UINT8) {
608+ pcb.SetAttributeValuesForAllPoints (att_id, attr_uint8_data[j].data (), 0 );
609+ } else if (dtype == draco::DT_UINT16) {
610+ pcb.SetAttributeValuesForAllPoints (att_id, attr_uint16_data[j].data (), 0 );
611+ } else if (dtype == draco::DT_UINT32) {
612+ pcb.SetAttributeValuesForAllPoints (att_id, attr_uint32_data[j].data (), 0 );
613+ }
614+ }
615+
535616 std::unique_ptr<draco::PointCloud> ptr_point_cloud = pcb.Finalize (!preserve_order);
536617 draco::PointCloud *point_cloud = ptr_point_cloud.get ();
537618 draco::Encoder encoder;
0 commit comments