-
Notifications
You must be signed in to change notification settings - Fork 67
New quaternion in HLSL #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…rm variants for lerp/flerp
include/nbl/builtin/hlsl/math/linalg/matrix_runtime_traits.hlsl
Outdated
Show resolved
Hide resolved
include/nbl/builtin/hlsl/math/linalg/matrix_runtime_traits.hlsl
Outdated
Show resolved
Hide resolved
include/nbl/builtin/hlsl/math/linalg/matrix_runtime_traits.hlsl
Outdated
Show resolved
Hide resolved
| assert(hlsl::length(start.data) == scalar_type(1.0)); | ||
| assert(hlsl::length(end.data) == scalar_type(1.0)); | ||
| // TODO: benchmark uint sign flip vs just *sign(totalPseudoAngle) | ||
| const data_type adjEnd = ieee754::flipSignIfRHSNegative<data_type>(end.data, hlsl::promote<data_type>(totalPseudoAngle)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, the promotion makes this expensive, you need to change the signature to
template <typename T, typename U=T>
NBL_CONSTEXPR_FUNC T flipSignIfRHSNegative(T val, U flip)and then add a partial specialization of flipSignIfRHSNegative_helper<Vectorial,typename vertor_traits<Vectorial>::scalar_type>
which does
using traits_v = hlsl::vector_traits<Vectorial>;
using scalar_t = typename traits_v::scalar_type;
using AsUint = typename unsigned_integer_of_size<sizeof(FloatingPoint)>::type;
const AsUint signFlipBit = ieee754::traits<scalar_t>::signMask & ieee754::impl::bitCastToUintType(flip);
Vectorial output;
array_get<Vectorial, scalar_t> getter_v;
for (uint32_t i = 0; i < traits_v::Dimension; ++i)
setter(output,i, ieee754::impl::bitCastToUintType(getter_v(val,i))^signFlipBit );There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw the comment about benchmark is no longer applicable, I realized that when totalPseudoAngle = 0 you have two different quaternions you can still interpolate between by a fraction which when normalized will produce a valid quaternion
(there's two 4D directions which are orthogonal, the resulting quaternion's data member is interpolated between them on shortest path / within a plane spanned by them, then after normalization its like interpolating on a 4D sphere great circle)
So we can't make the adjEnd = 0 in that case and code needs to stay as is, and all the above explanation needs to go in the comment instead of the TODO.
Btw there's a bit of a funny situation where we interpolate towards a different adjEnd when it dips slightly more than 90 degrees away from start in 4D space, thats correct but I don't yet have an understanding of why. My intuition tells me its because quaternions can represent 720 degree rotations and not just 360 due to half-angles being used in the definition, so its something to make the final rotation be performed "along the shortest path"
| this_t inverse() NBL_CONST_MEMBER_FUNC | ||
| { | ||
| this_t retval; | ||
| retval.data.xyz = -data.xyz; | ||
| retval.data.w = data.w; | ||
| return retval; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does HLSL not like the unary minus operator ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the unary operator, isn't it? Only the scalar component of the inverse isn't negated for a quaternion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean to have a this_t operator-() NBL_CONST_METHOD { instead of inverse()
even though HLSL can't overload resolve these operators for a -q call, you can still call them as q.operator-()
| static inline math::truncated_quaternion<T> __call(const math::truncated_quaternion<T> q) | ||
| { | ||
| assert(hlsl::length(q.data) == scalar_type(1.0)); | ||
|
|
||
| assert(testing::relativeApproxCompare(hlsl::length(q.data), scalar_type(1.0), scalar_type(1e-4))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong check, truncated should never be 1.0 (thats kinda the point, because it reconstructs w = 1-length(xyz), I have no clue how your tests passed in a Debug build (where asserts work)
Anyway I think that it makes no sense to have a normalize specialization for truncated quaternion. so can just delete the struct
| template<typename U=vector3_type, typename F=scalar_type NBL_FUNC_REQUIRES(is_same_v<vector3_type,U> && is_same_v<typename vector_traits<U>::scalar_type,F>) | ||
| static this_t create(const U axis, const F angle, const F uniformScale = F(1.0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just get rid of the F template argument, it will be much easier
| return q; | ||
| } | ||
|
|
||
| // applies rotation equivalent to 3x3 matrix in order of pitch * yaw * roll |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- do you mean
mul(pitch,mul(yaw,mul(roll,v)))ormul(roll,yaw,mul(pitch,v))) - around what axes https://math.stackexchange.com/questions/3526500/relating-pitch-roll-and-yaw-to-rotations-about-the-x-y-z-axis
The question is that "for our imaginary aircraft" which axis is pitch yaw roll
No description provided.