DKL9 GitList
Repositories
DKL9 home
voxels
Code
Commits
Branches
Tags
Search
Tree:
466ea72
Branches
Tags
master
voxels
camera.py
Make basic 3D "game" with two shapes
dkl9
commited
466ea72
at 2025-170 10:42:16
camera.py
Blame
History
Raw
from libs import * # https://iquilezles.org/articles/intersectors/ def intersect_tri(ro, rd, tv): e1 = tv[1] - tv[0] e2 = tv[2] - tv[0] to = ro - tv[0] n = np.cross(e1, e2) q = np.cross(to, rd) d = 1.0 / np.dot(rd, n) u = d * np.dot(-q, e2) v = d * np.dot(q, e1) t = d * np.dot(-n, to) if u > 0.0 and v > 0.0 and u + v < 1.0 and t > 1e-3: return t class Camera: def __init__(self, **kwargs): self.pos = vec([0, 0, 0]) self.theta = 0 self.phi = 0 self.fovy = kwargs.get("fovy", 90) self.aspect = 1 def looking(self): return vec([ np.cos(self.phi) * np.sin(self.theta), np.sin(self.phi), np.cos(self.phi) * np.cos(self.theta) ]) def up(self): return vec([0, 1, 0]) def view_mat(self): f = normalize(self.looking()) s = normalize(np.cross(f, self.up())) u = np.cross(s, f) m = np.identity(4, dtype=FLOAT) m[:3, :3] = [s, u, -f] m[:3, 3] = [-np.dot(s, self.pos), -np.dot(u, self.pos), np.dot(f, self.pos)] return m def persp_mat(self): near = 0.1 far = 100 f = 1.0 / np.tan(np.radians(self.fovy) / 2) depth = near - far return vec([ [f / self.aspect, 0, 0, 0], [0, f, 0, 0], [0, 0, (near + far) / depth, (2 * near * far) / depth], [0, 0, -1, 0] ]) def mvp(self, ent): return self.persp_mat() @ self.view_mat() @ ent.translate() @ ent.orient def draw(self, ent, loc_mvp, loc_col): if not ent.vao: ent.build_vao() glUniformMatrix4fv(loc_mvp, 1, GL_TRUE, self.mvp(ent)) glUniform4fv(loc_col, 1, ent.col) glBindVertexArray(ent.vao) glDrawArrays(ent.draw_mode, 0, len(ent.verts)) def target(self, scene): l = self.looking() d, c = None, None for ent in scene: if ent.draw_mode == GL_TRIANGLE_STRIP: tl = (ent.verts[i:i + 3] for i in range(len(ent.verts) - 2)) elif ent.draw_mode == GL_TRIANGLES: tl = (ent.verts[3 * i:3 * (i + 1)] for i in range(len(ent.verts) // 3)) else: raise NotImplementedError for t in tl: r = intersect_tri(self.pos, l, ent.pos + np.dot(ent.orient[:3, :3].T, t)) if r and (d is None or r < d): d, c = r, ent return c