Rotating object

Hi,

How would i rotate an object always that way i’m looking at it?

Example: dice

3
1265
4

^y
|
±>x

We are looking at 1 (so right of it is the 2, left the 5, behind 6, upside 3, downside 4)
And when i press my mouse move from left to right, i want to see the 5. When moving the mouse upside down i want the 3,…

That’s no problem this code can do it:

void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
{
	if (m_mouse.left)
	{
		// get the difference between last press and now
		QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;

		// update the new position
		m_mouse.position = QVector2D(e->localPos());

		// calculate the rotation axis and rotate
		QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();
		m_rotation *= QQuaternion::fromAxisAndAngle(rotationAxis * 0.75, diff.length());

		// request an update
		update();
	}
}

But the problem is, when i rotate the model in y direction (upside down) 180° (you can see the 6 upside down) and then i move the mouse from left to right, it rotates in the opposite direction it should move.

Any help about how to fix that??

As you can see in the following link:

http://quaternions.online

When you rotate a quaternion the sign change for every turn around the rotation’s axis.

m_rotation *= QQuaternion::fromAxisAndAngle(rotationAxis * 0.75, diff.length());

Always work with normalized vectors! That * 0.75, remove it.

Also this: QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();

Why are you doing it like that? Take a look at this:

Rotate UP FRONT: Quaternion(Vector3(1,0,0), ToRadians(90))
Rotate UP SIDE: Quaternion(Vector3(0,0,1), ToRadians(90))
Rotate DOWN FRONT: Quaternion(Vector3(1,0,0), ToRadians(270))
Rotate DOWN SIDE: Quaternion(Vector3(0,0,1), ToRadians(270))
Rotate Right: Quaternion(Vector3(0,1,0), ToRadians(90))
Rotate Left: Quaternion(Vector3(0,1,0), ToRadians(270))

Use them in the next way(to rotate left):

m_rotation *= Quaternion(Vector3(0,1,0), ToRadians(270))

If you want to move it a specific radius:

DistanceToRotate = (PointA - PointB).length();

m_rotation *= Quaternion(Vector3(0,1,0), DistanceToRotate )

Also take as default rotation: Quaternion(0,0,0,1)

Also i see that you are not catching right how to obtein a axis from the object’s perspective. Ill place here some examples:


    Vector3f GetForward() const
    {
        return Vector3f(0, 0, 1).Rotate(*this).Normalize();
    }

    Vector3f GetBack() const
    {
        return Vector3f(0, 0, -1).Rotate(*this).Normalize();
    }

    Vector3f GetUp() const
    {
        return Vector3f(0, 1, 0).Rotate(*this).Normalize();
    }

    Vector3f GetDown() const
    {
        return Vector3f(0, -1, 0).Rotate(*this).Normalize();
    }

    Vector3f GetRight() const
    {
        return Vector3f(1, 0, 0).Rotate(*this).Normalize();
    }

    Vector3f GetLeft() const
    {
        return Vector3f(-1, 0, 0).Rotate(*this).Normalize();
    }

Vector3f Vector3f::Rotate(const Quaternion & rotation) const
{
    Quaternion conjugateQ = rotation.Conjugate();
    Quaternion w = rotation * (*this) * conjugateQ;
    return Vector3f (w.x, w.y, w.z);
}

You can use this axis instead of the world axis if you want to rotate respect this ones.