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 #include "draco/compression/point_cloud/algorithms/float_points_tree_decoder.h"
16
17 #include <algorithm>
18
19 #include "draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h"
20 #include "draco/compression/point_cloud/algorithms/quantize_points_3.h"
21 #include "draco/core/math_utils.h"
22 #include "draco/core/quantization_utils.h"
23
24 namespace draco {
25
26 struct Converter {
27 typedef std::vector<uint32_t> SourceType;
28 typedef Point3ui TargetType;
operator ()draco::Converter29 Point3ui operator()(const std::vector<uint32_t> &v) {
30 return Point3ui(v[0], v[1], v[2]);
31 }
32 };
33
34 // Output iterator that is used to decode values directly into the data buffer
35 // of the modified PointAttribute.
36 template <class OutputIterator, class Converter>
37 class ConversionOutputIterator {
38 typedef ConversionOutputIterator<OutputIterator, Converter> Self;
39 typedef typename Converter::SourceType SourceType;
40 typedef typename Converter::TargetType TargetType;
41
42 public:
ConversionOutputIterator(OutputIterator oit)43 explicit ConversionOutputIterator(OutputIterator oit) : oit_(oit) {}
44
operator ++()45 const Self &operator++() {
46 ++oit_;
47 return *this;
48 }
operator ++(int)49 Self operator++(int) {
50 Self copy = *this;
51 ++oit_;
52 return copy;
53 }
operator *()54 Self &operator*() { return *this; }
operator =(const SourceType & source)55 const Self &operator=(const SourceType &source) {
56 *oit_ = Converter()(source);
57 return *this;
58 }
59
60 private:
61 OutputIterator oit_;
62 };
63
FloatPointsTreeDecoder()64 FloatPointsTreeDecoder::FloatPointsTreeDecoder()
65 : num_points_(0), compression_level_(0), num_points_from_header_(0) {
66 qinfo_.quantization_bits = 0;
67 qinfo_.range = 0;
68 }
69
DecodePointCloudKdTreeInternal(DecoderBuffer * buffer,std::vector<Point3ui> * qpoints)70 bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal(
71 DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) {
72 if (!buffer->Decode(&qinfo_.quantization_bits)) {
73 return false;
74 }
75 if (qinfo_.quantization_bits > 31) {
76 return false;
77 }
78 if (!buffer->Decode(&qinfo_.range)) {
79 return false;
80 }
81 if (!buffer->Decode(&num_points_)) {
82 return false;
83 }
84 if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) {
85 return false;
86 }
87 if (!buffer->Decode(&compression_level_)) {
88 return false;
89 }
90
91 // Only allow compression level in [0..6].
92 if (6 < compression_level_) {
93 DRACO_LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
94 compression_level_);
95 return false;
96 }
97
98 std::back_insert_iterator<std::vector<Point3ui>> oit_qpoints =
99 std::back_inserter(*qpoints);
100 ConversionOutputIterator<std::back_insert_iterator<std::vector<Point3ui>>,
101 Converter>
102 oit(oit_qpoints);
103 if (num_points_ > 0) {
104 qpoints->reserve(num_points_);
105 switch (compression_level_) {
106 case 0: {
107 DynamicIntegerPointsKdTreeDecoder<0> qpoints_decoder(3);
108 qpoints_decoder.DecodePoints(buffer, oit);
109 break;
110 }
111 case 1: {
112 DynamicIntegerPointsKdTreeDecoder<1> qpoints_decoder(3);
113 qpoints_decoder.DecodePoints(buffer, oit);
114 break;
115 }
116 case 2: {
117 DynamicIntegerPointsKdTreeDecoder<2> qpoints_decoder(3);
118 qpoints_decoder.DecodePoints(buffer, oit);
119 break;
120 }
121 case 3: {
122 DynamicIntegerPointsKdTreeDecoder<3> qpoints_decoder(3);
123 qpoints_decoder.DecodePoints(buffer, oit);
124 break;
125 }
126 case 4: {
127 DynamicIntegerPointsKdTreeDecoder<4> qpoints_decoder(3);
128 qpoints_decoder.DecodePoints(buffer, oit);
129 break;
130 }
131 case 5: {
132 DynamicIntegerPointsKdTreeDecoder<5> qpoints_decoder(3);
133 qpoints_decoder.DecodePoints(buffer, oit);
134 break;
135 }
136 case 6: {
137 DynamicIntegerPointsKdTreeDecoder<6> qpoints_decoder(3);
138 qpoints_decoder.DecodePoints(buffer, oit);
139 break;
140 }
141 default:
142 return false;
143 }
144 }
145
146 if (qpoints->size() != num_points_) {
147 return false;
148 }
149 return true;
150 }
151
152 } // namespace draco
153