I'm using the mouse to rotate the cube. The problem is that instead of rotating around its own center, the cube rotates around the origin and kind of just orbits it.
def mouseMovement(event):
global lastPosX, lastPosY, xRot, yRot, zRot
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 4: # scroll in
glScaled(1.03, 1.03, 1.03)
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 5: # scroll out
glScaled(0.97, 0.97, 0.97)
if event.type == pygame.MOUSEMOTION:
x, y = event.pos
dx = x - lastPosX
dy = y - lastPosY
mouseState = pygame.mouse.get_pressed()
if mouseState[0]: # left click occured
modelView = (GLfloat * 16)()
mvm = glGetFloatv(GL_MODELVIEW_MATRIX, modelView)
temp = (GLfloat * 3)()
temp[0] = modelView[0]*dy + modelView[1]*dx
temp[1] = modelView[4]*dy + modelView[5]*dx
temp[2] = modelView[8]*dy + modelView[9]*dx
norm_xy = math.sqrt(temp[0]*temp[0] + temp[1]*temp[1] + temp[2]*temp[2])
glTranslatef(-CUBE_SIZE / 2.0, -2.0, -10.0)
glRotatef(math.sqrt(dx*dx+dy*dy) / 2, temp[0]/norm_xy, temp[1]/norm_xy, temp[2]/norm_xy)
glTranslatef(CUBE_SIZE / 2.0, 2.0, 10.0)
lastPosX = x
lastPosY = y
I believe the problem lies within the above block of code. From other questions I've read, I need to translate back and forth from origin to where I want the cube to go with a rotation in-between.
glTranslatef(-CUBE_SIZE / 2.0, -2.0, -10.0)
glRotatef(math.sqrt(dx*dx+dy*dy) / 2, temp[0]/norm_xy, temp[1]/norm_xy, temp[2]/norm_xy)
glTranslatef(CUBE_SIZE / 2.0, 2.0, 10.0)
However it still is rotating around the origin. Any advice?
You need to transform the cube so that the center of the cube is at (0, 0, 0). Then rotate the cube and finally place the cube in its position in the world:
v' = world_translate * rotate * origin0_translate * v
If the left, bottom, near model coordinate of the cube is (0, 0, 0) and the right, top, far model coordinate is (CUBE_SIZE, CUBE_SIZE, CUBE_SIZE), this means:
glTranslatef(0, 0, -10.0)
glRotatef(math.sqrt(dx*dx+dy*dy) / 2, temp[0]/norm_xy, temp[1]/norm_xy, temp[2]/norm_xy)
glTranslatef(-CUBE_SIZE/2, -CUBE_SIZE/2, -CUBE_SIZE/2)
In general, you need to calculate the axis-aligned bounding box (minimum and maximum coordinates) of an object and move the center of the box to (0, 0, 0) before rotating the object:
min_v # minimum x, y, z coordinate
max_v # maximum x, y, z coordinate
center_x = (min_v[0] + max_v[0]) / 2
center_y = (min_v[1] + max_v[1]) / 2
center_z = (min_v[2] + max_v[2]) / 2
glTranslatef(world_pos_x, world_pos_y, world_pos_z)
glRotatef(angle, axis_x, axis_y, axis_z)
glTranslatef(-center_x, -center_y, -center_z)
Note that when drawing a cube, with the left, bottom, near model coordinate (-s/2, -s/2, -s/2) and the right, top, far model coordinate (s/2, s/2), s/2), this would become easier since the center of the cube is (0, 0, 0).