Thursday, January 2, 2020

c++ - Rotating an object in OpenGL about it's centre


Im writing a game for which, one of the models are loaded from an .obj file.


It's a model of a plane, and I want to rotate the propeller. The object file is broken into groups, and the propeller is identified, so that's all good. I'm writing the game in C++ with OpenGl/GLFW The drawing function is:



int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
float win_aspect = (float)win_width / (float)win_height;
glViewport(0, 0, win_width, win_height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, win_aspect, 1, 100.0);


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 30.0, 0, 0, 0, 0.0, 1.0, 0.0);

glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glEnable(GL_LIGHT1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 0.0f);
int vertexIndex = 0, normalIndex;
glRotatef(90, 0, 1, 0);
glPushMatrix();
for(int a = 0; a < (int)groups.size(); a++)
{
if(groups[a].type == "prop")

{
//Code for rotation
glPopMatrix();
glPushMatrix();
float x,y,z;
x = y = z = 0;
int Count = 0;
for(int k = 0; k < groups[a].faces.size(); k++)
{
for(int p = 0; p < groups[a].faces[k].vertices.size(); p++)

{
int _index = groups[a].faces[k].vertices[p];
y += vertices[_index].Dimensions[_y] ;
z += vertices[_index].Dimensions[_z];
Count++;
}
}
z /= Count;
y /= Count;
glTranslatef(0, -y, -z);

glRotatef(angle, 1, 0, 0);
glTranslatef(0, y, z);
}
for(int b = 0; b < (int)groups[a].faces.size(); b++)
{
glBegin(GL_POLYGON);
for(int c = 0; c < (int)groups[a].faces[b].vertices.size(); c++)
{
vertexIndex = groups[a].faces[b].vertices[c];
glVertex3d(vertices[vertexIndex].Dimensions[_x], vertices[vertexIndex].Dimensions[_y], vertices[vertexIndex].Dimensions[_z]);

}
glEnd();
}
}
glPopMatrix();
glfwSwapBuffers();

Since I don't know the exact centre of the propeller, that's what the for loop before the rotation is for. It finds the average of the y and z co-ordinates.


After I find it, I translate to -y,-z , rotate it, and then translate back. This makes the propeller spin as I want it to, but it also rotates along the origin >.< http://people.sc.fsu.edu/~jburkardt/data/obj/cessna.obj <- This is the object file.


groups is a vector of objects and each object has a vector of faces. I'm sure that the vertices and faces are being loaded correctly, since the whole model renders correctly.




Answer



OpenGL uses a column vector convention, which means the matrices must be applied in the opposite of the order in which you actually want the transformations to occur. Just replace this:


glTranslatef(0, -y, -z);
glRotatef(angle, 1, 0, 0);
glTranslatef(0, y, z);

with this:


glTranslatef(0, y, z);
glRotatef(angle, 1, 0, 0);
glTranslatef(0, -y, -z);


and that should fix it.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...