mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-07-26 14:54:30 +08:00

Changes: 1. Javascript decoder can now be built separately for meshes and point clouds. Together with other optimizations this results in about 33% smaller Javascript for mesh decoder. (pre-built javascript for meshes and point clouds is included). 2. Fixing bug in our symbol_encoder that resulted in failed encoding for certain cases when there were around 1<<18 symbols. 3. Changing default setting of our draco_encoder app to -cl 7
158 lines
5.5 KiB
C++
158 lines
5.5 KiB
C++
// 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 "compression/attributes/sequential_integer_attribute_encoder.h"
|
|
|
|
#include "compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h"
|
|
#include "compression/attributes/prediction_schemes/prediction_scheme_wrap_transform.h"
|
|
#include "core/bit_utils.h"
|
|
#include "core/symbol_encoding.h"
|
|
|
|
namespace draco {
|
|
|
|
SequentialIntegerAttributeEncoder::SequentialIntegerAttributeEncoder() {}
|
|
|
|
bool SequentialIntegerAttributeEncoder::Initialize(PointCloudEncoder *encoder,
|
|
int attribute_id) {
|
|
if (!SequentialAttributeEncoder::Initialize(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;
|
|
}
|
|
|
|
std::unique_ptr<PredictionSchemeTypedInterface<int32_t>>
|
|
SequentialIntegerAttributeEncoder::CreateIntPredictionScheme(
|
|
PredictionSchemeMethod method) {
|
|
return CreatePredictionSchemeForEncoder<
|
|
int32_t, PredictionSchemeWrapTransform<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_)
|
|
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()));
|
|
}
|
|
|
|
if (!PrepareValues(point_ids))
|
|
return false;
|
|
|
|
const int num_components = values_.size() / point_ids.size();
|
|
// All integer values are initialized. Process them using the prediction
|
|
// scheme if we have one.
|
|
if (prediction_scheme_) {
|
|
prediction_scheme_->Encode(values_.data(), &values_[0], values_.size(),
|
|
num_components, point_ids.data());
|
|
}
|
|
|
|
if (prediction_scheme_ == nullptr ||
|
|
!prediction_scheme_->AreCorrectionsPositive()) {
|
|
ConvertSignedIntsToSymbols(values_.data(), values_.size(),
|
|
reinterpret_cast<uint32_t *>(values_.data()));
|
|
}
|
|
|
|
if (encoder() == nullptr || encoder()->options()->GetGlobalBool(
|
|
"use_built_in_attribute_compression", true)) {
|
|
out_buffer->Encode(static_cast<uint8_t>(1));
|
|
if (!EncodeSymbols(reinterpret_cast<uint32_t *>(values_.data()),
|
|
point_ids.size() * num_components, num_components,
|
|
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 < values_.size(); ++i) {
|
|
masked_value |= values_[i];
|
|
}
|
|
// Compute the msb of the ORed value.
|
|
int value_msb_pos = 0;
|
|
if (masked_value != 0) {
|
|
value_msb_pos = bits::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 == sizeof(decltype(values_)::value_type)) {
|
|
out_buffer->Encode(values_.data(), sizeof(int32_t) * values_.size());
|
|
} else {
|
|
for (uint32_t i = 0; i < values_.size(); ++i) {
|
|
out_buffer->Encode(&values_[i], num_bytes);
|
|
}
|
|
}
|
|
}
|
|
if (prediction_scheme_) {
|
|
prediction_scheme_->EncodePredictionData(out_buffer);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SequentialIntegerAttributeEncoder::PrepareValues(
|
|
const std::vector<PointIndex> &point_ids) {
|
|
// Convert all values to int32_t format.
|
|
const PointAttribute *const attrib = attribute();
|
|
const int num_components = attrib->components_count();
|
|
const int num_entries = point_ids.size();
|
|
values_.resize(num_entries * num_components);
|
|
int dst_index = 0;
|
|
for (int i = 0; i < num_entries; ++i) {
|
|
const AttributeValueIndex att_id = attrib->mapped_index(point_ids[i]);
|
|
attrib->ConvertValue<int32_t>(att_id, &values_[dst_index]);
|
|
dst_index += num_components;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace draco
|