pygame 中的 3D 投影 [英] 3D Projection in pygame

查看:31
本文介绍了pygame 中的 3D 投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个简单的立方体 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)屏幕填充((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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