summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 57d5e8253..e6cccebf6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -182,19 +182,22 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
182RasterizerOpenGL::~RasterizerOpenGL() {} 182RasterizerOpenGL::~RasterizerOpenGL() {}
183 183
184/** 184/**
185 * This is a helper function to resolve an issue with opposite quaternions being interpolated by 185 * This is a helper function to resolve an issue when interpolating opposite quaternions. See below
186 * OpenGL. See below for a detailed description of this issue (yuriks): 186 * for a detailed description of this issue (yuriks):
187 * 187 *
188 * For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you 188 * For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you
189 * interpolate two quaternions that are opposite, instead of going from one rotation to another 189 * interpolate two quaternions that are opposite, instead of going from one rotation to another
190 * using the shortest path, you'll go around the longest path. You can test if two quaternions are 190 * using the shortest path, you'll go around the longest path. You can test if two quaternions are
191 * opposite by checking if Dot(Q1, W2) < 0. In that case, you can flip either of them, therefore 191 * opposite by checking if Dot(Q1, Q2) < 0. In that case, you can flip either of them, therefore
192 * making Dot(-Q1, W2) positive. 192 * making Dot(Q1, -Q2) positive.
193 * 193 *
194 * NOTE: This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This 194 * This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This is
195 * should be correct for nearly all cases, however a more correct implementation (but less trivial 195 * correct for most cases but can still rotate around the long way sometimes. An implementation
196 * and perhaps unnecessary) would be to handle this per-fragment, by interpolating the quaternions 196 * which did `lerp(lerp(Q1, Q2), Q3)` (with proper weighting), applying the dot product check
197 * manually using two Lerps, and doing this correction before each Lerp. 197 * between each step would work for those cases at the cost of being more complex to implement.
198 *
199 * Fortunately however, the 3DS hardware happens to also use this exact same logic to work around
200 * these issues, making this basic implementation actually more accurate to the hardware.
198 */ 201 */
199static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) { 202static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) {
200 Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()}; 203 Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()};