Welcome to mirror list, hosted at ThFree Co, Russian Federation.

point_attribute.h « attributes « draco « src « draco « draco « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ee36620313e3f07edccbb84cab693110e088d01c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2016 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_
#define DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_

#include <memory>

#include "draco/attributes/attribute_transform_data.h"
#include "draco/attributes/geometry_attribute.h"
#include "draco/core/draco_index_type_vector.h"
#include "draco/core/hash_utils.h"
#include "draco/core/macros.h"
#include "draco/draco_features.h"

namespace draco {

// Class for storing point specific data about each attribute. In general,
// multiple points stored in a point cloud can share the same attribute value
// and this class provides the necessary mapping between point ids and attribute
// value ids.
class PointAttribute : public GeometryAttribute {
 public:
  PointAttribute();
  explicit PointAttribute(const GeometryAttribute &att);

  // Make sure the move constructor is defined (needed for better performance
  // when new attributes are added to PointCloud).
  PointAttribute(PointAttribute &&attribute) = default;
  PointAttribute &operator=(PointAttribute &&attribute) = default;

  // Initializes a point attribute. By default the attribute will be set to
  // identity mapping between point indices and attribute values. To set custom
  // mapping use SetExplicitMapping() function.
  void Init(Type attribute_type, int8_t num_components, DataType data_type,
            bool normalized, size_t num_attribute_values);

  // Copies attribute data from the provided |src_att| attribute.
  void CopyFrom(const PointAttribute &src_att);

  // Prepares the attribute storage for the specified number of entries.
  bool Reset(size_t num_attribute_values);

  size_t size() const { return num_unique_entries_; }
  AttributeValueIndex mapped_index(PointIndex point_index) const {
    if (identity_mapping_) {
      return AttributeValueIndex(point_index.value());
    }
    return indices_map_[point_index];
  }
  DataBuffer *buffer() const { return attribute_buffer_.get(); }
  bool is_mapping_identity() const { return identity_mapping_; }
  size_t indices_map_size() const {
    if (is_mapping_identity()) {
      return 0;
    }
    return indices_map_.size();
  }

  const uint8_t *GetAddressOfMappedIndex(PointIndex point_index) const {
    return GetAddress(mapped_index(point_index));
  }

  // Sets the new number of unique attribute entries for the attribute. The
  // function resizes the attribute storage to hold |num_attribute_values|
  // entries.
  // All previous entries with AttributeValueIndex < |num_attribute_values|
  // are preserved. Caller needs to ensure that the PointAttribute is still
  // valid after the resizing operation (that is, each point is mapped to a
  // valid attribute value).
  void Resize(size_t new_num_unique_entries);

  // Functions for setting the type of mapping between point indices and
  // attribute entry ids.
  // This function sets the mapping to implicit, where point indices are equal
  // to attribute entry indices.
  void SetIdentityMapping() {
    identity_mapping_ = true;
    indices_map_.clear();
  }
  // This function sets the mapping to be explicitly using the indices_map_
  // array that needs to be initialized by the caller.
  void SetExplicitMapping(size_t num_points) {
    identity_mapping_ = false;
    indices_map_.resize(num_points, kInvalidAttributeValueIndex);
  }

  // Set an explicit map entry for a specific point index.
  void SetPointMapEntry(PointIndex point_index,
                        AttributeValueIndex entry_index) {
    DRACO_DCHECK(!identity_mapping_);
    indices_map_[point_index] = entry_index;
  }

  // Same as GeometryAttribute::GetValue(), but using point id as the input.
  // Mapping to attribute value index is performed automatically.
  void GetMappedValue(PointIndex point_index, void *out_data) const {
    return GetValue(mapped_index(point_index), out_data);
  }

#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
  // Deduplicate |in_att| values into |this| attribute. |in_att| can be equal
  // to |this|.
  // Returns -1 if the deduplication failed.
  AttributeValueIndex::ValueType DeduplicateValues(
      const GeometryAttribute &in_att);

  // Same as above but the values read from |in_att| are sampled with the
  // provided offset |in_att_offset|.
  AttributeValueIndex::ValueType DeduplicateValues(
      const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
#endif

  // Set attribute transform data for the attribute. The data is used to store
  // the type and parameters of the transform that is applied on the attribute
  // data (optional).
  void SetAttributeTransformData(
      std::unique_ptr<AttributeTransformData> transform_data) {
    attribute_transform_data_ = std::move(transform_data);
  }
  const AttributeTransformData *GetAttributeTransformData() const {
    return attribute_transform_data_.get();
  }

 private:
#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
  template <typename T>
  AttributeValueIndex::ValueType DeduplicateTypedValues(
      const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
  template <typename T, int COMPONENTS_COUNT>
  AttributeValueIndex::ValueType DeduplicateFormattedValues(
      const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
#endif

  // Data storage for attribute values. GeometryAttribute itself doesn't own its
  // buffer so we need to allocate it here.
  std::unique_ptr<DataBuffer> attribute_buffer_;

  // Mapping between point ids and attribute value ids.
  IndexTypeVector<PointIndex, AttributeValueIndex> indices_map_;
  AttributeValueIndex::ValueType num_unique_entries_;
  // Flag when the mapping between point ids and attribute values is identity.
  bool identity_mapping_;

  // If an attribute contains transformed data (e.g. quantized), we can specify
  // the attribute transform here and use it to transform the attribute back to
  // its original format.
  std::unique_ptr<AttributeTransformData> attribute_transform_data_;

  friend struct PointAttributeHasher;
};

// Hash functor for the PointAttribute class.
struct PointAttributeHasher {
  size_t operator()(const PointAttribute &attribute) const {
    GeometryAttributeHasher base_hasher;
    size_t hash = base_hasher(attribute);
    hash = HashCombine(attribute.identity_mapping_, hash);
    hash = HashCombine(attribute.num_unique_entries_, hash);
    hash = HashCombine(attribute.indices_map_.size(), hash);
    if (!attribute.indices_map_.empty()) {
      const uint64_t indices_hash = FingerprintString(
          reinterpret_cast<const char *>(attribute.indices_map_.data()),
          attribute.indices_map_.size());
      hash = HashCombine(indices_hash, hash);
    }
    if (attribute.attribute_buffer_ != nullptr) {
      const uint64_t buffer_hash = FingerprintString(
          reinterpret_cast<const char *>(attribute.attribute_buffer_->data()),
          attribute.attribute_buffer_->data_size());
      hash = HashCombine(buffer_hash, hash);
    }
    return hash;
  }
};

}  // namespace draco

#endif  // DRACO_ATTRIBUTES_POINT_ATTRIBUTE_H_