diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..522866e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +docs/_site diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..276cbf9 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.3.0 diff --git a/docs/_config.yml b/docs/_config.yml index 06dd47f..6c88dc6 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -30,5 +30,6 @@ gems: exclude: - Gemfile - Gemfile.lock + - docs/_site sass: style: compressed diff --git a/docs/_site/spec/00.00.03.last.modified.html b/docs/_site/spec/00.00.03.last.modified.html index 124fa6d..c73c61d 100644 --- a/docs/_site/spec/00.00.03.last.modified.html +++ b/docs/_site/spec/00.00.03.last.modified.html @@ -1,2 +1,2 @@ -

Last modified: 2017-07-09 18:30:06 -0700

+

Last modified: 2017-07-10 14:30:06 -0700

diff --git a/docs/_site/spec/edgebreaker.decoder.html b/docs/_site/spec/edgebreaker.decoder.html index d5a7db7..6dd5e50 100644 --- a/docs/_site/spec/edgebreaker.decoder.html +++ b/docs/_site/spec/edgebreaker.decoder.html @@ -348,1209 +348,3 @@ SetOppositeCorners(corner_0, corner_1) { Type - -

EdgeBreaker Hole and Topology Split Events

- -

DecodeHoleAndTopologySplitEvents()

- -

FIXME: Escaping angle brackets

- -
-DecodeHoleAndTopologySplitEvents() { Type - num_topologoy_splits UI32 - source_symbol_id = 0 - for (i = 0; i < num_topologoy_splits; ++i) { - DecodeVarint\<UI32\>(&delta) - split_data[i].source_symbol_id = delta + source_symbol_id - DecodeVarint\<UI32\>(&delta) - split_data[i].split_symbol_id = source_symbol_id - delta - } - for (i = 0; i < num_topologoy_splits; ++i) { - split_data[i].split_edge bits1 - split_data[i].source_edge bits1 - } - num_hole_events UI32 - symbol_id = 0 - for (i = 0; i < num_hole_events; ++i) { - DecodeVarint\<UI32\>(&delta) - hole_data[i].symbol_id = delta + symbol_id - } - return bytes_decoded; -} - -
- -

CreateAttributesDecoder

- -

FIXME: Escaping angle brackets

- -
-CreateAttributesDecoder() { Type - att_data_id I8 - decoder_type UI8 - if (att_data_id >= 0) { - attribute_data_[att_data_id].decoder_id = att_decoder_id; - } - traversal_method_encoded UI8 - if (decoder_type == MESH_VERTEX_ATTRIBUTE) { - if (att_data_id < 0) { - encoding_data = &pos_encoding_data_; - } else { - encoding_data = &attribute_data_[att_data_id].encoding_data; - attribute_data_[att_data_id].is_connectivity_used = false; - } - if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { - typedef EdgeBreakerTraverser\<AttProcessor, AttObserver\> AttTraverser; - sequencer = CreateVertexTraversalSequencer\<AttTraverser\>(encoding_data); - } else if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) { - typedef PredictionDegreeTraverser\<AttProcessor, AttObserver\> AttTraverser; - sequencer = CreateVertexTraversalSequencer\<AttTraverser\>(encoding_data); - } - } else { - // TODO - } - att_controller(new SequentialAttributeDecodersController(std::move(sequencer))) - decoder_->SetAttributesDecoder(att_decoder_id, std::move(att_controller)); -} - -
- -

Edgebreaker Traversal Decoder

- -

EdgebreakerTraversal_Start()

- -
-EdgebreakerTraversal_Start() { Type - size UI64 - symbol_buffer_ size * UI8 - size UI64 - start_face_buffer_ size * UI8 - if (num_attribute_data_ > 0) { - attribute_connectivity_decoders_ = std::unique_ptr<BinaryDecoder[]>( - new BinaryDecoder[num_attribute_data_]); - for (i = 0; i < num_attribute_data_; ++i) { - attribute_connectivity_decoders_[i].StartDecoding() - // RansBitDecoder_StartDecoding - } -} - -
- -

Traversal_DecodeSymbol()

- -
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()

- -
DecodeAttributeSeam(int attribute) {
-  return attribute_connectivity_decoders_[attribute].DecodeNextBit();
-}
-
-
- -

EdgeBreaker Traversal Valence Decoder

- -

EdgeBreakerTraversalValence_Start()

- -
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()

- -
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()

- -
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()

- -
TraversalValence_MergeVertices(dest, source) {
-  vertex_valences_[dest] += vertex_valences_[source];
-}
-
-
- -

Attributes Decoder

- -

DecodeAttributesDecoderData()

- -
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;
-}
-
-
- -

Sequential Attributes Decoders Controller

- -

DecodeAttributesDecoderData()

- -
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()

- -
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()

- -
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()
-  }
-}
-
-
- -

Sequential Attribute Decoder

- -
Initialize(...) {
-  // Init some members
-}
-
-
- -

DecodeValues()

- -
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;
-  }
-}
-
-
- -

Sequential Integer Attribute Decoder

- -
Initialize(...) {
-  SequentialAttributeDecoder_Initialize()
-}
-
-
- -

DecodeValues()

- -
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()

- -
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()
-}
-
-
- -

Sequential Quantization Attribute Decoder

- -
Initialize(...) {
-  SequentialIntegerAttributeDecoder_Initialize()
-}
-
-
- -

DecodeIntegerValues()

- -
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()

- -
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;
-  }
-}
-
-
- -

Prediction Scheme Transform

- -

ComputeOriginalValue()

- -
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];
-  }
-}
-
-
- -

Prediction Scheme Wrap Transform

- -

DecodeTransformData()

- -
DecodeTransformData(buffer) {
-  min_value_                                                                 DT
-  max_value_                                                                 DT
-}
-
-
- -

ComputeOriginalValue()

- -
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()

- -
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];
-}
-
-
- -

Mesh Prediction Scheme Parallelogram

- -

Decode()

- -
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()

- -
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;
-}
-
-
- -

CornerTable Traversal Processor

- -

IsFaceVisited()

- -
IsFaceVisited(corner_id) {
-  if (corner_id < 0)
-    return true
-  return is_face_visited_[corner_id / 3];
-}
-
-
- -

MarkFaceVisited()

- -
MarkFaceVisited(face_id) {
-  is_face_visited_[face_id] = true;
-}
-
-
- -

IsVertexVisited()

- -
IsVertexVisited(vert_id) {
-  return is_vertex_visited_[vert_id];
-}
-
-
- -

MarkVertexVisited()

- -
MarkVertexVisited(vert_id) {
-  is_vertex_visited_[vert_id] = true;
-}
-
-
- -

Mesh Attribute Indices Encoding Observer

- -

OnNewVertexVisited()

- -
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++;
-}
-
-
- -

EdgeBreaker Traverser

- -

TraverseFromCorner()

- -
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
-        }
-      }
-    }
-  }
-}
-
-
- -

Mesh Traversal Sequencer

- -

GenerateSequenceInternal()

- -
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()

- -
ProcessCorner(corner_id) {
-  traverser_.TraverseFromCorner(corner_id);
-}
-
-
- -

