Куб визуализируется как прямоугольник с матрицей проекцииPython

Программы на Python
Ответить
Anonymous
 Куб визуализируется как прямоугольник с матрицей проекции

Сообщение Anonymous »

Я сделал простой 3D-рендеринг на Python, используя pygame. Когда я запускаю программу, куб отображается в виде прямоугольника:
Изображение

Я умножаю позиции точек куба на матрицу проекции (также переменную Viewscale и добавляюPosition, чтобы сделать его видимым на экране), затем я умножаю эти точки с помощью матриц перемещения и вращения.
Я пробовал много способов исправить это. Я думаю, это связано с соотношением сторон, но я не уверен.
Когда я меняю соотношение сторон на соотношение 1:1, куб становится настоящим кубом. В матрице проекции мы делим по соотношению сторон, чтобы она не была похожа на куб ни в каком соотношении?
Я попробовал запустить ее на Replit, чтобы убедиться, что это не обязательно. делал с компьютером, но ничего не изменилось.
Я тоже не очень разбираюсь в матрице проекции, но она точно такая же, как и видео и документы, которые я смотрел и читал.
Вот полный код:
import pygame
import numpy as np
from math import sin, cos, radians, tan

# settings
Viewscale = 400
Postion = [940, 540]
#position and viewscale move and scale the cube into view
ScreenSize = [1920, 1080]
AspectRatio = ScreenSize[0] / ScreenSize[1]
fov = np.deg2rad(90)
NearPlane = 0.1
FarPlane = 100

# math variables
angle = 0
CubePoints = np.array([
(-1, -1, -1, 1), # Vertex 0
(1, -1, -1, 1), # Vertex 1
(1, 1, -1, 1), # Vertex 2
(-1, 1, -1, 1), # Vertex 3
(-1, -1, 1, 1), # Vertex 4
(1, -1, 1, 1), # Vertex 5
(1, 1, 1, 1), # Vertex 6
(-1, 1, 1, 1) # Vertex 7
])

# Define cube edges (pairs of points that need to be connected)
CubeEdges = [
(0, 1), (1, 2), (2, 3), (3, 0), # back face
(4, 5), (5, 6), (6, 7), (7, 4), # front face
(0, 4), (1, 5), (2, 6), (3, 7) # connecting edges
]

# Projection Matrix
ProjectionMatrix = np.array([
[(1 / tan(fov / 2)) / AspectRatio, 0, 0, 0],
[0, 1 / tan(fov / 2), 0, 0],
[0, 0, (FarPlane + NearPlane) / (NearPlane - FarPlane), (2 * FarPlane * NearPlane) / (NearPlane - FarPlane)],
[0, 0, -1, 0]
])

# rendering variables
pygame.init()
screen = pygame.display.set_mode((ScreenSize[0], ScreenSize[1]))
clock = pygame.time.Clock()
running = True

# Function to project 3D points to 2D
def project(point):
# Perform the projection
projected = np.dot(ProjectionMatrix, point)
# Avoid division by zero and perform perspective divide
if projected[3] != 0:
projected[0] /= projected[3]
projected[1] /= projected[3]
projected[2] /= projected[3]

# Scale and translate the points into screen space
x = int(projected[0] * Viewscale + Postion[0])
y = int(projected[1] * Viewscale + Postion[1])

return (x, y)

# rendering loop
while running:
angle += 1
angle_rad = radians(angle)
screen.fill("white")

# Rotation matrix
RotationMatrix = np.array([
[1, 0, 0, 0],
[0, cos(angle_rad), -sin(angle_rad), 0],
[0, sin(angle_rad), cos(angle_rad), 0],
[0, 0, 0, 1]
])

# Translation matrix
TranslationMatrix = np.array([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 5], # Move the cube away from the camera
[0, 0, 0, 1]
])

# Store projected points for drawing
Projetced2D = []

# Project each point of the cube
for point in CubePoints:
# Apply rotation and translation
rotated_point = np.dot(RotationMatrix, point)
translated_point = np.dot(TranslationMatrix, rotated_point)

# Project the point
projected_point = project(translated_point)
Projetced2D.append(projected_point)

# Draw each vertex as a small circle
pygame.draw.circle(screen, "blue", projected_point, 5)

# Draw edges between projected points
for edge in CubeEdges:
point1 = Projetced2D[edge[0]]
point2 = Projetced2D[edge[1]]
pygame.draw.line(screen, "black", point1, point2, 2)

# Handle quitting the game
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

pygame.display.flip()
clock.tick(60)

pygame.quit()


Подробнее здесь: https://stackoverflow.com/questions/793 ... ion-matrix
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»