pkamer (python3, doesn't expire)
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()