1 // Copyright 2017 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
16 #include "draco/attributes/attribute_octahedron_transform.h"
17
18 #include "draco/attributes/attribute_transform_type.h"
19 #include "draco/compression/attributes/normal_compression_utils.h"
20
21 namespace draco {
22
InitFromAttribute(const PointAttribute & attribute)23 bool AttributeOctahedronTransform::InitFromAttribute(
24 const PointAttribute &attribute) {
25 const AttributeTransformData *const transform_data =
26 attribute.GetAttributeTransformData();
27 if (!transform_data ||
28 transform_data->transform_type() != ATTRIBUTE_OCTAHEDRON_TRANSFORM) {
29 return false; // Wrong transform type.
30 }
31 quantization_bits_ = transform_data->GetParameterValue<int32_t>(0);
32 return true;
33 }
34
CopyToAttributeTransformData(AttributeTransformData * out_data) const35 void AttributeOctahedronTransform::CopyToAttributeTransformData(
36 AttributeTransformData *out_data) const {
37 out_data->set_transform_type(ATTRIBUTE_OCTAHEDRON_TRANSFORM);
38 out_data->AppendParameterValue(quantization_bits_);
39 }
40
TransformAttribute(const PointAttribute & attribute,const std::vector<PointIndex> & point_ids,PointAttribute * target_attribute)41 bool AttributeOctahedronTransform::TransformAttribute(
42 const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
43 PointAttribute *target_attribute) {
44 return GeneratePortableAttribute(attribute, point_ids,
45 target_attribute->size(), target_attribute);
46 }
47
InverseTransformAttribute(const PointAttribute & attribute,PointAttribute * target_attribute)48 bool AttributeOctahedronTransform::InverseTransformAttribute(
49 const PointAttribute &attribute, PointAttribute *target_attribute) {
50 if (target_attribute->data_type() != DT_FLOAT32) {
51 return false;
52 }
53
54 const int num_points = target_attribute->size();
55 const int num_components = target_attribute->num_components();
56 if (num_components != 3) {
57 return false;
58 }
59 constexpr int kEntrySize = sizeof(float) * 3;
60 float att_val[3];
61 const int32_t *source_attribute_data = reinterpret_cast<const int32_t *>(
62 attribute.GetAddress(AttributeValueIndex(0)));
63 uint8_t *target_address =
64 target_attribute->GetAddress(AttributeValueIndex(0));
65 OctahedronToolBox octahedron_tool_box;
66 if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) {
67 return false;
68 }
69 for (uint32_t i = 0; i < num_points; ++i) {
70 const int32_t s = *source_attribute_data++;
71 const int32_t t = *source_attribute_data++;
72 octahedron_tool_box.QuantizedOctahedralCoordsToUnitVector(s, t, att_val);
73
74 // Store the decoded floating point values into the attribute buffer.
75 std::memcpy(target_address, att_val, kEntrySize);
76 target_address += kEntrySize;
77 }
78 return true;
79 }
80
SetParameters(int quantization_bits)81 void AttributeOctahedronTransform::SetParameters(int quantization_bits) {
82 quantization_bits_ = quantization_bits;
83 }
84
EncodeParameters(EncoderBuffer * encoder_buffer) const85 bool AttributeOctahedronTransform::EncodeParameters(
86 EncoderBuffer *encoder_buffer) const {
87 if (is_initialized()) {
88 encoder_buffer->Encode(static_cast<uint8_t>(quantization_bits_));
89 return true;
90 }
91 return false;
92 }
93
DecodeParameters(const PointAttribute & attribute,DecoderBuffer * decoder_buffer)94 bool AttributeOctahedronTransform::DecodeParameters(
95 const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
96 uint8_t quantization_bits;
97 if (!decoder_buffer->Decode(&quantization_bits)) {
98 return false;
99 }
100 quantization_bits_ = quantization_bits;
101 return true;
102 }
103
GeneratePortableAttribute(const PointAttribute & attribute,const std::vector<PointIndex> & point_ids,int num_points,PointAttribute * target_attribute) const104 bool AttributeOctahedronTransform::GeneratePortableAttribute(
105 const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
106 int num_points, PointAttribute *target_attribute) const {
107 DRACO_DCHECK(is_initialized());
108
109 // Quantize all values in the order given by point_ids into portable
110 // attribute.
111 int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
112 target_attribute->GetAddress(AttributeValueIndex(0)));
113 float att_val[3];
114 int32_t dst_index = 0;
115 OctahedronToolBox converter;
116 if (!converter.SetQuantizationBits(quantization_bits_)) {
117 return false;
118 }
119 if (!point_ids.empty()) {
120 for (uint32_t i = 0; i < point_ids.size(); ++i) {
121 const AttributeValueIndex att_val_id =
122 attribute.mapped_index(point_ids[i]);
123 attribute.GetValue(att_val_id, att_val);
124 // Encode the vector into a s and t octahedral coordinates.
125 int32_t s, t;
126 converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
127 portable_attribute_data[dst_index++] = s;
128 portable_attribute_data[dst_index++] = t;
129 }
130 } else {
131 for (PointIndex i(0); i < num_points; ++i) {
132 const AttributeValueIndex att_val_id = attribute.mapped_index(i);
133 attribute.GetValue(att_val_id, att_val);
134 // Encode the vector into a s and t octahedral coordinates.
135 int32_t s, t;
136 converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
137 portable_attribute_data[dst_index++] = s;
138 portable_attribute_data[dst_index++] = t;
139 }
140 }
141
142 return true;
143 }
144
145 } // namespace draco
146