I am trying to learn about 3d graphics from first principles, so i have decided to implement a simple thing, create a circle in 3d space & rotate it along some axis. I understand the basics theory.
- position circle somewhere in 3d space.
- calculate its projection on some plane.
Once i can get this i can use rotation matrix to calculate the new position of vertices. but i am a bit stuck at 2nd step. this is my code:
import pygame
import math
(width, height) = (600, 500)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
running = True
K = 8 # view plane distance
cz = 10 # z location of circle initially.
# Pyagme 0.0 is at top left , but i want to center it at window?? is this even coorect to do or is should just continue using top left.
def translate_coords_to_center(x , y):
return (width/2 - x, height/2 - y)
# plots a pixel
def pixel(x,y,color=(100,20,30)):
s = pygame.Surface((1,1))
s.fill(color)
r,r.x,r.y = s.get_rect(),x,y
screen.blit(s,r)
# Draw the circle
def circle(cx, cy, cz, radius):
N = 100
PI = 3.14
angle = 360 / N
for i in range(N):
x2 = cx + radius * math.cos(PI* angle * i / 180)
y2 = cy + radius * math.sin(PI* angle * i / 180)
# Do a 2d projection
x2 = K* x2 / cz
y2 = K* y2 / cz
pixel(x2, y2)
while running:
x, y = translate_coords_to_center(0,0)
circle(x, y, cz, 50)
cz += 1
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
When i change the z position of circle, i get something like the below image, I am expecting the circle to not change its position but only its size, ( i know this cant be true as i am dividing by z
), am i missing some translation step? :
EDIT: Adding the translation after projection is also not working:
import pygame
import math
(width, height) = (600, 500)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
running = True
K = 8
cz = 10
def translate_coords_to_center(x , y):
return (width/2 - x, height/2 - y)
def pixel(x,y,color=(100,20,30)):
s = pygame.Surface((1,1))
s.fill(color)
r,r.x,r.y = s.get_rect(),x,y
screen.blit(s,r)
def circle(cx, cy, cz, radius):
N = 100
PI = 3.14
angle = 360 / N
for i in range(N):
x2 = cx + radius * math.cos(PI* angle * i / 180)
y2 = cy + radius * math.sin(PI* angle * i / 180)
# Do a 2d projection
x2 = K* x2 / cz
y2 = K* y2 / cz
sx, sy = translate_coords_to_center(x2, y2)
pixel(sx, sy)
while running:
circle(0,0, cz, 50) # this works correctly, but circles are centered at top left corner of screen,
cz += 1
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False