Surface-only mesh, crude mapgen, hidable crosshair
dkl9

dkl9 commited on 2025-172 08:49:54
Showing 3 changed files, with 43 additions and 15 deletions.

... ...
@@ -36,15 +36,14 @@ def click_mesh(self, button, ind):
36 36
         case 3:
37 37
             self.add_voxel(p + np.sign(a) * np.roll([0, 0, 1], abs(a)))
38 38
     if button % 2 == 1:
39
+        self.remesh()
39 40
         self.update_attr(0)
40 41
         self.update_attr(1)
41 42
 
42 43
 def build_scene():
43 44
     box = WorldRegion()
44
-    for i in range(2):
45
-        for j in range(2):
46
-            for k in range(2):
47
-                box.add_voxel((-i % 16, -j % 16, -k % 16))
45
+    box.gen_perlin(np.random.rand(2, 2, 2, 3))
46
+    box.remesh()
48 47
     box.onclick = click_mesh
49 48
     return [box]
50 49
 
... ...
@@ -63,6 +62,7 @@ def main():
63 62
     scene = build_scene()
64 63
     clock = pygame.time.Clock()
65 64
     cam = Player()
65
+    cam.pos = [8, 16, 8]
66 66
     cam.set_focus(True)
67 67
     while True:
68 68
         for ev in pygame.event.get():
... ...
@@ -28,6 +28,7 @@ class Player(camera.Camera):
28 28
     def set_focus(self, f): 
29 29
         pygame.event.set_grab(f)
30 30
         pygame.mouse.set_visible(not f)
31
+        self.hud["crosshair"].pos[0] = 2 * (not f)
31 32
 
32 33
     def get_focus(self):
33 34
         return not pygame.mouse.get_visible()
... ...
@@ -1,22 +1,49 @@
1 1
 from libs import *
2 2
 import mesh
3 3
 
4
+def smoothstep(x):
5
+    return x ** 2 * (3 - 2 * x)
6
+
7
+def interp(ab, t):
8
+    return ab[0] + smoothstep(t) * (ab[1] - ab[0])
9
+
4 10
 class WorldRegion(mesh.SquareMesh):
5 11
     def __init__(self, size=16):
6 12
         super().__init__()
7 13
         self.grid = np.zeros((size, size, size), dtype=VOXEL_TYPE)
8 14
 
9 15
     def add_voxel(self, pos, vt=1):
10
-        offset = vec([0.5, 0.0, 0.0])
11
-        for a in range(1, 4):
12
-            self.add_sq(a, 1, pos + offset, pos)
13
-            self.add_sq(-a, 1, pos - offset, pos)
14
-            offset = np.roll(offset, 1, 0)
15
-        self.grid[pos] = vt
16
-        return len(self.faces) - 12
16
+        self.grid[*pos] = vt
17 17
 
18 18
     def del_voxel(self, ind):
19
-        b = (ind // 12) * 12
20
-        self.grid[self.faces[ind][1]] = 0
21
-        for i in range(6):
22
-            self.del_sq(b)
19
+        self.grid[*self.faces[ind][1]] = 0
20
+
21
+    def remesh(self):
22
+        offset = vec([0.5, 0.0, 0.0])
23
+        r = self.grid.shape[0]
24
+        self.verts = np.empty((0, 3), dtype=FLOAT)
25
+        self.faces = []
26
+        for i in range(r):
27
+            for j in range(r):
28
+                for k in range(r):
29
+                    p = [i, j, k]
30
+                    if self.grid[*p]:
31
+                        for d in range(3):
32
+                            for s in range(2):
33
+                                ts = (-1) ** s
34
+                                if p[d] == [r - 1, 0][s] or not self.grid[*(p + np.roll([ts, 0, 0], d))]:
35
+                                    self.add_sq(ts * (d + 1), 1, p + ts * np.roll(offset, d), p)
36
+
37
+    def gen_perlin(self, grads):
38
+        r = self.grid.shape[0]
39
+        corners = np.array([(i, j, k) for i in range(2) for j in range(2) for k in range(2)])
40
+        for i in range(r):
41
+            for j in range(r):
42
+                for k in range(r):
43
+                    w = np.array((i, j, k)) / r
44
+                    d = [np.dot(grads[*c], w) for c in corners]
45
+                    d = [interp(d[2 * k:2 * (k + 1)], w[2]) for k in range(4)]
46
+                    d = [interp(d[:2], w[1]), interp(d[2:4], w[1])]
47
+                    p = interp(d, w[0])
48
+                    if p < 0.6:
49
+                        self.add_voxel((i, j, k))
23 50