graphics_3d.py

Created by valmontechno

Created on June 12, 2024

1.91 KB


from v_math import *
import graphics_engine as gh

class Camera:
    def __init__(self, position:Vector3, pitch:float, yaw:float, focalLenth:float=1, nearClip=0.01):
        self.position, self.pitch, self.yaw, self.focalLenth, self.nearClip = position, pitch, yaw, focalLenth, nearClip

    def getForward(self):
        return Vector3(-sin(self.yaw), 0, cos(self.yaw))
    
    def getRight(self):
        return Vector3(cos(self.yaw), 0, sin(self.yaw))
    
    def getLookAt(self):
        return Vector3(-sin(self.yaw)*cos(self.pitch),
                       sin(self.pitch),
                       cos(self.yaw)*cos(self.pitch))

def edgePlaneIntersection(edge:Edge3, planeNormal:Vector3, planePoint:Vector3):
    u = edge.v2.sub(edge.v1)
    dot = dot3(planeNormal, u)
    if abs(dot) < 1e-5:
        return None
    w = edge.v1.sub(planePoint)
    si = -dot3(planeNormal, w) / dot
    u = u.mulK(si)
    return edge.v1.add(u)

def clip(edge:Edge3, camera:Camera, planeNormal:Vector3):
    planePoint = camera.position.add(planeNormal.mulK(camera.nearClip))
    dotV1 = dot3(planePoint.sub(edge.v1), planeNormal)
    dotV2 = dot3(planePoint.sub(edge.v2), planeNormal)

    if dotV1 <= 0 and dotV2 <= 0:
        return edge
    elif dotV1 > 0 and dotV2 > 0:
        return None
    elif dotV1 > 0:
        return Edge3(edgePlaneIntersection(edge, planeNormal, planePoint), edge.v2)
    else:
        return Edge3(edge.v1, edgePlaneIntersection(edge, planeNormal, planePoint))

def drawMesh(mesh:list[Edge3], color, camera:Camera):
    lookAt = camera.getLookAt()
    for edge in mesh:
        edge = clip(edge, camera, lookAt)
        if edge:
            gh.drawEdge(edge
                        .translate(camera.position.opposite())
                        .rotationY(camera.yaw)
                        .rotationX(camera.pitch)
                        .projection(camera.focalLenth)
                        .toScreen(), color)