Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ / openGL: Rotating a QUAD toward a point using quaternions

When I have a QUAD at a certain position, how can I rotate it in such a way that its normal points toward a given point? Imagine the colored blocks are just rectangular quads, then this image shows a bit what I mean. The quads are all oriented in such a way they point toward the center of the sphere.

alt text http://emrahgunduz.com/wp-content/uploads/2009/01/material_id_gui-600x364.jpg

Maybe this second image shows a bit more what I'm trying to do: alt text http://img689.imageshack.us/img689/3130/screenshot20100708at555.png

I'm using openGL / C++ (and the Eigen lib). And I have this code to draw a simple quad:

#include "ofMain.h"
#include "Quad.h"
Quad::Quad(Vector3f oPosition):position(oPosition) {
}

void Quad::update() {
}

void Quad::draw() {
    float size = 1.3;
    glColor3f(1.0f, 0.0f, 0.6f);
    glPushMatrix();
        glTranslatef(position.x(), position.y(), position.z());
        glScalef(size, size,size);
        glBegin(GL_QUADS);
            glVertex3f(0,0,0);
            glVertex3f(1,0,0);
            glVertex3f(1,1,0);
            glVertex3f(0,1,0);
        glEnd();
    glPopMatrix();
}

Update 17-07 Dear reader,

Just got a little bit further with rotating the quads. I'm positioning a couple of quads randomly and then I rotate them towards a look_at vector3f using this code using the descriptions from the replies below:

void Quad::draw() {
    float size = 0.5;
    glColor3f(1.0f, 0.0f, 0.6f);
    glPushMatrix();
        Vector3f center = look_at - position;
        Vector3f center_norm = center.normalized();
        float r_angle   = acos(center_norm.dot(normal));
        Vector3f axis = normal.normalized().cross(center_norm);

        glPointSize(8);
        glLineWidth(4.0f);

        // draw the center point
        glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_POINTS); 
            glVertex3fv(look_at.data());
        glEnd();

        // draw the quad
        glColor4f(0.0f, 0.0f, 0.0f, 0.85f); 
        glTranslatef(position.x(), position.y(), position.z());
        glRotatef(r_angle * RAD_TO_DEG, axis.x(), axis.y(), axis.z());
        glScalef(size, size,size);
        glBegin(GL_QUADS);
            glVertex3f(-0.5,-0.5,0);
            glVertex3f(0.5,-0.5,0);
            glVertex3f(0.5,0.5,0);
            glVertex3f(-0.5,0.5,0);
        glEnd();

    glPopMatrix();
}

The result looks like this: alt text

As you can see I'm almost there, though the rotation of the quads is still a bit "strange". I you see the image below with the colored quads you clearly see the difference in rotation. How can I rotate the quad in such a way I get the same result as the colored sphere below?

like image 791
pollux Avatar asked Jul 08 '10 13:07

pollux


People also ask

How do you rotate a point using quaternion?

Rotate Point Using Quaternion Vector For convenient visualization, define the point on the x-y plane. Create a quaternion vector specifying two separate rotations, one to rotate the point 45 and another to rotate the point -90 degrees about the z-axis. Use rotatepoint to perform the rotation. Plot the rotated points.

How do you rotate a point in OpenGL?

To rotate around a different point, the formula: X = cx + (x-cx)*cosA - (y-cy)*sinA, Y = cy + (x-cx)*sinA + (y-cy)*cosA, cx, cy is centre coordinates, A is the angle of rotation. The OpenGL function is glRotatef (A, x, y, z).

What is a quaternion OpenGL?

A quaternion is a set of 4 numbers, [x y z w], which represents rotations the following way: // RotationAngle is in radians x = RotationAxis. x * sin(RotationAngle / 2) y = RotationAxis. y * sin(RotationAngle / 2) z = RotationAxis.

How do you make a quaternion?

Create Quaternion by Specifying Euler Angles You can create an N-by-1 quaternion array by specifying an N-by-3 array of Euler angles in radians or degrees. Use the euler syntax to create a scalar quaternion using a 1-by-3 vector of Euler angles in radians.


2 Answers

Rotation axis = normalize(crossproduct(currentNormal, desiredNormal))

Rotation angle = acos(dotproduct(normalize(currentNormal), normalize(desiredNormal)).

You can build either rotation matrix or quaternion from axis and angle. Exact formula can be found in any resource about quaternions.

You may need to flip angle or axis depending on whether you rotate normal around its' base or around its' tip.

Also THIS resource seems to have enough information about quaternions, rotations, and 3d space in general.

like image 164
SigTerm Avatar answered Oct 16 '22 03:10

SigTerm


You may have already found this - http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation - but I found it useful when I last looked into this topic.

like image 23
Michael Repucci Avatar answered Oct 16 '22 01:10

Michael Repucci