UpdatePointToAttributeIndexMapping()

- -
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()

- -
AddPointId(point_id) {
-  out_point_ids_->push_back(point_id);
-}
-
-
- -

Corner Table

- -

Opposite()

- -
Opposite(corner) {
-  return opposite_corners_[corner];
-}
-
-
- -

Next()

- -
Next(corner) {
-  return LocalIndex(++corner) ? corner : corner - 3;
-}
-
-
- -

Previous()

- -
Previous(corner) {
-  return LocalIndex(corner) ? corner - 1 : corner + 2;
-}
-
-
- -

Vertex()

- -
Vertex(corner) {
-  faces_[Face(corner)][LocalIndex(corner)];
-}
-
-
- -

Face()

- -
Face(corner) {
-  return corner / 3;
-}
-
-
- -

LocalIndex()

- -
LocalIndex(corner) {
-  return corner % 3;
-}
-
-
- -

num_vertices()

- -
num_vertices() {
-  return vertex_corners_.size();
-}
-
-
- -

num_corners()

- -
num_corners() {
-  return faces_.size() * 3;
-}
-
-
- -

num_faces()

- -
num_faces() {
-  return faces_.size();
-}
-
-
- -

bool IsOnBoundary()

- -
bool IsOnBoundary(vert) {
-  corner = LeftMostCorner(vert);
-  if (SwingLeft(corner) < 0)
-    return true;
-  return false;
-}
-
-
- -

SwingRight()

- -
SwingRight(corner) {
-  return Previous(Opposite(Previous(corner)));
-}
-
-
- -

SwingLeft()

- -
SwingLeft(corner) {
-  return Next(Opposite(Next(corner)));
-}
-
-
- -

GetLeftCorner()

- -
GetLeftCorner(corner_id) {
-  if (corner_id < 0)
-     return kInvalidCornerIndex;
-  return Opposite(Previous(corner_id));
-}
-
-
- -

GetRightCorner()

- -
GetRightCorner(corner_id) {
-  if (corner_id < 0)
-     return kInvalidCornerIndex;
-  return Opposite(Next(corner_id));
-}
-
-
- -

SetOppositeCorner()

- -
SetOppositeCorner(corner_id, pp_corner_id) {
-  opposite_corners_[corner_id] = opp_corner_id;
-}
-
-
- -

MapCornerToVertex()

- -
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()

- -
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()

- -
LeftMostCorner(v) {
-  return vertex_corners_[v];
-}
-
-
- -

MakeVertexIsolated()

- -
MakeVertexIsolated(vert) {
-  vertex_corners_[vert] = kInvalidCornerIndex;
-}
-
-
- -

Mesh Attribute Corner Table

- -

bool IsCornerOnSeam()

- -
bool IsCornerOnSeam(corner) {
-  return is_vertex_on_seam_[corner_table_->Vertex(corner)];
-}
-
-
- -

AddSeamEdge()

- -
AddSeamEdge(c) {
-  MarkSeam(c)
-  opp_corner = corner_table_->Opposite(c);
-  if (opp_corner >= 0) {
-    no_interior_seams_ = false;
-    MarkSeam(opp_corner)
-  }
-}
-
-
- -

MarkSeam()

- -
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()

- -
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);
-    }
-  }
-}
-
-
- -

Symbol Decoding

- -

DecodeSymbols()

- -
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()

- -
DecodeTaggedSymbols() {
-  FIXME
-}
-
-
- -

DecodeRawSymbols()

- -
DecodeRawSymbols() {
-  max_bit_length                                                             UI8
-  DecodeRawSymbolsInternal(max_bit_length, out_values)
-  return symbols
-}
-
-
- -

DecodeRawSymbolsInternal()

- -
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()

- -
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()

- -
RansSymbolDecoder_StartDecoding() {
-  bytes_encoded                                                              UI64
-  buffer                                                                     bytes_encoded * UI8
-  rans_read_init(buffer, bytes_encoded)
-}
-
-
- -

RansSymbolDecoder_DecodeSymbol()

- -
RansSymbolDecoder_DecodeSymbol() {
-  ans_.rans_read()
-}
-
-
- -

Rans Decoding

- -

ans_read_init()

- -
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()

- -
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()

- -
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()

- -
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()

- -
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()

- -
fetch_sym() {
-  symbol = lut_table[rem]
-  out->val = symbol
-  out->prob = probability_table_[symbol].prob;
-  out->cum_prob = probability_table_[symbol].cum_prob;
-}
-
-
- -

Rans Bit Decoder

- -

RansBitDecoder_StartDecoding()

- -
RansBitDecoder_StartDecoding(DecoderBuffer *source_buffer) {
-  prob_zero_                                                                 UI8
-  size                                                                       UI32
-  buffer_                                                                    size * UI8
-  ans_read_init(&ans_decoder_, buffer_, size)
-}
-
-
- -

DecodeNextBit()

- -
DecodeNextBit() {
-  uint8_t bit = rabs_desc_read(&ans_decoder_, prob_zero_);
-  return bit > 0;
-}
-
-
- -

Core Functions

- -

DecodeVarint

- -
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()

- -
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()

