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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc')
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc230
1 files changed, 230 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc
new file mode 100644
index 00000000000..2889e0521a0
--- /dev/null
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc
@@ -0,0 +1,230 @@
+// 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.
+//
+#include "draco/compression/attributes/sequential_integer_attribute_encoder.h"
+
+#include "draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h"
+#include "draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h"
+#include "draco/compression/entropy/symbol_encoding.h"
+#include "draco/core/bit_utils.h"
+
+namespace draco {
+
+SequentialIntegerAttributeEncoder::SequentialIntegerAttributeEncoder() {}
+
+bool SequentialIntegerAttributeEncoder::Init(PointCloudEncoder *encoder,
+ int attribute_id) {
+ if (!SequentialAttributeEncoder::Init(encoder, attribute_id)) {
+ return false;
+ }
+ if (GetUniqueId() == SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER) {
+ // When encoding integers, this encoder currently works only for integer
+ // attributes up to 32 bits.
+ switch (attribute()->data_type()) {
+ case DT_INT8:
+ case DT_UINT8:
+ case DT_INT16:
+ case DT_UINT16:
+ case DT_INT32:
+ case DT_UINT32:
+ break;
+ default:
+ return false;
+ }
+ }
+ // Init prediction scheme.
+ const PredictionSchemeMethod prediction_scheme_method =
+ GetPredictionMethodFromOptions(attribute_id, *encoder->options());
+
+ prediction_scheme_ = CreateIntPredictionScheme(prediction_scheme_method);
+
+ if (prediction_scheme_ && !InitPredictionScheme(prediction_scheme_.get())) {
+ prediction_scheme_ = nullptr;
+ }
+
+ return true;
+}
+
+bool SequentialIntegerAttributeEncoder::TransformAttributeToPortableFormat(
+ const std::vector<PointIndex> &point_ids) {
+ if (encoder()) {
+ if (!PrepareValues(point_ids, encoder()->point_cloud()->num_points())) {
+ return false;
+ }
+ } else {
+ if (!PrepareValues(point_ids, 0)) {
+ return false;
+ }
+ }
+
+ // Update point to attribute mapping with the portable attribute if the
+ // attribute is a parent attribute (for now, we can skip it otherwise).
+ if (is_parent_encoder()) {
+ // First create map between original attribute value indices and new ones
+ // (determined by the encoding order).
+ const PointAttribute *const orig_att = attribute();
+ PointAttribute *const portable_att = portable_attribute();
+ IndexTypeVector<AttributeValueIndex, AttributeValueIndex>
+ value_to_value_map(orig_att->size());
+ for (int i = 0; i < point_ids.size(); ++i) {
+ value_to_value_map[orig_att->mapped_index(point_ids[i])] =
+ AttributeValueIndex(i);
+ }
+ // Go over all points of the original attribute and update the mapping in
+ // the portable attribute.
+ for (PointIndex i(0); i < encoder()->point_cloud()->num_points(); ++i) {
+ portable_att->SetPointMapEntry(
+ i, value_to_value_map[orig_att->mapped_index(i)]);
+ }
+ }
+ return true;
+}
+
+std::unique_ptr<PredictionSchemeTypedEncoderInterface<int32_t>>
+SequentialIntegerAttributeEncoder::CreateIntPredictionScheme(
+ PredictionSchemeMethod method) {
+ return CreatePredictionSchemeForEncoder<
+ int32_t, PredictionSchemeWrapEncodingTransform<int32_t>>(
+ method, attribute_id(), encoder());
+}
+
+bool SequentialIntegerAttributeEncoder::EncodeValues(
+ const std::vector<PointIndex> &point_ids, EncoderBuffer *out_buffer) {
+ // Initialize general quantization data.
+ const PointAttribute *const attrib = attribute();
+ if (attrib->size() == 0) {
+ return true;
+ }
+
+ int8_t prediction_scheme_method = PREDICTION_NONE;
+ if (prediction_scheme_) {
+ if (!SetPredictionSchemeParentAttributes(prediction_scheme_.get())) {
+ return false;
+ }
+ prediction_scheme_method =
+ static_cast<int8_t>(prediction_scheme_->GetPredictionMethod());
+ }
+ out_buffer->Encode(prediction_scheme_method);
+ if (prediction_scheme_) {
+ out_buffer->Encode(
+ static_cast<int8_t>(prediction_scheme_->GetTransformType()));
+ }
+
+ const int num_components = portable_attribute()->num_components();
+ const int num_values =
+ static_cast<int>(num_components * portable_attribute()->size());
+ const int32_t *const portable_attribute_data = GetPortableAttributeData();
+
+ // We need to keep the portable data intact, but several encoding steps can
+ // result in changes of this data, e.g., by applying prediction schemes that
+ // change the data in place. To preserve the portable data we store and
+ // process all encoded data in a separate array.
+ std::vector<int32_t> encoded_data(num_values);
+
+ // All integer values are initialized. Process them using the prediction
+ // scheme if we have one.
+ if (prediction_scheme_) {
+ prediction_scheme_->ComputeCorrectionValues(
+ portable_attribute_data, &encoded_data[0], num_values, num_components,
+ point_ids.data());
+ }
+
+ if (prediction_scheme_ == nullptr ||
+ !prediction_scheme_->AreCorrectionsPositive()) {
+ const int32_t *const input =
+ prediction_scheme_ ? encoded_data.data() : portable_attribute_data;
+ ConvertSignedIntsToSymbols(input, num_values,
+ reinterpret_cast<uint32_t *>(&encoded_data[0]));
+ }
+
+ if (encoder() == nullptr || encoder()->options()->GetGlobalBool(
+ "use_built_in_attribute_compression", true)) {
+ out_buffer->Encode(static_cast<uint8_t>(1));
+ Options symbol_encoding_options;
+ if (encoder() != nullptr) {
+ SetSymbolEncodingCompressionLevel(&symbol_encoding_options,
+ 10 - encoder()->options()->GetSpeed());
+ }
+ if (!EncodeSymbols(reinterpret_cast<uint32_t *>(encoded_data.data()),
+ static_cast<int>(point_ids.size()) * num_components,
+ num_components, &symbol_encoding_options, out_buffer)) {
+ return false;
+ }
+ } else {
+ // No compression. Just store the raw integer values, using the number of
+ // bytes as needed.
+
+ // To compute the maximum bit-length, first OR all values.
+ uint32_t masked_value = 0;
+ for (uint32_t i = 0; i < static_cast<uint32_t>(num_values); ++i) {
+ masked_value |= encoded_data[i];
+ }
+ // Compute the msb of the ORed value.
+ int value_msb_pos = 0;
+ if (masked_value != 0) {
+ value_msb_pos = MostSignificantBit(masked_value);
+ }
+ const int num_bytes = 1 + value_msb_pos / 8;
+
+ out_buffer->Encode(static_cast<uint8_t>(0));
+ out_buffer->Encode(static_cast<uint8_t>(num_bytes));
+
+ if (num_bytes == DataTypeLength(DT_INT32)) {
+ out_buffer->Encode(encoded_data.data(), sizeof(int32_t) * num_values);
+ } else {
+ for (uint32_t i = 0; i < static_cast<uint32_t>(num_values); ++i) {
+ out_buffer->Encode(encoded_data.data() + i, num_bytes);
+ }
+ }
+ }
+ if (prediction_scheme_) {
+ prediction_scheme_->EncodePredictionData(out_buffer);
+ }
+ return true;
+}
+
+bool SequentialIntegerAttributeEncoder::PrepareValues(
+ const std::vector<PointIndex> &point_ids, int num_points) {
+ // Convert all values to int32_t format.
+ const PointAttribute *const attrib = attribute();
+ const int num_components = attrib->num_components();
+ const int num_entries = static_cast<int>(point_ids.size());
+ PreparePortableAttribute(num_entries, num_components, num_points);
+ int32_t dst_index = 0;
+ int32_t *const portable_attribute_data = GetPortableAttributeData();
+ for (PointIndex pi : point_ids) {
+ const AttributeValueIndex att_id = attrib->mapped_index(pi);
+ if (!attrib->ConvertValue<int32_t>(att_id,
+ portable_attribute_data + dst_index)) {
+ return false;
+ }
+ dst_index += num_components;
+ }
+ return true;
+}
+
+void SequentialIntegerAttributeEncoder::PreparePortableAttribute(
+ int num_entries, int num_components, int num_points) {
+ GeometryAttribute va;
+ va.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
+ false, num_components * DataTypeLength(DT_INT32), 0);
+ std::unique_ptr<PointAttribute> port_att(new PointAttribute(va));
+ port_att->Reset(num_entries);
+ SetPortableAttribute(std::move(port_att));
+ if (num_points) {
+ portable_attribute()->SetExplicitMapping(num_points);
+ }
+}
+
+} // namespace draco