aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2020-03-27 20:35:13 +0100
committerAdrian Kummerlaender2020-03-27 20:35:13 +0100
commit774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2 (patch)
tree0555f94cb71f1a038020d5913ad27f64843f0aec
parentee05ee023df26be65d143537e4ad26090572bd1e (diff)
downloadboltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar.gz
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar.bz2
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar.lz
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar.xz
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.tar.zst
boltzgas-774a4e4d6298f03ff61fb6e2c13a62ca25a2afb2.zip
Add wire box, enable depth testing
-rw-r--r--boltzgas/visual/__init__.py2
-rw-r--r--boltzgas/visual/box.py56
-rw-r--r--boltzgas/visual/camera.py106
-rw-r--r--boltzgas/visual/view.py141
-rw-r--r--boltzgas/visualizer.py17
-rw-r--r--random_velocities.py6
-rw-r--r--zero_velocities.py11
7 files changed, 234 insertions, 105 deletions
diff --git a/boltzgas/visual/__init__.py b/boltzgas/visual/__init__.py
index 3462d96..6156b48 100644
--- a/boltzgas/visual/__init__.py
+++ b/boltzgas/visual/__init__.py
@@ -1,4 +1,4 @@
-from .box import ColoredBox
+from .box import ColoredBox, WireBox
from .histogram import VelocityHistogram
from .tracer import Tracer
from .view import View
diff --git a/boltzgas/visual/box.py b/boltzgas/visual/box.py
index 0a6ab5a..0b4bd82 100644
--- a/boltzgas/visual/box.py
+++ b/boltzgas/visual/box.py
@@ -14,3 +14,59 @@ class ColoredBox:
glVertex(self.origin[0] , self.origin[1] + self.extend[1], 0.)
glVertex(self.origin[0] + self.extend[1], self.origin[1] + self.extend[1], 0.)
glEnd()
+
+class WireBox:
+ def __init__(self, x0, x1, y0, y1, z0, z1):
+ self.x0 = x0
+ self.x1 = x1
+ self.y0 = y0
+ self.y1 = y1
+ self.z0 = z0
+ self.z1 = z1
+
+ def display(self, uniform):
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x0, self.y0, self.z0)
+ glVertex(self.x0, self.y1, self.z0)
+ glVertex(self.x0, self.y1, self.z1)
+ glVertex(self.x0, self.y0, self.z1)
+ glVertex(self.x0, self.y0, self.z0)
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x1, self.y0, self.z0)
+ glVertex(self.x1, self.y1, self.z0)
+ glVertex(self.x1, self.y1, self.z1)
+ glVertex(self.x1, self.y0, self.z1)
+ glVertex(self.x1, self.y0, self.z0)
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x0, self.y0, self.z1)
+ glVertex(self.x1, self.y0, self.z1)
+ glVertex(self.x1, self.y1, self.z1)
+ glVertex(self.x0, self.y1, self.z1)
+ glVertex(self.x0, self.y0, self.z1)
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x0, self.y0, self.z0)
+ glVertex(self.x1, self.y0, self.z0)
+ glVertex(self.x1, self.y1, self.z0)
+ glVertex(self.x0, self.y1, self.z0)
+ glVertex(self.x0, self.y0, self.z0)
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x0, self.y0, self.z0)
+ glVertex(self.x1, self.y0, self.z0)
+ glVertex(self.x1, self.y0, self.z1)
+ glVertex(self.x0, self.y0, self.z1)
+ glVertex(self.x0, self.y0, self.z0)
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ glVertex(self.x0,self.y1,self.z0)
+ glVertex(self.x1,self.y1,self.z0)
+ glVertex(self.x1,self.y1,self.z1)
+ glVertex(self.x0,self.y1,self.z1)
+ glVertex(self.x0,self.y1,self.z0)
+ glEnd()
+
+
+
diff --git a/boltzgas/visual/camera.py b/boltzgas/visual/camera.py
new file mode 100644
index 0000000..44831f4
--- /dev/null
+++ b/boltzgas/visual/camera.py
@@ -0,0 +1,106 @@
+from OpenGL.GL import *
+from OpenGL.GLUT import *
+
+from pyrr import matrix44, quaternion
+
+import numpy as np
+
+class Projection:
+ def __init__(self, distance):
+ self.distance = distance
+ self.ratio = 4./3.
+ self.x = 0
+ self.y = 0
+ self.update()
+
+ def update(self):
+ projection = matrix44.create_perspective_projection(20.0, self.ratio, 0.1, 5000.0)
+ look = matrix44.create_look_at(
+ eye = [self.x, -self.distance, self.y],
+ target = [self.x, 0, self.y],
+ up = [0, 0,-1])
+
+ self.matrix = np.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 shift(self, x, y):
+ self.x -= x
+ self.y -= y
+ self.update()
+
+ def get(self):
+ return self.matrix
+
+class Rotation:
+ def __init__(self, shift, x = np.pi, z = np.pi):
+ self.matrix = matrix44.create_from_translation(shift),
+ self.rotation_x = quaternion.Quaternion()
+ self.update(x,z)
+
+ def shift(self, x, z):
+ self.matrix = np.matmul(
+ self.matrix,
+ matrix44.create_from_translation([x,0,z])
+ )
+ self.inverse_matrix = np.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 = np.matmul(
+ self.matrix,
+ matrix44.create_from_quaternion(rotation_z.cross(self.rotation_x))
+ )
+ self.inverse_matrix = np.linalg.inv(self.matrix)
+
+ def get(self):
+ return self.matrix
+
+ def get_inverse(self):
+ return self.inverse_matrix
+
+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/boltzgas/visual/view.py b/boltzgas/visual/view.py
index c1f92e6..300092f 100644
--- a/boltzgas/visual/view.py
+++ b/boltzgas/visual/view.py
@@ -1,11 +1,12 @@
from OpenGL.GL import *
from OpenGL.GLUT import *
-from pyrr import matrix44, quaternion
+from pyrr import matrix44
import numpy as np
from .shader import Shader
+from .camera import Projection, Rotation, MouseDragMonitor, MouseScrollMonitor
particle_shader = (
"""
@@ -25,9 +26,9 @@ particle_shader = (
n = normalize(n);
vec3 dir = normalize(camera_pos.xyz - particle_pos);
- vec3 color = vec3(1.,1.,1.) * dot(dir, n);
+ vec3 color = vec3(1.) * dot(dir, n);
- gl_FragColor = vec4(color.xyz, 0.0);
+ gl_FragColor = vec4(max(vec3(0.5), color.xyz), 1.0);
}
""",
"""
@@ -58,28 +59,23 @@ decoration_shader = (
"""
#version 430
- in vec3 color;
-
void main(){
- gl_FragColor = vec4(color.xyz, 0.0);
+ gl_FragColor = vec4(1.,1.,1., 1.0);
}
""",
"""
#version 430
- in vec3 vertex;
-
- out vec3 color;
+ layout (location=0) in vec3 vertex;
uniform mat4 projection;
- uniform vec3 face_color;
+ uniform mat4 rotation;
void main() {
- gl_Position = projection * vec4(vertex, 1.);
- color = face_color;
+ gl_Position = projection * rotation * vec4(vertex.xyz, 1.);
}
""",
- ['projection', 'face_color']
+ ['projection', 'rotation']
)
texture_shader = (
@@ -93,7 +89,12 @@ texture_shader = (
uniform float mixing;
void main() {
- gl_FragColor = mix(texture(picture[0], tex_coord), texture(picture[1], tex_coord), mixing);
+ vec3 color = mix(texture(picture[0], tex_coord), texture(picture[1], tex_coord), mixing).xyz;
+ if (color == vec3(0.,0.,0.)) {
+ gl_FragColor = vec4(color, 0.5);
+ } else {
+ gl_FragColor = vec4(color, 1.0);
+ }
}
""",
"""
@@ -115,68 +116,6 @@ texture_shader = (
)
-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, 0, -self.distance],
- target = [0, 0, 0],
- up = [0,-1, 0])
-
- self.matrix = np.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 = np.pi, z = np.pi):
- self.matrix = matrix44.create_from_translation(shift),
- self.rotation_x = quaternion.Quaternion()
- self.update(x,z)
-
- def shift(self, x, z):
- self.matrix = np.matmul(
- self.matrix,
- matrix44.create_from_translation([x,0,z])
- )
- self.inverse_matrix = np.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 = np.matmul(
- self.matrix,
- matrix44.create_from_quaternion(rotation_z.cross(self.rotation_x))
- )
- self.inverse_matrix = np.linalg.inv(self.matrix)
-
- def get(self):
- return self.matrix
-
- def get_inverse(self):
- return self.inverse_matrix
-
-
-
class View:
def __init__(self, gas, decorations, windows):
self.gas = gas
@@ -187,9 +126,18 @@ class View:
self.particle_shader = Shader(*particle_shader)
self.decoration_shader = Shader(*decoration_shader)
- self.projection3d = Projection(distance = 6)
- self.rotation3d = Rotation([-1, -1, -1/2], 5*np.pi/4, np.pi/4)
- self.camera_pos = np.matmul([0,self.projection3d.distance,0,1], self.rotation3d.get_inverse())
+ self.camera_projection = Projection(distance = 6)
+ self.camera_rotation = Rotation([-1/2, -1/2, -1/2])
+ self.camera_pos = np.matmul([0,-self.camera_projection.distance,0,1], self.camera_rotation.get_inverse())
+
+ self.mouse_monitors = [
+ MouseDragMonitor(GLUT_LEFT_BUTTON, lambda dx, dy: self.camera_rotation.update(0.005*dy, 0.005*dx)),
+ MouseDragMonitor(GLUT_RIGHT_BUTTON, lambda dx, dy: self.camera_projection.shift(0.005*dx, 0.005*dy)),
+ MouseScrollMonitor(lambda zoom: self.camera_projection.update_distance(0.1*zoom))
+ ]
+
+ self.show_histogram = False
+
def reshape(self, width, height):
glViewport(0,0,width,height)
@@ -202,6 +150,8 @@ class View:
projection = matrix44.create_orthogonal_projection(-world_width/2, world_width/2, -world_height/2, world_height/2, -1, 1)
translation = matrix44.create_from_translation([-1.05, -1.0/2, 0])
+ self.camera_projection.update_ratio(width, height)
+
self.pixels_per_unit = height / world_height
self.projection = np.matmul(translation, projection)
@@ -209,21 +159,16 @@ class View:
glClearColor(0.,0.,0.,1.)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
- self.decoration_shader.use()
- glUniformMatrix4fv(self.decoration_shader.uniform['projection'], 1, False, np.asfortranarray(self.projection))
- for decoration in self.decorations:
- decoration.display(self.decoration_shader.uniform)
+ glEnable(GL_DEPTH_TEST)
+ glDepthMask(GL_TRUE)
+ glDepthFunc(GL_LEQUAL)
- self.texture_shader.use()
- glUniformMatrix4fv(self.texture_shader.uniform['projection'], 1, False, np.asfortranarray(self.projection))
- for window in self.windows:
- window.display(self.texture_shader.uniform)
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
self.particle_shader.use()
- #glUniformMatrix4fv(self.particle_shader.uniform['projection'], 1, False, np.asfortranarray(self.projection))
-
- glUniformMatrix4fv(self.particle_shader.uniform['projection'], 1, False, np.ascontiguousarray(self.projection3d.get()))
- glUniformMatrix4fv(self.particle_shader.uniform['rotation'], 1, False, np.ascontiguousarray(self.rotation3d.get()))
+ glUniformMatrix4fv(self.particle_shader.uniform['projection'], 1, False, np.ascontiguousarray(self.camera_projection.get()))
+ glUniformMatrix4fv(self.particle_shader.uniform['rotation'], 1, False, np.ascontiguousarray(self.camera_rotation.get()))
glUniform3f(self.particle_shader.uniform['face_color'], 1., 1., 1.)
glUniform3f(self.particle_shader.uniform['trace_color'], 1., 0., 0.)
@@ -233,5 +178,19 @@ class View:
glEnable(GL_POINT_SPRITE)
glPointSize(2*self.gas.radius*self.pixels_per_unit)
self.gas.gl_draw_particles()
+ glBindVertexArray(0)
+
+ self.decoration_shader.use()
+ glUniformMatrix4fv(self.decoration_shader.uniform['projection'], 1, False, np.ascontiguousarray(self.camera_projection.get()))
+ glUniformMatrix4fv(self.decoration_shader.uniform['rotation'], 1, False, np.ascontiguousarray(self.camera_rotation.get()))
+ glLineWidth(2)
+ for decoration in self.decorations:
+ decoration.display(self.decoration_shader.uniform)
+
+ if self.show_histogram:
+ self.texture_shader.use()
+ glUniformMatrix4fv(self.texture_shader.uniform['projection'], 1, False, np.asfortranarray(self.projection))
+ for window in self.windows:
+ window.display(self.texture_shader.uniform)
glutSwapBuffers()
diff --git a/boltzgas/visualizer.py b/boltzgas/visualizer.py
index 44cec7a..373a181 100644
--- a/boltzgas/visualizer.py
+++ b/boltzgas/visualizer.py
@@ -57,12 +57,15 @@ def make_timer():
return on_timer
-def make_keyboard_handler(controller):
+def make_keyboard_handler(controller, view):
def on_keyboard(key, x, y):
- if controller.isRunning():
- controller.pause()
- else:
- controller.run()
+ if key == b' ':
+ if controller.isRunning():
+ controller.pause()
+ else:
+ controller.run()
+ if key == b'h':
+ view.show_histogram = not view.show_histogram
return on_keyboard
@@ -88,7 +91,9 @@ def simulate(config, gas, instruments, decorations, windows, updates_per_frame =
glutDisplayFunc(make_display_handler(controller, view))
glutReshapeFunc(make_reshape_handler(view))
glutTimerFunc(20, make_timer(), 20)
- glutKeyboardFunc(make_keyboard_handler(controller))
+ glutKeyboardFunc(make_keyboard_handler(controller, view))
glutCloseFunc(make_close_handler(controller))
+ glutMouseFunc(lambda *args: list(map(lambda m: m.on_mouse(*args), view.mouse_monitors)))
+ glutMotionFunc(lambda *args: list(map(lambda m: m.on_mouse_move(*args), view.mouse_monitors)))
glutMainLoop()
diff --git a/random_velocities.py b/random_velocities.py
index 2308bd3..3679dcc 100644
--- a/random_velocities.py
+++ b/random_velocities.py
@@ -2,7 +2,7 @@ import boltzgas.visualizer
from boltzgas import HardSphereSetup, HardSphereSimulation
from boltzgas.initial_condition import grid_of_random_velocity_particles
-from boltzgas.visual import VelocityHistogram, ColoredBox, Tracer
+from boltzgas.visual import VelocityHistogram, WireBox, Tracer
grid_width = 10
radius = 0.005
@@ -13,10 +13,12 @@ position, velocity = grid_of_random_velocity_particles(grid_width, radius, char_
config = HardSphereSetup(radius, char_u, position, velocity)
gas = HardSphereSimulation(config, opengl = True, t_scale=0.5)
+from OpenGL.GL import *
+
#tracer = Tracer(gas, int((grid_width**2)/2+grid_width/2))
histogram = VelocityHistogram(gas, [1.1,0], [1,1])
-decorations = [ ]
+decorations = [ WireBox(0,1,0,1,0,1) ]
instruments = [ histogram ]
windows = [ histogram ]
diff --git a/zero_velocities.py b/zero_velocities.py
index 135796a..54cb353 100644
--- a/zero_velocities.py
+++ b/zero_velocities.py
@@ -2,23 +2,24 @@ import boltzgas.visualizer
from boltzgas import HardSphereSetup, HardSphereSimulation
from boltzgas.initial_condition import grid_of_random_velocity_particles
-from boltzgas.visual import VelocityHistogram, ColoredBox
+from boltzgas.visual import VelocityHistogram, WireBox
-grid_width = 40
-radius = 0.002
+grid_width = 10
+radius = 0.005
char_u = 1120
position, velocity = grid_of_random_velocity_particles(grid_width, radius, char_u)
velocity[:,:] = 0
-velocity[0,0] = 10*char_u
+velocity[0,0] = 5*char_u
velocity[0,1] = 4*char_u
+velocity[0,2] = 3*char_u
config = HardSphereSetup(radius, char_u, position, velocity)
gas = HardSphereSimulation(config, opengl = True, t_scale = 0.5)
histogram = VelocityHistogram(gas, [1.1,0], [1,1])
-decorations = [ ColoredBox([0,0], [1,1], (0.2,0.2,0.2)) ]
+decorations = [ WireBox(0,1,0,1,0,1) ]
instruments = [ histogram ]
windows = [ histogram ]