LightCycles/utils/ground.py

111 lines
4.1 KiB
Python
Executable File

import pygame, math, sys
from pygame.locals import *
DEG_PER_CIRCLE = 128
DEG_TO_RAD = math.pi*2/DEG_PER_CIRCLE
FOV = DEG_PER_CIRCLE/3 # FOV in degrees
PROJDIST = 0.5 #1.5 # Distance to projection plane
PROJHEIGHT = 2.0 # Height of projection screen
PROJBOT = 1.5 # Bottom of projection screen
PROJTOP = PROJBOT+PROJHEIGHT # Top of projection screen
EYEHEIGHT = PROJBOT+PROJHEIGHT/2 # Eye height
HORIZON = 16#200
tex1 = [[(0,0,0),(255,0,0)],[(0,255,0),(0,0,255)]]
s = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
t = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
ds = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
dt = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
def setup(width, height):
global HORIZON
global s, t, ds, dt
print 'ST_TBL ; S, T, DS, DT angle+scanline table'
pixfov = math.tan(FOV/2*DEG_TO_RAD) / width/2
for angle in xrange(DEG_PER_CIRCLE):
viewv = math.sin(angle*DEG_TO_RAD)
viewu = math.cos(angle*DEG_TO_RAD)
scanv = viewu # sin((dirview+90)*DEG_TO_RAD)
scanu = -viewv # cos((dirview+90)*DEG_TO_RAD)
for scanline in xrange(0, height):
if scanline >= HORIZON:
break
scanheight = scanline * PROJHEIGHT / height + PROJBOT
if scanheight >= EYEHEIGHT:
break
scandist = EYEHEIGHT * PROJDIST / (EYEHEIGHT - scanheight)
if scandist > PROJDIST and scandist < 256:
s[scanline][angle] = viewu * scandist
t[scanline][angle] = viewv * scandist
dp = pixfov * scandist
ds[scanline][angle] = scanu * dp
dt[scanline][angle] = scanv * dp
fxs = int(math.floor(s[scanline][angle]*1024+0.5))
fxt = int(math.floor(t[scanline][angle]*1024+0.5))
fxds = int(math.floor(ds[scanline][angle]*65536+0.5))
fxdt = int(math.floor(dt[scanline][angle]*65536+0.5))
# fxs = int(s[scanline][angle]*1024+0.5) # 6.10 fixpt
# fxt = int(t[scanline][angle]*1024+0.5) # 6.10 fixpt
# fxds = int(ds[scanline][angle]*65536+0.5) # 0.16 fixpt
# fxdt = int(dt[scanline][angle]*65536+0.5) # 0.16 fixpt
if fxs < 0:
fxs += 65536
if fxt < 0:
fxt += 65536
if fxds < 0:
fxds += 65536
if fxdt < 0:
fxdt += 65536
print '\t!WORD\t$%04X, $%04X, $%04X, $%04X\t;scan %d angle %d' % (fxs, fxt, fxds, fxdt, scanline, angle)
if scanline > HORIZON:
HORIZON = scanline
def texel(s, t):
return tex1[int(math.floor(s))&1][int(math.floor(t))&1]
def draw(pixbuf, width, height, frame):
xview = 0
yview = 0
dirview = frame%DEG_PER_CIRCLE
for scanline in xrange(HORIZON):
_s = xview + s[scanline][dirview]
_t = yview + t[scanline][dirview]
#
# Draw right half of scanline
#
_ds = ds[scanline][dirview]
_dt = dt[scanline][dirview]
scans = _s + _ds / 2
scant = _t + _dt / 2
for x in xrange(width/2, width):
pixbuf[x][(height-1)-scanline] = texel(scans, scant)
scans += _ds
scant += _dt
#
# Draw left half of scanline
#
scans = _s - _ds / 2
scant = _t - _dt / 2
for x in xrange(width/2-1, -1, -1):
pixbuf[x][(height-1)-scanline] = texel(scans, scant)
scans -= _ds
scant -= _dt
WIDTH = 30#320
HEIGHT = 40#200
pygame.init()
surface = pygame.display.set_mode((WIDTH,HEIGHT))
surfpix = pygame.PixelArray(surface)
frame = 0
setup(WIDTH, HEIGHT)
while True:
draw(surfpix, WIDTH, HEIGHT, frame)
pygame.display.update()
frame += 1
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()