mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-24 18:32:49 -06:00
Merge pull request #2767 from yuriks/quaternion-flip-comment
OpenGL: Update comment on AreQuaternionsOpposite with new information
This commit is contained in:
commit
791cd14c8d
1 changed files with 11 additions and 8 deletions
|
@ -182,19 +182,22 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
|
||||||
RasterizerOpenGL::~RasterizerOpenGL() {}
|
RasterizerOpenGL::~RasterizerOpenGL() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper function to resolve an issue with opposite quaternions being interpolated by
|
* This is a helper function to resolve an issue when interpolating opposite quaternions. See below
|
||||||
* OpenGL. See below for a detailed description of this issue (yuriks):
|
* for a detailed description of this issue (yuriks):
|
||||||
*
|
*
|
||||||
* For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you
|
* For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you
|
||||||
* interpolate two quaternions that are opposite, instead of going from one rotation to another
|
* interpolate two quaternions that are opposite, instead of going from one rotation to another
|
||||||
* using the shortest path, you'll go around the longest path. You can test if two quaternions are
|
* using the shortest path, you'll go around the longest path. You can test if two quaternions are
|
||||||
* opposite by checking if Dot(Q1, W2) < 0. In that case, you can flip either of them, therefore
|
* opposite by checking if Dot(Q1, Q2) < 0. In that case, you can flip either of them, therefore
|
||||||
* making Dot(-Q1, W2) positive.
|
* making Dot(Q1, -Q2) positive.
|
||||||
*
|
*
|
||||||
* NOTE: This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This
|
* This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This is
|
||||||
* should be correct for nearly all cases, however a more correct implementation (but less trivial
|
* correct for most cases but can still rotate around the long way sometimes. An implementation
|
||||||
* and perhaps unnecessary) would be to handle this per-fragment, by interpolating the quaternions
|
* which did `lerp(lerp(Q1, Q2), Q3)` (with proper weighting), applying the dot product check
|
||||||
* manually using two Lerps, and doing this correction before each Lerp.
|
* between each step would work for those cases at the cost of being more complex to implement.
|
||||||
|
*
|
||||||
|
* Fortunately however, the 3DS hardware happens to also use this exact same logic to work around
|
||||||
|
* these issues, making this basic implementation actually more accurate to the hardware.
|
||||||
*/
|
*/
|
||||||
static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) {
|
static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) {
|
||||||
Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()};
|
Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()};
|
||||||
|
|
Loading…
Reference in a new issue