WIP: eevee-next-world-irradiance #108304
|
@ -468,6 +468,40 @@ struct CartesianBasis {
|
|||
from_orthonormal_axes(b_forward, b_up));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline VecBase<T, 3> transform_point(const CartesianBasis &basis,
|
||||
const VecBase<T, 3> &v)
|
||||
{
|
||||
VecBase<T, 3> result;
|
||||
result[basis.x().axis().as_int()] = basis.x().is_negative() ? -v[0] : v[0];
|
||||
result[basis.y().axis().as_int()] = basis.y().is_negative() ? -v[1] : v[1];
|
||||
result[basis.z().axis().as_int()] = basis.z().is_negative() ? -v[2] : v[2];
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the inverse transformation represented by the given basis.
|
||||
* This is conceptually the equivalent to a rotation matrix transpose, but much faster.
|
||||
*/
|
||||
[[nodiscard]] inline CartesianBasis invert(const CartesianBasis &basis)
|
||||
{
|
||||
/* Returns the column where the `axis` is found in. The sign is taken from the axis value. */
|
||||
auto search_axis = [](const CartesianBasis &basis, const Axis axis) {
|
||||
if (basis.x().axis() == axis) {
|
||||
return basis.x().is_negative() ? AxisSigned::X_NEG : AxisSigned::X_POS;
|
||||
}
|
||||
if (basis.y().axis() == axis) {
|
||||
return basis.y().is_negative() ? AxisSigned::Y_NEG : AxisSigned::Y_POS;
|
||||
}
|
||||
return basis.z().is_negative() ? AxisSigned::Z_NEG : AxisSigned::Z_POS;
|
||||
};
|
||||
CartesianBasis result;
|
||||
result.x() = search_axis(basis, Axis::X);
|
||||
result.y() = search_axis(basis, Axis::Y);
|
||||
result.z() = search_axis(basis, Axis::Z);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::math
|
||||
|
|
|
@ -641,10 +641,9 @@ TEST(math_rotation, CartesianBasis)
|
|||
expect.ptr());
|
||||
}
|
||||
|
||||
EXPECT_EQ(from_rotation<float3x3>(
|
||||
rotation_between(from_orthonormal_axes(src_forward, src_up),
|
||||
from_orthonormal_axes(dst_forward, dst_up))),
|
||||
expect);
|
||||
CartesianBasis rotation = rotation_between(from_orthonormal_axes(src_forward, src_up),
|
||||
from_orthonormal_axes(dst_forward, dst_up));
|
||||
EXPECT_EQ(from_rotation<float3x3>(rotation), expect);
|
||||
|
||||
if (src_forward == dst_forward) {
|
||||
expect = float3x3::identity();
|
||||
|
@ -656,6 +655,11 @@ TEST(math_rotation, CartesianBasis)
|
|||
}
|
||||
|
||||
EXPECT_EQ(from_rotation<float3x3>(rotation_between(src_forward, dst_forward)), expect);
|
||||
|
||||
float3 point(1.0f, 2.0f, 3.0f);
|
||||
CartesianBasis rotation_inv = invert(rotation);
|
||||
/* Test inversion identity. */
|
||||
EXPECT_EQ(transform_point(rotation_inv, transform_point(rotation, point)), point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -667,8 +671,23 @@ TEST(math_rotation, Transform)
|
|||
Quaternion q(0.927091f, 0.211322f, -0.124857f, 0.283295f);
|
||||
|
||||
float3 p(0.576f, -0.6546f, 46.354f);
|
||||
p = transform_point(q, p);
|
||||
EXPECT_V3_NEAR(p, float3(-4.33722f, -21.661f, 40.7608f), 1e-4f);
|
||||
float3 result = transform_point(q, p);
|
||||
EXPECT_V3_NEAR(result, float3(-4.33722f, -21.661f, 40.7608f), 1e-4f);
|
||||
|
||||
/* Validated using `to_quaternion` before doing the transform. */
|
||||
float3 p2(1.0f, 2.0f, 3.0f);
|
||||
result = transform_point(CartesianBasis(AxisSigned::X_POS, AxisSigned::Y_POS, AxisSigned::Z_POS),
|
||||
p2);
|
||||
EXPECT_EQ(result, float3(1.0f, 2.0f, 3.0f));
|
||||
result = transform_point(
|
||||
rotation_between(from_orthonormal_axes(AxisSigned::Y_POS, AxisSigned::Z_POS),
|
||||
from_orthonormal_axes(AxisSigned::X_POS, AxisSigned::Z_POS)),
|
||||
p2);
|
||||
EXPECT_EQ(result, float3(-2.0f, 1.0f, 3.0f));
|
||||
result = transform_point(from_orthonormal_axes(AxisSigned::Z_POS, AxisSigned::X_POS), p2);
|
||||
EXPECT_EQ(result, float3(3.0f, 1.0f, 2.0f));
|
||||
result = transform_point(from_orthonormal_axes(AxisSigned::X_NEG, AxisSigned::Y_POS), p2);
|
||||
EXPECT_EQ(result, float3(-2.0f, 3.0f, -1.0f));
|
||||
}
|
||||
|
||||
TEST(math_rotation, DualQuaternionNormalize)
|
||||
|
|
Loading…
Reference in New Issue