- -
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
-      }
-    }
-  }
-}
-
-
diff --git a/docs/_site/spec/edgebreaker.decoder.md b/docs/_site/spec/edgebreaker.decoder.md index 495901e..3536ec0 100644 --- a/docs/_site/spec/edgebreaker.decoder.md +++ b/docs/_site/spec/edgebreaker.decoder.md @@ -360,1315 +360,3 @@ SetOppositeCorners(corner_0, corner_1) { Type - - -## EdgeBreaker Hole and Topology Split Events - -### DecodeHoleAndTopologySplitEvents() - -FIXME: Escaping angle brackets - -
-DecodeHoleAndTopologySplitEvents() { Type - num_topologoy_splits UI32 - source_symbol_id = 0 - for (i = 0; i < num_topologoy_splits; ++i) { - DecodeVarint\(&delta) - split_data[i].source_symbol_id = delta + source_symbol_id - DecodeVarint\(&delta) - split_data[i].split_symbol_id = source_symbol_id - delta - } - for (i = 0; i < num_topologoy_splits; ++i) { - split_data[i].split_edge bits1 - split_data[i].source_edge bits1 - } - num_hole_events UI32 - symbol_id = 0 - for (i = 0; i < num_hole_events; ++i) { - DecodeVarint\(&delta) - hole_data[i].symbol_id = delta + symbol_id - } - return bytes_decoded; -} - -
- -### CreateAttributesDecoder - -FIXME: Escaping angle brackets - -
-CreateAttributesDecoder() { Type - att_data_id I8 - decoder_type UI8 - if (att_data_id >= 0) { - attribute_data_[att_data_id].decoder_id = att_decoder_id; - } - traversal_method_encoded UI8 - if (decoder_type == MESH_VERTEX_ATTRIBUTE) { - if (att_data_id < 0) { - encoding_data = &pos_encoding_data_; - } else { - encoding_data = &attribute_data_[att_data_id].encoding_data; - attribute_data_[att_data_id].is_connectivity_used = false; - } - if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { - typedef EdgeBreakerTraverser\ AttTraverser; - sequencer = CreateVertexTraversalSequencer\(encoding_data); - } else if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) { - typedef PredictionDegreeTraverser\ AttTraverser; - sequencer = CreateVertexTraversalSequencer\(encoding_data); - } - } else { - // TODO - } - att_controller(new SequentialAttributeDecodersController(std::move(sequencer))) - decoder_->SetAttributesDecoder(att_decoder_id, std::move(att_controller)); -} - -
- - -## Edgebreaker Traversal Decoder - -### EdgebreakerTraversal_Start() - -
-EdgebreakerTraversal_Start() { Type - size UI64 - symbol_buffer_ size * UI8 - size UI64 - start_face_buffer_ size * UI8 - if (num_attribute_data_ > 0) { - attribute_connectivity_decoders_ = std::unique_ptr( - new BinaryDecoder[num_attribute_data_]); - for (i = 0; i < num_attribute_data_; ++i) { - attribute_connectivity_decoders_[i].StartDecoding() - // RansBitDecoder_StartDecoding - } -} - -
- - -### Traversal_DecodeSymbol() - -~~~~~ -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() - -~~~~~ -DecodeAttributeSeam(int attribute) { - return attribute_connectivity_decoders_[attribute].DecodeNextBit(); -} -~~~~~ - - -## EdgeBreaker Traversal Valence Decoder - -### EdgeBreakerTraversalValence_Start() - -~~~~~ -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(&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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -TraversalValence_MergeVertices(dest, source) { - vertex_valences_[dest] += vertex_valences_[source]; -} -~~~~~ - - -## Attributes Decoder - -### DecodeAttributesDecoderData() - -~~~~~ -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; -} -~~~~~ - - - -## Sequential Attributes Decoders Controller - -### DecodeAttributesDecoderData() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - } -} -~~~~~ - - -## Sequential Attribute Decoder - -~~~~~ -Initialize(...) { - // Init some members -} -~~~~~ - - -### DecodeValues() - -~~~~~ -DecodeValues(const std::vector &point_ids) { - num_values = point_ids.size(); - entry_size = attribute_->byte_stride(); - std::unique_ptr 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; - } -} -~~~~~ - - -## Sequential Integer Attribute Decoder - -~~~~~ -Initialize(...) { - SequentialAttributeDecoder_Initialize() -} -~~~~~ - - -### DecodeValues() - -~~~~~ -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() - -~~~~~ -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() -} -~~~~~ - - - -## Sequential Quantization Attribute Decoder - -~~~~~ -Initialize(...) { - SequentialIntegerAttributeDecoder_Initialize() -} -~~~~~ - - -### DecodeIntegerValues() - -~~~~~ -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() - -~~~~~ -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; - } -} -~~~~~ - - - -## Prediction Scheme Transform - -### ComputeOriginalValue() - -~~~~~ -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]; - } -} -~~~~~ - - - -## Prediction Scheme Wrap Transform - -### DecodeTransformData() - -~~~~~ -DecodeTransformData(buffer) { - min_value_ DT - max_value_ DT -} -~~~~~ - - -### ComputeOriginalValue() - -~~~~~ -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() - -~~~~~ -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]; -} -~~~~~ - - - -## Mesh Prediction Scheme Parallelogram - -### Decode() - -~~~~~ -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() - -~~~~~ -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; -} -~~~~~ - - - -## CornerTable Traversal Processor - - -### IsFaceVisited() - -~~~~~ -IsFaceVisited(corner_id) { - if (corner_id < 0) - return true - return is_face_visited_[corner_id / 3]; -} -~~~~~ - - -### MarkFaceVisited() - -~~~~~ -MarkFaceVisited(face_id) { - is_face_visited_[face_id] = true; -} -~~~~~ - - -### IsVertexVisited() - -~~~~~ -IsVertexVisited(vert_id) { - return is_vertex_visited_[vert_id]; -} -~~~~~ - - -### MarkVertexVisited() - -~~~~~ -MarkVertexVisited(vert_id) { - is_vertex_visited_[vert_id] = true; -} -~~~~~ - - -## Mesh Attribute Indices Encoding Observer - -### OnNewVertexVisited() - -~~~~~ -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++; -} -~~~~~ - - -## EdgeBreaker Traverser - -### TraverseFromCorner() - -~~~~~ -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 - } - } - } - } -} -~~~~~ - - -## Mesh Traversal Sequencer - -### GenerateSequenceInternal() - -~~~~~ -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() - -~~~~~ -ProcessCorner(corner_id) { - traverser_.TraverseFromCorner(corner_id); -} -~~~~~ - - -### UpdatePointToAttributeIndexMapping() - -~~~~~ -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() - -~~~~~ -AddPointId(point_id) { - out_point_ids_->push_back(point_id); -} -~~~~~ - - - -## Corner Table - -### Opposite() - -~~~~~ -Opposite(corner) { - return opposite_corners_[corner]; -} -~~~~~ - - -### Next() - -~~~~~ -Next(corner) { - return LocalIndex(++corner) ? corner : corner - 3; -} -~~~~~ - - -### Previous() - -~~~~~ -Previous(corner) { - return LocalIndex(corner) ? corner - 1 : corner + 2; -} -~~~~~ - - -### Vertex() - -~~~~~ -Vertex(corner) { - faces_[Face(corner)][LocalIndex(corner)]; -} -~~~~~ - - -### Face() - -~~~~~ -Face(corner) { - return corner / 3; -} -~~~~~ - - -### LocalIndex() - -~~~~~ -LocalIndex(corner) { - return corner % 3; -} -~~~~~ - - -### num_vertices() - -~~~~~ -num_vertices() { - return vertex_corners_.size(); -} -~~~~~ - - -### num_corners() - -~~~~~ -num_corners() { - return faces_.size() * 3; -} -~~~~~ - - -### num_faces() - -~~~~~ -num_faces() { - return faces_.size(); -} -~~~~~ - - -### bool IsOnBoundary() - -~~~~~ -bool IsOnBoundary(vert) { - corner = LeftMostCorner(vert); - if (SwingLeft(corner) < 0) - return true; - return false; -} -~~~~~ - - - -### SwingRight() - -~~~~~ -SwingRight(corner) { - return Previous(Opposite(Previous(corner))); -} -~~~~~ - - -### SwingLeft() - -~~~~~ -SwingLeft(corner) { - return Next(Opposite(Next(corner))); -} -~~~~~ - - -### GetLeftCorner() - -~~~~~ -GetLeftCorner(corner_id) { - if (corner_id < 0) - return kInvalidCornerIndex; - return Opposite(Previous(corner_id)); -} -~~~~~ - - -### GetRightCorner() - -~~~~~ -GetRightCorner(corner_id) { - if (corner_id < 0) - return kInvalidCornerIndex; - return Opposite(Next(corner_id)); -} -~~~~~ - - -### SetOppositeCorner() - -~~~~~ -SetOppositeCorner(corner_id, pp_corner_id) { - opposite_corners_[corner_id] = opp_corner_id; -} -~~~~~ - - - -### MapCornerToVertex() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -LeftMostCorner(v) { - return vertex_corners_[v]; -} -~~~~~ - - -### MakeVertexIsolated() - -~~~~~ -MakeVertexIsolated(vert) { - vertex_corners_[vert] = kInvalidCornerIndex; -} -~~~~~ - - - -## Mesh Attribute Corner Table - -### bool IsCornerOnSeam() - -~~~~~ -bool IsCornerOnSeam(corner) { - return is_vertex_on_seam_[corner_table_->Vertex(corner)]; -} -~~~~~ - - -### AddSeamEdge() - -~~~~~ -AddSeamEdge(c) { - MarkSeam(c) - opp_corner = corner_table_->Opposite(c); - if (opp_corner >= 0) { - no_interior_seams_ = false; - MarkSeam(opp_corner) - } -} -~~~~~ - - -### MarkSeam() - -~~~~~ -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() - -~~~~~ -RecomputeVertices() { - // in code RecomputeVerticesInternal(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); - } - } -} -~~~~~ - - - - -## Symbol Decoding - -### DecodeSymbols() - -~~~~~ -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() - -~~~~~ -DecodeTaggedSymbols() { - FIXME -} -~~~~~ - - - -### DecodeRawSymbols() - -~~~~~ -DecodeRawSymbols() { - max_bit_length UI8 - DecodeRawSymbolsInternal(max_bit_length, out_values) - return symbols -} -~~~~~ - - - -### DecodeRawSymbolsInternal() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -RansSymbolDecoder_StartDecoding() { - bytes_encoded UI64 - buffer bytes_encoded * UI8 - rans_read_init(buffer, bytes_encoded) -} -~~~~~ - - - -### RansSymbolDecoder_DecodeSymbol() - -~~~~~ -RansSymbolDecoder_DecodeSymbol() { - ans_.rans_read() -} -~~~~~ - - -## Rans Decoding - -### ans_read_init() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -fetch_sym() { - symbol = lut_table[rem] - out->val = symbol - out->prob = probability_table_[symbol].prob; - out->cum_prob = probability_table_[symbol].cum_prob; -} -~~~~~ - - - -## Rans Bit Decoder - -### RansBitDecoder_StartDecoding() - -~~~~~ -RansBitDecoder_StartDecoding(DecoderBuffer *source_buffer) { - prob_zero_ UI8 - size UI32 - buffer_ size * UI8 - ans_read_init(&ans_decoder_, buffer_, size) -} -~~~~~ - - -### DecodeNextBit() - -~~~~~ -DecodeNextBit() { - uint8_t bit = rabs_desc_read(&ans_decoder_, prob_zero_); - return bit > 0; -} -~~~~~ - - -## Core Functions - -### DecodeVarint - -~~~~~ -DecodeVarint() { - If (std::is_unsigned::value) { - in UI8 - If (in & (1 << 7)) { - out = DecodeVarint() - out = (out << 7) | (in & ((1 << 7) - 1)) - } else { - typename std::make_unsigned::type UIT; - out = DecodeVarint() - out = ConvertSymbolToSignedInt(out) - } - return out; -} -~~~~~ - - - -### ConvertSymbolToSignedInt() - -~~~~~ -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() - -~~~~~ -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 - } - } - } -} -~~~~~ diff --git a/docs/_site/spec/index.html b/docs/_site/spec/index.html index 05d03ed..7013943 100644 --- a/docs/_site/spec/index.html +++ b/docs/_site/spec/index.html @@ -32,7 +32,7 @@ [author]
[author]

-

Last modified: 2017-07-09 18:30:06 -0700

+

Last modified: 2017-07-10 14:30:06 -0700

Abstract

diff --git a/docs/spec/attributes.decoder.md b/docs/spec/attributes.decoder.md new file mode 100644 index 0000000..af4512a --- /dev/null +++ b/docs/spec/attributes.decoder.md @@ -0,0 +1,20 @@ + +## Attributes Decoder + +### DecodeAttributesDecoderData() + +~~~~~ +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; +} +~~~~~ diff --git a/docs/spec/core.functions.md b/docs/spec/core.functions.md new file mode 100644 index 0000000..b86d93c --- /dev/null +++ b/docs/spec/core.functions.md @@ -0,0 +1,61 @@ + +## Core Functions + +### DecodeVarint + +~~~~~ +DecodeVarint() { + If (std::is_unsigned::value) { + in UI8 + If (in & (1 << 7)) { + out = DecodeVarint() + out = (out << 7) | (in & ((1 << 7) - 1)) + } else { + typename std::make_unsigned::type UIT; + out = DecodeVarint() + out = ConvertSymbolToSignedInt(out) + } + return out; +} +~~~~~ + + +### ConvertSymbolToSignedInt() + +~~~~~ +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() + +~~~~~ +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 + } + } + } +} +~~~~~ diff --git a/docs/spec/corner.table.md b/docs/spec/corner.table.md new file mode 100644 index 0000000..4f37171 --- /dev/null +++ b/docs/spec/corner.table.md @@ -0,0 +1,197 @@ + +## Corner Table + +### Opposite() + +~~~~~ +Opposite(corner) { + return opposite_corners_[corner]; +} +~~~~~ + + +### Next() + +~~~~~ +Next(corner) { + return LocalIndex(++corner) ? corner : corner - 3; +} +~~~~~ + + +### Previous() + +~~~~~ +Previous(corner) { + return LocalIndex(corner) ? corner - 1 : corner + 2; +} +~~~~~ + + +### Vertex() + +~~~~~ +Vertex(corner) { + faces_[Face(corner)][LocalIndex(corner)]; +} +~~~~~ + + +### Face() + +~~~~~ +Face(corner) { + return corner / 3; +} +~~~~~ + + +### LocalIndex() + +~~~~~ +LocalIndex(corner) { + return corner % 3; +} +~~~~~ + + +### num_vertices() + +~~~~~ +num_vertices() { + return vertex_corners_.size(); +} +~~~~~ + + +### num_corners() + +~~~~~ +num_corners() { + return faces_.size() * 3; +} +~~~~~ + + +### num_faces() + +~~~~~ +num_faces() { + return faces_.size(); +} +~~~~~ + + +### bool IsOnBoundary() + +~~~~~ +bool IsOnBoundary(vert) { + corner = LeftMostCorner(vert); + if (SwingLeft(corner) < 0) + return true; + return false; +} +~~~~~ + + + +### SwingRight() + +~~~~~ +SwingRight(corner) { + return Previous(Opposite(Previous(corner))); +} +~~~~~ + + +### SwingLeft() + +~~~~~ +SwingLeft(corner) { + return Next(Opposite(Next(corner))); +} +~~~~~ + + +### GetLeftCorner() + +~~~~~ +GetLeftCorner(corner_id) { + if (corner_id < 0) + return kInvalidCornerIndex; + return Opposite(Previous(corner_id)); +} +~~~~~ + + +### GetRightCorner() + +~~~~~ +GetRightCorner(corner_id) { + if (corner_id < 0) + return kInvalidCornerIndex; + return Opposite(Next(corner_id)); +} +~~~~~ + + +### SetOppositeCorner() + +~~~~~ +SetOppositeCorner(corner_id, pp_corner_id) { + opposite_corners_[corner_id] = opp_corner_id; +} +~~~~~ + + + +### MapCornerToVertex() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +LeftMostCorner(v) { + return vertex_corners_[v]; +} +~~~~~ + + +### MakeVertexIsolated() + +~~~~~ +MakeVertexIsolated(vert) { + vertex_corners_[vert] = kInvalidCornerIndex; +} +~~~~~ diff --git a/docs/spec/cornertable.traversal.processor.md b/docs/spec/cornertable.traversal.processor.md new file mode 100644 index 0000000..05b8390 --- /dev/null +++ b/docs/spec/cornertable.traversal.processor.md @@ -0,0 +1,40 @@ + +## CornerTable Traversal Processor + + +### IsFaceVisited() + +~~~~~ +IsFaceVisited(corner_id) { + if (corner_id < 0) + return true + return is_face_visited_[corner_id / 3]; +} +~~~~~ + + +### MarkFaceVisited() + +~~~~~ +MarkFaceVisited(face_id) { + is_face_visited_[face_id] = true; +} +~~~~~ + + +### IsVertexVisited() + +~~~~~ +IsVertexVisited(vert_id) { + return is_vertex_visited_[vert_id]; +} +~~~~~ + + +### MarkVertexVisited() + +~~~~~ +MarkVertexVisited(vert_id) { + is_vertex_visited_[vert_id] = true; +} +~~~~~ diff --git a/docs/spec/edgebreaker.decoder.md b/docs/spec/edgebreaker.decoder.md index 495901e..3536ec0 100644 --- a/docs/spec/edgebreaker.decoder.md +++ b/docs/spec/edgebreaker.decoder.md @@ -360,1315 +360,3 @@ SetOppositeCorners(corner_0, corner_1) { Type - - -## EdgeBreaker Hole and Topology Split Events - -### DecodeHoleAndTopologySplitEvents() - -FIXME: Escaping angle brackets - -
-DecodeHoleAndTopologySplitEvents() { Type - num_topologoy_splits UI32 - source_symbol_id = 0 - for (i = 0; i < num_topologoy_splits; ++i) { - DecodeVarint\(&delta) - split_data[i].source_symbol_id = delta + source_symbol_id - DecodeVarint\(&delta) - split_data[i].split_symbol_id = source_symbol_id - delta - } - for (i = 0; i < num_topologoy_splits; ++i) { - split_data[i].split_edge bits1 - split_data[i].source_edge bits1 - } - num_hole_events UI32 - symbol_id = 0 - for (i = 0; i < num_hole_events; ++i) { - DecodeVarint\(&delta) - hole_data[i].symbol_id = delta + symbol_id - } - return bytes_decoded; -} - -
- -### CreateAttributesDecoder - -FIXME: Escaping angle brackets - -
-CreateAttributesDecoder() { Type - att_data_id I8 - decoder_type UI8 - if (att_data_id >= 0) { - attribute_data_[att_data_id].decoder_id = att_decoder_id; - } - traversal_method_encoded UI8 - if (decoder_type == MESH_VERTEX_ATTRIBUTE) { - if (att_data_id < 0) { - encoding_data = &pos_encoding_data_; - } else { - encoding_data = &attribute_data_[att_data_id].encoding_data; - attribute_data_[att_data_id].is_connectivity_used = false; - } - if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { - typedef EdgeBreakerTraverser\ AttTraverser; - sequencer = CreateVertexTraversalSequencer\(encoding_data); - } else if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) { - typedef PredictionDegreeTraverser\ AttTraverser; - sequencer = CreateVertexTraversalSequencer\(encoding_data); - } - } else { - // TODO - } - att_controller(new SequentialAttributeDecodersController(std::move(sequencer))) - decoder_->SetAttributesDecoder(att_decoder_id, std::move(att_controller)); -} - -
- - -## Edgebreaker Traversal Decoder - -### EdgebreakerTraversal_Start() - -
-EdgebreakerTraversal_Start() { Type - size UI64 - symbol_buffer_ size * UI8 - size UI64 - start_face_buffer_ size * UI8 - if (num_attribute_data_ > 0) { - attribute_connectivity_decoders_ = std::unique_ptr( - new BinaryDecoder[num_attribute_data_]); - for (i = 0; i < num_attribute_data_; ++i) { - attribute_connectivity_decoders_[i].StartDecoding() - // RansBitDecoder_StartDecoding - } -} - -
- - -### Traversal_DecodeSymbol() - -~~~~~ -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() - -~~~~~ -DecodeAttributeSeam(int attribute) { - return attribute_connectivity_decoders_[attribute].DecodeNextBit(); -} -~~~~~ - - -## EdgeBreaker Traversal Valence Decoder - -### EdgeBreakerTraversalValence_Start() - -~~~~~ -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(&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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -TraversalValence_MergeVertices(dest, source) { - vertex_valences_[dest] += vertex_valences_[source]; -} -~~~~~ - - -## Attributes Decoder - -### DecodeAttributesDecoderData() - -~~~~~ -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; -} -~~~~~ - - - -## Sequential Attributes Decoders Controller - -### DecodeAttributesDecoderData() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - } -} -~~~~~ - - -## Sequential Attribute Decoder - -~~~~~ -Initialize(...) { - // Init some members -} -~~~~~ - - -### DecodeValues() - -~~~~~ -DecodeValues(const std::vector &point_ids) { - num_values = point_ids.size(); - entry_size = attribute_->byte_stride(); - std::unique_ptr 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; - } -} -~~~~~ - - -## Sequential Integer Attribute Decoder - -~~~~~ -Initialize(...) { - SequentialAttributeDecoder_Initialize() -} -~~~~~ - - -### DecodeValues() - -~~~~~ -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() - -~~~~~ -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() -} -~~~~~ - - - -## Sequential Quantization Attribute Decoder - -~~~~~ -Initialize(...) { - SequentialIntegerAttributeDecoder_Initialize() -} -~~~~~ - - -### DecodeIntegerValues() - -~~~~~ -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() - -~~~~~ -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; - } -} -~~~~~ - - - -## Prediction Scheme Transform - -### ComputeOriginalValue() - -~~~~~ -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]; - } -} -~~~~~ - - - -## Prediction Scheme Wrap Transform - -### DecodeTransformData() - -~~~~~ -DecodeTransformData(buffer) { - min_value_ DT - max_value_ DT -} -~~~~~ - - -### ComputeOriginalValue() - -~~~~~ -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() - -~~~~~ -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]; -} -~~~~~ - - - -## Mesh Prediction Scheme Parallelogram - -### Decode() - -~~~~~ -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() - -~~~~~ -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; -} -~~~~~ - - - -## CornerTable Traversal Processor - - -### IsFaceVisited() - -~~~~~ -IsFaceVisited(corner_id) { - if (corner_id < 0) - return true - return is_face_visited_[corner_id / 3]; -} -~~~~~ - - -### MarkFaceVisited() - -~~~~~ -MarkFaceVisited(face_id) { - is_face_visited_[face_id] = true; -} -~~~~~ - - -### IsVertexVisited() - -~~~~~ -IsVertexVisited(vert_id) { - return is_vertex_visited_[vert_id]; -} -~~~~~ - - -### MarkVertexVisited() - -~~~~~ -MarkVertexVisited(vert_id) { - is_vertex_visited_[vert_id] = true; -} -~~~~~ - - -## Mesh Attribute Indices Encoding Observer - -### OnNewVertexVisited() - -~~~~~ -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++; -} -~~~~~ - - -## EdgeBreaker Traverser - -### TraverseFromCorner() - -~~~~~ -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 - } - } - } - } -} -~~~~~ - - -## Mesh Traversal Sequencer - -### GenerateSequenceInternal() - -~~~~~ -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() - -~~~~~ -ProcessCorner(corner_id) { - traverser_.TraverseFromCorner(corner_id); -} -~~~~~ - - -### UpdatePointToAttributeIndexMapping() - -~~~~~ -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() - -~~~~~ -AddPointId(point_id) { - out_point_ids_->push_back(point_id); -} -~~~~~ - - - -## Corner Table - -### Opposite() - -~~~~~ -Opposite(corner) { - return opposite_corners_[corner]; -} -~~~~~ - - -### Next() - -~~~~~ -Next(corner) { - return LocalIndex(++corner) ? corner : corner - 3; -} -~~~~~ - - -### Previous() - -~~~~~ -Previous(corner) { - return LocalIndex(corner) ? corner - 1 : corner + 2; -} -~~~~~ - - -### Vertex() - -~~~~~ -Vertex(corner) { - faces_[Face(corner)][LocalIndex(corner)]; -} -~~~~~ - - -### Face() - -~~~~~ -Face(corner) { - return corner / 3; -} -~~~~~ - - -### LocalIndex() - -~~~~~ -LocalIndex(corner) { - return corner % 3; -} -~~~~~ - - -### num_vertices() - -~~~~~ -num_vertices() { - return vertex_corners_.size(); -} -~~~~~ - - -### num_corners() - -~~~~~ -num_corners() { - return faces_.size() * 3; -} -~~~~~ - - -### num_faces() - -~~~~~ -num_faces() { - return faces_.size(); -} -~~~~~ - - -### bool IsOnBoundary() - -~~~~~ -bool IsOnBoundary(vert) { - corner = LeftMostCorner(vert); - if (SwingLeft(corner) < 0) - return true; - return false; -} -~~~~~ - - - -### SwingRight() - -~~~~~ -SwingRight(corner) { - return Previous(Opposite(Previous(corner))); -} -~~~~~ - - -### SwingLeft() - -~~~~~ -SwingLeft(corner) { - return Next(Opposite(Next(corner))); -} -~~~~~ - - -### GetLeftCorner() - -~~~~~ -GetLeftCorner(corner_id) { - if (corner_id < 0) - return kInvalidCornerIndex; - return Opposite(Previous(corner_id)); -} -~~~~~ - - -### GetRightCorner() - -~~~~~ -GetRightCorner(corner_id) { - if (corner_id < 0) - return kInvalidCornerIndex; - return Opposite(Next(corner_id)); -} -~~~~~ - - -### SetOppositeCorner() - -~~~~~ -SetOppositeCorner(corner_id, pp_corner_id) { - opposite_corners_[corner_id] = opp_corner_id; -} -~~~~~ - - - -### MapCornerToVertex() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -LeftMostCorner(v) { - return vertex_corners_[v]; -} -~~~~~ - - -### MakeVertexIsolated() - -~~~~~ -MakeVertexIsolated(vert) { - vertex_corners_[vert] = kInvalidCornerIndex; -} -~~~~~ - - - -## Mesh Attribute Corner Table - -### bool IsCornerOnSeam() - -~~~~~ -bool IsCornerOnSeam(corner) { - return is_vertex_on_seam_[corner_table_->Vertex(corner)]; -} -~~~~~ - - -### AddSeamEdge() - -~~~~~ -AddSeamEdge(c) { - MarkSeam(c) - opp_corner = corner_table_->Opposite(c); - if (opp_corner >= 0) { - no_interior_seams_ = false; - MarkSeam(opp_corner) - } -} -~~~~~ - - -### MarkSeam() - -~~~~~ -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() - -~~~~~ -RecomputeVertices() { - // in code RecomputeVerticesInternal(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); - } - } -} -~~~~~ - - - - -## Symbol Decoding - -### DecodeSymbols() - -~~~~~ -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() - -~~~~~ -DecodeTaggedSymbols() { - FIXME -} -~~~~~ - - - -### DecodeRawSymbols() - -~~~~~ -DecodeRawSymbols() { - max_bit_length UI8 - DecodeRawSymbolsInternal(max_bit_length, out_values) - return symbols -} -~~~~~ - - - -### DecodeRawSymbolsInternal() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -RansSymbolDecoder_StartDecoding() { - bytes_encoded UI64 - buffer bytes_encoded * UI8 - rans_read_init(buffer, bytes_encoded) -} -~~~~~ - - - -### RansSymbolDecoder_DecodeSymbol() - -~~~~~ -RansSymbolDecoder_DecodeSymbol() { - ans_.rans_read() -} -~~~~~ - - -## Rans Decoding - -### ans_read_init() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -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() - -~~~~~ -fetch_sym() { - symbol = lut_table[rem] - out->val = symbol - out->prob = probability_table_[symbol].prob; - out->cum_prob = probability_table_[symbol].cum_prob; -} -~~~~~ - - - -## Rans Bit Decoder - -### RansBitDecoder_StartDecoding() - -~~~~~ -RansBitDecoder_StartDecoding(DecoderBuffer *source_buffer) { - prob_zero_ UI8 - size UI32 - buffer_ size * UI8 - ans_read_init(&ans_decoder_, buffer_, size) -} -~~~~~ - - -### DecodeNextBit() - -~~~~~ -DecodeNextBit() { - uint8_t bit = rabs_desc_read(&ans_decoder_, prob_zero_); - return bit > 0; -} -~~~~~ - - -## Core Functions - -### DecodeVarint - -~~~~~ -DecodeVarint() { - If (std::is_unsigned::value) { - in UI8 - If (in & (1 << 7)) { - out = DecodeVarint() - out = (out << 7) | (in & ((1 << 7) - 1)) - } else { - typename std::make_unsigned::type UIT; - out = DecodeVarint() - out = ConvertSymbolToSignedInt(out) - } - return out; -} -~~~~~ - - - -### ConvertSymbolToSignedInt() - -~~~~~ -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() - -~~~~~ -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 - } - } - } -} -~~~~~ diff --git a/docs/spec/edgebreaker.hole.and.topology.md b/docs/spec/edgebreaker.hole.and.topology.md new file mode 100644 index 0000000..32f4fe1 --- /dev/null +++ b/docs/spec/edgebreaker.hole.and.topology.md @@ -0,0 +1,67 @@ + +## EdgeBreaker Hole and Topology Split Events + +### DecodeHoleAndTopologySplitEvents() + +FIXME: Escaping angle brackets + +
+DecodeHoleAndTopologySplitEvents() { Type + num_topologoy_splits UI32 + source_symbol_id = 0 + for (i = 0; i < num_topologoy_splits; ++i) { + DecodeVarint\(&delta) + split_data[i].source_symbol_id = delta + source_symbol_id + DecodeVarint\(&delta) + split_data[i].split_symbol_id = source_symbol_id - delta + } + for (i = 0; i < num_topologoy_splits; ++i) { + split_data[i].split_edge bits1 + split_data[i].source_edge bits1 + } + num_hole_events UI32 + symbol_id = 0 + for (i = 0; i < num_hole_events; ++i) { + DecodeVarint\(&delta) + hole_data[i].symbol_id = delta + symbol_id + } + return bytes_decoded; +} + +
+ +### CreateAttributesDecoder + +FIXME: Escaping angle brackets + +
+CreateAttributesDecoder() { Type + att_data_id I8 + decoder_type UI8 + if (att_data_id >= 0) { + attribute_data_[att_data_id].decoder_id = att_decoder_id; + } + traversal_method_encoded UI8 + if (decoder_type == MESH_VERTEX_ATTRIBUTE) { + if (att_data_id < 0) { + encoding_data = &pos_encoding_data_; + } else { + encoding_data = &attribute_data_[att_data_id].encoding_data; + attribute_data_[att_data_id].is_connectivity_used = false; + } + if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { + typedef EdgeBreakerTraverser\ AttTraverser; + sequencer = CreateVertexTraversalSequencer\(encoding_data); + } else if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) { + typedef PredictionDegreeTraverser\ AttTraverser; + sequencer = CreateVertexTraversalSequencer\(encoding_data); + } + } else { + // TODO + } + att_controller(new SequentialAttributeDecodersController(std::move(sequencer))) + decoder_->SetAttributesDecoder(att_decoder_id, std::move(att_controller)); +} + +
+ diff --git a/docs/spec/edgebreaker.traversal.decoder.md b/docs/spec/edgebreaker.traversal.decoder.md new file mode 100644 index 0000000..d1ee28e --- /dev/null +++ b/docs/spec/edgebreaker.traversal.decoder.md @@ -0,0 +1,44 @@ + +## Edgebreaker Traversal Decoder + +### EdgebreakerTraversal_Start() + +
+EdgebreakerTraversal_Start() { Type + size UI64 + symbol_buffer_ size * UI8 + size UI64 + start_face_buffer_ size * UI8 + if (num_attribute_data_ > 0) { + attribute_connectivity_decoders_ = std::unique_ptr( + new BinaryDecoder[num_attribute_data_]); + for (i = 0; i < num_attribute_data_; ++i) { + attribute_connectivity_decoders_[i].StartDecoding() + // RansBitDecoder_StartDecoding + } +} + +
+ + +### Traversal_DecodeSymbol() + +~~~~~ +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() + +~~~~~ +DecodeAttributeSeam(int attribute) { + return attribute_connectivity_decoders_[attribute].DecodeNextBit(); +} +~~~~~ diff --git a/docs/spec/edgebreaker.traversal.valence.decoder.md b/docs/spec/edgebreaker.traversal.valence.decoder.md new file mode 100644 index 0000000..a0d77f8 --- /dev/null +++ b/docs/spec/edgebreaker.traversal.valence.decoder.md @@ -0,0 +1,88 @@ + +## EdgeBreaker Traversal Valence Decoder + +### EdgeBreakerTraversalValence_Start() + +~~~~~ +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(&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() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +TraversalValence_MergeVertices(dest, source) { + vertex_valences_[dest] += vertex_valences_[source]; +} +~~~~~ diff --git a/docs/spec/edgebreaker.traverser.md b/docs/spec/edgebreaker.traverser.md new file mode 100644 index 0000000..3cf8f68 --- /dev/null +++ b/docs/spec/edgebreaker.traverser.md @@ -0,0 +1,70 @@ + +## EdgeBreaker Traverser + +### TraverseFromCorner() + +~~~~~ +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 + } + } + } + } +} +~~~~~ diff --git a/docs/spec/index.md b/docs/spec/index.md index b94da7f..28c6157 100644 --- a/docs/spec/index.md +++ b/docs/spec/index.md @@ -13,18 +13,33 @@ version_date: Released 2017-xx-xx {% include_relative 00.00.05.toc.md %} {% include_relative 01.00.00.scope.md %} - {% include_relative 02.00.00.terms.md %} - {% include_relative 03.00.00.symbols.md %} - {% include_relative 04.00.00.conventions.md %} - {% include_relative draco.decoder.md %} - {% include_relative mesh.decoder.md %} - {% include_relative edgebreaker.decoder.md %} +{% include_relative edgebreaker.hole.and.topology.md %} +{% include_relative edgebreaker.traversal.decoder.md %} +{% include_relative edgebreaker.traversal.valence.decoder.md %} +{% include_relative attributes.decoder.md %} +{% include_relative sequential.attributes.decoders.controller.md %} +{% include_relative sequential.attribute.decoder.md %} +{% include_relative sequential.integer.attribute.decoder.md %} +{% include_relative sequential.quantization.attribute.decoder.md %} +{% include_relative prediction.scheme.transform.md %} +{% include_relative prediction.scheme.wrap.transform.md %} +{% include_relative mesh.prediction.scheme.parallelogram.md %} +{% include_relative cornertable.traversal.processor.md %} +{% include_relative mesh.attribute.indices.encoding.observer.md %} +{% include_relative edgebreaker.traverser.md %} +{% include_relative mesh.traversal.sequencer.md %} +{% include_relative corner.table.md %} +{% include_relative mesh.attribute.corner.table.md %} +{% include_relative symbol.decoding.md %} +{% include_relative rans.decoding.md %} +{% include_relative rans.bit.decoder.md %} +{% include_relative core.functions.md %} {% comment %} diff --git a/docs/spec/mesh.attribute.corner.table.md b/docs/spec/mesh.attribute.corner.table.md new file mode 100644 index 0000000..3e0b7af --- /dev/null +++ b/docs/spec/mesh.attribute.corner.table.md @@ -0,0 +1,74 @@ + +## Mesh Attribute Corner Table + +### bool IsCornerOnSeam() + +~~~~~ +bool IsCornerOnSeam(corner) { + return is_vertex_on_seam_[corner_table_->Vertex(corner)]; +} +~~~~~ + + +### AddSeamEdge() + +~~~~~ +AddSeamEdge(c) { + MarkSeam(c) + opp_corner = corner_table_->Opposite(c); + if (opp_corner >= 0) { + no_interior_seams_ = false; + MarkSeam(opp_corner) + } +} +~~~~~ + + +### MarkSeam() + +~~~~~ +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() + +~~~~~ +RecomputeVertices() { + // in code RecomputeVerticesInternal(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); + } + } +} +~~~~~ diff --git a/docs/spec/mesh.attribute.indices.encoding.observer.md b/docs/spec/mesh.attribute.indices.encoding.observer.md new file mode 100644 index 0000000..6260cbe --- /dev/null +++ b/docs/spec/mesh.attribute.indices.encoding.observer.md @@ -0,0 +1,17 @@ + +## Mesh Attribute Indices Encoding Observer + +### OnNewVertexVisited() + +~~~~~ +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++; +} +~~~~~ diff --git a/docs/spec/mesh.prediction.scheme.parallelogram.md b/docs/spec/mesh.prediction.scheme.parallelogram.md new file mode 100644 index 0000000..9abf023 --- /dev/null +++ b/docs/spec/mesh.prediction.scheme.parallelogram.md @@ -0,0 +1,58 @@ + +## Mesh Prediction Scheme Parallelogram + +### Decode() + +~~~~~ +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() + +~~~~~ +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; +} +~~~~~ diff --git a/docs/spec/mesh.traversal.sequencer.md b/docs/spec/mesh.traversal.sequencer.md new file mode 100644 index 0000000..4e56f9f --- /dev/null +++ b/docs/spec/mesh.traversal.sequencer.md @@ -0,0 +1,62 @@ + +## Mesh Traversal Sequencer + +### GenerateSequenceInternal() + +~~~~~ +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() + +~~~~~ +ProcessCorner(corner_id) { + traverser_.TraverseFromCorner(corner_id); +} +~~~~~ + + +### UpdatePointToAttributeIndexMapping() + +~~~~~ +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() + +~~~~~ +AddPointId(point_id) { + out_point_ids_->push_back(point_id); +} +~~~~~ diff --git a/docs/spec/prediction.scheme.transform.md b/docs/spec/prediction.scheme.transform.md new file mode 100644 index 0000000..1745e27 --- /dev/null +++ b/docs/spec/prediction.scheme.transform.md @@ -0,0 +1,14 @@ + +## Prediction Scheme Transform + +### ComputeOriginalValue() + +~~~~~ +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]; + } +} +~~~~~ diff --git a/docs/spec/prediction.scheme.wrap.transform.md b/docs/spec/prediction.scheme.wrap.transform.md new file mode 100644 index 0000000..e742adb --- /dev/null +++ b/docs/spec/prediction.scheme.wrap.transform.md @@ -0,0 +1,43 @@ + +## Prediction Scheme Wrap Transform + +### DecodeTransformData() + +~~~~~ +DecodeTransformData(buffer) { + min_value_ DT + max_value_ DT +} +~~~~~ + + +### ComputeOriginalValue() + +~~~~~ +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() + +~~~~~ +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]; +} +~~~~~ diff --git a/docs/spec/rans.bit.decoder.md b/docs/spec/rans.bit.decoder.md new file mode 100644 index 0000000..17bb373 --- /dev/null +++ b/docs/spec/rans.bit.decoder.md @@ -0,0 +1,23 @@ + +## Rans Bit Decoder + +### RansBitDecoder_StartDecoding() + +~~~~~ +RansBitDecoder_StartDecoding(DecoderBuffer *source_buffer) { + prob_zero_ UI8 + size UI32 + buffer_ size * UI8 + ans_read_init(&ans_decoder_, buffer_, size) +} +~~~~~ + + +### DecodeNextBit() + +~~~~~ +DecodeNextBit() { + uint8_t bit = rabs_desc_read(&ans_decoder_, prob_zero_); + return bit > 0; +} +~~~~~ diff --git a/docs/spec/rans.decoding.md b/docs/spec/rans.decoding.md new file mode 100644 index 0000000..358d506 --- /dev/null +++ b/docs/spec/rans.decoding.md @@ -0,0 +1,120 @@ + +## Rans Decoding + +### ans_read_init() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +fetch_sym() { + symbol = lut_table[rem] + out->val = symbol + out->prob = probability_table_[symbol].prob; + out->cum_prob = probability_table_[symbol].cum_prob; +} +~~~~~ diff --git a/docs/spec/sequential.attribute.decoder.md b/docs/spec/sequential.attribute.decoder.md new file mode 100644 index 0000000..1461087 --- /dev/null +++ b/docs/spec/sequential.attribute.decoder.md @@ -0,0 +1,26 @@ + +## Sequential Attribute Decoder + +~~~~~ +Initialize(...) { + // Init some members +} +~~~~~ + + +### DecodeValues() + +~~~~~ +DecodeValues(const std::vector &point_ids) { + num_values = point_ids.size(); + entry_size = attribute_->byte_stride(); + std::unique_ptr 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; + } +} +~~~~~ + diff --git a/docs/spec/sequential.attributes.decoders.controller.md b/docs/spec/sequential.attributes.decoders.controller.md new file mode 100644 index 0000000..fc7115f --- /dev/null +++ b/docs/spec/sequential.attributes.decoders.controller.md @@ -0,0 +1,52 @@ + +## Sequential Attributes Decoders Controller + +### DecodeAttributesDecoderData() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +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() + } +} +~~~~~ + diff --git a/docs/spec/sequential.integer.attribute.decoder.md b/docs/spec/sequential.integer.attribute.decoder.md new file mode 100644 index 0000000..211007d --- /dev/null +++ b/docs/spec/sequential.integer.attribute.decoder.md @@ -0,0 +1,52 @@ + +## Sequential Integer Attribute Decoder + +~~~~~ +Initialize(...) { + SequentialAttributeDecoder_Initialize() +} +~~~~~ + + +### DecodeValues() + +~~~~~ +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() + +~~~~~ +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() +} +~~~~~ + diff --git a/docs/spec/sequential.quantization.attribute.decoder.md b/docs/spec/sequential.quantization.attribute.decoder.md new file mode 100644 index 0000000..0653cdc --- /dev/null +++ b/docs/spec/sequential.quantization.attribute.decoder.md @@ -0,0 +1,46 @@ + +## Sequential Quantization Attribute Decoder + +~~~~~ +Initialize(...) { + SequentialIntegerAttributeDecoder_Initialize() +} +~~~~~ + + +### DecodeIntegerValues() + +~~~~~ +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() + +~~~~~ +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; + } +} +~~~~~ diff --git a/docs/spec/symbol.decoding.md b/docs/spec/symbol.decoding.md new file mode 100644 index 0000000..2c71d1c --- /dev/null +++ b/docs/spec/symbol.decoding.md @@ -0,0 +1,105 @@ + +## Symbol Decoding + +### DecodeSymbols() + +~~~~~ +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() + +~~~~~ +DecodeTaggedSymbols() { + FIXME +} +~~~~~ + + + +### DecodeRawSymbols() + +~~~~~ +DecodeRawSymbols() { + max_bit_length UI8 + DecodeRawSymbolsInternal(max_bit_length, out_values) + return symbols +} +~~~~~ + + + +### DecodeRawSymbolsInternal() + +~~~~~ +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() + +~~~~~ +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() + +~~~~~ +RansSymbolDecoder_StartDecoding() { + bytes_encoded UI64 + buffer bytes_encoded * UI8 + rans_read_init(buffer, bytes_encoded) +} +~~~~~ + + + +### RansSymbolDecoder_DecodeSymbol() + +~~~~~ +RansSymbolDecoder_DecodeSymbol() { + ans_.rans_read() +} +~~~~~