mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-06-04 11:25:44 +08:00
12 KiB
12 KiB
EdgeBreaker Decoder
ParseEdgebreakerConnectivityData()
void ParseEdgebreakerConnectivityData() {
edgebreaker_traversal_type UI8
num_encoded_vertices varUI32
num_faces varUI32
num_attribute_data UI8
num_encoded_symbols varUI32
num_encoded_split_symbols varUI32
}
{:.draco-syntax }
ParseTopologySplitEvents()
void ParseTopologySplitEvents() {
num_topology_splits varUI32
for (i = 0; i < num_topology_splits; ++i) {
source_id_delta[i] varUI32
split_id_delta[i] varUI32
}
for (i = 0; i < num_topology_splits; ++i) {
source_edge_bit[i] f[1]
}
ResetBitReader();
}
{:.draco-syntax }
DecodeEdgebreakerConnectivityData()
void DecodeEdgebreakerConnectivityData() {
curr_att_dec = 0;
curr_att = 0;
ParseEdgebreakerConnectivityData();
DecodeTopologySplitEvents();
EdgebreakerTraversalStart();
DecodeEdgeBreakerConnectivity();
}
{:.draco-syntax }
GetNumComponents()
int GetNumComponents() {
decoder_type = seq_att_dec_decoder_type[curr_att_dec][curr_att];
if (decoder_type == SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS) {
prediction_scheme = seq_att_dec_prediction_scheme[curr_att_dec][curr_att];
if (prediction_scheme == PREDICTION_DIFFERENCE) {
return 2;
}
}
return att_dec_num_components[curr_att_dec][curr_att];
}
{:.draco-syntax }
ProcessSplitData()
void ProcessSplitData() {
last_id = 0;
for (i = 0; i < source_id_delta.size(); ++i) {
source_symbol_id[i] = source_id_delta[i] + last_id;
split_symbol_id[i] = source_symbol_id[i] - split_id_delta[i];
last_id = source_symbol_id[i];
}
}
{:.draco-syntax }
DecodeTopologySplitEvents()
void DecodeTopologySplitEvents() {
ParseTopologySplitEvents();
ProcessSplitData();
}
{:.draco-syntax }
IsTopologySplit()
bool IsTopologySplit(encoder_symbol_id, out_face_edge,
out_encoder_split_symbol_id) {
if (source_symbol_id.back() != encoder_symbol_id)
return false;
out_face_edge = source_edge_bit.pop_back();
out_encoder_split_symbol_id = split_symbol_id.pop_back();
source_symbol_id.pop_back();
return true;
}
{:.draco-syntax }
ReplaceVerts()
void ReplaceVerts(from, to) {
for (i = 0; i < face_to_vertex[0].size(); ++i) {
if (face_to_vertex[0][i] == from) {
face_to_vertex[0][i] = to;
}
if (face_to_vertex[1][i] == from) {
face_to_vertex[1][i] = to;
}
if (face_to_vertex[2][i] == from) {
face_to_vertex[2][i] = to;
}
}
}
{:.draco-syntax }
UpdateCornersAfterMerge()
void UpdateCornersAfterMerge(c, v) {
opp_corner = PosOpposite(c);
if (opp_corner >= 0) {
corner_n = Next(opp_corner);
while (corner_n >= 0) {
MapCornerToVertex(corner_n, v);
corner_n = SwingLeft(0, corner_n);
}
}
}
{:.draco-syntax }
NewActiveCornerReached()
void NewActiveCornerReached(new_corner, symbol_id) {
check_topology_split = false;
switch (last_symbol_) {
case TOPOLOGY_C:
{
corner_a = active_corner_stack.back();
corner_b = Previous(corner_a);
while (PosOpposite(corner_b) >= 0) {
b_opp = PosOpposite(corner_b);
corner_b = Previous(b_opp);
}
SetOppositeCorners(corner_a, new_corner + 1);
SetOppositeCorners(corner_b, new_corner + 2);
active_corner_stack.back() = new_corner;
}
vert = CornerToVert(curr_att_dec, Next(corner_a));
next = CornerToVert(curr_att_dec, Next(corner_b));
prev = CornerToVert(curr_att_dec, Previous(corner_a));
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[next] += 1;
vertex_valences_[prev] += 1;
}
face_to_vertex[0].push_back(vert);
face_to_vertex[1].push_back(next);
face_to_vertex[2].push_back(prev);
is_vert_hole_[vert] = false;
MapCornerToVertex(new_corner, vert);
MapCornerToVertex(new_corner + 1, next);
MapCornerToVertex(new_corner + 2, prev);
break;
case TOPOLOGY_S:
{
corner_b = active_corner_stack.pop_back();
for (i = 0; i < topology_split_id.size(); ++i) {
if (topology_split_id[i] == symbol_id) {
active_corner_stack.push_back(split_active_corners[i]);
}
}
corner_a = active_corner_stack.back();
SetOppositeCorners(corner_a, new_corner + 2);
SetOppositeCorners(corner_b, new_corner + 1);
active_corner_stack.back() = new_corner;
}
vert = CornerToVert(curr_att_dec, Previous(corner_a));
next = CornerToVert(curr_att_dec, Next(corner_a));
prev = CornerToVert(curr_att_dec, Previous(corner_b));
MapCornerToVertex(new_corner, vert);
MapCornerToVertex(new_corner + 1, next);
MapCornerToVertex(new_corner + 2, prev);
corner_n = Next(corner_b);
vertex_n = CornerToVert(curr_att_dec, corner_n);
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[vert] += vertex_valences_[vertex_n];
}
ReplaceVerts(vertex_n, vert);
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[next] += 1;
vertex_valences_[prev] += 1;
}
face_to_vertex[0].push_back(vert);
face_to_vertex[1].push_back(next);
face_to_vertex[2].push_back(prev);
UpdateCornersAfterMerge(new_corner + 1, vert);
vertex_corners_[vertex_n] = kInvalidCornerIndex;
break;
case TOPOLOGY_R:
{
corner_a = active_corner_stack.back();
opp_corner = new_corner + 2;
SetOppositeCorners(opp_corner, corner_a);
active_corner_stack.back() = new_corner;
}
check_topology_split = true;
vert = CornerToVert(curr_att_dec, Previous(corner_a));
next = CornerToVert(curr_att_dec, Next(corner_a));
prev = ++last_vert_added;
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[vert] += 1;
vertex_valences_[next] += 1;
vertex_valences_[prev] += 2;
}
face_to_vertex[0].push_back(vert);
face_to_vertex[1].push_back(next);
face_to_vertex[2].push_back(prev);
MapCornerToVertex(new_corner + 2, prev);
MapCornerToVertex(new_corner, vert);
MapCornerToVertex(new_corner + 1, next);
break;
case TOPOLOGY_L:
{
corner_a = active_corner_stack.back();
opp_corner = new_corner + 1;
SetOppositeCorners(opp_corner, corner_a);
active_corner_stack.back() = new_corner;
}
check_topology_split = true;
vert = CornerToVert(curr_att_dec, Next(corner_a));
next = ++last_vert_added;
prev = CornerToVert(curr_att_dec, Previous(corner_a));
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[vert] += 1;
vertex_valences_[next] += 2;
vertex_valences_[prev] += 1;
}
face_to_vertex[0].push_back(vert);
face_to_vertex[1].push_back(next);
face_to_vertex[2].push_back(prev);
MapCornerToVertex(new_corner + 2, prev);
MapCornerToVertex(new_corner, vert);
MapCornerToVertex(new_corner + 1, next);
break;
case TOPOLOGY_E:
active_corner_stack.push_back(new_corner);
check_topology_split = true;
vert = last_vert_added + 1;
next = vert + 1;
prev = next + 1;
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
vertex_valences_[vert] += 2;
vertex_valences_[next] += 2;
vertex_valences_[prev] += 2;
}
face_to_vertex[0].push_back(vert);
face_to_vertex[1].push_back(next);
face_to_vertex[2].push_back(prev);
last_vert_added = prev;
MapCornerToVertex(new_corner, vert);
MapCornerToVertex(new_corner + 1, next);
MapCornerToVertex(new_corner + 2, prev);
break;
}
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
// Compute the new context that is going to be used
// to decode the next symbol.
active_valence = vertex_valences_[next];
if (active_valence < MIN_VALENCE) {
clamped_valence = MIN_VALENCE;
} else if (active_valence > MAX_VALENCE) {
clamped_valence = MAX_VALENCE;
} else {
clamped_valence = active_valence;
}
active_context_ = (clamped_valence - MIN_VALENCE);
}
if (check_topology_split) {
encoder_symbol_id = num_encoded_symbols - symbol_id - 1;
while (IsTopologySplit(encoder_symbol_id, &split_edge,
&enc_split_id)) {
act_top_corner = active_corner_stack.back();
if (split_edge == RIGHT_FACE_EDGE) {
new_active_corner = Next(act_top_corner);
} else {
new_active_corner = Previous(act_top_corner);
}
// Convert the encoder split symbol id to decoder symbol id.
dec_split_id = num_encoded_symbols - enc_split_id - 1;
topology_split_id.push_back(dec_split_id);
split_active_corners.push_back(new_active_corner);
}
}
}
{:.draco-syntax }
ParseEdgebreakerStandardSymbol()
void ParseEdgebreakerStandardSymbol() {
symbol = eb_symbol_buffer.ReadBits(1);
if (symbol != TOPOLOGY_C) {
// Else decode two additional bits.
symbol_suffix = eb_symbol_buffer.ReadBits(2);
symbol |= (symbol_suffix << 1);
}
last_symbol_ = symbol;
}
{:.draco-syntax }
EdgebreakerDecodeSymbol()
void EdgebreakerDecodeSymbol() {
if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
EdgebreakerValenceDecodeSymbol();
} else if (edgebreaker_traversal_type == STANDARD_EDGEBREAKER) {
ParseEdgebreakerStandardSymbol();
}
}
{:.draco-syntax }
DecodeEdgeBreakerConnectivity()
void DecodeEdgeBreakerConnectivity() {
is_vert_hole_.assign(num_encoded_vertices + num_encoded_split_symbols, true);
last_vert_added = -1;
for (i = 0; i < num_encoded_symbols; ++i) {
EdgebreakerDecodeSymbol();
corner = 3 * i;
NewActiveCornerReached(corner, i);
}
ProcessInteriorEdges();
}
{:.draco-syntax }
ProcessInteriorEdges()
void ProcessInteriorEdges() {
RansInitDecoder(ans_decoder_, eb_start_face_buffer,
eb_start_face_buffer_size, L_RANS_BASE);
while (active_corner_stack.size() > 0) {
corner_a = active_corner_stack.pop_back();
RabsDescRead(ans_decoder_,
eb_start_face_buffer_prob_zero, &interior_face);
if (interior_face) {
corner_b = Previous(corner_a);
while (PosOpposite(corner_b) >= 0) {
b_opp = PosOpposite(corner_b);
corner_b = Previous(b_opp);
}
corner_c = Next(corner_a);
while (PosOpposite(corner_c) >= 0) {
c_opp = PosOpposite(corner_c);
corner_c = Next(c_opp);
}
new_corner = face_to_vertex[0].size() * 3;
SetOppositeCorners(new_corner, corner_a);
SetOppositeCorners(new_corner + 1, corner_b);
SetOppositeCorners(new_corner + 2, corner_c);
CornerToVerts(0, corner_a, &temp_v, &next_a, &temp_p);
CornerToVerts(0, corner_b, &temp_v, &next_b, &temp_p);
CornerToVerts(0, corner_c, &temp_v, &next_c, &temp_p);
MapCornerToVertex(new_corner, next_b);
MapCornerToVertex(new_corner + 1, next_c);
MapCornerToVertex(new_corner + 2, next_a);
face_to_vertex[0].push_back(next_b);
face_to_vertex[1].push_back(next_c);
face_to_vertex[2].push_back(next_a);
// Mark all three vertices as interior.
is_vert_hole_[next_b] = false;
is_vert_hole_[next_c] = false;
is_vert_hole_[next_a] = false;
}
}
}
{:.draco-syntax }