Quaternion rotation gives me oppostie z-value?

Started by
8 comments, last by takis 19 years, 1 month ago
Hello, If i rotate a point P around two points P1 and P2, I get the good x and y values, but the opposite z-value. Here is my psuedo code. I dont know what is wrong. I checked everything a 1000 times. I hope there is a quaternion specialist online. Vector3D axis=P2-P1; Quaternion q; q.setFromRotation(axis, angle); q.rotate(P); void Quaternion::setFromRotation(const Vector3D& axis, float angle) { float sin=sinf(angle*0.5f); m_vector.setXYZ(axis.getX()*sin, axis.getY()*sin, axis.getZ()*sin); m_scalar=cosf(angle*0.5f); normalize(); } Vector3D Quaternion::rotate(const Vector3D &src) { // v' = q * [0, v] * con(q) Quaternion v(src, 0.0f); Quaternion tmp; tmp=*this; tmp.conjugate(); v.product(v,tmp); tmp.product(*this,v); return tmp.m_vector; } Thx
Advertisement
You might post your conjugate and mult functions also, just to make sure they're right (unless you already know they're correct).

What axis are you using for testing? It's quite possible that the quaternion is rotating your vector in the opposite direction than you expect. If your test axis is [0 1 0], this might have the effect of negating z.

If instead you used [0 0 1] as your test axis, the z value shouldn't change at all, regardless of direction of rotation. So if your z is negated in that case, there may be something wrong with your other functions.

So, perhaps you could post those other two functions, and tell us what axis you're rotating around.
You are right. If i rotate around (0,0,1), it gives the correct z value.
How does it come that if you rotate around the (0,1,0) axis that you get negative z value. Even if i negate the angle for the rotation, it keeps giving the opposite z-value.
I use the quaternion class also for my arcball implementation and there the rotations are perfect.

In my application, i have to rotate a 3d point around the common edge of two polygons A and B.
So my rotation axis is defined by the difference of the two vertices that form that common edge. AxisRot=Vertex1-Vertex0. rotationangle=acos(dotproduct(A.normal, B.normal)).

Vector3D axis=p1-p0;
q.setFromRotation(axis, rotAngle);
Vector3D newp=q.rotate(p);

Quaternions are cool if they work properly :-)

Here are my other function:

void Quaternion::conjugate()
{
m_vector= -(m_vector);
}

void Quaternion::product(const Quaternion& q1, const Quaternion& q2)
{
m_scalar=q1.m_scalar*q2.m_scalar-Vector3D::dotProduct(q1.m_vector, q2.m_vector);

Vector3D cross;
cross.crossProduct(q1.m_vector, q2.m_vector);

m_vector=q2.m_vector*q1.m_scalar+q1.m_vector*q2.m_scalar+cross;

normalize();
}

Quote:How does it come that if you rotate around the (0,1,0) axis that you get negative z value. Even if i negate the angle for the rotation, it keeps giving the opposite z-value.
Negating the angle of rotation about axis [0 1 0] should result in either the x or z component of the rotated vector changing signs. So depending on the original vector and the angle of rotation, negating the angle could leave z unchanged and reverse the sign of x instead. So does x change signs when you negate the angle?

Perhaps you could give us a concrete example. Tell us what the axis and angle are, what the original vector is, and what the output vector is. Maybe give two or three different examples. That would make it easier to figure out what the problem is.
Quote:Original post by takis
So my rotation axis is defined by the difference of the two vertices that form that common edge. AxisRot=Vertex1-Vertex0. rotationangle=acos(dotproduct(A.normal, B.normal)).

Vector3D axis=p1-p0;


Are you sure your axis is normalized? Your setFromRotation() doesn't do that for you, and I guess your normalize() works on the full quaternion.
jyk, you are right. If i negate the angle, then x-value changes sign.
Hopely you guys can help me.

An example:

Vector3D p0(2,3,10);
Vector3D p1(2,4,10);
Vector3D p(-2, 2, 10);
Vector3D axis=p1-p0;
axis.normalize();

q.setFromRotation(axis, MY_PI);
Vector3D newp=q.rotate(p);

Result is: (2, 2, -10)
Quote:Original post by takis
An example:

Vector3D p0(2,3,10);
Vector3D p1(2,4,10);
Vector3D p(-2, 2, 10);
Vector3D axis=p1-p0;
axis.normalize();

q.setFromRotation(axis, MY_PI);
Vector3D newp=q.rotate(p);

Result is: (2, 2, -10)


This result is correct, but probably not what you want.
What you ask it to do is a rotation around the line with direction given by axis, *passing through (0,0,0)*. You probably want some translations to get a rotation around the line passing through p0 and p1...

Try this:

Vector3D newp=q.rotate(p - p0);
newp += p0;
The result is now : (6,2,10).

Shouldn't that be (2,2,10)?






Quote:Original post by takis
The result is now : (6,2,10).

Shouldn't that be (2,2,10)?


No, that seems correct. (If I have understood correctly what it is you want to do...)

Your vectors:

Vector3D p0(2,3,10);
Vector3D p1(2,4,10);
Vector3D p(-2, 2, 10);
Vector3D axis=p1-p0;

could all be translated by (-2, -3, -10) to give:

Vector3D p0(0,0,0);
Vector3D p1(0,1,0);
Vector3D p(-4, -1, 0);

When p is rotated by π around the y-axis it should become (4,-1,0).
Translating it back (by adding (2, 3, 10)), it becomes (6, 2, 10).
thank you very much. I think i understand it.
Instinctive (sorry dont know the english word for it) you would say that the correct result is (2,2,10).
I wanna thank everyone who have helped me with my quaternions ;)

Greetings
takis

This topic is closed to new replies.

Advertisement