【问题标题】:3D Projection in pygamepygame中的3D投影
【发布时间】:2021-01-04 16:51:28
【问题描述】:

我正在尝试创建一个简单的立方体 3D 渲染。正如 Coding Train 的这段视频:第 14 分钟的https://www.youtube.com/watch?v=p4Iz0XJY-Qk。我一度陷入困境。由于我对这一切都很陌生,所以我不确定是什么导致了我的问题。当我开始项目时,立方体会随心所欲地旋转,但会从屏幕向左移动,看起来像是在做一个圆圈。

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()

我非常感谢您对为什么会发生这种情况以及如何解决它以使其只是旋转的任何帮助。

【问题讨论】:

  • 这段代码没有错误。这些点围绕左上角 (0, 0) 旋转。很可能您必须将教程看完。
  • 视频正在处理中。它不是蟒蛇。我有完全相同的矩阵,他没有这样的问题。这就是我要问的。为什么会旋转?
  • p5.js 使用不同的坐标系。在 p5.js (0, 0) 可以翻译到屏幕的中心。
  • 谢谢。现在我明白出了什么问题。干杯

标签: python numpy 3d pygame projection


【解决方案1】:

这段代码没有错误。这些点围绕左上角 (0, 0) 旋转。注意,在 3D 模式下,p5.js 使用与pygame 不同的坐标系。

如果要围绕窗口中心旋转点,则定义范围 [-1, 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]))
points.append(np.matrix([-0.5, -0.5, 1]))

定义一个从范围[-1, 1]到窗口空间的投影矩阵:

projectionMatrix = np.matrix([[height/2, 0, width/2],
                              [0, height/2, height/2]])

指定一个 3x3 旋转矩阵:

rotation = np.array([[math.cos(angle), -math.sin(angle), 0],
                     [math.sin(angle), math.cos(angle), 0],
                     [0, 0, 1]])

先旋转点,再投影到窗口:

projected2d = projectionMatrix * rotation * point.reshape((3, 1))

完整示例:

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()

【讨论】:

    猜你喜欢
    • 2015-03-07
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2011-06-03
    • 2018-05-03
    • 1970-01-01
    相关资源
    最近更新 更多