Why does my rotation (up / down) break when I rotate 90 degrees left or right, and how do I fix it?

1 week ago 3
ARTICLE AD BOX

I'm trying to make a simple 3d renderer in CMU Graphics using rotation matrices. When I rotate the camera 90 degrees (left or right), and I try rotating (up / down), it does a "barrel roll" when it should change the pitch.

The camera starts aligned with the z axis, then rotating up / down rotates around the x axis, but when I rotate so that the camera is aligned with the x axis, it still rotates around the x axis when it should rotate around the z axis.

Here is my code:

from cmu_graphics import * import numpy as np import math as m SCREEN_WIDTH = 400 SCREEN_HEIGHT = 400 move_speed = 0.1 rxyza = np.array([2.5, 2, 2]) rxyzb = np.array([2, 2.5, 2]) rxyzc = np.array([2, 2, 2.5]) app.cxyz = np.array([3.0, 2.0, 1.0]) app.B = np.identity(3) beta = m.radians(5) R1 = np.array([[1, 0, 0], [0, m.cos(beta), -m.sin(beta)], [0, m.sin(beta), m.cos(beta)]]) R2 = np.array([[m.cos(beta), 0, -m.sin(beta)], [0, 1, 0], [m.sin(beta), 0, m.cos(beta)]]) R3 = np.array([[m.cos(beta), -m.sin(beta), 0], [m.sin(beta), m.cos(beta), 0], [0, 0, 1]]) app.triangles = Group() def onMouseDrag(mouseX, mouseY): # on mouse move pass def onMousePress(mouseX, mouseY): # on mouse down pass def onMouseHold(mouseX, mouseY): # while key down pass def onMouseRelease(mouseX, mouseY): pass def onKeyDown(keys): # on key down pass def onKeyHold(keys): # while key down # move camera if "w" in keys: app.cxyz += app.B[:, 2] * move_speed if "a" in keys: app.cxyz -= app.B[:, 0] * move_speed if "s" in keys: app.cxyz -= app.B[:, 2] * move_speed if "d" in keys: app.cxyz += app.B[:, 0] * move_speed if "q" in keys: app.cxyz[1] += move_speed if "e" in keys: app.cxyz[1] -= move_speed # rotate camera if "up" in keys: app.B = R1.T @ app.B if "left" in keys: app.B = R2 @ app.B if "down" in keys: app.B = R1 @ app.B if "right" in keys: app.B = R2.T @ app.B def onKeyRelease(key): pass app.frame = 0 def onStep(): # on frame (30 fps) app.triangles.clear() p1 = app.B.T @ (rxyza - app.cxyz) p2 = app.B.T @ (rxyzb - app.cxyz) p3 = app.B.T @ (rxyzc - app.cxyz) if p1[2] > 0 and p2[2] > 0 and p3[2] > 0: # all points are in front of the camera scale = 500 points_2d = [] for p in [p1, p2, p3]: x = int(SCREEN_WIDTH / 2 + (p[0] / p[2]) * scale) y = int(SCREEN_HEIGHT / 2 - (p[1] / p[2]) * scale) points_2d.append((x, y)) app.triangles.add(Polygon(points_2d[0][0], points_2d[0][1], points_2d[1][0], points_2d[1][1], points_2d[2][0], points_2d[2][1], fill = None, border = "black")) app.frame += 1 cmu_graphics.run()
Read Entire Article