1 // Copyright 2016 The Draco Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 #ifndef DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_ 16 #define DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_ 17 18 #include <memory> 19 20 #include "draco/attributes/attribute_transform_data.h" 21 #include "draco/attributes/geometry_attribute.h" 22 #include "draco/core/draco_index_type_vector.h" 23 #include "draco/core/hash_utils.h" 24 #include "draco/core/macros.h" 25 #include "draco/draco_features.h" 26 27 namespace draco { 28 29 // Class for storing point specific data about each attribute. In general, 30 // multiple points stored in a point cloud can share the same attribute value 31 // and this class provides the necessary mapping between point ids and attribute 32 // value ids. 33 class PointAttribute : public GeometryAttribute { 34 public: 35 PointAttribute(); 36 explicit PointAttribute(const GeometryAttribute &att); 37 38 // Make sure the move constructor is defined (needed for better performance 39 // when new attributes are added to PointCloud). 40 PointAttribute(PointAttribute &&attribute) = default; 41 PointAttribute &operator=(PointAttribute &&attribute) = default; 42 43 // Initializes a point attribute. By default the attribute will be set to 44 // identity mapping between point indices and attribute values. To set custom 45 // mapping use SetExplicitMapping() function. 46 void Init(Type attribute_type, int8_t num_components, DataType data_type, 47 bool normalized, size_t num_attribute_values); 48 49 // Copies attribute data from the provided |src_att| attribute. 50 void CopyFrom(const PointAttribute &src_att); 51 52 // Prepares the attribute storage for the specified number of entries. 53 bool Reset(size_t num_attribute_values); 54 size()55 size_t size() const { return num_unique_entries_; } mapped_index(PointIndex point_index)56 AttributeValueIndex mapped_index(PointIndex point_index) const { 57 if (identity_mapping_) { 58 return AttributeValueIndex(point_index.value()); 59 } 60 return indices_map_[point_index]; 61 } buffer()62 DataBuffer *buffer() const { return attribute_buffer_.get(); } is_mapping_identity()63 bool is_mapping_identity() const { return identity_mapping_; } indices_map_size()64 size_t indices_map_size() const { 65 if (is_mapping_identity()) { 66 return 0; 67 } 68 return indices_map_.size(); 69 } 70 GetAddressOfMappedIndex(PointIndex point_index)71 const uint8_t *GetAddressOfMappedIndex(PointIndex point_index) const { 72 return GetAddress(mapped_index(point_index)); 73 } 74 75 // Sets the new number of unique attribute entries for the attribute. The 76 // function resizes the attribute storage to hold |num_attribute_values| 77 // entries. 78 // All previous entries with AttributeValueIndex < |num_attribute_values| 79 // are preserved. Caller needs to ensure that the PointAttribute is still 80 // valid after the resizing operation (that is, each point is mapped to a 81 // valid attribute value). 82 void Resize(size_t new_num_unique_entries); 83 84 // Functions for setting the type of mapping between point indices and 85 // attribute entry ids. 86 // This function sets the mapping to implicit, where point indices are equal 87 // to attribute entry indices. SetIdentityMapping()88 void SetIdentityMapping() { 89 identity_mapping_ = true; 90 indices_map_.clear(); 91 } 92 // This function sets the mapping to be explicitly using the indices_map_ 93 // array that needs to be initialized by the caller. SetExplicitMapping(size_t num_points)94 void SetExplicitMapping(size_t num_points) { 95 identity_mapping_ = false; 96 indices_map_.resize(num_points, kInvalidAttributeValueIndex); 97 } 98 99 // Set an explicit map entry for a specific point index. SetPointMapEntry(PointIndex point_index,AttributeValueIndex entry_index)100 void SetPointMapEntry(PointIndex point_index, 101 AttributeValueIndex entry_index) { 102 DRACO_DCHECK(!identity_mapping_); 103 indices_map_[point_index] = entry_index; 104 } 105 106 // Same as GeometryAttribute::GetValue(), but using point id as the input. 107 // Mapping to attribute value index is performed automatically. GetMappedValue(PointIndex point_index,void * out_data)108 void GetMappedValue(PointIndex point_index, void *out_data) const { 109 return GetValue(mapped_index(point_index), out_data); 110 } 111 112 #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED 113 // Deduplicate |in_att| values into |this| attribute. |in_att| can be equal 114 // to |this|. 115 // Returns -1 if the deduplication failed. 116 AttributeValueIndex::ValueType DeduplicateValues( 117 const GeometryAttribute &in_att); 118 119 // Same as above but the values read from |in_att| are sampled with the 120 // provided offset |in_att_offset|. 121 AttributeValueIndex::ValueType DeduplicateValues( 122 const GeometryAttribute &in_att, AttributeValueIndex in_att_offset); 123 #endif 124 125 // Set attribute transform data for the attribute. The data is used to store 126 // the type and parameters of the transform that is applied on the attribute 127 // data (optional). SetAttributeTransformData(std::unique_ptr<AttributeTransformData> transform_data)128 void SetAttributeTransformData( 129 std::unique_ptr<AttributeTransformData> transform_data) { 130 attribute_transform_data_ = std::move(transform_data); 131 } GetAttributeTransformData()132 const AttributeTransformData *GetAttributeTransformData() const { 133 return attribute_transform_data_.get(); 134 } 135 136 private: 137 #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED 138 template <typename T> 139 AttributeValueIndex::ValueType DeduplicateTypedValues( 140 const GeometryAttribute &in_att, AttributeValueIndex in_att_offset); 141 template <typename T, int COMPONENTS_COUNT> 142 AttributeValueIndex::ValueType DeduplicateFormattedValues( 143 const GeometryAttribute &in_att, AttributeValueIndex in_att_offset); 144 #endif 145 146 // Data storage for attribute values. GeometryAttribute itself doesn't own its 147 // buffer so we need to allocate it here. 148 std::unique_ptr<DataBuffer> attribute_buffer_; 149 150 // Mapping between point ids and attribute value ids. 151 IndexTypeVector<PointIndex, AttributeValueIndex> indices_map_; 152 AttributeValueIndex::ValueType num_unique_entries_; 153 // Flag when the mapping between point ids and attribute values is identity. 154 bool identity_mapping_; 155 156 // If an attribute contains transformed data (e.g. quantized), we can specify 157 // the attribute transform here and use it to transform the attribute back to 158 // its original format. 159 std::unique_ptr<AttributeTransformData> attribute_transform_data_; 160 161 friend struct PointAttributeHasher; 162 }; 163 164 // Hash functor for the PointAttribute class. 165 struct PointAttributeHasher { operatorPointAttributeHasher166 size_t operator()(const PointAttribute &attribute) const { 167 GeometryAttributeHasher base_hasher; 168 size_t hash = base_hasher(attribute); 169 hash = HashCombine(attribute.identity_mapping_, hash); 170 hash = HashCombine(attribute.num_unique_entries_, hash); 171 hash = HashCombine(attribute.indices_map_.size(), hash); 172 if (!attribute.indices_map_.empty()) { 173 const uint64_t indices_hash = FingerprintString( 174 reinterpret_cast<const char *>(attribute.indices_map_.data()), 175 attribute.indices_map_.size()); 176 hash = HashCombine(indices_hash, hash); 177 } 178 if (attribute.attribute_buffer_ != nullptr) { 179 const uint64_t buffer_hash = FingerprintString( 180 reinterpret_cast<const char *>(attribute.attribute_buffer_->data()), 181 attribute.attribute_buffer_->data_size()); 182 hash = HashCombine(buffer_hash, hash); 183 } 184 return hash; 185 } 186 }; 187 188 } // namespace draco 189 190 #endif // DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_ 191