mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-04-22 13:49:57 +08:00
191 lines
5.6 KiB
Markdown
191 lines
5.6 KiB
Markdown
## Normal Prediction Decoder
|
|
|
|
### GetPositionForDataId()
|
|
|
|
~~~~~
|
|
void GetPositionForDataId(data_id, pos) {
|
|
corner = encoded_attribute_value_index_to_corner_map[curr_att_dec][data_id];
|
|
point_id = corner_to_point_map[corner];
|
|
mapped_index = indices_map_[0][point_id];
|
|
pos_orig = seq_int_att_dec_original_values[0][0];
|
|
for (i = 0; i < 3; ++i) {
|
|
pos.push_back(pos_orig[(mapped_index * 3) + i]);
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### GetPositionForCorner()
|
|
|
|
~~~~~
|
|
void GetPositionForCorner(ci, pos) {
|
|
CornerToVerts(curr_att_dec, ci, &vert_id, &n, &p);
|
|
data_id = vertex_to_encoded_attribute_value_index_map[curr_att_dec][vert_id];
|
|
GetPositionForDataId(data_id, pos);
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### MeshPredictionSchemeGeometricNormalPredictorArea_ComputePredictedValue()
|
|
|
|
~~~~~
|
|
void MeshPredictionSchemeGeometricNormalPredictorArea_ComputePredictedValue(
|
|
corner_id, predicted_value_) {
|
|
GetPositionForCorner(corner_id, &pos_cent);
|
|
normal.assign(3, 0);
|
|
corner = corner_id;
|
|
start_corner_ = corner;
|
|
left_traversal_ = true;
|
|
while (corner >= 0) {
|
|
c_next = Next(corner);
|
|
c_prev = Previous(corner);
|
|
GetPositionForCorner(c_next, &pos_next);
|
|
GetPositionForCorner(c_prev, &pos_prev);
|
|
SubtractVectors(pos_next, pos_cent, &delta_next);
|
|
SubtractVectors(pos_prev, pos_cent, &delta_prev);
|
|
CrossProduct(delta_next, delta_prev, &cross);
|
|
AddVectors(normal, cross, &temp_norm);
|
|
for (i = 0; i < temp_norm.size(); ++i) {
|
|
normal[i] = temp_norm[i];
|
|
}
|
|
if (left_traversal_) {
|
|
left_c = SwingLeft(curr_att_dec, corner);
|
|
corner = left_c;
|
|
if (corner < 0) {
|
|
right_c = SwingRight(curr_att_dec, start_corner_);
|
|
corner = right_c;
|
|
left_traversal_ = false;
|
|
} else if (corner == start_corner_) {
|
|
corner = kInvalidCornerIndex;
|
|
}
|
|
} else {
|
|
right_c = SwingRight(curr_att_dec, corner);
|
|
corner = right_c;
|
|
}
|
|
}
|
|
AbsSum(normal, &abs_sum);
|
|
upper_bound = 1 << 29;
|
|
if (abs_sum > upper_bound) {
|
|
quotient = abs_sum / upper_bound;
|
|
DivideScalar(normal, quotient, &vec_div);
|
|
for (i = 0; i < vec_div.size(); ++i) {
|
|
normal[i] = vec_div[i];
|
|
}
|
|
}
|
|
predicted_value_[0] = normal[0];
|
|
predicted_value_[1] = normal[1];
|
|
predicted_value_[2] = normal[2];
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### CanonicalizeIntegerVector()
|
|
|
|
~~~~~
|
|
void CanonicalizeIntegerVector(vec, center_value_) {
|
|
abs_sum = Abs(vec[0]) + Abs(vec[1]) + Abs(vec[2]);
|
|
if (abs_sum == 0) {
|
|
vec[0] = center_value_;
|
|
} else {
|
|
vec[0] = (vec[0] * center_value_) / abs_sum;
|
|
vec[1] = (vec[1] * center_value_) / abs_sum;
|
|
if (vec[2] >= 0) {
|
|
vec[2] = center_value_ - Abs(vec[0]) - Abs(vec[1]);
|
|
} else {
|
|
vec[2] = -(center_value_ - Abs(vec[0]) - Abs(vec[1]));
|
|
}
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### CanonicalizeOctahedralCoords()
|
|
|
|
~~~~~
|
|
void CanonicalizeOctahedralCoords(s, t, out_s,
|
|
out_t, center_value_, max_value_) {
|
|
if ((s == 0 && t == 0) || (s == 0 && t == max_value_) ||
|
|
(s == max_value_ && t == 0)) {
|
|
s = max_value_;
|
|
t = max_value_;
|
|
} else if (s == 0 && t > center_value_) {
|
|
t = center_value_ - (t - center_value_);
|
|
} else if (s == max_value_ && t < center_value_) {
|
|
t = center_value_ + (center_value_ - t);
|
|
} else if (t == max_value_ && s < center_value_) {
|
|
s = center_value_ + (center_value_ - s);
|
|
} else if (t == 0 && s > center_value_) {
|
|
s = center_value_ - (s - center_value_);
|
|
}
|
|
out_s = s;
|
|
out_t = t;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### IntegerVectorToQuantizedOctahedralCoords()
|
|
|
|
~~~~~
|
|
void IntegerVectorToQuantizedOctahedralCoords(
|
|
int_vec, out_s, out_t, center_value_, max_value_) {
|
|
if (int_vec[0] >= 0) {
|
|
s = (int_vec[1] + center_value_);
|
|
t = (int_vec[2] + center_value_);
|
|
} else {
|
|
if (int_vec[1] < 0) {
|
|
s = Abs(int_vec[2]);
|
|
} else {
|
|
s = (max_value_ - Abs(int_vec[2]));
|
|
}
|
|
if (int_vec[2] < 0) {
|
|
t = Abs(int_vec[1]);
|
|
} else {
|
|
t = (max_value_ - Abs(int_vec[1]));
|
|
}
|
|
}
|
|
CanonicalizeOctahedralCoords(s, t, out_s, out_t, center_value_, max_value_);
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|
|
|
|
|
|
### MeshPredictionSchemeGeometricNormalDecoder_ComputeOriginalValues()
|
|
|
|
~~~~~
|
|
void MeshPredictionSchemeGeometricNormalDecoder_ComputeOriginalValues(num_values) {
|
|
signed_values = seq_int_att_dec_symbols_to_signed_ints[curr_att_dec][curr_att];
|
|
encoded_max_quantized_value =
|
|
pred_trasnform_normal_max_q_val[curr_att_dec][curr_att];
|
|
quantization_bits_ = MostSignificantBit(encoded_max_quantized_value) + 1;
|
|
max_quantized_value_ = (1 << quantization_bits_) - 1;
|
|
max_value_ = max_quantized_value_ - 1;
|
|
center_value_ = max_value_ / 2;
|
|
corner_map_size = num_values;
|
|
flip_normal_bits = pred_transform_normal_flip_normal_bits[curr_att_dec][curr_att];
|
|
out_values = signed_values;
|
|
for (data_id = 0; data_id < corner_map_size; ++data_id) {
|
|
corner_id = encoded_attribute_value_index_to_corner_map[curr_att_dec][data_id];
|
|
MeshPredictionSchemeGeometricNormalPredictorArea_ComputePredictedValue(
|
|
corner_id, &pred_normal_3d);
|
|
CanonicalizeIntegerVector(pred_normal_3d, center_value_);
|
|
if (flip_normal_bits[data_id]) {
|
|
for (i = 0; i < pred_normal_3d.size(); ++i) {
|
|
pred_normal_3d[i] = -pred_normal_3d[i];
|
|
}
|
|
}
|
|
IntegerVectorToQuantizedOctahedralCoords(&pred_normal_3d[0],
|
|
&pred_normal_oct[0], &pred_normal_oct[1], center_value_, max_value_);
|
|
data_offset = data_id * 2;
|
|
PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform_ComputeOriginalValue(
|
|
&pred_normal_oct[0], &out_values[data_offset], &out_values[data_offset]);
|
|
}
|
|
seq_int_att_dec_original_values[curr_att_dec][curr_att] = out_values;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax}
|