Merge pull request #2767 from yuriks/quaternion-flip-comment
OpenGL: Update comment on AreQuaternionsOpposite with new information
This commit is contained in:
		| @@ -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()}; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user