I'm learning about 3D perspective projection and matrices in python. I've got a pretty good understanding of the basics, but I don't understand how I will take my code which moves an object and apply a transformation which would make it into a first-person, camera like movement (for my own understanding, minecraft-like). Here is my code, which I've taken and modified from https://github.com/Josephbakulikira/3D-perspective-projection-with-python-. I just can't seem to find any info about this type of transformation, done directly with matrices.
So in this code, a list of points is dot-multiplied with a rotation matrix, and I can translate the shape adding to that result. I'm missing the understanding of how to take what I have so far and make it rotate about the camera. I've made this work in the past in pyOpenGL by following tutorials using gl matrix commands, but then the actual work is hidden in the functions.
I know that to appear like the camera is moving, the object will need to be transformed while simultaneously rotating. I can do both of those things, but when it comes to moving them at the right speed and angle, and also having movement be based on the local camera axis and not the global axis, I'm lost.
I'm trying to do this in the long run (My pygame/pyopengl code seems to apply a texture to every surface) but completely "by hand" without pyopenGL functions. If anyone has any examples or could explain how this works, I would appreciate it!
import pygame
import os
import math
from matrix import matrix_multiplication
os.environ["SDL_VIDEO_CENTERED"]='1'
black, white, blue = (20, 20, 20), (230, 230, 230), (0, 154, 255)
width, height = 640, 480
pygame.init()
pygame.display.set_caption("3D cube Projection")
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
fps = 60
Xangle = 0
Yangle = 0
Zangle = 0
cube_position = [width//2, height//2]
scale = 600
speed = 0.01
points = [n for n in range(8)]
points[0] = [[-1], [-1], [1]]
points[1] = [[1], [-1], [1]]
points[2] = [[1], [1], [1]]
points[3] = [[-1], [1], [1]]
points[4] = [[-1], [-1], [-1]]
points[5] = [[1], [-1], [-1]]
points[6] = [[1], [1], [-1]]
points[7] = [[-1], [1], [-1]]
def connect_point(i, j, k):
a = k[i]
b = k[j]
pygame.draw.line(screen, black, (a[0], a[1]), (b[0], b[1]), 2)
run = True
while run:
clock.tick(fps)
screen.fill(white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
Yangle += speed
if keys[pygame.K_RIGHT]:
Yangle -= speed
if keys[pygame.K_UP]:
Xangle += speed
if keys[pygame.K_DOWN]:
Xangle -= speed
if keys[pygame.K_p]:
Zangle += speed
if keys[pygame.K_o]:
Zangle -= speed
if keys[pygame.K_r]:
Yangle = 0
Xangle = 0
Zangle = 0
index = 0
projected_points = [j for j in range(len(points))]
rotation_x = [[1, 0, 0],
[0, math.cos(Xangle), -math.sin(Xangle)],
[0, math.sin(Xangle), math.cos(Xangle)]]
rotation_y = [[math.cos(Yangle), 0, -math.sin(Yangle)],
[0, 1, 0],
[math.sin(Yangle), 0, math.cos(Yangle)]]
rotation_z = [[math.cos(Zangle), -math.sin(Zangle), 0],
[math.sin(Zangle), math.cos(Zangle), 0],
[0, 0 ,1]]
for point in points:
rotated_2d = matrix_multiplication(rotation_y, point)
rotated_2d = matrix_multiplication(rotation_x, rotated_2d)
rotated_2d = matrix_multiplication(rotation_z, rotated_2d)
distance = 5
z = 1/(distance - rotated_2d[2][0])
projection_matrix = [[z, 0, 0],
[0, z, 0]]
projected_2d = matrix_multiplication(projection_matrix, rotated_2d)
x = int(projected_2d[0][0] * scale) + cube_position[0]
y = int(projected_2d[1][0] * scale) + cube_position[1]
projected_points[index] = [x, y]
pygame.draw.circle(screen, blue, (x, y), 10)
index += 1
#draw edges
for m in range(4):
connect_point(m, (m+1)%4, projected_points)
connect_point(m+4, (m+1)%4 + 4, projected_points)
connect_point(m, m+4, projected_points)
#Xangle += speed
#Yangle += speed
#Zangle += speed
pygame.display.update()
pygame.quit()

Moving the camera only means that the object is moved in the opposite direction than you want to move the camera. Define a camera position and calculate the position of the object relative to this camera position:
When you change the camera position, the object will move. For a movement in the first person perspective, you must always move the camera relative to the viewing direction. A camera rotation means to rotate the object in the opposite direction and move the camera position circularly around the object. So your problem is only about finding the appropriate position of the camera.
Also see Does PyGame do 3d?, Pygame rotating cubes around axis and Close range 3d display messed up