git.haldean.org symrep / c22e252
add voxel rendering! Will Haldean Brown 4 years ago
4 changed file(s) with 156 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
00 import numpy as np
11 from symrep import *
2 from symrep.render import *
23 from symrep.solids import *
34
45 n = union(
4041 vec(0., 3., 0.),
4142 ),
4243 )
44 bbox_lo = np.array((-2., -2., -2.))
45 bbox_hi = np.array((5., 5., 2.))
4346
4447 with open("sphere.dot", "w") as f:
4548 to_dot(n, f)
4649
47 points = sample_solid(
48 n, (-2, -2, -2), (5, 5, 2), is_on_surface(0.05), max_sec=30)
50 points = list(sample_solid(
51 n, bbox_lo, bbox_hi, is_inside, max_sec=30))
4952 with open("sphere.xyz", "w") as f:
5053 solids.write_point_cloud(points, f)
54
55 voxel_map = voxelize(points, bbox_lo, bbox_hi, 0.1)
56 show_voxels(voxel_map)
00 from .base import *
11 from . import audio
2 from . import render
23 from . import solids
0 import numpy as np
1 import pygame
2 from pygame.locals import *
3
4 from OpenGL.GL import *
5 from OpenGL.GLU import *
6
7 def draw_voxels(voxel_map):
8 max_i, max_j, max_k = voxel_map.voxels.shape
9
10 def point(i, j, k):
11 glVertex3f(
12 voxel_map.lo[0] + i * voxel_map.resolution,
13 voxel_map.lo[1] + j * voxel_map.resolution,
14 voxel_map.lo[2] + k * voxel_map.resolution,
15 )
16
17 glColor3fv((1., 0.7, 0.))
18 glBegin(GL_QUADS)
19
20 for j in range(max_j):
21 for k in range(max_k):
22 last_val = 0
23 for i in range(max_i):
24 val = voxel_map.voxels[i, j, k]
25 if val == last_val:
26 continue
27 last_val = val
28 if val == 1:
29 glNormal3f(1, 0, 0)
30 else:
31 glNormal3f(-1, 0, 0)
32 point(i, j, k)
33 point(i, j+1, k)
34 point(i, j+1, k+1)
35 point(i, j, k+1)
36 if last_val:
37 glNormal3f(-1, 0, 0)
38 point(i+1, j, k)
39 point(i+1, j+1, k)
40 point(i+1, j+1, k+1)
41 point(i+1, j, k+1)
42
43 for i in range(max_i):
44 for k in range(max_k):
45 last_val = 0
46 for j in range(max_j):
47 val = voxel_map.voxels[i, j, k]
48 if val == last_val:
49 continue
50 last_val = val
51 if val == 1:
52 glNormal3f(0, 1, 0)
53 else:
54 glNormal3f(0, -1, 0)
55 point(i, j, k)
56 point(i+1, j, k)
57 point(i+1, j, k+1)
58 point(i, j, k+1)
59 if last_val:
60 glNormal3f(0, -1, 0)
61 point(i, j+1, k)
62 point(i+1, j+1, k)
63 point(i+1, j+1, k+1)
64 point(i, j+1, k+1)
65
66 for i in range(max_i):
67 for j in range(max_j):
68 last_val = 0
69 for k in range(max_k):
70 val = voxel_map.voxels[i, j, k]
71 if val == last_val:
72 continue
73 last_val = val
74 if val == 1:
75 glNormal3f(0, 0, 1)
76 else:
77 glNormal3f(0, 0, -1)
78 point(i, j, k)
79 point(i+1, j, k)
80 point(i+1, j+1, k)
81 point(i, j+1, k)
82 if last_val:
83 glNormal3f(0, 0, -1)
84 point(i, j, k+1)
85 point(i+1, j, k+1)
86 point(i+1, j+1, k+1)
87 point(i, j+1, k+1)
88 glEnd()
89
90 def show_voxels(voxel_map):
91 dist = -np.linalg.norm(voxel_map.hi - voxel_map.lo)
92 pygame.init()
93 pygame.display.set_mode((640,480), OPENGL|DOUBLEBUF)
94 glEnable(GL_DEPTH_TEST)
95 glClearColor(.7, .7, .7, 1.)
96
97 glEnable(GL_LIGHTING)
98 glEnable(GL_LIGHT0)
99 glLightfv(GL_LIGHT0, GL_AMBIENT, (.2, .2, .2, 1.))
100 glLightfv(GL_LIGHT0, GL_POSITION, (0., dist, -dist, 1.))
101 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (1., .5, 0., 1.))
102 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (1., 1., 1., 1.))
103 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (50.,))
104
105 glMatrixMode(GL_PROJECTION)
106 gluPerspective(45.0, 640 / 480.0, 0.1, 100.0)
107 glTranslatef(0.0, -2.0, dist)
108 glRotatef(25, 1, 0, 0)
109
110 while True:
111 event = pygame.event.poll()
112 if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
113 break
114
115 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
116 glRotatef(1, 0, 1, 0)
117
118 draw_voxels(voxel_map)
119 pygame.display.flip()
120 pygame.time.wait(0)
6767 if max_points is None and max_sec is None:
6868 raise ValueError(
6969 "either a deadline or a number of points must be given")
70
7170 found = 0
7271 tried = 0
7372 t = np.ones(4)
7776 t[1] = random.uniform(lo[1], hi[1])
7877 t[2] = random.uniform(lo[2], hi[2])
7978 if eval_pt(root, t):
80 yield t
79 yield np.array(t)
8180 found += 1
8281 tried += 1
8382 if tried % 1000 == 0:
9695 return val <= 0 and abs(val) <= accuracy
9796 return eval_t
9897
98 class VoxelMap(object):
99 def __init__(self, voxels, lo, hi, resolution):
100 self.voxels = voxels
101 self.lo = lo
102 self.hi = hi
103 self.resolution = resolution
104
105 def voxelize(points, lo=None, hi=None, resolution=None, voxel_map=None):
106 if voxel_map is None:
107 size = (hi - lo)[:3]
108 px_size = np.ceil(size / resolution).astype(np.int)
109 print("allocating voxel array of size {}".format(
110 "x".join(map(str, px_size))))
111 print(" scene size is {:.3f}x{:.3f}x{:.3f}".format(*size))
112 print(" using {:.3f} megabytes".format(np.product(px_size) * 1e-6))
113 voxel_map = VoxelMap(
114 np.zeros(px_size, dtype=np.uint8), lo, hi, resolution)
115 else:
116 voxel_map.voxels.fill(0)
117 for p in points:
118 idx = ((p[:3] - lo) / resolution).astype(np.int)
119 voxel_map.voxels[tuple(idx)] = 1
120 return voxel_map
121
99122 def write_point_cloud(points, f):
100123 for point in points:
101124 f.write("{} {} {}\n".format(*(point[:3])))
125