from OpenGL.GL import * import itertools import numpy as np import pygame FLOAT = np.float32 VOXEL_TYPE = np.uint8 VERTEX_ATTRS = ["vec3 position", "vec4 col", "vec3 normal", "vec4 refls"] UNIFORMS = { "MVP": ["vert", "mat4", None], "lightPos": ["frag", "vec4", None], "camPos": ["frag", "vec3", None] } LIGHT_POS = [5, 30, 10] REGION_SIZE = 8 GRAVITY = 1 VIEW_DIST = 30 FPS = 60 ARROWS = [ ["RIGHT", "e", "d"], ["LEFT", "a"], ["SPACE"], ["LSHIFT"], ["UP", "COMMA", "w"], ["DOWN", "o", "s"], ] ARROWS = [[getattr(pygame, f"K_{n}") for n in opts] for opts in ARROWS] def vec(l): return np.array(l, dtype=FLOAT) RED = vec([1.0, 0.0, 0.0, 1.0]) YELLOW = vec([1.0, 1.0, 0.0, 1.0]) GREEN = vec([0.0, 1.0, 0.0, 1.0]) def normalise(v): norm = np.linalg.norm(v) return v / norm if norm > 0 else v def roll_vec3(l, k): match k: case 1: l[:] = [l[2], l[0], l[1]] case 2: l[:] = [l[1], l[2], l[0]] def axis2offset(a, mag=1): o = [0, 0, mag * np.sign(a)] roll_vec3(o, abs(a)) return o def smerp(corners, weights): for w in weights: t = w ** 2 * (3 - 2 * w) pairs = zip(corners[::2], corners[1::2]) corners = [a + t * (b - a) for (a, b) in pairs] return corners[0] def norm_tri(verts): assert verts.shape[0] == 3 return normalise(np.cross(verts[2] - verts[0], verts[1] - verts[0])) def update_attr(ent, n, l=None): if isinstance(n, int): i, name = n, VERTEX_ATTRS[n].split()[1] elif isinstance(n, str): # https://stackoverflow.com/a/30197797 i, name = next((i for (i, s) in enumerate(VERTEX_ATTRS) if n in s)), n if l is None: match name: case "position": l = ent.verts case "col": l = ent.mat_list()[0] case "normal": l = ent.norm_list() case "refls": l = ent.mat_list()[1] if ent.vao: glBindBuffer(GL_ARRAY_BUFFER, ent.vbos[i][0]) if l.shape[0] != ent.vbos[i][1]: glBufferData(GL_ARRAY_BUFFER, l.nbytes, l, GL_DYNAMIC_DRAW) ent.vbos[i][1] = l.shape[0] else: glBufferSubData(GL_ARRAY_BUFFER, 0, l.nbytes, l) return l