Skip to content

Instantly share code, notes, and snippets.

@Centrinia
Last active March 3, 2016 08:09
Show Gist options
  • Save Centrinia/637ef4d2a5e9c34acdf8 to your computer and use it in GitHub Desktop.
Save Centrinia/637ef4d2a5e9c34acdf8 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
#import png
import itertools
import time
import numpy as np
import math
import random
import os
import sys
import struct
#import pprint
import re
from fractions import Fraction, gcd
import scipy.ndimage as ndimage
#import svgwrite
import OpenGL.GL as gl
import OpenGL.GLU as glu
from OpenGL.arrays import vbo
from OpenGL.GL import shaders
import pygame
STEREOSCOPIC=False
def normalize(x):
n = np.linalg.norm(x)
if n != 0:
return x/n
else:
return x
def dot_product(a, b):
return sum(x * y for (x, y) in zip(a, b))
def line_distance(l, a):
return dot_product(l['normal'], a) - l['dist']
def segment_length_squared(s):
return sum([(x-y)*(x-y) for (x, y) in zip(s[0], s[1])])
def normalize_integer(x):
return (1 if x > 0 else 0) - (1 if x < 0 else 0)
def intersect_lines(a, b):
det = a['normal'][0] * b['normal'][1] - a['normal'][1] * b['normal'][0]
detx = a['dist'] * b['normal'][1] - a['normal'][1] * b['dist']
dety = a['normal'][0] * b['dist'] - a['dist'] * b['normal'][0]
if abs(det) == 1:
return [detx*det, dety*det]
elif det != 0:
return [Fraction(detx, det), Fraction(dety, det)]
else:
return None
def make_line(seg):
t = [b-a for (b, a) in zip(seg[1], seg[0])]
# The normal points toward the left of the directed segment starting with the endpoint seg[0]
n = [-t[1], t[0]]
return {'normal': n, 'tangent': t, 'dist': sum([a * b for (a, b) in zip(n, seg[0])])}
def split_polygon(invertexes, splitter):
vertexes = [[], []]
circular_vertexes = invertexes+invertexes[:1]
previous_side = None
for v in reversed(invertexes):
previous_side = normalize_integer(line_distance(splitter, v))
if previous_side != 0:
break
#print('splitter: {}'.format(splitter_edge['name']))
#print('split: {}, {}'.format(splitter_edge, splitter))
for i in range(len(invertexes)):
vertex = circular_vertexes[i:i+2]
line = make_line(vertex)
intersection = intersect_lines(splitter, line)
# Determine which side of the splitter the current vertex is on.
sides = [normalize_integer(line_distance(splitter, v)) for v in vertex]
if sides[0] != 0:
side_index = (sides[0]+1)//2
else:
side_index = (previous_side+1)//2
# If there was an intersection on the line segment, then add it to both output polygons.
if intersection is not None and sides[0]*sides[1] < 0:
#if sides[0]*sides[1] < 0:
# Add the vertex to the output polygon that is on the same side of the splitter. Annotate the edge with the current splitter.
vertexes[side_index].append(vertex[0])
# Add the intersection to the polygon on the other side of the splitter. The edge is the originating edge and is also annotated with the splitter.
vertexes[1-side_index].append(intersection)
# Add the intersection to the polygon on the same side of the splitter. The edge is the splitter edge.
vertexes[side_index].append(intersection)
previous_side = sides[0]
elif sides[0] * sides[1] > 0 or sides[0] != 0:
# Add the vertex to the output polygon that is on the same side of the splitter.
vertexes[side_index].append(vertex[0])
previous_side = sides[0]
elif sides[0] == 0 and sides[1] == 0:
vertexes[1-side_index].append(vertex[0])
# The vertex is on the splitter. Add it to the polygon on the same side of the splitter and annotate its edge with the splitter.
vertexes[side_index].append(vertex[0])
elif sides[0] == 0 and sides[1] != 0:
if previous_side == sides[1]:
vertexes[side_index].append(vertex[0])
else:
vertexes[side_index].append(vertex[0])
vertexes[1-side_index].append(vertex[0])
return tuple(vertexes)
def vector_add(p0, p1):
return tuple([a+b for (a, b) in zip(list(p0), list(p1))])
def rotation_matrix(axis, theta):
a = math.cos(theta/2)
b, c, d = -normalize(axis)*math.sin(theta/2)
return np.array(
[[a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(b*d+a*c)],
[2*(b*c+a*d), a*a+c*c-b*b-d*d, 2*(c*d-a*b)],
[2*(b*d-a*c), 2*(c*d+a*b), a*a+d*d-b*b-c*c]])
ANGLE_TO_RADIANS = math.pi / 180
class Player:
UP_VECTOR = np.array([0, 0, 1])
def __init__(self, viewpoint=[0.0, 0.0, 0.0], direction=0.0, pitch=0.0):
cs = math.cos(direction)
sn = math.sin(direction)
pcs = math.cos(pitch)
psn = math.sin(pitch)
self.direction = normalize(np.array([cs*pcs, sn*pcs, psn], dtype=np.float64))
self.viewpoint = np.array(viewpoint, dtype=np.float64)
def move_forward(self, step):
self.viewpoint += self.direction * step
def move_left(self, step):
left_vector = np.cross(self.direction, -self.UP_VECTOR)
self.viewpoint += left_vector * step
def move_up(self, step):
self.viewpoint += self.UP_VECTOR * step
def turn_left(self, angle):
self.direction = np.dot(rotation_matrix(self.UP_VECTOR, -angle), self.direction)
def look_up(self, angle):
right_vector = np.cross(self.direction, self.UP_VECTOR)
new_direction = np.dot(rotation_matrix(right_vector, -angle), self.direction)
if abs(np.dot(new_direction, self.UP_VECTOR)) < (1-1e-2):
self.direction = new_direction
def update_OpenGL(self, iod=0, focal_distance=None):
scale_factor = 1/100.0
right_vector = np.cross(self.direction, self.UP_VECTOR)
if focal_distance is not None:
glu.gluLookAt(*tuple(list(self.viewpoint+right_vector * (iod / 2)) +
list(self.direction*focal_distance + self.viewpoint) + list(self.UP_VECTOR)))
else:
glu.gluLookAt(*tuple(list(self.viewpoint+right_vector*(iod/2))+
list(self.direction+self.viewpoint+right_vector*(iod/2))+list(self.UP_VECTOR)))
def pitch_angle(self):
cs = np.linalg.norm(self.direction[0:1])
sn = self.direction[2]
return math.atan2(sn, cs)
def direction_angle(self):
cs = self.direction[0]
sn = self.direction[1]
angle = math.atan2(sn, cs)
return angle
def set_angle(self, direction, pitch=0):
cs = math.cos(direction)
sn = math.sin(direction)
pcs = math.cos(pitch)
psn = math.sin(pitch)
self.direction = normalize(np.array([cs*pcs, sn*pcs, psn], dtype=np.float64))
def set_elevation(self, z):
self.viewpoint[2] = z
def get_position(self):
return self.viewpoint[:]
def set_position(self, pos):
self.viewpoint = pos[:]
# The wad file lump strings have a constant length are padded with null bytes at the end.
# This function will convert a lump string into a python string.
def parse_string8(b):
return b.decode('ascii', 'ignore').partition('\0')[0]
# Load all of the levels in a wad file.
def level_lumps(wad, directory, mapname=None, wadtype = 'doom'):
levels = {}
level = None
level_name_regex = re.compile('MAP\d\d|E\d\M\d')
#parse_node_child_link = lambda c: ('subsector', c&0x7fff) if c & 0x8000 != 0 else ('node', c)
parse_node_child_link = lambda c: ('subsector', c&0x7fff) if c & 0x8000 != 0 else ('node', c&0x7fff)
if wadtype == 'hexen':
lump_fields = {
'THINGS': ['tid', 'x_position', 'y_position', 'height', 'angle', 'type', 'options', 'action', 'arguments'],
'LINEDEFS': ['vertex_start', 'vertex_end', 'flags', 'function', 'arguments', 'sidedef_right', ('sidedef_left', lambda l: None if l==-1 else l)],
'SIDEDEFS': ['xoffset', 'yoffset', ('uppertexture', parse_string8), ('lowertexture', parse_string8), ('middletexture', parse_string8), 'sector_ref'],
'VERTEXES': ['X_coord', 'Y_coord'],
'SEGS': ['vertex_start', 'vertex_end', 'bams', 'line_num', 'segside', 'segoffset'],
'SSECTORS': ['numsegs', 'start_seg'],
'NODES': ['x', 'y', 'dx', 'dy', 'box0top', 'box0bottom', 'box0left', 'box0right', 'box1top', 'box1bottom', 'box1left', 'box1right', ('child0', parse_node_child_link), ('child1', parse_node_child_link)],
'SECTORS': ['floorheight', 'ceilingheight', ('floorpic', parse_string8), ('ceilingpic', parse_string8), 'lightlevel', 'special_sector', 'tag']
}
parse_lump_format = {
'THINGS': struct.Struct('<7hc5s'),
'LINEDEFS': struct.Struct('<3hc5s2h'),
'SIDEDEFS': struct.Struct('<2h8s8s8sh'),
'VERTEXES': struct.Struct('<2h'),
'SEGS': struct.Struct('<6h'),
'SSECTORS': struct.Struct('<2h'),
'NODES': struct.Struct('<4h8h2H'),
'SECTORS': struct.Struct('<2h8s8s3h')
}
else:
lump_fields = {
'THINGS': ['x_position', 'y_position', 'angle', 'type', 'options'],
'LINEDEFS': ['vertex_start', 'vertex_end', 'flags', 'function', 'tag', 'sidedef_right', ('sidedef_left', lambda l: None if l==-1 else l)],
'SIDEDEFS': ['xoffset', 'yoffset', ('uppertexture', parse_string8), ('lowertexture', parse_string8), ('middletexture', parse_string8), 'sector_ref'],
'VERTEXES': ['X_coord', 'Y_coord'],
'SEGS': ['vertex_start', 'vertex_end', 'bams', 'line_num', 'segside', 'segoffset'],
'SSECTORS': ['numsegs', 'start_seg'],
'NODES': ['x', 'y', 'dx', 'dy', 'box0top', 'box0bottom', 'box0left', 'box0right', 'box1top', 'box1bottom', 'box1left', 'box1right', ('child0', parse_node_child_link), ('child1', parse_node_child_link)],
'SECTORS': ['floorheight', 'ceilingheight', ('floorpic', parse_string8), ('ceilingpic', parse_string8), 'lightlevel', 'special_sector', 'tag']
}
parse_lump_format = {
'THINGS': struct.Struct('<5h'),
'LINEDEFS': struct.Struct('<7h'),
'SIDEDEFS': struct.Struct('<2h8s8s8sh'),
'VERTEXES': struct.Struct('<2h'),
'SEGS': struct.Struct('<6h'),
'SSECTORS': struct.Struct('<2h'),
'NODES': struct.Struct('<4h8h2H'),
'SECTORS': struct.Struct('<2h8s8s3h')
}
LEVEL_LUMP_NAMES = ['THINGS', 'LINEDEFS', 'SIDEDEFS', 'VERTEXES', 'SEGS', 'SSECTORS', 'NODES', 'SECTORS', 'REJECT', 'BLOCKMAP']
for lump in directory:
if level_name_regex.match(lump['name']):
if level and not (mapname is not None and level['name'] != mapname):
levels[level['name']] = level
level = {'name':lump['name']}
# Skip this level if it is not the selected map.
if mapname is not None and level is not None and level['name'] != mapname:
continue
if lump['name'] in LEVEL_LUMP_NAMES and lump['name'] in parse_lump_format:
lump_name = lump['name']
parser = parse_lump_format[lump_name]
fields = lump_fields[lump_name]
wad.seek(lump['filepos'])
entries = []
for i in range(lump['size'] // parser.size):
values = parser.unpack(wad.read(parser.size))
entry = {'id':i}
for (field, value) in zip(fields, values):
if isinstance(field, tuple):
(fieldname, field_parser) = field
entry[fieldname] = field_parser(value)
else:
entry[field] = value
entries.append(entry)
level[lump_name] = entries
#level[lump['name']] = load_level_lump[lump['name']](lump)
if level and not (mapname is not None and level['name'] != mapname):
levels[level['name']] = level
return levels
def load_colormaps(wad, directory):
lump = directory['COLORMAP']
wad.seek(lump['filepos'])
data = wad.read(256*34)
palette = load_palette(wad, directory)
colormaps = np.zeros([256, 34, 4], dtype=np.uint8)
for i in range(34):
colormap = data[i*256:(i+1)*256]
#colormaps += [list(colormap)]
#colormaps[:, i] = list(data[i*256:(i+1)*256])
for j in range(256):
colormaps[j, i, :] = palette[colormap[j]]
#colormaps[j, i, :] = palette[j]
return colormaps
def load_palette(wad, directory, index=0):
lump = directory['PLAYPAL']
wad.seek(lump['filepos']+index*256*3)
data = wad.read(256*3)
colors = np.zeros([256, 4], dtype=np.uint8)
for i in range(256):
colors[i, :3] = list(data[i*3:(i+1)*3])
colors[i, 3] = 255
return colors
def load_flat(wad, lump):
wad.seek(lump['filepos'])
data = list(wad.read(64**2))
return {'width':64,
'height':64,
'left': 0,
'top': 0,
'data': data}
def least_twoexp(x):
i = 1
while i < x:
i *= 2
return i
def read_texture(wad, directory, texture):
data = [None] * texture['width']*texture['height']
for patch in texture['patches']:
patch_name = patch['name']
load_picture(data, wad, directory[patch_name.upper()], (texture['width'], texture['height']), patch['origin'])
#for i in range(len(data)):
# data[i] = random.randint(0, 255)
return {'width':texture['width'],
'height':texture['height'],
'data':data}
def write_texture(tex, name):
fn = 'textures/{}.png'.format(name.lower())
wrt = png.Writer(width=tex['width'], height=tex['height'], palette=palette)
with open(fn, 'wb') as of:
wrt.write_array(of, [(0 if x is None else x) for x in list(tex['data'])])
def load_picture(data, wad, lump, texsize, origin=(0, 0)):
wad.seek(lump['filepos'])
width, height, left, top = struct.unpack('<4h', wad.read(8))
columns = list(struct.unpack('<{}I'.format(width), wad.read(4*width)))
originx, originy = origin
for i, column in enumerate(columns):
x = i+originx
if x < 0: continue
if x >= texsize[0]: break
wad.seek(lump['filepos'] + column)
while True:
rowstart = wad.read(1)[0]
if rowstart == 255:
break
pixel_count = wad.read(1)[0]
pixels = wad.read(pixel_count+2)
for j in range(pixel_count):
#x = i+originx+left
#y = j+rowstart+originy+top
y = j+rowstart+originy
if y < 0: continue
if y >= texsize[1]: break
data[y*texsize[0]+x] = pixels[j+1]
return {'width':width,
'height':height,
'left':left,
'top':top}
def render_level(filename, mapname, wadtype = 'doom'):
with open(filename, "rb") as wad:
magic, numlumps, infotableofs = struct.unpack('<4sII', wad.read(12))
#print("{} {} {}".format(magic, numlumps, infotableofs))
#if : print('Hexen!')
# Load the directory table.
directory = []
wad.seek(infotableofs)
directory_map = {}
for _ in range(numlumps):
filepos, size, name = struct.unpack('<II8s', wad.read(16))
if 'VERBOSE_OUTPUT' in os.environ:
print("{} at {} with {} bytes".format(parse_string8(name), filepos, size))
entry = {'filepos':filepos, 'size':size, 'name':parse_string8(name)}
directory.append(entry)
directory_map[entry['name']] = entry
#pprint.pprint(directory)
#pprint.pprint(directory[start_index:end_index])
#pprint.pprint(level_lumps(wad, directory, mapname))
#pprint.pprint(level_lumps(wad, directory, mapname))
for level in level_lumps(wad, directory, mapname, wadtype).values():
vertexes = level['VERTEXES']
segs = level['SEGS']
linedefs = level['LINEDEFS']
sidedefs = level['SIDEDEFS']
nodes = level['NODES']
subsectors = level['SSECTORS']
sectors = level['SECTORS']
things = level['THINGS']
#pprint.pprint(level)
for subsector in subsectors:
s = subsector['start_seg']
n = subsector['numsegs']
#pprint.pprint([(seg['vertex_start'], seg['vertex_end']) for seg in segs[s:s+n]])
#print('\n')
sector_refs = []
for seg in segs[s:s+n]:
linedef = linedefs[seg['line_num']]
sidedef_index = linedef['sidedef_' + ('right' if seg['segside'] == 0 else 'left')]
sector_ref = sidedefs[sidedef_index]['sector_ref']
sector_refs += [sector_ref]
subsector['sector_ref'] = sector_ref
if min(sector_refs) != max(sector_refs):
print(sector_refs)
sys.exit(0)
for sector in sectors:
sector['color'] = tuple([random.randint(0, 100) for _ in range(3)] + ['%'])
#'NODES': ['x', 'y', 'dx', 'dy', 'box0top', 'box0bottom', 'box0left', 'box0right', 'box1top', 'box1bottom', 'box1left', 'box1right', ('child0', parse_node_child_link), ('child1', parse_node_child_link)],
bbpadding = 16
bb = [[min([v['X_coord'] for v in vertexes])-bbpadding,
min([v['Y_coord'] for v in vertexes])-bbpadding],
[max([v['X_coord'] for v in vertexes])+bbpadding,
max([v['Y_coord'] for v in vertexes])+bbpadding]]
outer_vertexes = list([bb[1], [bb[1][0], bb[0][1]], bb[0], [bb[0][0], bb[1][1]]])
nodes[-1]['hull'] = outer_vertexes
#def traverse_node(node):
for node in reversed(nodes):
def get_vertex(n, p=''):
return tuple([n[p+k] for k in ['x', 'y']])
node['splitter'] = make_line([
get_vertex(node),
vector_add(get_vertex(node), get_vertex(node, 'd'))])
if 'hull' not in node:
continue
for i, sub in enumerate(split_polygon(node['hull'], node['splitter'])):
_, child_index = node['child{}'.format(i)]
if node['child{}'.format(i)][0] == 'node':
nodes[child_index]['hull'] = sub
#traverse_node(nodes[child_index])
if child_index >= node['id']:
print('error')
print(node)
sys.exit(0)
else:
subsectors[child_index]['hull'] = sub
#traverse_node(nodes[-1])
for subsector in subsectors:
if 'hull' not in subsector: continue
hull = subsector['hull']
s = subsector['start_seg']
n = subsector['numsegs']
for seg in segs[s:s+n]:
vs = [tuple([vertexes[vertex_index][k + '_coord'] for k in ['X', 'Y']])
for vertex_index in [seg['vertex_' + k] for k in ['start', 'end']]]
segline = make_line(vs)
hull, _ = split_polygon(hull, segline)
subsector['hull'] = hull
#split_polygon(hull, segline)
sf = 2000
aspect_ratio = (bb[1][1] - bb[0][1]) / (bb[1][0]-bb[0][0])
if aspect_ratio > 1:
scale_factor = [sf/aspect_ratio, sf]
else:
scale_factor = [sf, sf * aspect_ratio]
palette = load_palette(wad, directory_map)
colormaps = load_colormaps(wad, directory_map)
if False:
# Make svg.
dwg = svgwrite.Drawing('out.svg', profile='tiny')
PADDING = 20
dwg.viewbox(minx=0, miny=0, width=scale_factor[0]+2*PADDING, height=scale_factor[1]+2*PADDING)
sgrp = dwg.g()
sgrp.fill(opacity=0)
sgrp.translate(tx=PADDING, ty=PADDING)
sgrp.translate(tx=0, ty=1)
sgrp.scale(sx=scale_factor[0], sy=scale_factor[1])
sgrp.translate(tx=0, ty=1)
sgrp.scale(sx=1/(bb[1][0]-bb[0][0]), sy=-1/(bb[1][1]-bb[0][1]))
sgrp.translate(tx=-bb[0][0], ty=-bb[0][1])
grp = dwg.g()
grp.stroke(color='gray', width=5)
for subsector in subsectors:
if 'hull' not in subsector: continue
if len(subsector['hull']) == 0: continue
vs = [[float(c) for c in v] for v in subsector['hull']]
#e = dwg.polygon(points=vs, fill=svgwrite.rgb(*sector_colors[poly.get_aux()['sector']['aux']['id']]))
sector = sectors[subsector['sector_ref']]
e = dwg.polygon(points=vs)
e.fill(color=svgwrite.rgb(*sector['floorcolor']))
grp.add(e)
sgrp.add(grp)
dwg.add(sgrp)
dwg.save()
# Get PNAMES
wad.seek(directory_map['PNAMES']['filepos'])
nummappatches, = struct.unpack('<I', wad.read(4))
pnames = []
for _ in range(nummappatches):
pname = parse_string8(wad.read(8))
pnames += [pname]
# Load texture data.
textures = {}
textures['-'] = {'width':1, 'height': 1}
for tdname in ['TEXTURE{}'.format(k) for k in [1, 2]]:
if tdname not in directory_map: continue
tdoffset = directory_map[tdname]['filepos']
wad.seek(tdoffset)
numtextures, = struct.unpack('<I', wad.read(4))
offsets = list(struct.unpack('<{}I'.format(numtextures), wad.read(4*numtextures)))
for offset in offsets:
wad.seek(tdoffset+offset)
if wadtype == 'strife':
texture_name, _, width, height, patchcount = struct.unpack('<8sIhhh', wad.read(18))
else:
texture_name, _, width, height, _, patchcount = struct.unpack('<8sIhhIh', wad.read(22))
texture_name = parse_string8(texture_name)
texture = {
'name':texture_name,
'width':width,
'height':height,
'texheight': least_twoexp(height),
'patches': []}
for _ in range(patchcount):
if wadtype == 'strife':
originx, originy, patch = struct.unpack('<3h', wad.read(6))
else:
originx, originy, patch, _, _ = struct.unpack('<5h', wad.read(10))
texture['patches'] += [{
'origin': (originx, originy),
'name': pnames[patch]}]
textures[texture_name] = texture
# Group subsectors by texture.
flat_groups = {}
texture_groups = {}
def texture_group_insert(groups, pic, item):
if pic not in groups: groups[pic] = {'items':[]}
groups[pic]['items'] += [item['id']]
for subsector in subsectors:
sector = sectors[subsector['sector_ref']]
texture_group_insert(flat_groups, sector['ceilingpic'], subsector)
texture_group_insert(flat_groups, sector['floorpic'], subsector)
for seg in segs:
linedef = linedefs[seg['line_num']]
sidedef_index = linedef['sidedef_' + ('right' if seg['segside'] == 0 else 'left')]
sidedef = sidedefs[sidedef_index]
texture_group_insert(texture_groups, sidedef['uppertexture'], seg)
texture_group_insert(texture_groups, sidedef['middletexture'], seg)
texture_group_insert(texture_groups, sidedef['lowertexture'], seg)
for name in texture_groups.keys():
if name == '-': continue
texture_groups[name]['width'] = 1
texture_groups[name]['texheight'] = 1
texture_groups[name]['height'] = 1
texture_groups[name]['picture'] = read_texture(wad, directory_map, textures[name.upper()])
for name in flat_groups.keys():
if name == '-': continue
flat_groups[name]['picture'] = load_flat(wad, directory_map[name])
sky_pictures = {}
for k in ['{}SKY{}'.format(s, i+1) for i in range(4) for s in ['', 'R']]:
if k not in directory_map: continue
data = [None] * 256*128
load_picture(data, wad, directory_map[k], (256, 128))
sky_pictures[k] = {'width':256, 'height':256, 'texheight':256, 'data':data+data}
if wadtype == 'strife':
for k in ['SKYMNT0{}'.format(i+1) for i in range(2)]:
sky_pictures[k] = read_texture(wad, directory_map, textures[k.upper()])
if False:
#for name in textures.keys():
for name in texture_groups.keys():
if name == '-': continue
#tex = read_texture(wad, directory_map, textures[name.upper()])
write_texture(texture_normal(texture_groups[name]['picture']), name)
sys.exit(0)
#pprint.pprint(bsp.root())
#pprint.pprint(directory[start_index:end_index])
#pprint.pprint(directory[start_index:end_index])
#pprint.pprint(directory[start_index:end_index])
def traverse_bsp(node, position):
side_index = (normalize_integer(line_distance(node['splitter'], position))+1)//2
child_type, child_index = node['child{}'.format(side_index)]
if child_type == 'node':
return traverse_bsp(nodes[child_index], position)
else:
return subsectors[child_index]
player_start = [0, 0]
for thing in things:
if thing['type'] == 1:
player_start = [thing[k + '_position'] for k in ['x', 'y']]
player_start += [sectors[traverse_bsp(nodes[-1], player_start)['sector_ref']]['floorheight'] + 56//2]
# Play the level.
pygame.init()
#(screenx, screeny)=(1280, 720)
if STEREOSCOPIC:
#(screenx, screeny)=(800, 600)
(screenx, screeny)=(1200, 600)
else:
(screenx, screeny)=(1600, 900)
pygame.display.set_mode((screenx, screeny), pygame.OPENGL|pygame.DOUBLEBUF)
pygame.display.gl_set_attribute(pygame.GL_STEREO, 1)
print(pygame.display.gl_get_attribute(pygame.GL_STEREO))
#gl.glClearColor(0.0, 0.0, 0.0, 1.0)
gl.glClearColor(0.0, 0.0, 0.0, 1.0)
gl.glMatrixMode(gl.GL_PROJECTION)
def perspective(fov, aspect, near, far):
t = near * math.tan(fov*math.pi/360)
r = t*aspect
gl.glFrustum(-r, r, -t, t, near, far)
perspective(90, 1.0*screenx/screeny, 0.001, 10000)
gl.glMatrixMode(gl.GL_MODELVIEW)
player = Player(player_start, math.pi/2)
#player = Player()
done = False
gl.glFrontFace(gl.GL_CW)
#gl.glFrontFace(gl.GL_CCW)
gl.glEnable(gl.GL_CULL_FACE)
#gl.glDisable(gl.GL_CULL_FACE)
gl.glEnable(gl.GL_DEPTH_TEST)
#gl.glEnable(gl.GL_BLEND)
pygame.key.set_repeat(10, 5)
gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
gl.glEnableClientState(gl.GL_INDEX_ARRAY)
#for sector in sectors:
# print(sector['lightlevel'])
#for subsector in subsectors:
# pprint.pprint(subsector)
def produce_wall(seg, lower, upper, texture, sector, level=0, two_sided=True):
vs = [[vertexes[vertex_index][k + '_coord'] for k in ['X', 'Y']]
for vertex_index in [seg['vertex_' + k] for k in ['start', 'end']]]
v3 = [vs[0] + [upper],
vs[1] + [upper],
vs[1] + [lower],
vs[0] + [lower]]
#t2 = [[0, 0], [1, 0], [1, 1], [0, 1]]
wall_length = np.linalg.norm(np.array(vs[0])-np.array(vs[1]))
wall_height = upper-lower
#print(wall_length)
#print(texture)
linedef = linedefs[seg['line_num']]
sidedef_index = linedef['sidedef_' + ('right' if seg['segside'] == 0 else 'left')]
sidedef = sidedefs[sidedef_index]
ceiling = sectors[sidedef['sector_ref']]['ceilingheight']
floor = sectors[sidedef['sector_ref']]['floorheight']
#print(sidedef, seg)
#print(seg['segoffset']+sidedef['xoffset'])
#offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset'], 0], dtype=np.float32)
if level>0:
if (linedef['flags'] & 0x18) == 0:
t = wall_height + texture['height']**2 / texture['texheight']
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset']-t, 0], dtype=np.float32)
else:
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset'], 0], dtype=np.float32)
elif level < 0:
#offset = np.array([seg['segoffset']+sidedef['xoffset'], -upper+ceiling-sidedef['yoffset'], 0], dtype=np.float32)
if (linedef['flags'] & 0x10) > 0:
voffset = floor - ceiling
t = wall_height + texture['height']**2 / texture['texheight']
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset']-voffset-t, 0], dtype=np.float32)
else:
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset'], 0], dtype=np.float32)
else:
# TODO: Correct middle textures for two sided linedefs.
if (linedef['flags'] & 0x10) > 0:
t = wall_height + texture['height']**2 / texture['texheight']
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset']-t, 0], dtype=np.float32)
else:
offset = np.array([seg['segoffset']+sidedef['xoffset'], sidedef['yoffset'], 0], dtype=np.float32)
offset /= np.array([texture['width'], texture['height'], 1], dtype=np.float32)
# yoffset+upper sector floor height = 0 (mod texture height)
#print(offset)
#print(sidedef)
t2 = [None]*4
t2[0] = [0, 0, 0]
t2[1] = [0, 0, 0]
t2[2] = [0, 0, 0]
t2[3] = [0, 0, 0]
t2[1][0] = wall_length/texture['width']
t2[2][0] = wall_length/texture['width']
t2[2][1] = wall_height/texture['texheight']
t2[3][1] = wall_height/texture['texheight']
v3 = [np.array(v, dtype=np.float32) for v in v3]
t2 = [np.array(t+offset, dtype=np.float32) for t in t2]
# Bli78
normal = normalize(np.cross(v3[3]-v3[0], v3[1]-v3[0]))
#normal = (np.cross(v3[3]-v3[0], v3[1]-v3[0]))
#normal /= math.sqrt(np.linalg.norm(normal))
tangent = v3[1] - v3[0]
bitangent = v3[3] - v3[0]
tangent_lengths = np.array([np.linalg.norm(v) for v in [tangent, bitangent, normal]], dtype=np.float32)
for v, n in zip([tangent, bitangent, normal], tangent_lengths):
if n != 0:
v /= n
lightlevel = (sector['lightlevel'] >> 3) & 31
for vertex, texcoord in zip(v3, t2):
texcoord[2] = lightlevel
yield np.append(vertex, [normal, texcoord, tangent, bitangent, tangent_lengths])
def produce_flat(hull, height, sector, is_ceiling=False):
normal = np.array([0, 0, -1 if is_ceiling else 1], dtype=np.float32)
#tangent = normalize(np.array(hull[-1 if is_ceiling else 1]+[height], dtype=np.float32) - np.array(hull[0]+[height], dtype=np.float32))
tangent = np.array([64, 0, 0], dtype=np.float32)
bitangent = np.array([0, -64, 0], dtype=np.float32)
tangent_lengths = np.array([np.linalg.norm(v) for v in [tangent, bitangent, normal]], dtype=np.float32)
for v, n in zip([tangent, bitangent, normal], tangent_lengths):
if n != 0:
v /= n
lightlevel = (sector['lightlevel'] >> 3) & 31
for v in (reversed(hull) if is_ceiling else hull):
vertex = np.array(v + [height], dtype=np.float32)
texcoord = np.array([1, -1, 0], dtype=np.float32)*np.array(v[:2]+[0], dtype=np.float32)/64
texcoord[2] = lightlevel
yield np.append(vertex, [normal, texcoord, tangent, bitangent, tangent_lengths])
if wadtype == 'hexen':
SKY_FLAT = 'F_SKY'
elif wadtype == 'strife':
SKY_FLAT = 'F_SKY001'
else:
SKY_FLAT = 'F_SKY1'
vertex_array = []
index_array = []
starting_index = 0
index_count = 0
for picname, group in flat_groups.items():
group['starting index'] = index_count
group['ending index'] = index_count
group['count'] = 0
if picname == '-': continue
if picname == SKY_FLAT: continue
triangle_count = 0
group['starting index'] = index_count
for subsector in [subsectors[i] for i in group['items']]:
if len(subsector['hull']) < 3: continue
sector = sectors[subsector['sector_ref']]
# Make floors.
if sector['floorpic'] == picname:
vertex_array += [list(produce_flat(subsector['hull'], sector['floorheight'], sector))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, len(subsector['hull'])-1)], []))),
dtype=np.int32)]
starting_index += len(subsector['hull'])
triangle_count += len(subsector['hull']) - 2
index_count += (len(subsector['hull'])-2)*3
# Make ceilings.
if sector['ceilingpic'] == picname:
vertex_array += [list(produce_flat(subsector['hull'], sector['ceilingheight'], sector, is_ceiling=True))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, len(subsector['hull'])-1)], []))),
dtype=np.int32)]
starting_index += len(subsector['hull'])
triangle_count += len(subsector['hull']) - 2
index_count += (len(subsector['hull'])-2)*3
group['ending index'] = index_count
group['count'] = triangle_count
for picname, group in texture_groups.items():
group['starting index'] = index_count
group['ending index'] = index_count
group['count'] = 0
if picname == '-': continue
triangle_count = 0
# Make walls.
group['starting index'] = index_count
for seg in [segs[i] for i in group['items']]:
linedef = linedefs[seg['line_num']]
sidedef_index = linedef['sidedef_' + ('right' if seg['segside'] == 0 else 'left')]
other_sidedef_index = linedef['sidedef_' + ('left' if seg['segside'] == 0 else 'right')]
sidedef = sidedefs[sidedef_index]
sector = sectors[sidedef['sector_ref']]
if other_sidedef_index is None:
if picname == sidedef['middletexture']:
vertex_array += [list(produce_wall(seg, sector['floorheight'], sector['ceilingheight'], textures[picname.upper()], sector, two_sided=False))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
else:
other_sidedef = sidedefs[other_sidedef_index]
other_sector = sectors[other_sidedef['sector_ref']]
# Make upper wall.
if picname == sidedef['uppertexture'] and sector['ceilingheight'] > other_sector['ceilingheight']:
if other_sector['ceilingpic'] != SKY_FLAT:
vertex_array += [list(produce_wall(seg, other_sector['ceilingheight'], sector['ceilingheight'], textures[picname.upper()], sector, 1))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
# Make lower wall.
if picname == sidedef['lowertexture'] and sector['floorheight'] < other_sector['floorheight']:
if other_sector['floorpic'] != SKY_FLAT:
vertex_array += [list(produce_wall(seg, sector['floorheight'], other_sector['floorheight'], textures[picname.upper()], sector, -1))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
# Make middle wall.
if picname == sidedef['middletexture'] and \
sector['floorheight'] < other_sector['ceilingheight'] and \
other_sector['floorheight'] < other_sector['ceilingheight'] and \
other_sector['floorheight'] < sector['ceilingheight']:
texture_height = min(128, other_sector['ceilingheight']-other_sector['floorheight'])
vertex_array += [list(produce_wall(seg, other_sector['floorheight'], other_sector['floorheight']+texture_height, textures[picname.upper()], sector, 0))]
#vertex_array += [list(produce_wall(seg, other_sector['floorheight'], other_sector['ceilingheight'], textures[picname.upper()], 0))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
group['ending index'] = index_count
group['count'] = triangle_count
# Collect sky wall textures.
sky_group = {}
data = []
if mapname[0] == 'E' and mapname[2] == 'M':
sky_name = 'SKY{}'.format(int(mapname[1]))
elif mapname[:3] == 'MAP':
map_index = int(mapname[3:])
sky_index = 1 if map_index <= 11 else 2 if map_index <=20 else 3
sky_name = 'RSKY{}'.format(sky_index)
if sky_name in sky_pictures:
sky_group['picture'] = sky_pictures[sky_name]
else:
sky_group['picture'] = sky_pictures[list(sky_pictures.keys())[0]]
sky_group['flat starting index'] = index_count
triangle_count = 0
for subsector in subsectors:
if len(subsector['hull']) < 3: continue
sector = sectors[subsector['sector_ref']]
# Make floors.
if sector['floorpic'] == SKY_FLAT:
vertex_array += [list(produce_flat(subsector['hull'], sector['floorheight'], sector))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, len(subsector['hull'])-1)], []))),
dtype=np.int32)]
starting_index += len(subsector['hull'])
triangle_count += len(subsector['hull']) - 2
index_count += (len(subsector['hull'])-2)*3
# Make ceilings.
if sector['ceilingpic'] == SKY_FLAT:
vertex_array += [list(produce_flat(subsector['hull'], sector['ceilingheight'], sector, is_ceiling=True))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, len(subsector['hull'])-1)], []))),
dtype=np.int32)]
starting_index += len(subsector['hull'])
triangle_count += len(subsector['hull']) - 2
index_count += (len(subsector['hull'])-2)*3
sky_group['flat ending index'] = index_count
sky_group['flat count'] = triangle_count
min_height = sectors[0]['floorheight']
max_height = sectors[0]['ceilingheight']
for sector in sectors[1:]:
min_height = min(min_height, sector['floorheight'])
max_height = max(max_height, sector['ceilingheight'])
sky_group['wall starting index'] = index_count
triangle_count = 0
for seg in segs:
linedef = linedefs[seg['line_num']]
sidedef_index = linedef['sidedef_' + ('right' if seg['segside'] == 0 else 'left')]
other_sidedef_index = linedef['sidedef_' + ('left' if seg['segside'] == 0 else 'right')]
sidedef = sidedefs[sidedef_index]
sector = sectors[sidedef['sector_ref']]
if other_sidedef_index is not None:
other_sidedef = sidedefs[other_sidedef_index]
other_sector = sectors[other_sidedef['sector_ref']]
if sector['floorheight'] < other_sector['floorheight'] and other_sector['floorpic'] == SKY_FLAT:
vertex_array += [list(produce_wall(seg, sector['floorheight'], other_sector['floorheight'], textures[picname.upper()], sector, -1))]
#vertex_array += [list(produce_wall(seg, min_height, other_sector['floorheight'], textures[picname.upper()], -1))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
if other_sector['ceilingheight'] < sector['ceilingheight'] and other_sector['ceilingpic'] == SKY_FLAT:
vertex_array += [list(produce_wall(seg, other_sector['ceilingheight'], sector['ceilingheight'], textures[picname.upper()], sector, 1))]
#vertex_array += [list(produce_wall(seg, other_sector['ceilingheight'], max_height, textures[picname.upper()], 1))]
index_array += [np.array(
list(map(lambda i:i+starting_index, sum([[0, i, i+1] for i in range(1, 3)], []))),
dtype=np.int32)]
starting_index += 4
triangle_count += 2
index_count += 6
index_count += 6
sky_group['wall ending index'] = index_count
sky_group['wall count'] = triangle_count
#for picname, group in texture_groups.items():
# if picname=='-': continue
# print(picname, group['starting index'], group['ending index'], group['count'])
vertex_array = np.concatenate(vertex_array)
index_array = np.concatenate(index_array)
#print(index_array)
#print(vertex_array)
vbo_vertices = vbo.VBO(vertex_array)
vbo_indices = vbo.VBO(index_array, target=gl.GL_ELEMENT_ARRAY_BUFFER)
vbo_vertices.bind()
vbo_indices.bind()
VERTEX_SHADER_CODE = """// GLSL
#version 130
in vec3 aPosition;
in vec3 aNormal;
in vec3 aTangent;
in vec3 aBitangent;
in vec2 aTexCoord;
out vec3 vNormal;
out vec4 vPosition;
out vec2 vTexCoord;
out vec3 vView;
out vec3 vLight;
//out mat3 tangent_basis;
out mat3 tangent_normbasis;
in vec3 v_tangent_lengths;
in float v_lightlevel;
flat out float lightlevel;
out vec3 tangent_lengths;
out float v_dist;
void main() {
vTexCoord = aTexCoord;
vNormal = normalize(gl_NormalMatrix * aNormal);
vPosition = gl_ModelViewMatrix * vec4(aPosition, 1);
gl_Position = gl_ProjectionMatrix * vPosition;
v_dist = gl_Position.w;
/* Maps from model space to tangent space when multiplied by a row vector. */
tangent_normbasis[0] = aTangent;
tangent_normbasis[1] = aBitangent;
tangent_normbasis[2] = aNormal;
tangent_normbasis = gl_NormalMatrix * tangent_normbasis;
tangent_lengths = v_tangent_lengths;
lightlevel = v_lightlevel;
}
"""
FRAGMENT_SHADER_CODE = """// GLSL
#version 130
flat in float lightlevel;
in vec3 vNormal;
in vec4 vPosition;
in vec2 vTexCoord;
in mat3 tangent_basis;
in mat3 tangent_normbasis;
in vec3 vView;
in vec3 tangent_lengths;
in vec4 vProjPosition;
uniform sampler2D diffuseSampler;
uniform sampler2D normalSampler;
uniform sampler2D colormapSampler;
// The relief mapping scale and bias.
uniform vec2 scale_bias;
uniform vec2 texture_size;
// The distance to the fragment.
in float v_dist;
#define DIST_SCALE 64.0
#define LIGHT_SCALE 2.0
#define LIGHT_BIAS 1e-4
#define LINEAR_SEARCH_STEPS 256
#define BIN_ITER 10
#define USE_PARALLAX_MAPPING 0
#define USE_BINARY_SEARCH 0
#define USE_BINARY_REFINEMENT 1
#define USE_LINEAR_SEARCH 1
#define USE_SPHERE_BUMP 0
vec4 sphere_normal(vec2 uv) {
vec2 xy = mod(uv, 1)*2-1;
float t = sqrt(max(1-dot(xy, xy), 0));
vec4 v;
if(t!=0) {
v = vec4(xy, t, t);
} else {
v = vec4(0, 0, 1, t);
}
return v;
}
vec3 line_sphere(vec3 c, float r, vec3 o, vec3 l) {
vec3 oc = o-c;
float t = dot(l, oc);
float disc = t*t - dot(oc, oc) + r*r;
float d;
if(disc>=0) {
float d0 = -t + disc;
float d1 = -t - disc;
d= min(d0, d1);
} else {
d = 0;
}
return o+d*l;
}
float height_map(vec2 uv) {
#if USE_SPHERE_BUMP
float h = sphere_normal(uv).a;
#else
float h = texture(normalSampler, uv).a;
#endif
return dot(vec2(h, 1), scale_bias);
}
/* Interpolate view between the top height level and the bottom height level respectively. */
vec3 uvt_lerp(float t, vec2 uv, vec3 view) {
vec3 uv0 = vec3(uv, 0);
//vec3 uv_min = uv0 - scale_bias.y * view.xy / view.z;
return uv0 + dot(scale_bias, vec2(1-t, 1)) * vec3(view.xy / view.z, 1);
}
vec2 binsearch(vec2 uv, vec3 view, float a, float b) {
vec3 uv_i;
// f(tmax) is below the curve whereas f(tmin) is above the curve.
float tmax=b, tmin = a;
for(int i=0;i<BIN_ITER;i++) {
float t = (tmax+tmin)/2;
uv_i = uvt_lerp(t, uv, view);
float h = height_map(uv_i.xy);
if(uv_i.z > h) {
tmin = t;
} else {
tmax = t;
}
}
return uv_i.xy;
}
vec2 linsearch(vec2 uv, vec3 view, int steps) {
for(int i=0;i<steps;i++) {
vec3 uv_i = uvt_lerp(float(i)/steps, uv, view);
float h = height_map(uv_i.xy);
if(h >= uv_i.z) {
#if USE_BINARY_REFINEMENT
return binsearch(uv, view, float(i-1)/steps, float(i)/steps);
#else
return uv_i.xy;
#endif
}
}
return uvt_lerp(1, uv, view).xy;
}
vec4 retro_color(float lightlevel, float diffuseIndex) {
float lightlevel_scaled = lightlevel / 31.0;
float dist_term = min(1.0, 1.0 - DIST_SCALE / (v_dist + DIST_SCALE));
float light_discrete = min(lightlevel_scaled, lightlevel_scaled * LIGHT_SCALE - dist_term);
light_discrete = clamp(1.0 - light_discrete, LIGHT_BIAS, 1.0 - LIGHT_BIAS);
light_discrete *= 32/34.0;
return texture(colormapSampler, vec2(diffuseIndex, light_discrete));
}
vec4 bilinearInterpolate(sampler2D samp, vec2 uv, float lightlevel) {
vec2 uv00 = floor(uv*texture_size) / texture_size;
vec4 p00 = retro_color(lightlevel, texture(samp, uv00).r);
vec2 uv10 = floor(uv*texture_size + vec2(1,0)) / texture_size;
vec4 p10 = retro_color(lightlevel, texture(samp, uv10).r);
vec2 uv01 = floor(uv*texture_size + vec2(0,1)) / texture_size;
vec4 p01 = retro_color(lightlevel, texture(samp, uv01).r);
vec2 uv11 = floor(uv*texture_size + vec2(1,1)) / texture_size;
vec4 p11 = retro_color(lightlevel, texture(samp, uv11).r);
return
mix(
mix(p00,p01, mod(uv.y*texture_size.y,1.0) ),
mix(p10,p11, mod(uv.y*texture_size.y,1.0) ),
mod(uv.x*texture_size.x,1.0)
)
;
}
void main() {
#if USE_SPHERE_BUMP
vec4 nm = sphere_normal(vTexCoord);
#else
vec4 nm = texture(normalSampler, vTexCoord)*2-1;
#endif
float attenuation = 0.0;
/* The light vector is the normalized view vector pointing at the viewer.
It coincides with surface normals. */
vec3 light = -normalize(vPosition.xyz*tangent_normbasis);
vec2 uv = vTexCoord;
/* The view vector is in the texture space (the tangent space scaled to
texture coordinates. It points away from the viewer. */
//vec3 view = vPosition.xyz*tangent_normbasis/tangent_lengths;
vec3 view = vPosition.xyz * tangent_normbasis/tangent_lengths;
/* Perform parallax mapping. */
#if USE_PARALLAX_MAPPING
float h = dot(vec2(nm.a, 1), scale_bias);
uv += h*view.xy/view.z;
#endif
#if USE_LINEAR_SEARCH
uv = linsearch(uv, view, LINEAR_SEARCH_STEPS);
#endif
#if USE_BINARY_SEARCH
uv = binsearch(uv, view, 0, 1);
#endif
nm = texture(normalSampler, uv)*2-1;
#if 0
vec4 diffuseIndex = texture(diffuseSampler, uv);
vec4 color = retro_color(lightlevel, diffuseIndex.r);
if(diffuseIndex.a < 0.5) {
discard;
}
#else
vec4 diffuseIndex = texture(diffuseSampler, uv);
if(diffuseIndex.a < 0.5) {
discard;
}
vec4 color = bilinearInterpolate(diffuseSampler, uv, lightlevel);
#endif
//color.a = 1.0;
color.rgb += 1e-2;
attenuation += max(dot(nm.rgb, light), 0);
//attenuation = max(attenuation,0.75);
gl_FragColor = color*attenuation;
//gl_FragColor = color;
}
"""
diffuse_texture = gl.glGenTextures(1)
normal_texture = gl.glGenTextures(1)
sky_texture = gl.glGenTextures(1)
# Create the paletted textures.
gl.glActiveTexture(gl.GL_TEXTURE2)
colormap_texture = gl.glGenTextures(1)
gl.glBindTexture(gl.GL_TEXTURE_2D, colormap_texture)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, 256, 34, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, np.concatenate(np.transpose(colormaps, (1, 0, 2))))
def load_texture(picture, light_level, is_flat=True):
if 'colors' not in picture:
data = picture['data']
texture_data = np.zeros((picture['width'], picture['height'], 4), dtype=np.uint8)
texture_indexes = np.zeros((picture['width'], picture['height'], 4), dtype=np.uint8)
#colormap = colormaps[(255-light_level) // 8]
#for c in data:
for x, y in itertools.product(range(picture['width']), range(picture['height'])):
c = data[x+y*picture['width']]
if c is not None:
color = list(palette[c])
else:
color = [0, 0, 0, 0]
texture_data[x, y, :] = color
if c is not None:
texture_indexes[x, y, 0] = c
texture_indexes[x, y, 3] = 255
else:
texture_indexes[x, y, 3] = 0
picture['colors pixels'] = texture_data
picture['colors'] = np.concatenate(np.transpose(texture_indexes, (1, 0, 2)))
if 'normals' not in picture:
BUMP_STRENGTH = 2
#intensities = np.average(np.array(picture['colors pixels'], dtype=np.float32), axis=2)/255
#intensities = np.linalg.norm(ndimage.filters.sobel(np.array(picture['colors pixels'], dtype=np.float32)/255), axis=2)
#intensities = np.average(ndimage.filters.laplace(np.array(picture['colors pixels'], dtype=np.float32)/255, mode='wrap'), axis=2)
intensities = np.linalg.norm(ndimage.filters.laplace(np.array(picture['colors pixels'], dtype=np.float32)/255, mode='wrap'), axis=2)
#intensities = ndimage.gaussian_filter(intensities, sigma=1.5, mode='wrap')
intensities = ndimage.gaussian_filter(intensities, sigma=1.0, mode='wrap')
zs = np.zeros((picture['width'], picture['height']), dtype=np.float32)
if False:
wh = [picture['width'], picture['height']]
#intensities = np.max(1-np.sum(((np.transpose(np.mgrid[:wh[0], :wh[1]], (1, 2, 0)) - wh) / wh)**2, axis=2), zs)
intensities = 1-np.sqrt(
np.maximum(1-np.sum(((np.transpose(np.mgrid[:wh[0], :wh[1]], (1, 2, 0)) - np.array(wh, dtype=np.float32)/2)
/ (np.array(wh, dtype=np.float32)/2))**2, axis=2), zs)
)
print(intensities)
#print((1-np.sum(((np.transpose(np.mgrid[:wh[0], :wh[1]], (1, 2, 0)) - wh) / wh)**2, axis=2)).shape, zs.shape)
def rescale(x):
x -= np.amin(x)
mx = np.amax(x)
if mx != 0:
x /= mx
return x
intensities = 1 - rescale(intensities)
nd = np.transpose([ndimage.filters.sobel(intensities, axis=axis, mode='wrap') for axis in range(2)]+[zs]*2, (1, 2, 0))
nd[:, :, 2] = -1
nd[:, :, 3] = intensities
ndn = -np.linalg.norm(nd[:, :, :3], axis=2)
nd[:, :, 0] /= ndn
nd[:, :, 1] /= ndn
nd[:, :, 2] /= ndn
nd = (nd+1)/2
normal_data = nd
picture['normals pixels'] = normal_data
picture['normals'] = np.concatenate(np.transpose(normal_data, (1, 0, 2)))
if 'normals' not in picture and False:
def apply_kernel(x, y, px, width, height, kernel):
s = 0
for i in range(3):
xi = i+x-1
if not (0 <= xi and xi < width): continue
for j in range(3):
yj = y+j-1
if not (0 <= yj and yj < height): continue
s += kernel[i+j*3]*px[xi + yj*width]
return s
XKERNEL = [-1, 0, 1, -2, 0, 2, -1, 0, 1]
YKERNEL = [1, 2, 1, 0, 0, 0, -1, -2, -1]
ZSTRENGTH = 1
intensities = [0] * picture['width'] * picture['height']
for x in range(picture['width']):
for y in range(picture['height']):
idx = x+y*picture['width']
c = sum(picture['colors'][idx*4:(idx+1)*4-1])/255.0
intensities[idx] = c
normal_data = []
for x in range(picture['width']):
for y in range(picture['width']):
#idx = x+y*picture['width']
#c = sum(picture['colors'][idx*4:(idx+1)*4-1])/255.0
#v = np.array(
# [apply_kernel(x, y, intensities, picture['width'], picture['height'], k) for k in [XKERNEL, YKERNEL]]+[1/ZSTRENGTH]
# , dtype=np.float32)
#v /= np.linalg.norm(v)
#print(v)
normal_data += [v]
normal_data = np.concatenate(normal_data)
picture['normals'] = normal_data
width, height = picture['width'], picture['height']
texture_data = picture['colors']
normal_data = picture['normals']
gl.glUniform2f(gl.glGetUniformLocation(shader, b'texture_size'), width,height)
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glBindTexture(gl.GL_TEXTURE_2D, diffuse_texture)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, texture_data)
gl.glActiveTexture(gl.GL_TEXTURE1)
gl.glBindTexture(gl.GL_TEXTURE_2D, normal_texture)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_FLOAT, normal_data)
return texture, width, height
def load_sky(picture):
if 'colors' not in picture:
data = picture['data']
texture_data = np.zeros((picture['width'], picture['height'], 4), dtype=np.uint8)
texture_indexes = np.zeros((picture['width'], picture['height'], 4), dtype=np.uint8)
for x, y in itertools.product(range(picture['width']), range(picture['height'])):
c = data[x+y*picture['width']]
if c is not None:
color = list(palette[c])
else:
color = [0, 0, 0, 0]
texture_data[x, y, :] = color
if c is not None:
texture_indexes[x, y, 0] = c
texture_indexes[x, y, 3] = 255
else:
texture_indexes[x, y, 3] = 0
texture_indexes = np.concatenate(np.transpose(texture_indexes, (1, 0, 2)))
texture_data = np.concatenate(texture_data)
picture['colors'] = texture_data
picture['indexes'] = texture_indexes
print(texture_data)
width, height = picture['width'], picture['height']
texture_data = picture['colors']
texture_indexes = picture['indexes']
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glBindTexture(gl.GL_TEXTURE_2D, sky_texture)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, texture_indexes)
#empty_data = np.array([0, 255, 255], dtype=np.uint8)
#gl.glTexImage2D(gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.GL_RGB, 1, 1, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, empty_data)
#gl.glTexImage2D(gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.GL_RGB, 1, 1, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, empty_data)
#load_texture(textures['SKY1'], 255)
#load_texture(flats['F_SKY1'], 255)
vertex_shader = shaders.compileShader(VERTEX_SHADER_CODE, gl.GL_VERTEX_SHADER)
fragment_shader = shaders.compileShader(FRAGMENT_SHADER_CODE, gl.GL_FRAGMENT_SHADER)
shader = shaders.compileProgram(vertex_shader, fragment_shader)
SKY_VERTEX_SHADER_CODE = """// GLSL
#version 130
in vec3 aPosition;
out vec3 vCoords;
void main() {
vec4 position = gl_ModelViewMatrix * vec4(aPosition, 1);
vCoords = vec3((position - vec4(0, 0, 0, 1))*gl_ModelViewMatrix);
gl_Position = gl_ProjectionMatrix * position;
}"""
SKY_FRAGMENT_SHADER_CODE = """// GLSL
#version 130
#define PI 3.141592653589793238
in vec3 vCoords;
uniform sampler2D cubeSampler;
uniform sampler2D colormapSampler;
void main() {
vec3 v = (vCoords * vec3(1, 1, -1)) / length(vCoords.xy);
vec3 t = abs(v);
vec2 s = vec2(0, 0);
s.t = v.z;
if(t.x <= t.y) {
s.s = v.x/t.y;
} else {
s.s = v.y/t.x;
}
s /= 2;
vec4 diffuseIndex = texture(cubeSampler, mod(s, 1));
vec4 color = texture(colormapSampler, vec2(diffuseIndex.r, 0.5));
gl_FragColor = color;
}
"""
def draw_scene():
if False:
#dd = demodata.demodata[gametic % len(demodata.demodata)]
dd = demodata.demodata[int((time.clock()-timebegin)/INTERVAL) % len(demodata.demodata)]
player.set_position(dd['pos'])
player.move_up(40)
player.set_angle(dd['angle'])
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN and pygame.key.get_mods() & pygame.KMOD_LALT:
scale = 20 if pygame.key.get_mods() & pygame.KMOD_LSHIFT else 1
if event.key == pygame.K_LEFT:
player.move_left(STRAFE_DISTANCE*scale)
elif event.key == pygame.K_RIGHT:
player.move_left(-STRAFE_DISTANCE*scale)
elif event.key == pygame.K_UP:
player.move_up(STRAFE_DISTANCE*scale)
elif event.key == pygame.K_DOWN:
player.move_up(-STRAFE_DISTANCE*scale)
elif event.type == pygame.KEYDOWN and pygame.key.get_mods() & pygame.KMOD_LCTRL:
if event.key == pygame.K_UP:
player.look_up(TURN_ANGLE)
elif event.key == pygame.K_DOWN:
player.look_up(-TURN_ANGLE)
elif event.type==pygame.KEYDOWN:
scale = 20 if pygame.key.get_mods() & pygame.KMOD_LSHIFT else 1
if event.key == pygame.K_LEFT:
player.turn_left(TURN_ANGLE)
elif event.key == pygame.K_RIGHT:
player.turn_left(-TURN_ANGLE)
elif event.key == pygame.K_UP:
player.move_forward(FORWARD_DISTANCE * scale)
elif event.key == pygame.K_DOWN:
player.move_forward(-FORWARD_DISTANCE *scale)
elif event.key == pygame.K_q:
done = True
#elif event.type==pygame.JOYAXISMOTION:
# print(joystick.get_axis(0), joystick.get_axis(1))
#player.move_forward(FORWARD_DISTANCE * -joystick.get_axis(1))
#player.move_left(STRAFE_DISTANCE * -joystick.get_axis(0))
def joystick_deadzone(x):
return x if abs(x) > JOYSTICK_DEADZONE else 0
if joystick is not None:
joystick_boost = math.pow(2, joystick_deadzone(joystick.get_axis(2)-joystick.get_axis(5))*3)
player.move_forward(FORWARD_DISTANCE * JOYSTICK_SCALE * -joystick_deadzone(joystick.get_axis(1))*joystick_boost)
player.move_left(STRAFE_DISTANCE * JOYSTICK_SCALE * -joystick_deadzone(joystick.get_axis(0))*joystick_boost)
player.turn_left(TURN_ANGLE * JOYSTICK_TURN_SCALE * -joystick_deadzone(joystick.get_axis(3)))
player.look_up(TURN_ANGLE * JOYSTICK_TURN_SCALE * -joystick_deadzone(joystick.get_axis(4)))
node_type, node = ('node', nodes[-1])
while node_type == 'node':
side = line_distance(node['splitter'], player.get_position()[:2])
#print(node, side)
if side <= 0:
node_type, node_index = node['child0']
else:
node_type, node_index = node['child1']
if node_type == 'node':
node = nodes[node_index]
else:
node = subsectors[node_index]
#print(node['id'], node_type)
#pprint.pprint(sectors[node['sector_ref']]['floorheight']+40)
if joystick is not None and joystick.get_button(0):
player.set_elevation(sectors[node['sector_ref']]['floorheight']+40)
if joystick is not None and joystick.get_button(3):
gl.glDisable(gl.GL_CULL_FACE)
gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE)
else:
gl.glEnable(gl.GL_CULL_FACE)
gl.glPolygonMode(gl.GL_FRONT, gl.GL_FILL)
#stride = 6*4+3*4+2*3*4 + 3*4 + 4
stride = 6*4+3*4+2*3*4 + 3*4
# Render the sky.
shaders.glUseProgram(sky_shader)
shaders.glUseProgram(sky_shader)
sky_position_location = gl.glGetAttribLocation(sky_shader, b'aPosition')
if sky_position_location >= 0:
gl.glEnableVertexAttribArray(sky_position_location)
gl.glVertexAttribPointer(sky_position_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices)
texcoord_location = gl.glGetAttribLocation(sky_shader, b'aTexCoord')
if texcoord_location >= 0:
gl.glEnableVertexAttribArray(texcoord_location)
gl.glVertexAttribPointer(texcoord_location, 2, gl.GL_FLOAT, False, stride, vbo_vertices+6*4)
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glUniform1i(gl.glGetUniformLocation(sky_shader, b'cubeSampler'), 0)
gl.glBindTexture(gl.GL_TEXTURE_2D, sky_texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
gl.glActiveTexture(gl.GL_TEXTURE1)
gl.glUniform1i(gl.glGetUniformLocation(sky_shader, b'colormapSampler'), 1)
gl.glBindTexture(gl.GL_TEXTURE_2D, colormap_texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
#gl.glBindTexture(gl.GL_TEXTURE_CUBE_MAP, sky_texture)
#gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
#gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)
#gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_R, gl.GL_CLAMP_TO_EDGE)
#gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
#gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
load_sky(sky_group['picture'])
gl.glDrawElements(gl.GL_TRIANGLES, sky_group['flat count']*3, gl.GL_UNSIGNED_INT, vbo_indices+sky_group['flat starting index']*4)
#gl.glClear(gl.GL_DEPTH_BUFFER_BIT)
gl.glDrawElements(gl.GL_TRIANGLES, sky_group['wall count']*3, gl.GL_UNSIGNED_INT, vbo_indices+sky_group['wall starting index']*4)
#gl.glDrawElements(gl.GL_LINES, len(index_array), gl.GL_UNSIGNED_INT, None)
# gl.glDrawRangeElements(gl.GL_TRIANGLES,
# group['starting index'],
# group['ending index'],
# group['count'], gl.GL_UNSIGNED_INT, None)
#gl.glDrawElements(gl.GL_TRIANGLES, len(index_array), gl.GL_UNSIGNED_INT, vbo_indices+12)
shaders.glUseProgram(shader)
#gl.glVertexPointer(3, gl.GL_FLOAT, 0, None)
#gl.glVertexPointerf(vbo_positions)
shaders.glUseProgram(shader)
position_location = gl.glGetAttribLocation(shader, b'aPosition')
if position_location >= 0:
gl.glEnableVertexAttribArray(position_location)
gl.glVertexAttribPointer(position_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices)
normal_location = gl.glGetAttribLocation(shader, b'aNormal')
if normal_location >= 0:
gl.glEnableVertexAttribArray(normal_location)
gl.glVertexAttribPointer(normal_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices+3*4)
tangent_location = gl.glGetAttribLocation(shader, b'aTangent')
if tangent_location >= 0:
gl.glEnableVertexAttribArray(tangent_location)
gl.glVertexAttribPointer(tangent_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices+9*4)
bitangent_location = gl.glGetAttribLocation(shader, b'aBitangent')
if bitangent_location >= 0:
gl.glEnableVertexAttribArray(bitangent_location)
gl.glVertexAttribPointer(bitangent_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices+12*4)
texcoord_location = gl.glGetAttribLocation(shader, b'aTexCoord')
if texcoord_location >= 0:
gl.glEnableVertexAttribArray(texcoord_location)
gl.glVertexAttribPointer(texcoord_location, 2, gl.GL_FLOAT, False, stride, vbo_vertices+6*4)
tangent_lengths_location = gl.glGetAttribLocation(shader, b'v_tangent_lengths')
if tangent_lengths_location >= 0:
gl.glEnableVertexAttribArray(tangent_lengths_location)
gl.glVertexAttribPointer(tangent_lengths_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices+15*4)
lightlevel_location = gl.glGetAttribLocation(shader, b'v_lightlevel')
if lightlevel_location >= 0:
gl.glEnableVertexAttribArray(lightlevel_location)
gl.glVertexAttribPointer(lightlevel_location, 1, gl.GL_FLOAT, False, stride, vbo_vertices+8*4)
#gl.glDrawElements(gl.GL_TRIANGLES, len(index_array), gl.GL_UNSIGNED_INT, None)
#gl.glDrawElements(gl.GL_TRIANGLES, len(index_array), gl.GL_UNSIGNED_INT, None)
#gl.glDrawElements(gl.GL_LINES, len(index_array), gl.GL_UNSIGNED_INT, None)
#gl.glDrawArrays(gl.GL_TRIANGLES, 0, len(index_array))
T = 5e-2
#scale_bias = (math.cos(gametic*T)*10-5, math.sin(gametic*T)*10-5)
#scale = (math.cos(gametic*T)+1)*20
#bias = math.sin(gametic*T*math.sqrt(2))*2
#scale_bias = (scale, bias-scale)
#scale_bias = ((math.cos(gametic*T)+1)*10, -10)
#scale_bias = ((math.cos(gametic*T)+1)*10, 0)
#scale_bias = (scale_bias[0], -scale_bias[0]-1)
#scale_bias = (0, 0)
#scale_bias = (0, (math.cos(gametic*T))*10)
scale_bias = (10, -11)
#scale_bias = (20, -21)
#scale_bias = (5, -2.5)
#scale_bias = (5, -6)
#scale_bias = (5, 0.5)
#scale_bias = (7, 0.1)
#scale_bias = (5, 0.1)
gl.glUniform2f(gl.glGetUniformLocation(shader, b'scale_bias'), *scale_bias)
#print(scale_bias)
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glUniform1i(gl.glGetUniformLocation(shader, b'diffuseSampler'), 0)
gl.glBindTexture(gl.GL_TEXTURE_2D, diffuse_texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
gl.glActiveTexture(gl.GL_TEXTURE1)
gl.glUniform1i(gl.glGetUniformLocation(shader, b'normalSampler'), 1)
gl.glBindTexture(gl.GL_TEXTURE_2D, normal_texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)
gl.glActiveTexture(gl.GL_TEXTURE2)
gl.glUniform1i(gl.glGetUniformLocation(shader, b'colormapSampler'), 2)
gl.glBindTexture(gl.GL_TEXTURE_2D, colormap_texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
for picname, group in texture_groups.items():
if picname == '-': continue
#print(picname, group)
load_texture(group['picture'], 255)
#gl.glDrawElements(gl.GL_TRIANGLES, group['count']*12, gl.GL_UNSIGNED_INT, vbo_indices+group['starting index']*12)
gl.glDrawElements(gl.GL_TRIANGLES, group['count']*3, gl.GL_UNSIGNED_INT, vbo_indices+group['starting index']*4)
for picname, group in flat_groups.items():
if picname == '-': continue
load_texture(group['picture'], 255)
#gl.glDrawElements(gl.GL_TRIANGLES, group['count']*12, gl.GL_UNSIGNED_INT, vbo_indices+group['starting index']*12)
gl.glDrawElements(gl.GL_TRIANGLES, group['count']*3, gl.GL_UNSIGNED_INT, vbo_indices+group['starting index']*4)
#gl.glDrawElements(gl.GL_TRIANGLES, group['count'], gl.GL_UNSIGNED_INT, vbo_indices+group['starting index']*4)
sky_vertex_shader = shaders.compileShader(SKY_VERTEX_SHADER_CODE, gl.GL_VERTEX_SHADER)
sky_fragment_shader = shaders.compileShader(SKY_FRAGMENT_SHADER_CODE, gl.GL_FRAGMENT_SHADER)
sky_shader = shaders.compileProgram(sky_vertex_shader, sky_fragment_shader)
JOYSTICK_SCALE = 5.0
JOYSTICK_TURN_SCALE = 5e-1
JOYSTICK_DEADZONE = 3e-1
STRAFE_DISTANCE = 5.0
FORWARD_DISTANCE = 5.0
TURN_ANGLE = 10*math.pi/180
try:
texcoord_location = None
gl.glPolygonMode(gl.GL_FRONT, gl.GL_LINE)
#gl.glPolygonMode(gl.GL_FRONT, gl.GL_FILL)
#gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL)
#gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE)
pygame.joystick.init()
if pygame.joystick.get_count() > 0:
joystick = pygame.joystick.Joystick(0)
if joystick.get_name() == 'Microsoft X-Box 360 pad':
joystick.init()
else:
joystick = None
else:
joystick = None
#stride = 6*4+2
#gl.glVertexAttribPointer(color_location, 3, gl.GL_FLOAT, False, stride, vbo_vertices+3*4)
gl.glIndexPointeri(vbo_indices)
gametic = 0
timebegin = time.clock()
INTERVAL = 1/35
IOD = 15
#gl.glEnable(gl.GL_SCISSOR_TEST)
focal_distance = None # 10+(math.sin(gametic/50.0)+1.2)*40.0
focal_distance = 16*10
while not done:
if STEREOSCOPIC:
gl.glClear(gl.GL_COLOR_BUFFER_BIT|gl.GL_DEPTH_BUFFER_BIT)
gl.glViewport(0, 0, screenx//2, screeny)
gl.glLoadIdentity()
player.move_left(IOD/2.0)
player.update_OpenGL()
draw_scene()
gl.glViewport(screenx//2, 0, screenx//2, screeny)
gl.glLoadIdentity()
player.move_left(-IOD)
player.update_OpenGL()
draw_scene()
pygame.display.flip()
player.move_left(IOD/2.0)
else:
gl.glViewport(0, 0, screenx, screeny)
gl.glClear(gl.GL_COLOR_BUFFER_BIT|gl.GL_DEPTH_BUFFER_BIT)
gl.glLoadIdentity()
player.update_OpenGL()
draw_scene()
pygame.display.flip()
time.sleep(INTERVAL)
gametic += 1
finally:
if joystick is not None:
joystick.quit()
vbo_indices.unbind()
vbo_vertices.unbind()
if texcoord_location >= 0:
gl.glDisableVertexAttribArray(texcoord_location)
gl.glDisableVertexAttribArray(normal_location)
gl.glDisableVertexAttribArray(position_location)
gl.glDeleteTextures(normal_texture)
gl.glDeleteTextures(diffuse_texture)
gl.glDeleteTextures(sky_texture)
gl.glUseProgram(0)
if len(sys.argv) > 2:
wadtype = 'doom'
wadname = os.path.basename(sys.argv[1]).lower()
if wadname == 'hexen.wad': wadtype = 'hexen'
if wadname == 'strife1.wad': wadtype = 'strife'
render_level(sys.argv[1], sys.argv[2] if len(sys.argv)>2 else None, wadtype)
else:
print('Usage: renderer.py [iwad] [map name]')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment