# projecting 3d onto 2d plane is not showing up correctly

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.

1. position circle somewhere in 3d space.
2. 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
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)

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


Your translate_coords_to_center(0,0) function should be done after you have done the projection from 3d to 2d.

e.g.

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(sy, sy)

while running:
circle(0, 0, cz, 50)
cz += 1
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False


The effect you are seeing is caused by 2 things.

1. Because a constant x/y offset is incorrectly added in 3d world space the array of circles will appear to the right and below of the camera's position.
2. Because the 0,0 origin of view/camera space is not the centre of the display, instead it's at the top-left (Adding the window centre coords AFTER projection fixes that)
• after adding the translation after projection , i get a straight line from center to the top left corner of screen Nov 3, 2020 at 10:40
• Can you post your modified code so I can check it for you ? Nov 3, 2020 at 10:48
• Did you remove the translation before projection ? (so circle has 0,0 passed for its X,Y coord) Nov 3, 2020 at 10:56