citra-emu
/
citra
Archived
1
0
Fork 0

OpenGL: Update comment on AreQuaternionsOpposite with new information

While debugging the software renderer implementation, it was noticed
that this is actually exactly what the hardware does, upgrading the
status of this "hack" to being a proper implementation. And there was
much rejoicing.
This commit is contained in:
Yuri Kunde Schlesner 2017-06-10 01:55:17 -07:00
parent 9a8a90b52b
commit ba01a8302a
1 changed files with 11 additions and 8 deletions

View File

@ -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()};