aboutsummaryrefslogtreecommitdiff
path: root/channel_3d_gl_interop.py
diff options
context:
space:
mode:
Diffstat (limited to 'channel_3d_gl_interop.py')
-rw-r--r--channel_3d_gl_interop.py290
1 files changed, 120 insertions, 170 deletions
diff --git a/channel_3d_gl_interop.py b/channel_3d_gl_interop.py
index 695dbfe..3b93f86 100644
--- a/channel_3d_gl_interop.py
+++ b/channel_3d_gl_interop.py
@@ -12,40 +12,44 @@ from OpenGL.GLUT import *
from OpenGL.GL import shaders
-from pyrr import matrix44, quaternion
+from geometry.sphere import Sphere
+from geometry.box import Box
+from geometry.cylinder import Cylinder
+
+from utility.projection import Projection, Rotation
+from utility.mouse import MouseDragMonitor, MouseScrollMonitor
lattice_x = 256
lattice_y = 64
lattice_z = 64
-cylinder_r = 10
-
updates_per_frame = 10
-particle_count = 50000
+particle_count = 100000
-lid_speed = 0.05
+lid_speed = 0.02
relaxation_time = 0.51
-def circle(cx, cy, cz, r):
- return lambda x, y, z: (x - cx)**2 + (y - cy)**2 + (z - cz)**2 < r*r
-
-def cylinder(cx, cz, r):
- return lambda x, y, z: (x - cx)**2 + (z - cz)**2 < r*r
-
-def get_cavity_material_map(geometry):
+def get_cavity_material_map(g):
return [
- (lambda x, y, z: x > 0 and x < geometry.size_x-1 and
- y > 0 and y < geometry.size_y-1 and
- z > 0 and z < geometry.size_z-1, 1), # bulk fluid
- (lambda x, y, z: x == 1 or x == geometry.size_x-2 or
- y == 1 or y == geometry.size_y-2 or
- z == 1 or z == geometry.size_z-2, 2), # walls
+ (lambda x, y, z: x > 0 and x < g.size_x-1 and
+ y > 0 and y < g.size_y-1 and
+ z > 0 and z < g.size_z-1, 1), # bulk fluid
+ (lambda x, y, z: x == 1 or x == g.size_x-2 or
+ y == 1 or y == g.size_y-2 or
+ z == 1 or z == g.size_z-2, 2), # walls
(lambda x, y, z: x == 1, 3), # inflow
- (lambda x, y, z: x == geometry.size_x-2, 4), # outflow
- (cylinder(geometry.size_x//6, geometry.size_z//2, cylinder_r), 5), # obstacle
- (lambda x, y, z: x == 0 or x == geometry.size_x-1 or
- y == 0 or y == geometry.size_y-1 or
- z == 0 or z == geometry.size_z-1, 0) # ghost cells
+ (lambda x, y, z: x == g.size_x-2, 4), # outflow
+
+ (Box(g.size_x//10, 1.5*g.size_x//10, 0, 2*g.size_y//5, 0, g.size_z), 5),
+ (Box(g.size_x//10, 1.5*g.size_x//10, 3*g.size_y//5, g.size_y, 0, g.size_z), 5),
+
+ (Sphere(g.size_x//3, g.size_y//2, g.size_z//2, 16), 5),
+ (Cylinder(g.size_x//3, 0, g.size_z//2, 5, l = g.size_y), 5),
+ (Cylinder(g.size_x//3, g.size_y//2, 0, 5, h = g.size_z), 5),
+
+ (lambda x, y, z: x == 0 or x == g.size_x-1 or
+ y == 0 or y == g.size_y-1 or
+ z == 0 or z == g.size_z-1, 0) # ghost cells
]
boundary = Template("""
@@ -66,39 +70,6 @@ boundary = Template("""
"inflow": lid_speed
})
-def get_projection(width, height):
- world_width = lattice_x
- world_height = world_width / width * height
-
- projection = matrix44.create_perspective_projection(20.0, width/height, 0.1, 1000.0)
- look = matrix44.create_look_at(
- eye = [0, -2*lattice_x, 0],
- target = [0, 0, 0],
- up = [0, 0, -1])
-
- point_size = 1
-
- return numpy.matmul(look, projection), point_size
-
-class Rotation:
- def __init__(self, shift, x = numpy.pi, z = numpy.pi):
- self.shift = shift
- self.rotation_x = x
- self.rotation_z = z
-
- def update(self, x, z):
- self.rotation_x += x
- self.rotation_z += z
-
- def get(self):
- qx = quaternion.Quaternion(quaternion.create_from_eulers([self.rotation_x,0,0]))
- qz = quaternion.Quaternion(quaternion.create_from_eulers([0,0,self.rotation_z]))
- rotation = qz.cross(qx)
- return numpy.matmul(
- matrix44.create_from_translation(self.shift),
- matrix44.create_from_quaternion(rotation)
- )
-
def glut_window(fullscreen = False):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
@@ -120,10 +91,7 @@ particle_shader = shaders.compileShader("""
#version 430
layout (location=0) in vec4 particles;
-
-out VS_OUT {
- vec3 color;
-} vs_out;
+ out vec3 color;
uniform mat4 projection;
uniform mat4 rotation;
@@ -144,68 +112,91 @@ void main() {
1.
);
- vs_out.color = fire(1.0-particles[3]);
+ color = fire(1.0-particles[3]);
}""", GL_VERTEX_SHADER)
-geometry_shader = shaders.compileShader("""
+vertex_shader = shaders.compileShader(Template("""
#version 430
-layout (points) in;
-layout (triangle_strip, max_vertices=4) out;
+layout (location=0) in vec4 vertex;
+ out vec3 color;
-in VS_OUT {
- vec3 color;
-} gs_in[];
+uniform mat4 projection;
+uniform mat4 rotation;
-out vec3 color;
+void main() {
+ gl_Position = projection * rotation * vertex;
+ color = vec3(1.0,1.0,1.0);
+}""").substitute({}), GL_VERTEX_SHADER)
-void emitSquareAt(vec4 position) {
- const float size = 0.5;
+fragment_shader = shaders.compileShader("""
+#version 430
- gl_Position = position + vec4(-size, -size, 0.0, 0.0);
- EmitVertex();
- gl_Position = position + vec4( size, -size, 0.0, 0.0);
- EmitVertex();
- gl_Position = position + vec4(-size, size, 0.0, 0.0);
- EmitVertex();
- gl_Position = position + vec4( size, size, 0.0, 0.0);
- EmitVertex();
-}
+in vec3 color;
-void main() {
- color = gs_in[0].color;
- emitSquareAt(gl_in[0].gl_Position);
- EndPrimitive();
-}""", GL_GEOMETRY_SHADER)
+layout(location = 0) out vec4 frag_color;
-vertex_shader = shaders.compileShader(Template("""
+void main(){
+ frag_color = vec4(color.xyz, 0.0);
+}""", GL_FRAGMENT_SHADER)
+
+lighting_vertex_shader = shaders.compileShader("""
#version 430
layout (location=0) in vec4 vertex;
+layout (location=2) in vec4 normal;
out vec3 color;
+ out vec3 frag_pos;
+ out vec3 frag_normal;
uniform mat4 projection;
uniform mat4 rotation;
void main() {
gl_Position = projection * rotation * vertex;
- color = vec3(0.5,0.5,0.5);
-}""").substitute({}), GL_VERTEX_SHADER)
+ frag_pos = vertex.xyz;
+ frag_normal = normalize(normal.xyz);
+ color = vec3(0.6,0.6,0.6);
+}""", GL_VERTEX_SHADER)
-fragment_shader = shaders.compileShader("""
+lighting_fragment_shader = shaders.compileShader(Template("""
#version 430
in vec3 color;
+in vec3 frag_pos;
+in vec3 frag_normal;
+
+uniform vec4 camera_pos;
+
+out vec4 result;
void main(){
- gl_FragColor = vec4(color.xyz, 0.0);
-}""", GL_FRAGMENT_SHADER)
+ const vec3 light_color = vec3(1.0,1.0,1.0);
-particle_program = shaders.compileProgram(particle_shader, geometry_shader, fragment_shader)
-projection_id = shaders.glGetUniformLocation(particle_program, 'projection')
-rotation_id = shaders.glGetUniformLocation(particle_program, 'rotation')
+ const vec3 ray = camera_pos.xyz - frag_pos;
+ float brightness = dot(frag_normal, ray) / length(ray);
+ brightness = clamp(brightness, 0, 1);
-geometry_program = shaders.compileProgram(vertex_shader, fragment_shader)
+ result = vec4(max(0.4,brightness) * light_color * color.rgb, 1.0);
+}
+""").substitute({
+ "size_x": lattice_x,
+ "size_y": lattice_y,
+ "size_z": lattice_z
+}), GL_FRAGMENT_SHADER)
+
+particle_program = shaders.compileProgram(particle_shader, fragment_shader)
+particle_projection_id = shaders.glGetUniformLocation(particle_program, 'projection')
+particle_rotation_id = shaders.glGetUniformLocation(particle_program, 'rotation')
+
+domain_program = shaders.compileProgram(vertex_shader, fragment_shader)
+domain_projection_id = shaders.glGetUniformLocation(domain_program, 'projection')
+domain_rotation_id = shaders.glGetUniformLocation(domain_program, 'rotation')
+
+obstacle_program = shaders.compileProgram(lighting_vertex_shader, lighting_fragment_shader)
+obstacle_projection_id = shaders.glGetUniformLocation(obstacle_program, 'projection')
+obstacle_rotation_id = shaders.glGetUniformLocation(obstacle_program, 'rotation')
+obstacle_camera_pos_id = shaders.glGetUniformLocation(obstacle_program, 'camera_pos')
lattice = Lattice(
descriptor = D3Q27,
@@ -216,66 +207,32 @@ lattice = Lattice(
opengl = True
)
-lattice.apply_material_map(
- get_cavity_material_map(lattice.geometry))
+material_map = get_cavity_material_map(lattice.geometry)
+primitives = list(map(lambda material: material[0], filter(lambda material: not callable(material[0]), material_map)))
+lattice.apply_material_map(material_map)
lattice.sync_material()
particles = Particles(
- lattice.context,
- lattice.queue,
- lattice.memory.float_type,
+ lattice,
numpy.mgrid[
2*lattice.geometry.size_x//100:4*lattice.geometry.size_x//100:particle_count/10000j,
- lattice.geometry.size_y//10:9*lattice.geometry.size_y//10:100j,
- lattice.geometry.size_z//10:9*lattice.geometry.size_z//10:100j,
+ lattice.geometry.size_y//16:15*lattice.geometry.size_y//16:100j,
+ lattice.geometry.size_z//16:15*lattice.geometry.size_z//16:100j,
].reshape(3,-1).T)
+projection = Projection(distance = 2*lattice_x)
rotation = Rotation([-lattice_x/2, -lattice_y/2, -lattice_z/2])
cube_vertices, cube_edges = lattice.geometry.wireframe()
-def draw_cylinder(cx, cz, height, radius, num_slices):
- r = radius
- h = height
- n = float(num_slices)
-
- circle_pts = []
- for i in range(int(n) + 1):
- angle = 2 * numpy.pi * (i/n)
- x = cx + r * numpy.cos(angle)
- z = cz + r * numpy.sin(angle)
- pt = (x, z)
- circle_pts.append(pt)
-
- glBegin(GL_TRIANGLE_FAN)
- glVertex(cx, 0, cz)
- for (x, z) in circle_pts:
- y = 0
- glVertex(x, y, z)
- glEnd()
-
- glBegin(GL_TRIANGLE_FAN)
- glVertex(cx, h, cz)
- for (x, z) in circle_pts:
- y = h
- glVertex(x, y, z)
- glEnd()
-
- glBegin(GL_TRIANGLE_STRIP)
- for (x, z) in circle_pts:
- y = h
- glVertex(x, 0, z)
- glVertex(x, h, z)
- glEnd()
-
def on_display():
for i in range(0,updates_per_frame):
lattice.evolve()
- lattice.collect_gl_moments()
+ lattice.update_moments()
for i in range(0,updates_per_frame):
- lattice.update_gl_particles(particles, aging = True)
+ particles.update(aging = True)
lattice.sync()
@@ -284,57 +241,50 @@ def on_display():
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
- glEnableClientState(GL_VERTEX_ARRAY)
- particles.gl_particles.bind()
-
shaders.glUseProgram(particle_program)
- glUniformMatrix4fv(projection_id, 1, False, numpy.ascontiguousarray(projection))
- glUniformMatrix4fv(rotation_id, 1, False, numpy.ascontiguousarray(rotation.get()))
- glVertexPointer(4, GL_FLOAT, 0, particles.gl_particles)
+ glUniformMatrix4fv(particle_projection_id, 1, False, numpy.ascontiguousarray(projection.get()))
+ glUniformMatrix4fv(particle_rotation_id, 1, False, numpy.ascontiguousarray(rotation.get()))
+ particles.bind()
glEnable(GL_POINT_SMOOTH)
- glPointSize(point_size)
+ glPointSize(1)
glDrawArrays(GL_POINTS, 0, particles.count)
- shaders.glUseProgram(geometry_program)
- glUniformMatrix4fv(projection_id, 1, False, numpy.ascontiguousarray(projection))
- glUniformMatrix4fv(rotation_id, 1, False, numpy.ascontiguousarray(rotation.get()))
- glLineWidth(2*point_size)
+ shaders.glUseProgram(domain_program)
+ glUniformMatrix4fv(domain_projection_id, 1, False, numpy.ascontiguousarray(projection.get()))
+ glUniformMatrix4fv(domain_rotation_id, 1, False, numpy.ascontiguousarray(rotation.get()))
+ glLineWidth(2)
glBegin(GL_LINES)
for i, j in cube_edges:
- glVertex3fv(cube_vertices[i])
- glVertex3fv(cube_vertices[j])
+ glVertex(cube_vertices[i])
+ glVertex(cube_vertices[j])
glEnd()
- draw_cylinder(lattice.geometry.size_x//6, lattice.geometry.size_z//2, lattice.geometry.size_y, cylinder_r, 32)
+ camera_pos = numpy.matmul([0,-projection.distance,0,1], rotation.get_inverse())
- glutSwapBuffers()
-
-def on_reshape(width, height):
- global projection, point_size
- glViewport(0,0,width,height)
- projection, point_size = get_projection(width, height)
+ shaders.glUseProgram(obstacle_program)
+ glUniformMatrix4fv(obstacle_projection_id, 1, False, numpy.ascontiguousarray(projection.get()))
+ glUniformMatrix4fv(obstacle_rotation_id, 1, False, numpy.ascontiguousarray(rotation.get()))
+ glUniform4fv(obstacle_camera_pos_id, 1, camera_pos)
-def on_keyboard(key, x, y):
- global rotation
+ for primitive in primitives:
+ primitive.draw()
- x = {
- b'w': -numpy.pi/10,
- b's': numpy.pi/10
- }.get(key, 0.0)
- z = {
- b'a': numpy.pi/10,
- b'd': -numpy.pi/10
- }.get(key, 0.0)
+ glutSwapBuffers()
- rotation.update(x,z)
+mouse_monitors = [
+ MouseDragMonitor(GLUT_LEFT_BUTTON, lambda dx, dy: rotation.update(0.005*dy, 0.005*dx)),
+ MouseDragMonitor(GLUT_RIGHT_BUTTON, lambda dx, dy: rotation.shift(0.25*dx, 0.25*dy)),
+ MouseScrollMonitor(lambda zoom: projection.update_distance(5*zoom))
+]
def on_timer(t):
glutTimerFunc(t, on_timer, t)
glutPostRedisplay()
glutDisplayFunc(on_display)
-glutReshapeFunc(on_reshape)
-glutKeyboardFunc(on_keyboard)
+glutReshapeFunc(lambda w, h: projection.update_ratio(w, h))
+glutMouseFunc(lambda *args: list(map(lambda m: m.on_mouse(*args), mouse_monitors)))
+glutMotionFunc(lambda *args: list(map(lambda m: m.on_mouse_move(*args), mouse_monitors)))
glutTimerFunc(10, on_timer, 10)
glutMainLoop()