import turtle
import math
from math import sin, tan
wn = turtle.Screen()
wn.tracer(0)
t = turtle.Turtle()
t.setundobuffer(0)
turtle.setworldcoordinates(-1,-1,1,1)
vertices = [[-1, -1, -1], [-1, +1, -1], [+1, +1, -1], [+1, -1, -1],
[-1, -1, +1], [+1, -1, +1], [+1, +1, +1], [-1, +1, +1],
[-1, -1, -1], [-1, -1, +1], [-1, +1, +1], [-1, +1, -1],
[+1, -1, -1], [+1, +1, -1], [+1, +1, +1], [+1, -1, +1],
[+1, +1, -1], [-1, +1, -1], [-1, +1, +1], [+1, +1, +1],
[+1, -1, -1], [+1, -1, +1], [-1, -1, +1], [-1, -1, -1]]
def ident3():
return [[1,0,0],[0,1,0],[0,0,1]]
def ident4():
return [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
def dot(v1, v2):
return sum(ea*eb for ea,eb in zip(v1,v2))
def transpose(m):
return list(zip(*m))
def multvm(v, m):
return [dot(v,b) for b in transpose(m)]
def multmv(m, v):
return [dot(v,b) for b in m]
def multmm(m1, m2):
return [multvm(a, m2) for a in m1]
def translate4(v):
Mt = ident4()
Mt[0][3] = v[0]
Mt[1][3] = v[1]
Mt[2][3] = v[2]
return Mt
def multcm(c, m):
return [[c*e for e in v] for v in m]
def summm(m1, m2):
return [[a+b for a,b in zip(v1,v2)] for v1,v2 in zip(m1,m2)]
def diffv(v1, v2):
return [a-b for a,b in zip(v1,v2)]
def normal(triangle):
v = diffv([triangle[3*2],triangle[3*2+1],triangle[3*2+2]],[triangle[0],triangle[1],triangle[2]])
w = diffv([triangle[3*3],triangle[3*3+1],triangle[3*3+2]],[triangle[0],triangle[1],triangle[2]])
nx = v[1]*w[2]-v[2]*w[1]
ny = v[2]*w[0]-v[0]*w[2]
nz = v[0]*w[1]-v[1]*w[0]
return [nx,ny,nz]
def magnitude(v):
return math.sqrt(sum([x*x for x in v]))
def rotate4(v, theta):
mag = magnitude(v)
x = v[0]/mag
y = v[1]/mag
z = v[2]/mag
W = [[0,-z,y],[z,0,-x],[-y,x,0]]
Mr = summm(ident3(),summm(multcm(sin(theta),W),multcm(2*sin(theta/2)*sin(theta/2), multmm(W,W))))
return [Mr[0]+[0],Mr[1]+[0],Mr[2]+[0],[0,0,0,1]]
def rad(deg):
return deg * math.pi / 180
def perspective(fov, aspect, near, far):
tfov = tan(fov/2)
Mp = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
Mp[0][0] = 1/(aspect*tfov)
Mp[1][1] = 1/tfov
Mp[2][2] = -(far+near)/(far-near)
Mp[2][3] = -1
Mp[3][2] = -(2*far*near)/(far-near)
return Mp
angle = 0
while True:
t.clear()
angle += 0.1
model = ident4()
model = multmm(rotate4([0,0,1],rad(angle)),model)
model = multmm(rotate4([1,1,0],rad(angle)),model)
view = multmm(translate4([0,0,-5]),model)
projection = perspective(rad(80), 1, 0.1, 100)
T = multmm(projection, multmm(view, model))
transformed_vertices = []
for v in vertices:
transformed_vector = multmv(T,v+[1])
transformed_vertices.append(transformed_vector)
polygons = []
hidden = []
for i in range(len(transformed_vertices)//4):
face = []
polygon = []
for j in range(0, 4):
x,y,z,w = transformed_vertices[i*4+j]
face+=[x,y,z]
polygon+=[x/z,y/z]
norm = normal(face)
vec = [face[0],face[1],face[2]]
if dot(norm, vec) > 0:
hidden.append(False)
else:
hidden.append(True)
polygons.append(polygon)
# print(polygons)
def poly(coords):
t.up()
t.teleport(coords[0], coords[1])
t.begin_fill()
t.down()
for i in range(2, len(coords), 2):
t.goto(coords[i], coords[i + 1])
t.goto(coords[0], coords[1])
t.up()
t.end_fill()
for i in range(len(polygons)):
if i % 6 == 0:
t.fillcolor('red')
elif i % 6 == 1:
t.fillcolor('green')
elif i % 6 == 2:
t.fillcolor('yellow')
elif i % 6 == 3:
t.fillcolor('blue')
elif i % 6 == 4:
t.fillcolor('cyan')
elif i % 6 == 5:
t.fillcolor('magenta')
if not hidden[i]:
poly(polygons[i])
wn.update()
wn.mainloop()