through some tutorials Implemented perspective projection into python with pygame. When I ran the program, a cube I was trying to render,
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)
])
appeared shrunk on the X axis.
I also tried to rotate the cube but it looked really weird. If I removed perspective division from my code, the cube rotated better but it was still shrunk. Here is my full code. Sorry if its messy!
import pygame
import numpy as np
from math import sin, cos, radians, tan
import time
#settings
Viewscale=200
Postion = [940,540]
ScreenSize=[1920,1080]
AspectRatio = ScreenSize[0]/ScreenSize[1]
fov = radians(90)
NearPlane = 0.1
FarPlane = 100
# math variables
angle = 0
Projetced2D = []
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)
])
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
# rendering
while running:
angle += 1
angle_rad = radians(angle)
screen.fill("white")
# projection math
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)
])
for CurrentPoint in CubePoints:
Rotated3d = np.dot(RotationMatrix, CurrentPoint)
Projetced3D = np.dot(ProjectionMatrix, Rotated3d)
Projetced3D[0] /= Projetced3D[3]
Projetced3D[1] /= Projetced3D[3]
print(Projetced3D[0])
print(Projetced3D[1])
pygame.draw.circle(screen,"blue",[Projetced3D[0]*Viewscale+Postion[0],Projetced3D[1]*Viewscale+Postion[1]],5)
# poll for events
# pygame.QUIT event means the user clicked X to close your window
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
clock.tick(60) # limits FPS to 60
pygame.quit()
Thanks!