-1

So I was trying to make a 3d engine from scratch in Python when i tried to rotate the plane. All axes were fine as predefined rotations in 3d space, but when updating rotation in the code, only the x and z axes were working. But as for the y-axis, when updating rotation, looked like an octagonal origami mess.

a deformed square

Though it looks fine, it keeps on jittering on and on . I can't show you the video but you most likely get the idea.

Here's all the code which I have made so far:

# imports
import pygame as pg
from vec import Vec3, Vec2
from math import sin, cos, tau

pg.init()

# screen
screen_dim: tuple[int, int] = (480, 360)
screen = pg.display.set_mode(screen_dim)

origin: Vec2 = Vec2(screen_dim[0] / 2, screen_dim[1] / 2)

# undertale
clock = pg.time.Clock()
delta: float = 1000 / clock.tick(60)

running: bool = True

# camera
class Camera:
        def __init__(self, pos: Vec3, fov: float) -> None:
                self.pos: Vec3 = pos
                self.fov: float = fov

camera: Camera = Camera(Vec3(0, 0, -1), 120)

# vertex
class Vertex:
        def __init__(self, pos: Vec3) -> None:
                self.pos: Vec3 = pos

vertices = []

# creation
def create_vertex(pos: Vec3) -> None:
        vertices.append(Vertex(pos))

def create_line(pos1: Vec3, pos2: Vec3) -> None:
        vertices.append(Vertex(pos1))
        vertices.append(Vertex(pos2))

def create_plane(pos: Vec3, dim: Vec2, rot: Vec3) -> None:
        for i in range(-1, 2, 2):
                for j in range(-1, 2, 2):
                        x_pos: float = dim.x / 2 * i
                        y_pos: float = dim.y / 2 * j
                        z_pos: float = 0

                        vertices.append(Vertex(Vec3(
                                pos.x + \
                                x_pos*(cos(rot.y)*cos(rot.z)) + \
                                y_pos*(cos(rot.z)*sin(rot.x)*sin(rot.y) - cos(rot.x)*sin(rot.z)) + \
                                z_pos*(cos(rot.x)*cos(rot.z)*sin(rot.y) + sin(rot.x)*sin(rot.z)), # y * z

                                pos.y + \
                                x_pos*(cos(rot.y)*sin(rot.z)) + \
                                y_pos*(cos(rot.x)*cos(rot.z) + sin(rot.x)*sin(rot.y)*sin(rot.z)) + \
                                z_pos*(cos(rot.x)*sin(rot.y)*sin(rot.z) - cos(rot.z)*sin(rot.x)), # x * z

                                pos.z + \
                                x_pos*(-sin(rot.y)) + \
                                y_pos*(cos(rot.y)*sin(rot.x)) + \
                                z_pos*(cos(rot.x)*cos(rot.y)) # x * y
                        )))

def calculate_vertex(vertex: Vertex) -> tuple[float, float]:
        return (origin.x + (vertex.pos.x-camera.pos.x) * camera.fov/(vertex.pos.z-camera.pos.z),
                origin.y + (vertex.pos.y-camera.pos.y) * camera.fov/(vertex.pos.z-camera.pos.z))

n: Vec3 = Vec3(0, 0, 0)

# drawing
def draw_vertex(vert_id: int, color: str, radius: float) -> None:
        # NOTE: "vert_id" refers to the index of a vertex in th list
        vertex: Vertex = vertices[vert_id]

        pg.draw.circle(screen, color, calculate_vertex(vertex), radius)

def draw_line(vert_id: int, other_vert_id: int, color: str, width: float) -> None:
        vertex: Vertex = vertices[vert_id]
        other_vertex: Vertex = vertices[other_vert_id]

        pg.draw.line(
                screen, color,
                calculate_vertex(vertex),
                calculate_vertex(other_vertex),
                width
        )
        
# wireframe
def draw_plane_wf(vert_id: int, color: str, width: float) -> None:
        if width == 0:
                raise ValueError('it has wf for a reason')

        pg.draw.polygon(
                screen, color, 
                [calculate_vertex(vertices[vert_id]),
                 calculate_vertex(vertices[vert_id + 2]),
                 calculate_vertex(vertices[vert_id + 1]),
                 calculate_vertex(vertices[vert_id + 3])],
                width
                )

# filled in color

def draw_plane(vert_id, color: str) -> None:
        vertex: Vertex = vertices[vert_id]

create_line(Vec3(1, 1, 1), Vec3(-1, -1, 1))
create_plane(Vec3(0, 0, 1), Vec2(1, 1), Vec3.zero())

while running:
        delta: float = clock.tick(60) / 1000

        # loop
        for ev in pg.event.get():
                if ev.type == pg.QUIT:
                        running = False

        # update
        del vertices[2:-1]

        create_plane(Vec3(0, 0, 1), Vec2(1, 1), n)

        n += Vec3(0, tau, 0) * delta

        # draw
        screen.fill('black')

        for i in range(len(vertices)):
                draw_vertex(i, 'white', 2)

        draw_line(0, 1, 'red', 1)
        draw_plane_wf(2, 'green', 2)

        

        pg.display.flip()

And also, only the y-axis is buggy when updating, not the other axes.

0

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.