Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Attemping 3D.
#1
I've been following a tutorial on making 3D graphics from scratch, and I've looked over my code many a time and can't figure out what's wrong. Can someone help?

NOTE: The tutorial is in C++, but the underlying logic should be the same, so I'm attempting to follow it in python like a complete idiot. Now it's not working and I don't know why.

Tutorial: https://www.youtube.com/watch?v=ih20l3pJoeU (I've done everything up to the 35-minute mark, no rotating yet)

My code:
import pygame
from math import tan, radians as rad
pygame.init()

screen = pygame.display.set_mode((1024,960))
pygame.display.set_caption("olcEngine3D")

BLACK = 0, 0, 0
WHITE = 255, 255, 255

fNear = 0.1
fFar = 1000.0
fFov = 90.0
fAspectRatio = float(screen.get_height()) / float(screen.get_width())
fFovRad = 1.0/tan(rad(fFov)*.5)

class vect3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0

class triangle:
    def __init__(self, x1 = 0.0, y1 = 0.0, z1 = 0.0, x2 = 0.0, y2 = 0.0, z2 = 0.0, x3 = 0.0, y3 = 0.0, z3 = 0.0):
        self.p = [vect3d() for i in range(3)]
        self.p[0].x,y,z = x1, y1, z1
        self.p[1].x,y,z = x2, y2, z2
        self.p[2].x,y,z = x3, y3, z3

class mesh:
    def __init__(self):
        self.tris = []

class mat4x4:
    def __init__(self):
        self.m = [[0.0 for i in range(4)] for j in range(4)]

meshCube = mesh()
matProj = mat4x4()
meshCube.tris = [triangle(0.0, 0.0, 0.0,   0.0, 1.0, 0.0,  1.0, 1.0, 0.0),
                 triangle(0.0, 0.0, 0.0,   1.0, 1.0, 0.0,  1.0, 0.0, 0.0),

                 triangle(1.0, 0.0, 0.0,   1.0, 1.0, 0.0,  1.0, 1.0, 1.0),
                 triangle(1.0, 0.0, 0.0,   1.0, 1.0, 1.0,  1.0, 0.0, 1.0),

                 triangle(1.0, 0.0, 1.0,   1.0, 1.0, 1.0,  0.0, 1.0, 1.0),
                 triangle(1.0, 0.0, 1.0,   0.0, 1.0, 1.0,  0.0, 0.0, 1.0),

                 triangle(0.0, 0.0, 1.0,   0.0, 1.0, 1.0,  0.0, 1.0, 0.0),
                 triangle(0.0, 0.0, 1.0,   0.0, 1.0, 0.0,  0.0, 0.0, 0.0),

                 triangle(0.0, 1.0, 0.0,   0.0, 1.0, 1.0,  1.0, 1.0, 1.0),
                 triangle(0.0, 1.0, 0.0,   1.0, 1.0, 1.0,  1.0, 1.0, 0.0),

                 triangle(1.0, 0.0, 1.0,   0.0, 0.0, 1.0,  0.0, 0.0, 0.0),
                 triangle(1.0, 0.0, 1.0,   0.0, 0.0, 0.0,  1.0, 0.0, 0.0)]

matProj.m[0][0] = fAspectRatio * fFovRad
matProj.m[1][1] = fFovRad
matProj.m[2][2] = fFar / (fFar - fNear)
matProj.m[3][2] = (-fFar * fNear) / (fFar - fNear)
matProj.m[2][3] = 1.0
matProj.m[3][3] = 0.0

def MultiplyMatrixVector(i, m):
    o = vect3d()
    o.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + m.m[3][0]
    o.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + m.m[3][1]
    o.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + m.m[3][2]
    w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + m.m[3][3]

    if w != 0.0:
        o.x /= w
        o.y /= w
        o.z /= w

    return o

while True:
    for EVENT in pygame.event.get():
        if EVENT.type == pygame.QUIT:
            pygame.quit()
            quit()

    screen.fill(BLACK)
    for tri in meshCube.tris:
        triProjected = triangle()
        triProjected.p[0] = MultiplyMatrixVector(tri.p[0], matProj)
        triProjected.p[1] = MultiplyMatrixVector(tri.p[1], matProj)
        triProjected.p[2] = MultiplyMatrixVector(tri.p[2], matProj)

        triProjected.p[0].x += 1.0
        triProjected.p[0].y += 1.0
        triProjected.p[1].x += 1.0
        triProjected.p[1].y += 1.0
        triProjected.p[2].x += 1.0
        triProjected.p[2].y += 1.0

        triProjected.p[0].x = triProjected.p[0].x * 0.5 * float(screen.get_width())
        triProjected.p[0].y = triProjected.p[0].y * 0.5 * float(screen.get_height())
        triProjected.p[1].x = triProjected.p[1].x * 0.5 * float(screen.get_width())
        triProjected.p[1].y = triProjected.p[1].y * 0.5 * float(screen.get_height())
        triProjected.p[2].x = triProjected.p[2].x * 0.5 * float(screen.get_width())
        triProjected.p[2].y = triProjected.p[2].y * 0.5 * float(screen.get_height())

        pygame.draw.polygon(screen, WHITE, ((triProjected.p[0].x, triProjected.p[0].y),
                                            (triProjected.p[1].x, triProjected.p[1].y),
                                            (triProjected.p[2].x, triProjected.p[2].y)), 4)

    pygame.display.update()
It's not neat or anything, I just want something that functions... I know this is a ton to ask but can anyone help?

-Zman
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020