F. Malato
F. Malato

Reputation: 302

Rotate a gluCylinder() around specific axis?

I'm writing a function to draw a Cylinder that has the center of each base on a specific point, using the OpenGL pipeline commands and the gluCylinder() function.

As a first attempt, I just tried to draw the cylinder, and the result was a cylinder with the lower base centered in (0, 0, 0) and with the other base centered in (0, 0, height), where height has been passed as a function argument.

Then, I've tried to center the first base on the first point I chose, and everything worked like a charm.

Now, I'm struggling to get the right position for the second point: I've computed the distance between the two points and stored the distance along each axis as to get the vector difference, so all I need to do is to perform a rotation so that at any frame the axis of the cylinder lies on the vector difference of the two points.

Still, I need to find the coordinates of the cylinder's axis and rotate it, and I don't know how to do that.

Here is my code, hoping it will be useful:

void drawCylinder(float pHeight, std::vector<float> center1, std::vector<float> center2) {

    const GLfloat* projection = glm::value_ptr(glm::perspective(glm::radians(fov), (float)WIN_WIDTH / (float)WIN_HEIGHT, 0.1f, 100.0f));
    const GLfloat* view = glm::value_ptr(camera.GetViewMatrix());

    glm::vec3 diff = glm::vec3(center2[0] - center1[0], center2[1] - center1[1], center2[2] - center1[2]);
    float distance = sqrt(pow(center2[0] - center1[0], 2) + pow(center2[1] - center1[1], 2) + pow(center2[2] - center1[2], 2));

    glUseProgram(0);

    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(projection);

    glPushMatrix();
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(view);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glColor3f(1.0f, 1.0f, 0.0f);
    glTranslated(center1[0] - 12.25f, (center1[1]) + 0.0f, (center1[2]) - 12.25f);
    // Here I should perform the rotation in order to draw the cylinder in the right position
    gluCylinder(quadric, 0.1f, 0.1f, pHeight, 32, 32);
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

}

I've thought about both the Euler angles ant the quaternions methods, but I can't really figure out how to use any of them. Maybe, given that I'm useing the OpenGL pipeline commands method, the Euler angles would be better. Still, if you have a better way to do the whole thing, I'll be glad to learn something new.

How can I define this rotation?

Upvotes: 2

Views: 638

Answers (1)

Rabbid76
Rabbid76

Reputation: 210876

I recommend to use a math library like the OpenGL Mathematics (GLM) library.

The glm library is a template library. For the following operations you've just to include the following files:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Calculate the vector from center2 to center1. And define a reference vector e.g. (0, 0, 1):

glm::vec3 ref  = lm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 diff = glm::vec3(center2[0] - center1[0],
                           center2[1] - center1[1],
                           center2[2] - center1[2]);

You want to define a rotation matrix which rotates from ref to diff. Calculate the rotation angle - the Dot product of 2 Unit vectors returns the cosine of the angle between the 2 vectors (a unit vector has a length of 1 and a vector can be turned to a unit vector by glm::normalize). The rotation axis can be calculated by the Cross product. Setup a rotation matrix which rotates around the axis by the angle:

float     angle  = acos(glm::dot(ref, glm::normalize(diff)));
glm::vec3 axis   = glm::cross(b, a);
glm::mat4 rotmat = glm::rotate(glm::mat4(1.0f), angle, axis);

Use glMultMatrixf to multiply the current matrix by the rotation matrix. e.g:

glTranslated(center1[0] - 12.25f, (center1[1]) + 0.0f, (center1[2]) - 12.25f);

// multiply current matrix by the rotation matrix
glMultMatrixf(glm::value_ptr(rotmat))

gluCylinder(quadric, 0.1f, 0.1f, pHeight, 32, 32);

Upvotes: 2

Related Questions