Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h')
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h133
1 files changed, 75 insertions, 58 deletions
diff --git a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
index 32e27c711e3..be5ee5b09e3 100644
--- a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
+++ b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
@@ -53,6 +53,7 @@ class OctahedronToolBox {
: quantization_bits_(-1),
max_quantized_value_(-1),
max_value_(-1),
+ dequantization_scale_(1.f),
center_value_(-1) {}
bool SetQuantizationBits(int32_t q) {
@@ -62,6 +63,7 @@ class OctahedronToolBox {
quantization_bits_ = q;
max_quantized_value_ = (1 << quantization_bits_) - 1;
max_value_ = max_quantized_value_ - 1;
+ dequantization_scale_ = 2.f / max_value_;
center_value_ = max_value_ / 2;
return true;
}
@@ -192,64 +194,11 @@ class OctahedronToolBox {
}
}
- // TODO(b/149328891): Change function to not use templates as |T| is only
- // float.
- template <typename T>
- void OctaherdalCoordsToUnitVector(T in_s, T in_t, T *out_vector) const {
- DRACO_DCHECK_GE(in_s, 0);
- DRACO_DCHECK_GE(in_t, 0);
- DRACO_DCHECK_LE(in_s, 1);
- DRACO_DCHECK_LE(in_t, 1);
- T s = in_s;
- T t = in_t;
- T spt = s + t;
- T smt = s - t;
- T x_sign = 1.0;
- if (spt >= 0.5 && spt <= 1.5 && smt >= -0.5 && smt <= 0.5) {
- // Right hemisphere. Don't do anything.
- } else {
- // Left hemisphere.
- x_sign = -1.0;
- if (spt <= 0.5) {
- s = 0.5 - in_t;
- t = 0.5 - in_s;
- } else if (spt >= 1.5) {
- s = 1.5 - in_t;
- t = 1.5 - in_s;
- } else if (smt <= -0.5) {
- s = in_t - 0.5;
- t = in_s + 0.5;
- } else {
- s = in_t + 0.5;
- t = in_s - 0.5;
- }
- spt = s + t;
- smt = s - t;
- }
- const T y = 2.0 * s - 1.0;
- const T z = 2.0 * t - 1.0;
- const T x = std::min(std::min(2.0 * spt - 1.0, 3.0 - 2.0 * spt),
- std::min(2.0 * smt + 1.0, 1.0 - 2.0 * smt)) *
- x_sign;
- // Normalize the computed vector.
- const T normSquared = x * x + y * y + z * z;
- if (normSquared < 1e-6) {
- out_vector[0] = 0;
- out_vector[1] = 0;
- out_vector[2] = 0;
- } else {
- const T d = 1.0 / std::sqrt(normSquared);
- out_vector[0] = x * d;
- out_vector[1] = y * d;
- out_vector[2] = z * d;
- }
- }
-
- template <typename T>
- void QuantizedOctaherdalCoordsToUnitVector(int32_t in_s, int32_t in_t,
- T *out_vector) const {
- T scale = 1.0 / static_cast<T>(max_value_);
- OctaherdalCoordsToUnitVector(in_s * scale, in_t * scale, out_vector);
+ inline void QuantizedOctahedralCoordsToUnitVector(int32_t in_s, int32_t in_t,
+ float *out_vector) const {
+ OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f,
+ in_t * dequantization_scale_ - 1.f,
+ out_vector);
}
// |s| and |t| are expected to be signed values.
@@ -333,9 +282,77 @@ class OctahedronToolBox {
int32_t center_value() const { return center_value_; }
private:
+ inline void OctahedralCoordsToUnitVector(float in_s_scaled, float in_t_scaled,
+ float *out_vector) const {
+ // Background about the encoding:
+ // A normal is encoded in a normalized space <s, t> depicted below. The
+ // encoding correponds to an octahedron that is unwrapped to a 2D plane.
+ // During encoding, a normal is projected to the surface of the octahedron
+ // and the projection is then unwrapped to the 2D plane. Decoding is the
+ // reverse of this process.
+ // All points in the central diamond are located on triangles on the
+ // right "hemisphere" of the octahedron while all points outside of the
+ // diamond are on the left hemisphere (basically, they would have to be
+ // wrapped along the diagonal edges to form the octahedron). The central
+ // point corresponds to the right most vertex of the octahedron and all
+ // corners of the plane correspond to the left most vertex of the
+ // octahedron.
+ //
+ // t
+ // ^ *-----*-----*
+ // | | /|\ |
+ // | / | \ |
+ // | / | \ |
+ // | / | \ |
+ // *-----*---- *
+ // | \ | / |
+ // | \ | / |
+ // | \ | / |
+ // | \|/ |
+ // *-----*-----* --> s
+
+ // Note that the input |in_s_scaled| and |in_t_scaled| are already scaled to
+ // <-1, 1> range. This way, the central point is at coordinate (0, 0).
+ float y = in_s_scaled;
+ float z = in_t_scaled;
+
+ // Remaining coordinate can be computed by projecting the (y, z) values onto
+ // the surface of the octahedron.
+ const float x = 1.f - std::abs(y) - std::abs(z);
+
+ // |x| is essentially a signed distance from the diagonal edges of the
+ // diamond shown on the figure above. It is positive for all points in the
+ // diamond (right hemisphere) and negative for all points outside the
+ // diamond (left hemisphere). For all points on the left hemisphere we need
+ // to update their (y, z) coordinates to account for the wrapping along
+ // the edges of the diamond.
+ float x_offset = -x;
+ x_offset = x_offset < 0 ? 0 : x_offset;
+
+ // This will do nothing for the points on the right hemisphere but it will
+ // mirror the (y, z) location along the nearest diagonal edge of the
+ // diamond.
+ y += y < 0 ? x_offset : -x_offset;
+ z += z < 0 ? x_offset : -x_offset;
+
+ // Normalize the computed vector.
+ const float norm_squared = x * x + y * y + z * z;
+ if (norm_squared < 1e-6) {
+ out_vector[0] = 0;
+ out_vector[1] = 0;
+ out_vector[2] = 0;
+ } else {
+ const float d = 1.0f / std::sqrt(norm_squared);
+ out_vector[0] = x * d;
+ out_vector[1] = y * d;
+ out_vector[2] = z * d;
+ }
+ }
+
int32_t quantization_bits_;
int32_t max_quantized_value_;
int32_t max_value_;
+ float dequantization_scale_;
int32_t center_value_;
};
} // namespace draco