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