【发布时间】:2021-10-22 02:19:15
【问题描述】:
我想将 3d 点投影到 2d 平面(屏幕)上。
这是我的代码以及将 3d 坐标转换为 2d 坐标的类。
将3d坐标转换为2d坐标的类:
class dtod(pygame.sprite.Sprite):
def __init__(self, point, scale):
super().__init__()
self.point = numpy.array(point)
width, height = pygame.display.get_surface().get_size()
self.angle = 0
self.point[0] = (self.point[0] * 1) / self.point[2]
self.point[1] = (self.point[1] * 1) / self.point[2]
self.projection = numpy.array(
[[math.cos(self.angle), math.sin(self.angle), 0.], [math.sin(self.angle), math.cos(self.angle), 0.]])
self.point = numpy.dot(self.projection, self.point)
self.point = ((self.point[0] * scale) + width / 2, height / 2 - (self.point[1] * scale))
我画东西的主要代码:
import pygame
import numpy as np
from coord import dtod
import math
pygame.init()
screen = pygame.display.set_mode((0, 0))
run = True
width, height = screen.get_size()
colors = {"white": (255, 255, 255), "red": (255, 0, 0), "green": (150, 253, 55), "blue": (0,
227, 227), "orange": (255, 127, 39), "grey": (64, 64, 64), "yellow": (255, 240, 0)}
tx, ty, tz = 0., 0., 0.
fps = pygame.time.Clock()
def cos(x):
return math.cos(x)
def sin(x):
return math.sin(x)
rx = np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0., sin(tx), cos(tx)]])
ry = np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-sin(ty), 0., cos(ty)]])
rz = np.array([[cos(tz), -sin(ty), 0.], [sin(ty), cos(ty), 0.], [0., 0., 1.]])
scale = 200
p1 = np.array([0.5, 0.5, 1.])
p2 = np.array([-0.5, 0.5, 1.])
p3 = np.array([-0.5, -0.5, 1.])
p4 = np.array([0.5, -0.5, 1.])
p5 = np.array([0.5, 0.5, -2.])
p6 = np.array([-0.5, 0.5, -2.])
p7 = np.array([-0.5, -0.5, -2.])
p8 = np.array([0.5, -0.5, -2.])
def transform(tx, ty, tz):
global rx, ry, rz, p1, p2, p3, p4, p5, p6, p7, p8
rx = np.array([[1., 0., 0.], [0., cos(tx), -sin(tx)], [0., sin(tx), cos(tx)]])
ry = np.array([[cos(ty), 0., sin(ty)], [0., 1., 0.], [-sin(ty), 0., cos(ty)]])
rz = np.array([[cos(tz), -sin(ty), 0.], [sin(ty), cos(ty), 0.], [0., 0., 1.]])
p1 = np.dot(rx, p1)
p1 = np.dot(ry, p1)
p1 = np.dot(rz, p1)
p2 = np.dot(rx, p2)
p2 = np.dot(ry, p2)
p2 = np.dot(rz, p2)
p3 = np.dot(rx, p3)
p3 = np.dot(ry, p3)
p3 = np.dot(rz, p3)
p4 = np.dot(rx, p4)
p4 = np.dot(ry, p4)
p4 = np.dot(rz, p4)
p5 = np.dot(rx, p5)
p5 = np.dot(ry, p5)
p5 = np.dot(rz, p5)
p6 = np.dot(rx, p6)
p6 = np.dot(ry, p6)
p6 = np.dot(rz, p6)
p7 = np.dot(rx, p7)
p7 = np.dot(ry, p7)
p7 = np.dot(rz, p7)
p8 = np.dot(rx, p8)
p8 = np.dot(ry, p8)
p8 = np.dot(rz, p8)
while run:
screen.fill((0, 0, 0))
fps.tick(60)
transform(tx, ty, tz)
pygame.draw.circle(screen, colors["white"], dtod(p1, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p2, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p3, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p4, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p5, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p6, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p7, scale).point, 5)
pygame.draw.circle(screen, colors["white"], dtod(p8, scale).point, 5)
pygame.draw.line(screen, colors["white"], dtod(p1, scale).point, dtod(p2, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p2, scale).point, dtod(p3, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p3, scale).point, dtod(p4, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p4, scale).point, dtod(p1, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p5, scale).point, dtod(p6, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p6, scale).point, dtod(p7, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p7, scale).point, dtod(p8, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p8, scale).point, dtod(p5, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p1, scale).point, dtod(p5, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p6, scale).point, dtod(p2, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p7, scale).point, dtod(p3, scale).point)
pygame.draw.line(screen, colors["white"], dtod(p8, scale).point, dtod(p4, scale).point)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
run = False
pygame.display.update()
pygame.quit()
我使用的逻辑:
我正在使用正交投影技术,为了获得感知的感觉,我在实际转换 3d->2d 之前将 x 和 y 坐标除以深度(z 分量)。
提前谢谢你
【问题讨论】:
-
您是如何生成这些图像的?以这种方式旋转立方体我该怎么做?
-
@Rabbid76,左边是我尝试将正交转换为透视时的实验结果。正确的是刚刚从网上下载的,所以我可以在问题中说出我想要实现的目标。
-
@Rabbid76 我想研究 3d 投影,如何在 2d 中渲染 3d 图形。有没有像可汗学院或 3b1b YouTube 频道这样的好资源。我是那个领域的绝对初学者。但是对线性代数和二维图有很好的理解。此外,我通过编程创建了很多动画,所以请推荐一个高级教学的好地方。
标签: pygame 3d projection