From 2bfe7506c24bb3cf6411efc7d291eab4831b93ea Mon Sep 17 00:00:00 2001 From: cutealien Date: Sun, 30 Jul 2023 16:34:24 +0000 Subject: [PATCH] Optimization in quaternion::rotationFromTo from Robert Eisele Turns out we can avoid a square root and a division. Patch comes even with proof: https://raw.org/proof/quaternion-from-two-vectors (I also tested it a while and indeed got same results) git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6511 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 1 + include/quaternion.h | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/changes.txt b/changes.txt index b1a31f9d..f10c1134 100644 --- a/changes.txt +++ b/changes.txt @@ -1,6 +1,7 @@ -------------------------- Changes in 1.9 (not yet released) +- Optimize quaternion::rotationFromTo. Thanks @Robert Eisele for patch and proof (https://raw.org/proof/quaternion-from-two-vectors) - Shader materials shows now how to pass material values. In 1.8 we could still use gl_FrontMaterial, but that is no longer supported in shaders - Get IMeshBuffer::append functions working for a few more cases and adapt interface so one can prevent the BoundingBox update. diff --git a/include/quaternion.h b/include/quaternion.h index 77a05995..863f073e 100644 --- a/include/quaternion.h +++ b/include/quaternion.h @@ -721,6 +721,8 @@ inline core::quaternion& quaternion::makeIdentity() inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const vector3df& to) { // Based on Stan Melax's article in Game Programming Gems + // Optimized by Robert Eisele: https://raw.org/proof/quaternion-from-two-vectors + // Copy, since cannot modify local vector3df v0 = from; vector3df v1 = to; @@ -745,10 +747,8 @@ inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const return set(axis.X, axis.Y, axis.Z, 0).normalize(); } - const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt - const f32 invs = 1.f / s; - const vector3df c = v0.crossProduct(v1)*invs; - return set(c.X, c.Y, c.Z, s * 0.5f).normalize(); + const vector3df c = v0.crossProduct(v1); + return set(c.X, c.Y, c.Z, 1 + d).normalize(); }