FIXME: Escaping angle brackets
FIXME: Escaping angle brackets
Traversal_DecodeSymbol() {
symbol_buffer_.DecodeLeastSignificantBits32(1, &symbol); bits1
if (symbol != TOPOLOGY_C) {
symbol_buffer_.DecodeLeastSignificantBits32(2, &symbol_suffix); bits2
symbol |= (symbol_suffix << 1);
}
return symbol
}
DecodeAttributeSeam(int attribute) {
return attribute_connectivity_decoders_[attribute].DecodeNextBit();
}
EdgeBreakerTraversalValence_Start(num_vertices, num_attribute_data) {
out_buffer = EdgebreakerTraversal_Start()
num_split_symbols I32
mode == 0 I8
num_vertices_ += num_split_symbols
vertex_valences_ init to 0
vertex_valences_.resize(num_vertices_, 0);
min_valence_ = 2;
max_valence_ = 7;
num_unique_valences = 6 (max_valence_ - min_valence_ + 1)
for (i = 0; i < num_unique_valences; ++i) {
DecodeVarint<UI32>(&num_symbols, out_buffer)
If (num_symbols > 0) {
DecodeSymbols(num_symbols, out_buffer, &context_symbols_[i])
}
context_counters_[i] = num_symbols
}
return out_buffer;
}
TraversalValence_DecodeSymbol() {
if (active_context_ != -1) {
symbol_id = context_symbols_[active_context_]
[--context_counters_[active_context_]]
last_symbol_ = edge_breaker_symbol_to_topology_id[symbol_id]
} else {
last_symbol_ = Traversal_DecodeSymbol()
}
return last_symbol_
}
TraversalValence_NewActiveCornerReached(corner) {
switch (last_symbol_) {
case TOPOLOGY_C:
case TOPOLOGY_S:
vertex_valences_[ct(next)] += 1;
vertex_valences_[ct(prev)] += 1;
break;
case TOPOLOGY_R:
vertex_valences_[corner] += 1;
vertex_valences_[ct(next)] += 1;
vertex_valences_[ct(prev)] += 2;
break;
case TOPOLOGY_L:
vertex_valences_[corner] += 1;
vertex_valences_[ct(next)] += 2;
vertex_valences_[ct(prev)] += 1;
break;
case TOPOLOGY_E:
vertex_valences_[corner] += 2;
vertex_valences_[ct(next)] += 2;
vertex_valences_[ct(prev)] += 2;
break;
}
valence = vertex_valences_[ct(next)]
valence = max(valence, min_valence_)
valence = min(valence, max_valence_)
active_context_ = (valence - min_valence_);
}
TraversalValence_MergeVertices(dest, source) {
vertex_valences_[dest] += vertex_valences_[source];
}
DecodeAttributesDecoderData(buffer) {
num_attributes I32
point_attribute_ids_.resize(num_attributes);
for (i = 0; i < num_attributes; ++i) {
att_type UI8
data_type UI8
components_count UI8
normalized UI8
custom_id UI16
Initialize GeometryAttribute ga
att_id = pc->AddAttribute(new PointAttribute(ga));
point_attribute_ids_[i] = att_id;
}
DecodeAttributesDecoderData(buffer) {
AttributesDecoder_DecodeAttributesDecoderData(buffer)
sequential_decoders_.resize(num_attributes());
for (i = 0; i < num_attributes(); ++i) {
decoder_type UI8
sequential_decoders_[i] = CreateSequentialDecoder(decoder_type);
sequential_decoders_[i]->Initialize(decoder(), GetAttributeId(i))
}
DecodeAttributes(buffer) {
sequencer_->GenerateSequence(&point_ids_)
for (i = 0; i < num_attributes(); ++i) {
pa = decoder()->point_cloud()->attribute(GetAttributeId(i));
sequencer_->UpdatePointToAttributeIndexMapping(pa)
}
for (i = 0; i < num_attributes(); ++i) {
sequential_decoders_[i]->Decode(point_ids_, buffer)
//SequentialAttributeDecoder_Decode()
}
}
CreateSequentialDecoder(type) {
switch (type) {
case SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC:
return new SequentialAttributeDecoder()
case SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER:
return new SequentialIntegerAttributeDecoder()
case SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION:
return new SequentialQuantizationAttributeDecoder()
case SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS:
return new SequentialNormalAttributeDecoder()
}
}
Initialize(...) {
// Init some members
}
DecodeValues(const std::vector<PointIndex> &point_ids) {
num_values = point_ids.size();
entry_size = attribute_->byte_stride();
std::unique_ptr<uint8_t[]> value_data_ptr(new uint8_t[entry_size]);
out_byte_pos = 0;
for (i = 0; i < num_values; ++i) {
value_data UI8 * entry_size
attribute_->buffer()->Write(out_byte_pos, value_data, entry_size);
out_byte_pos += entry_size;
}
}
Initialize(...) {
SequentialAttributeDecoder_Initialize()
}
DecodeValues(point_ids) {
prediction_scheme_method I8
if (prediction_scheme_method != PREDICTION_NONE) {
prediction_transform_type I8
prediction_scheme_ = CreateIntPredictionScheme(...)
}
if (prediction_scheme_) {
}
DecodeIntegerValues(point_ids)
//SequentialQuantizationAttributeDecoder_DecodeIntegerValues()
//StoreValues()
DequantizeValues(num_values)
}
DecodeIntegerValues(point_ids) {
compressed UI8
if (compressed) {
DecodeSymbols(..., values_.data())
} else {
// TODO
}
if (!prediction_scheme_->AreCorrectionsPositive()) {
ConvertSymbolsToSignedInts(...)
}
if (prediction_scheme_) {
prediction_scheme_->DecodePredictionData(buffer)
// DecodeTransformData(buffer)
if (!values_.empty()) {
prediction_scheme_->Decode(values_.data(), &values_[0],
values_.size(), num_components, point_ids.data())
// MeshPredictionSchemeParallelogram_Decode()
}
Initialize(...) {
SequentialIntegerAttributeDecoder_Initialize()
}
DecodeIntegerValues(point_ids) {
// DecodeQuantizedDataInfo()
num_components = attribute()->components_count();
for (i = 0; i < num_components; ++i) {
min_value_[i] F32
}
max_value_dif_ F32
quantization_bits_ UI8
SequentialIntegerAttributeDecoder::DecodeIntegerValues()
}
DequantizeValues(num_values) {
max_quantized_value = (1 << (quantization_bits_)) - 1;
num_components = attribute()->components_count();
entry_size = sizeof(float) * num_components;
quant_val_id = 0;
out_byte_pos = 0;
for (i = 0; i < num_values; ++i) {
for (c = 0; c < num_components; ++c) {
value = dequantizer.DequantizeFloat(values()->at(quant_val_id++));
value = value + min_value_[c];
att_val[c] = value;
}
attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
out_byte_pos += entry_size;
}
}
ComputeOriginalValue(const DataTypeT *predicted_vals,
const CorrTypeT *corr_vals,
DataTypeT *out_original_vals, int val_id) {
for (i = 0; i < num_components_; ++i) {
out_original_vals[i] = predicted_vals[i] + corr_vals[val_id + i];
}
}
DecodeTransformData(buffer) {
min_value_ DT
max_value_ DT
}
ComputeOriginalValue(const DataTypeT *predicted_vals,
const CorrTypeT *corr_vals,
DataTypeT *out_original_vals, int val_id) {
clamped_vals = ClampPredictedValue(predicted_vals);
ComputeOriginalValue(clamped_vals, corr_vals, out_original_vals, val_id)
// PredictionSchemeTransform_ComputeOriginalValue()
for (i = 0; i < this->num_components(); ++i) {
if (out_original_vals[i] > max_value_) {
out_original_vals[i] -= max_dif_;
} else if (out_original_vals[i] < min_value_) {
out_original_vals[i] += max_dif_;
}
}
ClampPredictedValue(const DataTypeT *predicted_val) {
for (i = 0; i < this->num_components(); ++i) {
clamped_value_[i] = min(predicted_val[i], max_value_)
clamped_value_[i] = max(predicted_val[i], min_value_)
}
return &clamped_value_[0];
}
Decode(...) {
this->transform().InitializeDecoding(num_components);
// restore the first value
this->transform().ComputeOriginalValue(pred_vals.get(),
in_corr, out_data, 0);
// PredictionSchemeWrapTransform_ComputeOriginalValue()
corner_map_size = this->mesh_data().data_to_corner_map()->size();
for (p = 1; p < corner_map_size; ++p) {
corner_id = this->mesh_data().data_to_corner_map()->at(p);
dst_offset = p * num_components;
b= ComputeParallelogramPrediction(p, corner_id, table,
*vertex_to_data_map, out_data,
num_components, pred_vals.get())
if (!b) {
src_offset = (p - 1) * num_components;
this->transform().ComputeOriginalValue(out_data + src_offset, in_corr,
out_data + dst_offset, dst_offset);
// PredictionSchemeWrapTransform_ComputeOriginalValue()
} else {
this->transform().ComputeOriginalValue(pred_vals.get(), in_corr,
out_data + dst_offset, dst_offset);
// PredictionSchemeWrapTransform_ComputeOriginalValue()
}
}
}
MeshPredictionSchemeParallelogramShared
ComputeParallelogramPrediction(...) {
oci = table->Opposite(ci);
vert_opp = vertex_to_data_map[table->Vertex(ci)];
vert_next = vertex_to_data_map[table->Vertex(table->Next(ci))];
vert_prev = vertex_to_data_map[table->Vertex(table->Previous(ci))];
if (vert_opp < data_entry_id && vert_next < data_entry_id &&
vert_prev < data_entry_id) {
v_opp_off = vert_opp * num_components;
v_next_off = vert_next * num_components;
v_prev_off = vert_prev * num_components;
for (c = 0; c < num_components; ++c) {
out_prediction[c] = (in_data[v_next_off + c] + in_data[v_prev_off + c]) -
in_data[v_opp_off + c];
}
Return true;
}
return false;
}
IsFaceVisited(corner_id) {
if (corner_id < 0)
return true
return is_face_visited_[corner_id / 3];
}
MarkFaceVisited(face_id) {
is_face_visited_[face_id] = true;
}
IsVertexVisited(vert_id) {
return is_vertex_visited_[vert_id];
}
MarkVertexVisited(vert_id) {
is_vertex_visited_[vert_id] = true;
}
OnNewVertexVisited(vertex, corner) {
point_id = mesh_->face(corner / 3)[corner % 3];
sequencer_->AddPointId(point_id);
// Keep track of visited corners.
encoding_data_->encoded_attribute_value_index_to_corner_map.push_back(corner);
encoding_data_
->vertex_to_encoded_attribute_value_index_map[vertex] =
encoding_data_->num_values;
encoding_data_->num_values++;
}
TraverseFromCorner(corner_id) {
if (processor_.IsFaceVisited(corner_id))
return
corner_traversal_stack_.clear();
corner_traversal_stack_.push_back(corner_id);
next_vert = corner_table_->Vertex(corner_table_->Next(corner_id));
prev_vert = corner_table_->Vertex(corner_table_->Previous(corner_id));
if (!processor_.IsVertexVisited(next_vert)) {
processor_.MarkVertexVisited(next_vert);
traversal_observer_.OnNewVertexVisited(next_vert,
corner_table_->Next(corner_id));
}
if (!processor_.IsVertexVisited(prev_vert)) {
processor_.MarkVertexVisited(prev_vert);
traversal_observer_.OnNewVertexVisited(prev_vert,
corner_table_->Previous(corner_id));
}
while (!corner_traversal_stack_.empty()) {
corner_id = corner_traversal_stack_.back();
face_id =corner_id / 3;
if (processor_.IsFaceVisited(face_id)) {
corner_traversal_stack_.pop_back();
continue
}
while(true) {
face_id = corner_id / 3;
processor_.MarkFaceVisited(face_id);
traversal_observer_.OnNewFaceVisited(face_id);
vert_id = corner_table_->Vertex(corner_id);
on_boundary = corner_table_->IsOnBoundary(vert_id);
if (!processor_.IsVertexVisited(vert_id)) {
processor_.MarkVertexVisited(vert_id);
traversal_observer_.OnNewVertexVisited(vert_id, corner_id);
if (!on_boundary) {
corner_id = corner_table_->GetRightCorner(corner_id);
continue;
}
}
// The current vertex has been already visited or it was on a boundary.
right_corner_id = corner_table_->GetRightCorner(corner_id);
left_corner_id = corner_table_->GetLeftCorner(corner_id);
right_face_id((right_corner_id < 0 ? -1 : right_corner_id / 3));
left_face_id((left_corner_id < 0 ? -1 : left_corner_id / 3));
if (processor_.IsFaceVisited(right_face_id)) {
if (processor_.IsFaceVisited(left_face_id)) {
corner_traversal_stack_.pop_back();
break; // Break from while(true) loop
} else {
corner_id = left_corner_id;
}
} else {
if (processor_.IsFaceVisited(left_face_id)) {
corner_id = right_corner_id;
} else {
// Split the traversal.
corner_traversal_stack_.back() = left_corner_id;
corner_traversal_stack_.push_back(right_corner_id);
break; // Break from while(true) loop
}
}
}
}
}
GenerateSequenceInternal() {
traverser_.OnTraversalStart();
If (corner_order_) {
// TODO
} else {
int32_t num_faces = traverser_.corner_table()->num_faces();
for (i = 0; i < num_faces; ++i) {
ProcessCorner(3 * i)
}
}
traverser_.OnTraversalEnd();
}
ProcessCorner(corner_id) {
traverser_.TraverseFromCorner(corner_id);
}
UpdatePointToAttributeIndexMapping(PointAttribute *attribute) {
corner_table = traverser_.corner_table();
attribute->SetExplicitMapping(mesh_->num_points());
num_faces = mesh_->num_faces();
num_points = mesh_->num_points();
for (f = 0; f < num_faces; ++f) {
face = mesh_->face(f);
for (p = 0; p < 3; ++p) {
point_id = face[p];
vert_id = corner_table->Vertex(3 * f + p);
att_entry_id(
encoding_data_
->vertex_to_encoded_attribute_value_index_map[vert_id]);
attribute->SetPointMapEntry(point_id, att_entry_id);
}
}
}
PointsSequencer
AddPointId(point_id) {
out_point_ids_->push_back(point_id);
}
Opposite(corner) {
return opposite_corners_[corner];
}
Next(corner) {
return LocalIndex(++corner) ? corner : corner - 3;
}
Previous(corner) {
return LocalIndex(corner) ? corner - 1 : corner + 2;
}
Vertex(corner) {
faces_[Face(corner)][LocalIndex(corner)];
}
Face(corner) {
return corner / 3;
}
LocalIndex(corner) {
return corner % 3;
}
num_vertices() {
return vertex_corners_.size();
}
num_corners() {
return faces_.size() * 3;
}
num_faces() {
return faces_.size();
}
bool IsOnBoundary(vert) {
corner = LeftMostCorner(vert);
if (SwingLeft(corner) < 0)
return true;
return false;
}
SwingRight(corner) {
return Previous(Opposite(Previous(corner)));
}
SwingLeft(corner) {
return Next(Opposite(Next(corner)));
}
GetLeftCorner(corner_id) {
if (corner_id < 0)
return kInvalidCornerIndex;
return Opposite(Previous(corner_id));
}
GetRightCorner(corner_id) {
if (corner_id < 0)
return kInvalidCornerIndex;
return Opposite(Next(corner_id));
}
SetOppositeCorner(corner_id, pp_corner_id) {
opposite_corners_[corner_id] = opp_corner_id;
}
MapCornerToVertex(corner_id, vert_id) {
face = Face(corner_id);
faces_[face][LocalIndex(corner_id)] = vert_id;
if (vert_id >= 0) {
vertex_corners_[vert_id] = corner_id;
}
}
UpdateVertexToCornerMap(vert) {
first_c = vertex_corners_[vert];
if (first_c < 0)
return;
act_c = SwingLeft(first_c);
c = first_c;
while (act_c >= 0 && act_c != first_c) {
c = act_c;
act_c = SwingLeft(act_c);
}
if (act_c != first_c) {
vertex_corners_[vert] = c;
}
}
LeftMostCorner(v) {
return vertex_corners_[v];
}
MakeVertexIsolated(vert) {
vertex_corners_[vert] = kInvalidCornerIndex;
}
bool IsCornerOnSeam(corner) {
return is_vertex_on_seam_[corner_table_->Vertex(corner)];
}
AddSeamEdge(c) {
MarkSeam(c)
opp_corner = corner_table_->Opposite(c);
if (opp_corner >= 0) {
no_interior_seams_ = false;
MarkSeam(opp_corner)
}
}
MarkSeam(c) {
is_edge_on_seam_[c] = true;
is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Next(c))] = true;
is_vertex_on_seam_[corner_table_->Vertex(corner_table_->Previous(c))
] = true;
}
RecomputeVertices() {
// in code RecomputeVerticesInternal<false>(nullptr, nullptr)
num_new_vertices = 0;
for (v = 0; v < corner_table_->num_vertices(); ++v) {
c = corner_table_->LeftMostCorner(v);
if (c < 0)
continue;
first_vert_id(num_new_vertices++);
vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
first_c = c;
if (is_vertex_on_seam_[v]) {
act_c = SwingLeft(first_c);
while (act_c >= 0) {
first_c = act_c;
act_c = SwingLeft(act_c);
}
}
corner_to_vertex_map_[first_c] =first_vert_id;
vertex_to_left_most_corner_map_.push_back(first_c);
act_c = corner_table_->SwingRight(first_c);
while (act_c >= 0 && act_c != first_c) {
if (is_edge_on_seam_[corner_table_->Next(act_c)]) {
// in code IsCornerOppositeToSeamEdge()
first_vert_id = AttributeValueIndex(num_new_vertices++);
vertex_to_attribute_entry_id_map_.push_back(first_vert_id);
vertex_to_left_most_corner_map_.push_back(act_c);
}
corner_to_vertex_map_[act_c] = first_vert_id;
act_c = corner_table_->SwingRight(act_c);
}
}
}
DecodeSymbols(num_symbols, out_buffer, out_values) {
scheme UI8
If (scheme == 0) {
DecodeTaggedSymbols<>(num_symbols, src_buffer, out_values)
} else if (scheme == 1) {
DecodeRawSymbols<>(num_symbols, src_buffer, out_values)
}
}
DecodeTaggedSymbols() {
FIXME
}
DecodeRawSymbols() {
max_bit_length UI8
DecodeRawSymbolsInternal(max_bit_length, out_values)
return symbols
}
DecodeRawSymbolsInternal(max_bit_length, out_values) {
decoder = CreateRansSymbolDecoder(max_bit_length)
decoder.StartDecoding()
// RansSymbolDecoder_StartDecoding
for (i = 0; i < num_values; ++i) {
out_values[i] = decoder.DecodeSymbol()
// RansSymbolDecoder_DecodeSymbol
}
}
CreateRansSymbolDecoder(max_bit_length) {
rans_precision_bits = (3 * max_bit_length) / 2;
rans_precision_bits = min(rans_precision_bits, 20)
rans_precision_bits = max(rans_precision_bits, 12)
rans_precision = 1 << rans_precision_bits_;
l_rans_base = rans_precision * 4;
num_symbols_ UI32
for (i = 0; i < num_symbols_; ++i) {
prob_data UI8
if ((prob_data & 3) == 3) {
offset = prob_data >> 2
for (j = 0; j < offset + 1; ++j) {
probability_table_[i + j] = 0;
}
i += offset;
} else {
prob = prob_data >> 2
for (j = 0; j < token; ++j) {
eb UI8
prob = prob | (eb << (8 * (j + 1) - 2)
}
probability_table_[i] = prob;
}
}
rans_build_look_up_table()
}
RansSymbolDecoder_StartDecoding() {
bytes_encoded UI64
buffer bytes_encoded * UI8
rans_read_init(buffer, bytes_encoded)
}
RansSymbolDecoder_DecodeSymbol() {
ans_.rans_read()
}
ans_read_init(struct AnsDecoder *const ans, const uint8_t *const buf,
int offset) {
x = buf[offset - 1] >> 6
If (x == 0) {
ans->buf_offset = offset - 1;
ans->state = buf[offset - 1] & 0x3F;
} else if (x == 1) {
ans->buf_offset = offset - 2;
ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF;
} else if (x == 2) {
ans->buf_offset = offset - 3;
ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
} else if (x == 3) {
// x == 3 implies this byte is a superframe marker
return 1;
}
ans->state += l_base;
}
int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
AnsP8 p = ans_p8_precision - p0;
if (ans->state < l_base) {
ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
}
x = ans->state;
quot = x / ans_p8_precision;
rem = x % ans_p8_precision;
xn = quot * p;
val = rem < p;
if (val) {
ans->state = xn + rem;
} else {
ans->state = x - xn - p;
}
return val;
}
rans_read_init(UI8 *buf, int offset) {
ans_.buf = buf;
x = buf[offset - 1] >> 6
If (x == 0) {
ans_.buf_offset = offset - 1;
ans_.state = buf[offset - 1] & 0x3F;
} else if (x == 1) {
ans_.buf_offset = offset - 2;
ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
} else if (x == 2) {
ans_.buf_offset = offset - 3;
ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
} else if (x == 3) {
ans_.buf_offset = offset - 4;
ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
}
ans_.state += l_rans_base;
}
rans_build_look_up_table() {
cum_prob = 0
act_prob = 0
for (i = 0; i < num_symbols; ++i) {
probability_table_[i].prob = token_probs[i];
probability_table_[i].cum_prob = cum_prob;
cum_prob += token_probs[i];
for (j = act_prob; j < cum_prob; ++j) {
Lut_table_[j] = i
}
act_prob = cum_prob
}
rans_read() {
while (ans_.state < l_rans_base) {
ans_.state = ans_.state * io_base + ans_.buf[--ans_.buf_offset];
}
quo = ans_.state / rans_precision;
rem = ans_.state % rans_precision;
sym = fetch_sym()
ans_.state = quo * sym.prob + rem - sym.cum_prob;
return sym.val;
}
fetch_sym() {
symbol = lut_table[rem]
out->val = symbol
out->prob = probability_table_[symbol].prob;
out->cum_prob = probability_table_[symbol].cum_prob;
}
RansBitDecoder_StartDecoding(DecoderBuffer *source_buffer) {
prob_zero_ UI8
size UI32
buffer_ size * UI8
ans_read_init(&ans_decoder_, buffer_, size)
}
DecodeNextBit() {
uint8_t bit = rabs_desc_read(&ans_decoder_, prob_zero_);
return bit > 0;
}
DecodeVarint<IT>() {
If (std::is_unsigned<IT>::value) {
in UI8
If (in & (1 << 7)) {
out = DecodeVarint<IT>()
out = (out << 7) | (in & ((1 << 7) - 1))
} else {
typename std::make_unsigned<IT>::type UIT;
out = DecodeVarint<UIT>()
out = ConvertSymbolToSignedInt(out)
}
return out;
}
ConvertSymbolToSignedInt() {
abs_val = val >> 1
If (val & 1 == 0) {
return abs_val
} else {
signed_val = -abs_val - 1
}
return signed_val
}
Sequential Decoder
decode_connectivity() {
num_faces I32
num_points I32
connectivity _method UI8
If (connectivity _method == 0) {
// TODO
} else {
loop num_faces {
If (num_points < 256) {
face[] UI8
} else if (num_points < (1 << 16)) {
face[] UI16
} else {
face[] UI32
}
}
}
}