1
2## Attributes Decoder
3
4### ParseAttributeDecodersData()
5
6~~~~~
7void ParseAttributeDecodersData() {
8  num_attributes_decoders                                                             UI8
9  if (encoder_method == MESH_EDGEBREAKER_ENCODING) {
10    for (i = 0; i < num_attributes_decoders; ++i) {
11      att_dec_data_id[i]                                                              UI8
12      att_dec_decoder_type[i]                                                         UI8
13      att_dec_traversal_method[i]                                                     UI8
14    }
15  }
16  for (i = 0; i < num_attributes_decoders; ++i) {
17    att_dec_num_attributes[i]                                                         varUI32
18    for (j = 0; j < att_dec_num_attributes[i]; ++j) {
19      att_dec_att_type[i][j]                                                          UI8
20      att_dec_data_type[i][j]                                                         UI8
21      att_dec_num_components[i][j]                                                    UI8
22      att_dec_normalized[i][j]                                                        UI8
23      att_dec_unique_id[i][j]                                                         varUI32
24    }
25    for (j = 0; j < att_dec_num_attributes[i]; ++j) {
26      seq_att_dec_decoder_type[i][j]                                                  UI8
27    }
28  }
29}
30~~~~~
31{:.draco-syntax }
32
33
34### DecodeAttributeData()
35
36~~~~~
37void DecodeAttributeData() {
38  ParseAttributeDecodersData();
39  vertex_visited_point_ids.assign(num_attributes_decoders, 0);
40  curr_att_dec = 0;
41  if (encoder_method == MESH_EDGEBREAKER_ENCODING) {
42    DecodeAttributeSeams();
43    for (i = 0; i < num_encoded_vertices + num_encoded_split_symbols; ++i) {
44      if (is_vert_hole_[i]) {
45        UpdateVertexToCornerMap(i);
46      }
47    }
48    for (i = 1; i < num_attributes_decoders; ++i) {
49      curr_att_dec = i;
50      RecomputeVerticesInternal();
51    }
52    Attribute_AssignPointsToCorners();
53  }
54  for (i = 0; i < num_attributes_decoders; ++i) {
55    curr_att_dec = i;
56    is_face_visited_.assign(num_faces, false);
57    is_vertex_visited_.assign(num_faces * 3, false);
58    GenerateSequence();
59    if (encoder_method == MESH_EDGEBREAKER_ENCODING) {
60      UpdatePointToAttributeIndexMapping();
61    }
62  }
63  for (i = 0; i < num_attributes_decoders; ++i) {
64    for (j = 0; j < att_dec_num_attributes[i]; ++j) {
65      att_dec_num_values_to_decode[i][j] =
66          encoded_attribute_value_index_to_corner_map[i].size();
67    }
68  }
69  for (i = 0; i < num_attributes_decoders; ++i) {
70    curr_att_dec = i;
71    DecodePortableAttributes();
72    DecodeDataNeededByPortableTransforms();
73    TransformAttributesToOriginalFormat();
74  }
75}
76~~~~~
77{:.draco-syntax }
78
79
80### RecomputeVerticesInternal()
81
82~~~~~
83void RecomputeVerticesInternal() {
84  attr = curr_att_dec - 1;
85  num_new_vertices = 0;
86  attr_face_to_vertex.push_back(face_to_vertex);
87  corner_to_vertex_map_[curr_att_dec].assign(
88      attr_face_to_vertex[attr][0].size() * 3, -1);
89  for (v = 0; v < num_encoded_vertices + num_encoded_split_symbols; ++v) {
90    c = vertex_corners_[v];
91    if (c < 0)
92      continue;
93    first_vert_id = num_new_vertices++;
94    first_c = c;
95    if (IsVertexOnAttributeSeam(attr, v)) {
96      act_c = SwingLeft(curr_att_dec, first_c);
97      while (act_c >= 0) {
98        first_c = act_c;
99        act_c = SwingLeft(curr_att_dec, act_c);
100      }
101    }
102    corner_to_vertex_map_[curr_att_dec][first_c] = first_vert_id;
103    vertex_to_left_most_corner_map_[attr].push_back(first_c);
104    act_c = SwingRight(0, first_c);
105    while (act_c >= 0 && act_c != first_c) {
106      next_act_c = Next(act_c);
107      if (IsCornerOppositeToSeamEdge(next_act_c)) {
108        first_vert_id = num_new_vertices++;
109        vertex_to_left_most_corner_map_[attr].push_back(act_c);
110      }
111      corner_to_vertex_map_[curr_att_dec][act_c] = first_vert_id;
112      act_c = SwingRight(0, act_c);
113    }
114  }
115
116  for (i = 0; i < corner_to_vertex_map_[curr_att_dec].size(); i += 3) {
117    face = i / 3;
118    attr_face_to_vertex[attr][0][face] = corner_to_vertex_map_[curr_att_dec][i];
119    attr_face_to_vertex[attr][1][face] = corner_to_vertex_map_[curr_att_dec][i + 1];
120    attr_face_to_vertex[attr][2][face] = corner_to_vertex_map_[curr_att_dec][i + 2];
121  }
122}
123~~~~~
124{:.draco-syntax }
125
126
127### Attribute_AssignPointsToCorners()
128
129~~~~~
130void Attribute_AssignPointsToCorners() {
131  point_to_corner_map_count = 0;
132  for (v = 0; v < num_encoded_vertices + num_encoded_split_symbols; ++v) {
133    c = vertex_corners_[v];
134    if (c < 0)
135      continue;
136    deduplication_first_corner = c;
137    if (is_vert_hole_[v]) {
138      deduplication_first_corner = c;
139    } else {
140      for (i = 1; i < num_attributes_decoders; ++i) {
141        attr_id = i - 1;
142        if (!IsCornerOnAttributeSeam(0, attr_id, c))
143          continue;
144        vert_id = corner_to_vertex_map_[i][c];
145        act_c = SwingRight(0, c);
146        seam_found = false;
147        while (act_c != c) {
148          act_vert_id = corner_to_vertex_map_[i][act_c];
149          if (act_vert_id != vert_id) {
150            deduplication_first_corner = act_c;
151            seam_found = true;
152            break;
153          }
154          act_c = SwingRight(0, act_c);
155        }
156        if (seam_found)
157          break;
158      }
159    }
160
161    c = deduplication_first_corner;
162    corner_to_point_map[c] = point_to_corner_map_count++;
163    prev_c = c;
164    c = SwingRight(0, c);
165    while (c >= 0 && c != deduplication_first_corner) {
166      attribute_seam = false;
167      for (i = 1; i < num_attributes_decoders; ++i) {
168        vert_id = corner_to_vertex_map_[i][c];
169        prev_vert_id = corner_to_vertex_map_[i][prev_c];
170        if (vert_id != prev_vert_id) {
171          attribute_seam = true;
172          break;
173        }
174      }
175      if (attribute_seam) {
176        corner_to_point_map[c] = point_to_corner_map_count++;
177      } else {
178        corner_to_point_map[c] = corner_to_point_map[prev_c];
179      }
180      prev_c = c;
181      c = SwingRight(0, c);
182    }
183  }
184}
185~~~~~
186{:.draco-syntax }
187
188
189### SequentialGenerateSequence()
190
191~~~~~
192void SequentialGenerateSequence() {
193  for (i = 0; i < num_points; ++i) {
194    encoded_attribute_value_index_to_corner_map[curr_att_dec][i] = i;
195  }
196}
197~~~~~
198{:.draco-syntax }
199
200
201### EdgebreakerGenerateSequence()
202
203~~~~~
204void EdgebreakerGenerateSequence() {
205  if (att_dec_traversal_method[curr_att_dec] == MESH_TRAVERSAL_PREDICTION_DEGREE) {
206    prediction_degree_.assign(num_encoded_vertices + num_encoded_split_symbols, 0);
207  }
208  for (i = 0; i < num_faces; ++i) {
209    if (att_dec_traversal_method[curr_att_dec] == MESH_TRAVERSAL_DEPTH_FIRST) {
210      if (curr_att_dec == 0) {
211        EdgeBreakerTraverser_ProcessCorner(3 * i);
212      } else {
213        EdgeBreakerAttributeTraverser_ProcessCorner(3 * i);
214      }
215    } else {
216      PredictionDegree_TraverseFromCorner(3 * i);
217    }
218  }
219}
220~~~~~
221{:.draco-syntax }
222
223
224### GenerateSequence()
225
226~~~~~
227void GenerateSequence() {
228  if (encoder_method == MESH_EDGEBREAKER_ENCODING)
229    EdgebreakerGenerateSequence();
230  else
231    SequentialGenerateSequence();
232}
233~~~~~
234{:.draco-syntax }
235
236
237### UpdatePointToAttributeIndexMapping()
238
239~~~~~
240void UpdatePointToAttributeIndexMapping() {
241  indices_map_.assign(num_faces * 3, -1);
242  for (f = 0; f < num_faces; ++f) {
243    for (p = 0; p < 3; ++p) {
244      corner = (f * 3) + p;
245      point_id = corner_to_point_map[corner];
246      CornerToVerts(curr_att_dec, corner, &vert, &next, &prev);
247      att_entry_id =
248          vertex_to_encoded_attribute_value_index_map[curr_att_dec][vert];
249      indices_map_[point_id] = att_entry_id;
250    }
251  }
252}
253~~~~~
254{:.draco-syntax }
255
256
257### TransformAttributesToOriginalFormat_StoreValues()
258
259~~~~~
260void TransformAttributesToOriginalFormat_StoreValues() {
261  num_components = GetNumComponents();
262  num_values = att_dec_num_values_to_decode[curr_att_dec][curr_att];
263  portable_attribute_data = seq_int_att_dec_original_values[curr_att_dec][curr_att];
264  for (i = 0; i < num_values; ++i) {
265    for (c = 0; c < num_components; ++c) {
266      out_values.push_back(portable_attribute_data[(i * num_components) + c]);
267    }
268  }
269  seq_int_att_dec_dequantized_values[curr_att_dec][curr_att] = out_values;
270}
271~~~~~
272{:.draco-syntax }
273
274
275### TransformAttributesToOriginalFormat()
276
277~~~~~
278void TransformAttributesToOriginalFormat() {
279  for (i = 0; i < att_dec_num_attributes.back(); ++i) {
280    curr_att = i;
281    dec_type = seq_att_dec_decoder_type[curr_att_dec][curr_att];
282    if (dec_type == SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS) {
283      TransformAttributesToOriginalFormat_Normal();
284    } else if (dec_type == SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER) {
285      TransformAttributesToOriginalFormat_StoreValues();
286    } else {
287      SequentialQuantizationAttributeDecoder_DequantizeValues();
288    }
289  }
290}
291~~~~~
292{:.draco-syntax }
293