summaryrefslogtreecommitdiff
path: root/interacticle/visual/view.py
diff options
context:
space:
mode:
Diffstat (limited to 'interacticle/visual/view.py')
-rw-r--r--interacticle/visual/view.py242
1 files changed, 242 insertions, 0 deletions
diff --git a/interacticle/visual/view.py b/interacticle/visual/view.py
new file mode 100644
index 0000000..14ff487
--- /dev/null
+++ b/interacticle/visual/view.py
@@ -0,0 +1,242 @@
+from OpenGL.GL import *
+from OpenGL.GLUT import *
+
+from pyrr import matrix44
+
+import numpy as np
+
+from .shader import Shader, GeometryShader
+from .camera import Projection, Rotation, MouseDragMonitor, MouseScrollMonitor
+
+particle_shader = (
+ """
+ #version 430
+
+ uniform vec4 camera_pos;
+
+ in GS_OUT
+ {
+ vec3 particle_pos;
+ vec3 atom_color;
+ vec2 tex_coord;
+ } fs_in;
+
+ void main(){
+ if (length(fs_in.tex_coord - vec2(0.5)) > 0.5) {
+ discard;
+ }
+
+ vec3 n = vec3(fs_in.tex_coord - vec2(0.5), 0.);
+ n.z = -sqrt(1 - length(n))*0.6;
+ n = normalize(n);
+
+ vec3 dir = normalize(camera_pos.xyz - fs_in.particle_pos);
+ vec3 color = fs_in.atom_color * dot(dir, n);
+
+ gl_FragColor = vec4(color.xyz, 1.0);
+ }
+ """,
+ """
+ #version 430
+
+ layout (points) in;
+ layout (triangle_strip, max_vertices=4) out;
+
+ out GS_OUT
+ {
+ vec3 particle_pos;
+ vec3 atom_color;
+ vec2 tex_coord;
+ } gs_out;
+
+ uniform mat4 projection;
+ uniform mat4 rotation;
+
+ uniform vec4 camera_pos;
+
+ vec4 project(vec3 v) {
+ return projection * rotation * vec4(v, 1.);
+ }
+
+ void emitSquareAt(vec3 position, float mass) {
+ mat4 m = projection * rotation;
+ vec3 camera_right = normalize(vec3(m[0][0], m[1][0], m[2][0]));
+ vec3 camera_up = normalize(vec3(m[0][1], m[1][1], m[2][1]));
+
+ gs_out.particle_pos = project(position).xyz;
+ gs_out.atom_color = float(mass == 39.948) * vec3(1,0,1) * 0.7
+ + float(mass == 20.18) * vec3(0.62,0.45,0.79)
+ + float(mass == 12.011) * vec3(0.5)
+ + float(mass == 15.9992) * vec3(1,0,0) * 0.6
+ + float(mass == 1.008) * vec3(1) * 0.7
+ + float(mass == 1.0079) * vec3(1) * 0.7;
+
+ float r = 0.02 * pow(mass, 0.2);
+
+ gl_Position = project(position + camera_right * -r + camera_up * -r);
+ gs_out.tex_coord = vec2(0.,0.);
+ EmitVertex();
+ gl_Position = project(position + camera_right * r + camera_up * -r);
+ gs_out.tex_coord = vec2(1.,0.);
+ EmitVertex();
+ gl_Position = project(position + camera_right * -r + camera_up * r);
+ gs_out.tex_coord = vec2(0.,1.);
+ EmitVertex();
+ gl_Position = project(position + camera_right * r + camera_up * r);
+ gs_out.tex_coord = vec2(1.,1.);
+ EmitVertex();
+ }
+
+ void main() {
+ emitSquareAt(gl_in[0].gl_Position.xyz, gl_in[0].gl_Position.w);
+ EndPrimitive();
+ }
+ """,
+ """
+ #version 430
+
+ layout (location=0) in vec4 particle_pos;
+
+ void main() {
+ gl_Position = particle_pos;
+ }
+ """,
+ ['projection', 'rotation', 'camera_pos']
+)
+
+decoration_shader = (
+ """
+ #version 430
+
+ uniform vec3 color;
+
+ void main(){
+ gl_FragColor = vec4(color, 1);
+ }
+ """,
+ """
+ #version 430
+
+ layout (location=0) in vec3 vertex;
+
+ uniform mat4 projection;
+ uniform mat4 rotation;
+
+ void main() {
+ gl_Position = projection * rotation * vec4(vertex.xyz, 1.);
+ }
+ """,
+ ['projection', 'rotation', 'color']
+)
+
+texture_shader = (
+ """
+ #version 430
+
+ in vec2 tex_coord;
+
+ uniform sampler2D picture[2];
+
+ uniform float mixing;
+
+ void main() {
+ 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);
+ }
+ }
+ """,
+ """
+ #version 430
+
+ layout (location=0) in vec2 screen_vertex;
+ layout (location=1) in vec2 texture_vertex;
+
+ out vec2 tex_coord;
+
+ uniform mat4 projection;
+
+ void main() {
+ gl_Position = projection * vec4(screen_vertex, 0.0, 1.0);
+ tex_coord = texture_vertex;
+ }
+ """,
+ ['picture','projection','mixing']
+)
+
+
+class View:
+ def __init__(self, simulation, instruments):
+ self.simulation = simulation
+ self.instruments = instruments
+
+ self.texture_shader = Shader(*texture_shader)
+ self.particle_shader = GeometryShader(*particle_shader)
+ self.decoration_shader = Shader(*decoration_shader)
+
+ self.camera_projection = Projection(distance = 5*simulation.domain_size)
+ self.camera_rotation = Rotation([-0.5*simulation.domain_size, -0.5*simulation.domain_size, -0.5*simulation.domain_size], np.pi/2, 0)
+ 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_windows = False
+ self.show_decorations = True
+
+ def reshape(self, width, height):
+ glViewport(0,0,width,height)
+
+ world_height = 1.4
+ world_width = world_height / height * width
+
+ projection = Projection(10)
+
+ 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)
+
+
+ def display(self):
+ glClearColor(0,0,0,1.)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ glEnable(GL_DEPTH_TEST)
+ glDepthMask(GL_TRUE)
+ glDepthFunc(GL_LEQUAL)
+
+ 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.ascontiguousarray(self.camera_projection.get()))
+ glUniformMatrix4fv(self.particle_shader.uniform['rotation'], 1, False, np.ascontiguousarray(self.camera_rotation.get()))
+ glUniform4fv(self.particle_shader.uniform['camera_pos'], 1, self.camera_pos)
+
+ self.simulation.gl_draw_particles()
+ glBindVertexArray(0)
+
+ if self.show_decorations:
+ 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(3)
+ for instrument in self.instruments:
+ instrument.display_decoration(self.decoration_shader.uniform)
+
+ if self.show_windows:
+ self.texture_shader.use()
+ glUniformMatrix4fv(self.texture_shader.uniform['projection'], 1, False, np.asfortranarray(self.projection))
+ for instrument in self.instruments:
+ instrument.display_window(self.texture_shader.uniform)
+
+ glutSwapBuffers()