diff options
Diffstat (limited to 'utility')
-rw-r--r-- | utility/mouse.py | 34 | ||||
-rw-r--r-- | utility/opengl.py | 87 | ||||
-rw-r--r-- | utility/particles.py | 49 | ||||
-rw-r--r-- | utility/projection.py | 67 | ||||
-rw-r--r-- | utility/streamline.py | 71 |
5 files changed, 302 insertions, 6 deletions
diff --git a/utility/mouse.py b/utility/mouse.py new file mode 100644 index 0000000..5d7dd5d --- /dev/null +++ b/utility/mouse.py @@ -0,0 +1,34 @@ +from OpenGL.GLUT import * + +class MouseDragMonitor: + def __init__(self, button, callback): + self.button = button + self.active = False + self.callback = callback + + def on_mouse(self, button, state, x, y): + if button == self.button: + self.active = (state == GLUT_DOWN) + self.last_x = x + self.last_y = y + + def on_mouse_move(self, x, y): + if self.active: + delta_x = self.last_x - x + delta_y = y - self.last_y + self.last_x = x + self.last_y = y + self.callback(delta_x, delta_y) + +class MouseScrollMonitor: + def __init__(self, callback): + self.callback = callback + + def on_mouse(self, button, state, x, y): + if button == 3: + self.callback(-1.0) + elif button == 4: + self.callback(1.0) + + def on_mouse_move(self, x, y): + pass diff --git a/utility/opengl.py b/utility/opengl.py new file mode 100644 index 0000000..456259b --- /dev/null +++ b/utility/opengl.py @@ -0,0 +1,87 @@ +import pyopencl as cl +mf = cl.mem_flags + +import numpy +import sympy + +from mako.template import Template +from pathlib import Path + +from OpenGL.GL import * + + +class MomentsTexture: + def __init__(self, lattice, include_materials = True): + self.lattice = lattice + self.include_materials = include_materials + self.gl_texture_buffer = numpy.ndarray(shape=(self.lattice.memory.volume, 4), dtype=self.lattice.memory.float_type) + self.gl_texture_buffer[:,:] = 0.0 + + self.gl_moments = glGenTextures(1) + self.gl_texture_type = {2: GL_TEXTURE_2D, 3: GL_TEXTURE_3D}.get(self.lattice.descriptor.d) + glBindTexture(self.gl_texture_type, self.gl_moments) + + if self.gl_texture_type == GL_TEXTURE_3D: + glTexImage3D(self.gl_texture_type, 0, GL_RGBA32F, self.lattice.memory.size_x, self.lattice.memory.size_y, self.lattice.memory.size_z, 0, GL_RGBA, GL_FLOAT, self.gl_texture_buffer) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE) + self.cl_gl_moments = cl.GLTexture(self.lattice.context, mf.READ_WRITE, self.gl_texture_type, 0, self.gl_moments, 3) + elif self.gl_texture_type == GL_TEXTURE_2D: + glTexImage2D(self.gl_texture_type, 0, GL_RGBA32F, self.lattice.memory.size_x, self.lattice.memory.size_y, 0, GL_RGBA, GL_FLOAT, self.gl_texture_buffer) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) + self.cl_gl_moments = cl.GLTexture(self.lattice.context, mf.READ_WRITE, self.gl_texture_type, 0, self.gl_moments, 2) + + self.build_kernel() + + def build_kernel(self): + program_src = Template(filename = str(Path(__file__).parent/'../template/opengl.mako')).render( + descriptor = self.lattice.descriptor, + geometry = self.lattice.geometry, + memory = self.lattice.memory, + + moments_subexpr = self.lattice.moments[0], + moments_assignment = self.lattice.moments[1], + collide_subexpr = self.lattice.collide[0], + collide_assignment = self.lattice.collide[1], + + float_type = self.lattice.float_type[1], + + ccode = sympy.ccode + ) + self.program = cl.Program(self.lattice.context, program_src).build(self.lattice.compiler_args) + + def bind(self, location = GL_TEXTURE0): + glEnable(self.gl_texture_type) + glActiveTexture(location); + glBindTexture(self.gl_texture_type, self.gl_moments) + + def collect_moments_from_pop_to_texture(self, population): + if self.include_materials: + self.program.collect_gl_moments_and_materials_to_texture( + self.lattice.queue, + self.lattice.grid.size(), + self.lattice.layout, + population, + self.lattice.memory.cl_material, + self.cl_gl_moments) + else: + self.program.collect_gl_moments_to_texture( + self.lattice.queue, + self.lattice.grid.size(), + self.lattice.layout, + population, + self.cl_gl_moments) + + def collect(self): + cl.enqueue_acquire_gl_objects(self.lattice.queue, [self.cl_gl_moments]) + + if self.lattice.tick: + self.collect_moments_from_pop_to_texture(self.lattice.memory.cl_pop_b) + else: + self.collect_moments_from_pop_to_texture(self.lattice.memory.cl_pop_a) diff --git a/utility/particles.py b/utility/particles.py index a7ef777..75d2245 100644 --- a/utility/particles.py +++ b/utility/particles.py @@ -3,16 +3,22 @@ mf = cl.mem_flags import numpy +from mako.template import Template +from pathlib import Path + import OpenGL.GL as gl from OpenGL.arrays import vbo class Particles: - def __init__(self, context, queue, float_type, grid): - self.context = context + def __init__(self, lattice, grid): + self.lattice = lattice + self.context = self.lattice.context + self.queue = self.lattice.queue + self.float_type = self.lattice.memory.float_type self.count = len(grid) - self.np_particles = numpy.ndarray(shape=(self.count, 4), dtype=float_type) - self.np_init_particles = numpy.ndarray(shape=(self.count, 4), dtype=float_type) + self.np_particles = numpy.ndarray(shape=(self.count, 4), dtype=self.float_type) + self.np_init_particles = numpy.ndarray(shape=(self.count, 4), dtype=self.float_type) if len(grid[0,:]) == 2: self.np_particles[:,0:2] = grid @@ -28,5 +34,36 @@ class Particles: self.gl_particles.bind() self.cl_gl_particles = cl.GLBuffer(self.context, mf.READ_WRITE, int(self.gl_particles)) - self.cl_init_particles = cl.Buffer(context, mf.READ_ONLY, size=self.count * 4*numpy.float32(0).nbytes) - cl.enqueue_copy(queue, self.cl_init_particles, self.np_init_particles).wait(); + self.cl_init_particles = cl.Buffer(self.context, mf.READ_ONLY, size=self.count * 4*numpy.float32(0).nbytes) + cl.enqueue_copy(self.queue, self.cl_init_particles, self.np_init_particles).wait(); + + self.build_kernel() + + def build_kernel(self): + program_src = Template(filename = str(Path(__file__).parent/'../template/particles.mako')).render( + descriptor = self.lattice.descriptor, + geometry = self.lattice.geometry, + memory = self.lattice.memory, + float_type = self.float_type, + ) + self.program = cl.Program(self.lattice.context, program_src).build(self.lattice.compiler_args) + + def bind(self): + gl.glEnableClientState(gl.GL_VERTEX_ARRAY) + self.gl_particles.bind() + gl.glVertexPointer(4, gl.GL_FLOAT, 0, self.gl_particles) + + def update(self, aging = False): + cl.enqueue_acquire_gl_objects(self.queue, [self.cl_gl_particles]) + + if aging: + age = numpy.float32(0.000006) + else: + age = numpy.float32(0.0) + + self.program.update_particles( + self.queue, (self.count,1), None, + self.lattice.memory.cl_moments, + self.lattice.memory.cl_material, + self.cl_gl_particles, self.cl_init_particles, + age) diff --git a/utility/projection.py b/utility/projection.py new file mode 100644 index 0000000..76791d9 --- /dev/null +++ b/utility/projection.py @@ -0,0 +1,67 @@ +import numpy + +from OpenGL.GL import glViewport + +from pyrr import matrix44, quaternion + +class Projection: + def __init__(self, distance): + self.distance = distance + self.ratio = 4./3. + self.update() + + def update(self): + projection = matrix44.create_perspective_projection(20.0, self.ratio, 0.1, 5000.0) + look = matrix44.create_look_at( + eye = [0, -self.distance, 0], + target = [0, 0, 0], + up = [0, 0, -1]) + + self.matrix = numpy.matmul(look, projection) + + def update_ratio(self, width, height, update_viewport = True): + if update_viewport: + glViewport(0,0,width,height) + + self.ratio = width/height + self.update() + + def update_distance(self, change): + self.distance += change + self.update() + + def get(self): + return self.matrix + +class Rotation: + def __init__(self, shift, x = numpy.pi, z = numpy.pi): + self.matrix = matrix44.create_from_translation(shift), + self.rotation_x = quaternion.Quaternion() + self.update(x,z) + + def shift(self, x, z): + self.matrix = numpy.matmul( + self.matrix, + matrix44.create_from_translation([x,0,z]) + ) + self.inverse_matrix = numpy.linalg.inv(self.matrix) + + def update(self, x, z): + rotation_x = quaternion.Quaternion(quaternion.create_from_eulers([x,0,0])) + rotation_z = self.rotation_x.conjugate.cross( + quaternion.Quaternion(quaternion.create_from_eulers([0,0,z]))) + self.rotation_x = self.rotation_x.cross(rotation_x) + + self.matrix = numpy.matmul( + self.matrix, + matrix44.create_from_quaternion(rotation_z.cross(self.rotation_x)) + ) + self.inverse_matrix = numpy.linalg.inv(self.matrix) + + def get(self): + return self.matrix + + def get_inverse(self): + return self.inverse_matrix + + diff --git a/utility/streamline.py b/utility/streamline.py new file mode 100644 index 0000000..9f0fb55 --- /dev/null +++ b/utility/streamline.py @@ -0,0 +1,71 @@ +import pyopencl as cl +mf = cl.mem_flags + +import numpy + +from mako.template import Template +from pathlib import Path + +from OpenGL.GL import * +from OpenGL.arrays import vbo + +class Streamlines: + def __init__(self, lattice, origins): + self.lattice = lattice + self.context = self.lattice.context + self.queue = self.lattice.queue + self.float_type = self.lattice.memory.float_type + + self.count = len(origins) + self.np_origins = numpy.ndarray(shape=(self.count, 2), dtype=self.float_type) + + for i, pos in enumerate(origins): + self.np_origins[i,:] = pos + + self.cl_origins = cl.Buffer(self.context, mf.READ_ONLY, size=self.count * 2*numpy.float32(0).nbytes) + cl.enqueue_copy(self.queue, self.cl_origins, self.np_origins).wait(); + + self.gl_texture_buffer = numpy.ndarray(shape=(self.lattice.memory.volume, 4), dtype=self.lattice.memory.float_type) + self.gl_texture_buffer[:,:] = 0.0 + + self.gl_streamlines = glGenTextures(1) + self.gl_texture_type = GL_TEXTURE_2D + glBindTexture(self.gl_texture_type, self.gl_streamlines) + + glTexImage2D(self.gl_texture_type, 0, GL_RGBA32F, self.lattice.memory.size_x, self.lattice.memory.size_y, 0, GL_RGBA, GL_FLOAT, self.gl_texture_buffer) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(self.gl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) + glTexParameteri(self.gl_texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) + self.cl_gl_streamlines = cl.GLTexture(self.lattice.context, mf.READ_WRITE, self.gl_texture_type, 0, self.gl_streamlines, 2) + + self.build_kernel() + + def build_kernel(self): + program_src = Template(filename = str(Path(__file__).parent/'../template/streamline.mako')).render( + descriptor = self.lattice.descriptor, + geometry = self.lattice.geometry, + memory = self.lattice.memory, + float_type = self.float_type, + ) + self.program = cl.Program(self.lattice.context, program_src).build(self.lattice.compiler_args) + + def bind(self, location = GL_TEXTURE0): + glEnable(self.gl_texture_type) + glActiveTexture(location); + glBindTexture(self.gl_texture_type, self.gl_streamlines) + + def update(self): + cl.enqueue_acquire_gl_objects(self.queue, [self.cl_gl_streamlines]) + + self.program.dillute( + self.queue, (self.lattice.memory.size_x,self.lattice.memory.size_y), None, + self.lattice.memory.cl_material, + self.cl_gl_streamlines) + + self.program.draw_streamline( + self.queue, (self.count,1), None, + self.lattice.memory.cl_moments, + self.lattice.memory.cl_material, + self.cl_origins, + self.cl_gl_streamlines) |