Commit 5ba7ae5a authored by hybrid's avatar hybrid

Fix rotationFromTo as suggested by AgentD, using the from vector instead of...

Fix rotationFromTo as suggested by AgentD, using the from vector instead of the current values from the quaternion. After all, this quaternion has nothing to do with from or to so far, so the values contained there are rather arbitrary. Moreover, I'm normalizing the quaternion before returning it, as it is a rotation quaternion, which should be a unit quat. Test cases are also extended. For now only in trunk, may be backported after further testing.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3905 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 059af8ca
......@@ -648,24 +648,20 @@ inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const
else if (d <= -1.0f) // exactly opposite
{
core::vector3df axis(1.0f, 0.f, 0.f);
axis = axis.crossProduct(core::vector3df(X,Y,Z));
axis = axis.crossProduct(v0);
if (axis.getLength()==0)
{
axis.set(0.f,1.f,0.f);
axis.crossProduct(core::vector3df(X,Y,Z));
axis.crossProduct(v0);
}
return this->fromAngleAxis(core::PI, axis);
// same as fromAngleAxis(core::PI, axis).normalize();
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;
X = c.X;
Y = c.Y;
Z = c.Z;
W = s * 0.5f;
return *this;
return set(c.X, c.Y, c.Z, s * 0.5f).normalize();
}
......
......@@ -32,7 +32,7 @@ inline bool compareQ(const core::vector3df& v, const core::vector3df& turn=core:
return true;
}
core::vector3df vals[] = {
const core::vector3df vals[] = {
core::vector3df(0.f, 0.f, 0.f),
core::vector3df(0.f, 0.f, 24.04f),
core::vector3df(0.f, 0.f, 71.f),
......@@ -100,39 +100,52 @@ bool testEulerConversion()
bool testRotationFromTo()
{
bool result = true;
core::quaternion q1;
core::matrix4 mat;
core::quaternion q4(mat);
core::quaternion q;
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(1.f,0.f,0.f));
if (q4 != q1)
q.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(1.f,0.f,0.f));
if (q != core::quaternion())
{
logTestString("Quaternion rotationFromTo method did not yield identity.\n");
result = false;
}
q1.set(0.f,0.f,core::PI);
core::quaternion q2(0.f,core::PI,0.f);
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(-1.f,0.f,0.f));
if ((q4 != q1)&&(q4 != q2))
core::vector3df from(1.f,0.f,0.f);
q.rotationFromTo(from, core::vector3df(-1.f,0.f,0.f));
from=q*from;
if (from != core::vector3df(-1.f,0.f,0.f))
{
logTestString("Quaternion rotationFromTo method did not yield x flip.\n");
result = false;
}
q4.rotationFromTo(core::vector3df(10.f,20.f,30.f), core::vector3df(-10.f,-20.f,-30.f));
if ((q4 != q1)&&(q4 != q2))
from.set(1.f,2.f,3.f);
q.rotationFromTo(from, core::vector3df(-1.f,-2.f,-3.f));
from=q*from;
if (from != core::vector3df(-1.f,-2.f,-3.f))
{
logTestString("Quaternion rotationFromTo method did not yield x flip for non-axis.\n");
result = false;
}
q1.set(0.f,0.f,core::PI/2);
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(0.f,1.f,0.f));
if (!q4.equals(q1))
from.set(1.f,0.f,0.f);
q.rotationFromTo(from, core::vector3df(0.f,1.f,0.f));
from=q*from;
if (from != core::vector3df(0.f,1.f,0.f))
{
logTestString("Quaternion rotationFromTo method did not yield 90 degree rotation.\n");
result = false;
}
for (u32 i=1; i<sizeof(vals)/sizeof(vals[0])-1; ++i)
{
from.set(vals[i]).normalize();
core::vector3df to(vals[i+1]);
to.normalize();
q.rotationFromTo(from, to);
from = q*from;
result &= (from.equals(to, 0.00012f));
}
return result;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment