为什么立方体在屏幕边缘时会出现失真?



我已经使用pygame从头开始制作了一个立方体渲染器。我一直在遵循在线指南并将其翻译成python,并且非常成功,直到我开始玩这个程序。一切都很好,但是我注意到,当立方体远离中心时,有一个很大的扭曲效果。比如,不合理的大扭曲。射线的计算方法有问题吗?(方向键移动镜头)

import pygame
width = 720
height = 480
red = (255, 0, 0)
white = (255, 255, 255)
black = (0,0,0)
screen = pygame.display.set_mode((width, height))
running = True
clock = pygame.time.Clock()
runSpeed = 30
cube = [0, 0, 0], [8, 0, 0], [8, 0, 8], [0, 0, 8], [0, 8, 0], [8, 8, 0], [8, 8, 8], [0, 8, 8]
cubeCoords = [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
moveCubeCoords = [8, -4, -4]
camCoord = [0, 0, 0]
camSpeed = 1
canvasDis = 1
scale = 80

def coordConvert(x, y):
newX = (width / 2) + x
newY = (height / 2) + y
return newX, newY

def drawCircle(x, y):
pygame.draw.circle(screen, red, (x, y), 5)

def moveCube():
for i in range(len(cube)):
for e in range(3):
cube[i][e] = cube[i][e] + moveCubeCoords[e]

def onEvent(event):
if event.key == pygame.K_UP:
camCoord[1] = camCoord[1] + camSpeed
if event.key == pygame.K_DOWN:
camCoord[1] = camCoord[1] - camSpeed
if event.key == pygame.K_RIGHT:
camCoord[2] = camCoord[2] + camSpeed
if event.key == pygame.K_LEFT:
camCoord[2] = camCoord[2] - camSpeed
print(camCoord)

def main():
pygame.init()
print("Initialized")
pygame.display.set_caption("Cube rendering")
moveCube()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
onEvent(event)
for i, point in enumerate(cube):  # gets all coords of cube
pX = point[0] - camCoord[0]
pY = point[1] - camCoord[1]
pZ = point[2] - camCoord[2]
mpX = pZ / pX
mpY = pY / -pX  # canvas Y deviation from origin
newCoords = coordConvert(mpX * scale, mpY * scale)
cubeCoords[i][0] = newCoords[0]
cubeCoords[i][1] = newCoords[1]
drawCircle(newCoords[0], newCoords[1])
for i in range(4):  # Vert lines
pygame.draw.line(screen, black, (cubeCoords[i][0], cubeCoords[i][1]),
(cubeCoords[i + 4][0], cubeCoords[i + 4][1]), 2)
for i in range(3):# Bottom lines
pygame.draw.line(screen, black, (cubeCoords[i][0], cubeCoords[i][1]),
(cubeCoords[i + 1][0], cubeCoords[i + 1][1]), 2)
pygame.draw.line(screen, black, (cubeCoords[3][0], cubeCoords[3][1]),
(cubeCoords[0][0], cubeCoords[0][1]), 2)
for i in range(3): # Top lines
pygame.draw.line(screen, black, (cubeCoords[i+4][0], cubeCoords[i+4][1]),
(cubeCoords[i + 5][0], cubeCoords[i + 5][1]), 2)
#lazy lines
pygame.draw.line(screen, black, (cubeCoords[3][0], cubeCoords[3][1]),
(cubeCoords[0][0], cubeCoords[0][1]), 2)
pygame.draw.line(screen, black, (cubeCoords[7][0], cubeCoords[7][1]),
(cubeCoords[4][0], cubeCoords[4][1]), 2)
print(cubeCoords)
clock.tick(runSpeed)
pygame.display.update()
screen.fill(white)

if __name__ == '__main__':
main()

立方体地图正确投影的唯一位置是立方体的中心。这些图像已经扭曲了,从任何其他角度看它们都会开始扭曲。
如果你想让玩家在一个区域内移动,你可以将立方体设置得非常大以最小化扭曲,因为玩家不会相对于立方体远离中心。这是典型的游戏环境。

下面是立方体映射投影的解释。http://wiki.polycount.com/wiki/Cube_map

能看到的叫做透视失真

无论如何,你可以简化和清理代码:

import pygame
pygame.init()
window = pygame.display.set_mode((600, 400))
width, height = window.get_size()
clock = pygame.time.Clock()
cube = [-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1], [-1, 1, -1], [1, 1, -1], [1, 1, 1], [-1, 1, 1]
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (4, 5), (5, 6), (6, 7), (7, 4), (0, 4), (1, 5), (2, 6), (3, 7)]
cam_coord, cam_speed = [0, 0, 0], 0.5
scale = 200
translate = [4, 0, 0]
for i in range(len(cube)):
for e in range(3):
cube[i][e] += translate[e]
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
cam_coord[1] -= (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * cam_speed
cam_coord[2] -= (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * cam_speed
cube_coords = []
for point in cube:
x = (width / 2) + scale * (point[2] - cam_coord[2]) / (point[0] - cam_coord[0])
y = (height / 2) +  scale * (point[1] - cam_coord[1]) / (point[0] - cam_coord[0])
cube_coords.append((x, y))
window.fill((255, 255, 255))
for edge in edges:
pygame.draw.line(window, (0, 0, 0), cube_coords[edge[0]], cube_coords[edge[1]], 2)
for coord in cube_coords:
pygame.draw.circle(window, (255, 0, 0), coord, 5)
pygame.display.update()

pygame.quit()
exit()

最新更新