Wednesday, October 16, 2024
spot_img

3d – How do I implement flooring and ceilings correctly to my DOOM Type Renderer?


I am engaged on a tiny DOOM Type Renderer and I’ve managed to piece collectively one thing that may render partitions. I pieced it collectively by taking a look at movies from 3DSage and The Outdated Faculty Coder; I received a clipping perform from Yuriy Georgiev’s Github for his DOOM Type Renderer which mounted my “bending wall” drawback. My aim for this mission is to get one thing working properly sufficient that I can ultimately make a small sport and study some stuff about software program renderers.

Onto my drawback, I’ve tried to make use of the approach 3DSage utilized in his ‘Let’s Program DOOM’ collection and used that for my factor right here. The approach which can be utilized to render flooring and ceilings is the place you save a Y-Place for a column once you’re creating partitions on the ‘high’, then save the ‘backside’ Y-Place which lets you draw a flooring. This does not work, as a result of every time I’m going within a sector or space (no matter you’d prefer to name it), the partitions are all the time backfacing and the ‘x’ index for ‘floorx_ylutT’ is rarely set to Y2.

I might prefer to understand how I ought to repair my drawback and be pushed within the correct course. I am more than pleased to offer extra particulars. Apologies if any of that is poorly written. Thanks upfront

Video showcasing the issue;
https://youtu.be/MewYpAyW0fg

from numba import njit, prange
from clipping import Clipping
from vector import Vector3
import numpy as np
import pygame, math

screenArray = None
W, H = None, None

emptyx_ylut = [0]*320
floorx_ylutT = [0]*320
floorx_ylutB = [0]*320

def clearfloorCeilLut():
    international floorx_ylutT
    international floorx_ylutB
    floorx_ylutT = emptyx_ylut.copy()
    floorx_ylutB = emptyx_ylut.copy()

@staticmethod
@njit(fastmath=True, parallel=True)
def rasterizeFloor(screenArray, floorx_ylutT, floorx_ylutB):
    def canDraw(x, y):
        if x > W-1 or x  H-1 or y  0:
            return False
        return True
    for x in prange(1, W-1):
        pfy1 = floorx_ylutT[x]
        pfy2 = floorx_ylutB[x]
        if pfy1  x1:
        x1, x0 = x0, x1
        y1, y0, y3, y2 = y0, y1, y2, y3
        backfacing = True
    dyb = y1-y0
    dyt = y3-y2
    dx = max(x1-x0, 1)

    i0 = max(min(int(x0), W-1), 1)
    i1 = max(min(int(x1), W-1), 1)
    def canDraw(x, y):
        if x > W-1 or x  H-1 or y  0:
            return False
        return True
    for x in prange(i0, i1):
        Y1=dyb*(x-x0+0.5)/dx+y0
        Y2=dyt*(x-x0+0.5)/dx+y2
        if backfacing:
            floorx_ylutB[x] = Y2
        else:
            floorx_ylutT[x] = Y2
        for y in prange(int(Y2), int(Y1)):
            #y = int(max(min(y, H-1), 1))
            if canDraw(x, y):
                screenArray[x, y] = col            
@staticmethod
@njit(fastmath=True)
def transformVector(v, cs, sn):
    x, y = v
    tx = x*cs-y*sn
    ty = y*cs+x*sn
    return (tx, ty)
@staticmethod
@njit(fastmath=True)
def transformToScreen(f, v):
    x, y, z = v
    y = 1+abs(y)
    sx = (x/y)*f+W/2
    sy = (z/y)*f+H/2
    return (sx, sy)
    
class Engine:
    def __init__(self, w, h, FOV, FocalLength, display screen):
        international screenArray
        international W
        international H
        self.w=w
        self.h=h
        self.w2=w/2
        self.h=h
        self.h2=h/2
        self.FOV=FOV
        self.FocalLength=FocalLength
        self.sin = [0]*360
        self.cos = [0]*360
        self.blankArray = pygame.surfarray.array3d(pygame.floor.Floor((w,h)))
        screenArray = self.blankArray.copy()
        W=w
        H=h
        self.display screen = display screen

        for x in vary(360):
            self.sin[x] = math.sin(x/180*math.pi)
            self.cos[x] = math.cos(x/180*math.pi)
    def clip_behind_player(self, ax, ay, bx, by):
        px1 = 1
        py1 = 1
        px2 = W
        py2 = 1
        a = (px1 - px2) * (ay - py2) - (py1 - py2) * (ax - px2)
        b = (py1 - py2) * (ax - bx) - (px1 - px2) * (ay - by)
        t = a / (b+1)
        ax -= t * (bx - ax)
        ay -= t * (by - ay)
        return ax, ay
    
    def replace(self, degree, character):
        cx, cy, cz = character.x, character.y, character.z
        yaw = int(character.yaw)
        cs = self.cos[yaw]
        sn = self.sin[yaw]
        f = character.FocalLength
        clearfloorCeilLut()
        for sector in degree:
            sector_height = sector[0]
            sector_elevation = sector[1]
            partitions = sector[3]
            for wall in partitions:
                x0, y0, x1, y1, wall_h, wall_clr, wall_portal, portal_bottom, portal_top  = wall
                x0 -= cx
                x1 -= cx
                y0 -= cy
                y1 -= cy
                wx0, wy0 = transformVector((x0, y0), cs, sn)
                wx1, wy1 = transformVector((x1, y1), cs, sn)
                if wy0 ```

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -spot_img

Latest Articles