mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-06-04 11:25:44 +08:00
172 lines
6.6 KiB
C++
172 lines
6.6 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/encode.h"
|
|
|
|
#include "compression/mesh/mesh_edgebreaker_encoder.h"
|
|
#include "compression/mesh/mesh_sequential_encoder.h"
|
|
#include "compression/point_cloud/point_cloud_kd_tree_encoder.h"
|
|
#include "compression/point_cloud/point_cloud_sequential_encoder.h"
|
|
|
|
namespace draco {
|
|
|
|
// Encodes header common to all methods.
|
|
bool EncodeHeader(const PointCloudEncoder &encoder, EncoderBuffer *out_buffer) {
|
|
// Encode the header according to our v1 specification.
|
|
// Five bytes for Draco format.
|
|
out_buffer->Encode("DRACO", 5);
|
|
// Version (major, minor).
|
|
const uint8_t major_version = 1;
|
|
const uint8_t minor_version = 1;
|
|
out_buffer->Encode(major_version);
|
|
out_buffer->Encode(minor_version);
|
|
// Type of the encoder (point cloud, mesh, ...).
|
|
const uint8_t encoder_type = encoder.GetGeometryType();
|
|
out_buffer->Encode(encoder_type);
|
|
// Unique identifier for the selected encoding method (edgebreaker, etc...).
|
|
out_buffer->Encode(encoder.GetEncodingMethod());
|
|
// Reserved for flags.
|
|
out_buffer->Encode(static_cast<uint16_t>(0));
|
|
return true;
|
|
}
|
|
|
|
bool EncodeGeometryToBuffer(PointCloudEncoder *encoder,
|
|
const EncoderOptions &options,
|
|
EncoderBuffer *out_buffer) {
|
|
if (!encoder)
|
|
return false;
|
|
if (!EncodeHeader(*encoder, out_buffer))
|
|
return false;
|
|
if (!encoder->Encode(options, out_buffer))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool EncodePointCloudToBuffer(const PointCloud &pc,
|
|
const EncoderOptions &options,
|
|
EncoderBuffer *out_buffer) {
|
|
std::unique_ptr<PointCloudEncoder> encoder;
|
|
const int encoding_method = options.GetGlobalInt("encoding_method", -1);
|
|
if (encoding_method == POINT_CLOUD_KD_TREE_ENCODING ||
|
|
(options.GetSpeed() < 10 && pc.num_attributes() == 1)) {
|
|
const PointAttribute *const att = pc.attribute(0);
|
|
bool create_kd_tree_encoder = true;
|
|
// Kd-Tree encoder can be currently used only under following conditions:
|
|
// - Point cloud has one attribute describing positions
|
|
// - Position is described by three components (x,y,z)
|
|
// - Position data type is one of the following:
|
|
// -float32 and quantization is enabled
|
|
// -uint32
|
|
if (att->attribute_type() != GeometryAttribute::POSITION ||
|
|
att->components_count() != 3)
|
|
create_kd_tree_encoder = false;
|
|
if (create_kd_tree_encoder && att->data_type() != DT_FLOAT32 &&
|
|
att->data_type() != DT_UINT32)
|
|
create_kd_tree_encoder = false;
|
|
if (create_kd_tree_encoder && att->data_type() == DT_FLOAT32 &&
|
|
options.GetAttributeInt(0, "quantization_bits", -1) <= 0)
|
|
create_kd_tree_encoder = false; // Quantization not enabled.
|
|
if (create_kd_tree_encoder) {
|
|
// Create kD-tree encoder (all checks passed).
|
|
encoder =
|
|
std::unique_ptr<PointCloudEncoder>(new PointCloudKdTreeEncoder());
|
|
} else if (encoding_method == POINT_CLOUD_KD_TREE_ENCODING) {
|
|
// Encoding method was explicitly specified but we cannot use it for the
|
|
// given input (some of the checks above failed).
|
|
return false;
|
|
}
|
|
}
|
|
if (!encoder) {
|
|
// Default choice.
|
|
encoder =
|
|
std::unique_ptr<PointCloudEncoder>(new PointCloudSequentialEncoder());
|
|
}
|
|
if (encoder)
|
|
encoder->SetPointCloud(pc);
|
|
return EncodeGeometryToBuffer(encoder.get(), options, out_buffer);
|
|
}
|
|
|
|
bool EncodeMeshToBuffer(const Mesh &m, const EncoderOptions &options,
|
|
EncoderBuffer *out_buffer) {
|
|
std::unique_ptr<MeshEncoder> encoder;
|
|
// Select the encoding method only based on the provided options.
|
|
int encoding_method = options.GetGlobalInt("encoding_method", -1);
|
|
if (encoding_method == -1) {
|
|
// For now select the edgebreaker for all options expect of speed 10
|
|
if (options.GetSpeed() == 10) {
|
|
encoding_method = MESH_SEQUENTIAL_ENCODING;
|
|
} else {
|
|
encoding_method = MESH_EDGEBREAKER_ENCODING;
|
|
}
|
|
}
|
|
if (encoding_method == MESH_EDGEBREAKER_ENCODING) {
|
|
encoder = std::unique_ptr<MeshEncoder>(new MeshEdgeBreakerEncoder());
|
|
} else {
|
|
encoder = std::unique_ptr<MeshEncoder>(new MeshSequentialEncoder());
|
|
}
|
|
if (encoder)
|
|
encoder->SetMesh(m);
|
|
return EncodeGeometryToBuffer(encoder.get(), options, out_buffer);
|
|
}
|
|
|
|
EncoderOptions CreateDefaultEncoderOptions() {
|
|
return EncoderOptions::CreateDefaultOptions();
|
|
}
|
|
|
|
void SetSpeedOptions(EncoderOptions *options, int encoding_speed,
|
|
int decoding_speed) {
|
|
options->GetGlobalOptions()->SetInt("encoding_speed", encoding_speed);
|
|
options->GetGlobalOptions()->SetInt("decoding_speed", decoding_speed);
|
|
}
|
|
|
|
void SetNamedAttributeQuantization(EncoderOptions *options,
|
|
const PointCloud &pc,
|
|
GeometryAttribute::Type type,
|
|
int quantization_bits) {
|
|
Options *const o = options->GetNamedAttributeOptions(pc, type);
|
|
if (o) {
|
|
SetAttributeQuantization(o, quantization_bits);
|
|
}
|
|
}
|
|
|
|
void SetAttributeQuantization(Options *options, int quantization_bits) {
|
|
options->SetInt("quantization_bits", quantization_bits);
|
|
}
|
|
|
|
void SetUseBuiltInAttributeCompression(EncoderOptions *options, bool enabled) {
|
|
options->GetGlobalOptions()->SetBool("use_built_in_attribute_compression",
|
|
enabled);
|
|
}
|
|
|
|
void SetEncodingMethod(EncoderOptions *options, int encoding_method) {
|
|
options->GetGlobalOptions()->SetInt("encoding_method", encoding_method);
|
|
}
|
|
|
|
void SetNamedAttributePredictionScheme(EncoderOptions *options,
|
|
const PointCloud &pc,
|
|
GeometryAttribute::Type type,
|
|
int prediction_scheme_method) {
|
|
Options *const o = options->GetNamedAttributeOptions(pc, type);
|
|
if (o) {
|
|
SetAttributePredictionScheme(o, prediction_scheme_method);
|
|
}
|
|
}
|
|
|
|
void SetAttributePredictionScheme(Options *options,
|
|
int prediction_scheme_method) {
|
|
options->SetInt("prediction_scheme", prediction_scheme_method);
|
|
}
|
|
|
|
} // namespace draco
|