Skip to content

Conversation

@keptsecret
Copy link
Contributor

No description provided.

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));
Copy link
Member

@devshgraphicsprogramming devshgraphicsprogramming Jan 13, 2026

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 );

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"

Comment on lines +306 to +312
this_t inverse() NBL_CONST_MEMBER_FUNC
{
this_t retval;
retval.data.xyz = -data.xyz;
retval.data.w = data.w;
return retval;
}

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 ?

Copy link
Contributor Author

@keptsecret keptsecret Jan 13, 2026

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.

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-()

Comment on lines 339 to 341
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)));

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

Comment on lines +55 to +56
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))

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. do you mean mul(pitch,mul(yaw,mul(roll,v))) or mul(roll,yaw,mul(pitch,v)))
  2. 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants