pygame 中的 3D 投影 [英] 3D Projection in pygame
问题描述
我正在尝试创建一个简单的立方体 3d 渲染.正如 Coding Train 中的这段视频:
导入pygame将 numpy 导入为 np导入操作系统导入数学白色 = (255,255,255)宽度,高度 = 400, 300screen = pygame.display.set_mode((width, height))时钟 = pygame.time.Clock()点数 = []角度 = 0点附加(np.matrix([ 0.5, 0.5, 1]))点附加(np.matrix([ 0.5,-0.5,1]))点附加(np.matrix([-0.5,0.5,1]))点附加(np.matrix([-0.5,-0.5,1]))投影矩阵 = np.matrix([[高度/2, 0, 宽度/2],[0, 高度/2, 高度/2]])为真:时钟滴答(30)screen.fill((0,0,0))旋转 = np.matrix([[math.cos(angle), -math.sin(angle), 0],[math.sin(angle), math.cos(angle), 0],[0, 0, 1]])对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:os._exit(1)对于点数:投影 2d = 投影矩阵 * 旋转 * point.reshape((3, 1))pygame.draw.circle(screen, WHITE, (int(projected2d[0][0]), int(projected2d[1][0])), 5)角度 += 0.01pygame.display.update()
I'm trying to create a simple 3d rendering of a cube. As in this video from the Coding Train: https://www.youtube.com/watch?v=p4Iz0XJY-Qk on minute 14. I got stuck at one point. Since I'm pretty new to all of this, I'm not exactly sure what's causing my issue. When I start the project, the cube rotates as I want it to, but moves away from the screen to the left and it looks like it's making a circle.
import pygame
import numpy as np
import os
import math
WHITE = (255,255,255)
width, height = 700, 700
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
points = []
angle = 0
points.append(np.array([[300], [250], [1]]))
points.append(np.array([[300], [350], [1]]))
points.append(np.array([[400], [250], [1]]))
points.append(np.array([[400], [350], [1]]))
projectionMatrix = np.array([[1, 0, 0],
[0, 1, 0]])
while True:
clock.tick(30)
screen.fill((0,0,0))
rotation = np.array([[math.cos(angle), -math.sin(angle)],
[math.sin(angle), math.cos(angle)]])
for event in pygame.event.get():
if event.type == pygame.QUIT:
os._exit(1)
for point in points:
projected2d = np.dot(projectionMatrix, point)
rotated = np.dot(rotation, projected2d)
pygame.draw.circle(screen, WHITE, (int(rotated[0][0]), int(rotated[1][0])), 5)
angle += 0.01
pygame.display.update()
I would really appreciate any help to why this is happening and how I could fix it so it's just rotating around.
There is no bug in this code. The points rotate around the top left (0, 0). Note, In 3D mode, p5.js uses a different coordinate system than pygame.
If you want to rotate the dots around the centre of the window, then define the points in range [-1, 1] (normalized device space:
points.append(np.matrix([ 0.5, 0.5, 1]))
points.append(np.matrix([ 0.5, -0.5, 1]))
points.append(np.matrix([-0.5, 0.5, 1]))
points.append(np.matrix([-0.5, -0.5, 1]))
Define a projection matrix from the range[-1, 1] to window space:
projectionMatrix = np.matrix([[height/2, 0, width/2],
[0, height/2, height/2]])
Specify a 3x3 rotation matrix:
rotation = np.array([[math.cos(angle), -math.sin(angle), 0],
[math.sin(angle), math.cos(angle), 0],
[0, 0, 1]])
First rotate the points, then project it to the window:
projected2d = projectionMatrix * rotation * point.reshape((3, 1))
Complete example:
import pygame
import numpy as np
import os
import math
WHITE = (255,255,255)
width, height = 400, 300
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
points = []
angle = 0
points.append(np.matrix([ 0.5, 0.5, 1]))
points.append(np.matrix([ 0.5, -0.5, 1]))
points.append(np.matrix([-0.5, 0.5, 1]))
points.append(np.matrix([-0.5, -0.5, 1]))
projectionMatrix = np.matrix([[height/2, 0, width/2],
[0, height/2, height/2]])
while True:
clock.tick(30)
screen.fill((0,0,0))
rotation = np.matrix([[math.cos(angle), -math.sin(angle), 0],
[math.sin(angle), math.cos(angle), 0],
[0, 0, 1]])
for event in pygame.event.get():
if event.type == pygame.QUIT:
os._exit(1)
for point in points:
projected2d = projectionMatrix * rotation * point.reshape((3, 1))
pygame.draw.circle(screen, WHITE, (int(projected2d[0][0]), int(projected2d[1][0])), 5)
angle += 0.01
pygame.display.update()
这篇关于pygame 中的 3D 投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!