git.haldean.org symrep / f636f96
more efficient voxel rendering Will Haldean Brown 4 years ago
2 changed file(s) with 87 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
4848 to_dot(n, f)
4949
5050 points = list(sample_solid(
51 n, bbox_lo, bbox_hi, is_inside, max_sec=30))
51 n, bbox_lo, bbox_hi, is_inside, max_sec=10))
5252 with open("sphere.xyz", "w") as f:
5353 solids.write_point_cloud(points, f)
5454
55 voxel_map = voxelize(points, bbox_lo, bbox_hi, 0.1)
55 voxel_map = voxelize(points, bbox_lo, bbox_hi, 0.125)
5656 show_voxels(voxel_map)
44 from OpenGL.GL import *
55 from OpenGL.GLU import *
66
7 def draw_voxels(voxel_map):
7 def voxels_to_quads(voxel_map):
88 max_i, max_j, max_k = voxel_map.voxels.shape
9 quads = []
910
1011 def point(i, j, k):
11 glVertex3f(
12 return np.array((
1213 voxel_map.lo[0] + i * voxel_map.resolution,
1314 voxel_map.lo[1] + j * voxel_map.resolution,
1415 voxel_map.lo[2] + k * voxel_map.resolution,
15 )
16
17 glColor3fv((1., 0.7, 0.))
18 glBegin(GL_QUADS)
16 ))
1917
2018 for j in range(max_j):
2119 for k in range(max_k):
2624 continue
2725 last_val = val
2826 if val == 1:
29 glNormal3f(1, 0, 0)
27 norm = np.array((1, 0, 0))
3028 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)
29 norm = np.array((-1, 0, 0))
30 quads.append(([
31 point(i, j, k),
32 point(i, j+1, k),
33 point(i, j+1, k+1),
34 point(i, j, k+1),
35 ], norm))
3636 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)
37 quads.append(([
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 ], np.array((-1, 0, 0))))
4243
4344 for i in range(max_i):
4445 for k in range(max_k):
4950 continue
5051 last_val = val
5152 if val == 1:
52 glNormal3f(0, 1, 0)
53 norm = np.array((0, 1, 0))
5354 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)
55 norm = np.array((0, -1, 0))
56 quads.append(([
57 point(i, j, k),
58 point(i+1, j, k),
59 point(i+1, j, k+1),
60 point(i, j, k+1),
61 ], norm))
5962 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)
63 quads.append(([
64 point(i, j+1, k),
65 point(i+1, j+1, k),
66 point(i+1, j+1, k+1),
67 point(i, j+1, k+1),
68 ], np.array((0, -1, 0))))
6569
6670 for i in range(max_i):
6771 for j in range(max_j):
7276 continue
7377 last_val = val
7478 if val == 1:
75 glNormal3f(0, 0, 1)
79 norm = np.array((0, 0, 1))
7680 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)
81 norm = np.array((0, 0, -1))
82 quads.append(([
83 point(i, j, k),
84 point(i+1, j, k),
85 point(i+1, j+1, k),
86 point(i, j+1, k),
87 ], norm))
8288 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)
89 quads.append(([
90 point(i, j, k+1),
91 point(i+1, j, k+1),
92 point(i+1, j+1, k+1),
93 point(i, j+1, k+1),
94 ], np.array((0, 0, -1))))
95
96 return quads
97
98 def draw_quads(quads, rot):
99 glPushMatrix()
100 glColor3fv((1., 0.7, 0.))
101 glRotatef(4, 1, 0, 0)
102
103 glPushMatrix()
104 glRotatef(rot, 0, 1, 0)
105 glBegin(GL_QUADS)
106 for quad, normal in quads:
107 glNormal3f(*normal)
108 for pt in quad:
109 glVertex3f(*pt)
88110 glEnd()
111 glPopMatrix()
112
113 glPopMatrix()
89114
90115 def show_voxels(voxel_map):
91116 dist = -np.linalg.norm(voxel_map.hi - voxel_map.lo)
117 w = 800
118 h = 800
92119 pygame.init()
93 pygame.display.set_mode((640,480), OPENGL|DOUBLEBUF)
120 pygame.display.set_mode((w, h), OPENGL|DOUBLEBUF)
121
94122 glEnable(GL_DEPTH_TEST)
95 glClearColor(.7, .7, .7, 1.)
123 glClearColor(.2, .2, .3, 1.)
124
125 glMatrixMode(GL_PROJECTION)
126 glLoadIdentity()
127 gluPerspective(45.0, float(w) / float(h), 0.1, 100.0)
128 glTranslatef(0.0, -2.0, dist)
129
130 glMatrixMode(GL_MODELVIEW)
131 glLoadIdentity()
96132
97133 glEnable(GL_LIGHTING)
98134 glEnable(GL_LIGHT0)
99135 glLightfv(GL_LIGHT0, GL_AMBIENT, (.2, .2, .2, 1.))
100 glLightfv(GL_LIGHT0, GL_POSITION, (0., dist, -dist, 1.))
136 glLightfv(GL_LIGHT0, GL_POSITION, (dist, dist, 0, 1.))
101137 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (1., .5, 0., 1.))
102138 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (1., 1., 1., 1.))
103139 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (50.,))
104140
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
141 quads = voxels_to_quads(voxel_map)
142 rot = 0
110143 while True:
111144 event = pygame.event.poll()
112 if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
145 if event.type == QUIT or (
146 event.type == KEYDOWN and event.key == K_ESCAPE):
113147 break
114148
115149 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
116 glRotatef(1, 0, 1, 0)
117150
118 draw_voxels(voxel_map)
151 draw_quads(quads, rot)
119152 pygame.display.flip()
120 pygame.time.wait(0)
153 pygame.time.wait(3)
154 rot += 2.