Commit 84754fec authored by Karol Actun's avatar Karol Actun
Browse files

small bug fixes and changes with saving screenshots and scenarios. implemented...

small bug fixes and changes with saving screenshots and scenarios. implemented rendering of the border + show/hide border checkbox in gui
parent 9d9f8776
......@@ -32,7 +32,7 @@ gui = default_gui
;particle_model_file = 2d_particle.obj
;tile_model_file = 2d_quad_tile.obj
;location_model_file = 2d_location.obj
;grid_size = 1000
;grid_size = 100
;# end of Quadratic grid configs
......@@ -107,6 +107,12 @@ fov = 40
cursor_offset = -10
render_distance = 1000
# turns the rendering of the border on and off
#works only with the border flag set to True
show_border = True
# color of the border lines
border_color = (1.0, 0.0, 0.0, 1.0)
[World]
## False = Unlimited world size
......
......@@ -29,9 +29,9 @@ class CCPGrid(Grid):
def get_box(self, width):
locations = []
for x in range(-int(width / 2), int(width / 2)):
for y in range(-int(width / 2), int(width / 2)):
for z in range(-int(width / 2), int(width / 2)):
for x in range(-width, width+1):
for y in range(-width, width+1):
for z in range(-width, width+1):
if self.are_valid_coordinates((x, y, z)):
locations.append((x, y, z))
......
......@@ -22,9 +22,9 @@ class CubicGrid(Grid):
def get_box(self, width):
locations = []
for x in range(int(-width / 2), int(width / 2)):
for y in range(int(-width / 2), int(width / 2)):
for z in range(int(-width / 2), int(width / 2)):
for x in range(-width, width+1):
for y in range(-width, width+1):
for z in range(-width, width+1):
locations.append((x, y, z))
return locations
......
......@@ -20,8 +20,8 @@ class QuadraticGrid(Grid):
def get_box(self, width):
locations = []
for x in range(int(-width / 2), int(width / 2)):
for y in range(int(-width / 2), int(width / 2)):
for x in range(-width, width+1):
for y in range(-width, width+1):
locations.append((x, y, 0.0))
return locations
......
......@@ -24,8 +24,8 @@ class TriangularGrid(Grid):
def get_box(self, width):
locs = []
for y in range(-int(width/2),int(width/2)):
for x in range(-int(width / 2), int(width / 2)):
for y in range(-width, width+1):
for x in range(-width, width+1):
if y % 2 == 0:
locs.append((x, y, 0.0))
else:
......
......@@ -14,7 +14,7 @@ def create_gui(world, vis: Visualization):
tabbar.setMinimumWidth(200)
tabbar.addTab(sim_tab(vis, world), "Simulation")
tabbar.addTab(vis_tab(vis), "Visualization")
tabbar.addTab(grid_tab(vis), "Grid")
tabbar.addTab(grid_tab(world, vis), "Grid")
tabbar.addTab(matter_tab(vis), "Matter")
tabbar.addTab(help_tab(), "Help")
......@@ -136,6 +136,7 @@ def vis_tab(vis: Visualization):
layout.addLayout(get_drag_sens_slider(vis))
layout.addLayout(get_zoom_sens_slider(vis))
layout.addLayout(get_rota_sens_slider(vis))
layout.addLayout(get_vis_show_checkboxes(vis))
reset_position_button = QPushButton("reset position")
reset_position_button.clicked.connect(vis.reset_camera_position)
layout.addWidget(reset_position_button, alignment=Qt.AlignBaseline)
......@@ -144,12 +145,12 @@ def vis_tab(vis: Visualization):
return tab
def grid_tab(vis: Visualization):
def grid_tab(world, vis: Visualization):
tab = QTabBar()
layout = QVBoxLayout()
layout.addLayout(get_grid_lines_scale_slider(vis))
layout.addLayout(get_grid_coordinates_scale_slider(vis))
layout.addLayout(get_show_checkboxes(vis))
layout.addLayout(get_show_checkboxes(world, vis))
layout.addLayout(recalculate_grid(vis))
layout.addLayout(get_color_picker(vis))
layout.addStretch(0)
......@@ -470,25 +471,7 @@ def get_render_distance_slider(vis):
return vbox
def get_show_checkboxes(vis):
lines_cb = QCheckBox()
lines_cb.setText("show lines")
lines_cb.setChecked(vis.get_show_lines())
def lines_clicked():
vis.set_show_lines(lines_cb.isChecked())
lines_cb.clicked.connect(lines_clicked)
coords_cb = QCheckBox()
coords_cb.setText("show coordinates")
coords_cb.setChecked(vis.get_show_coordinates())
def coords_clicked():
vis.set_show_coordinates(coords_cb.isChecked())
coords_cb.clicked.connect(coords_clicked)
def get_vis_show_checkboxes(vis):
center_cb = QCheckBox()
center_cb.setText("show center")
center_cb.setChecked(vis.get_show_center())
......@@ -516,20 +499,48 @@ def get_show_checkboxes(vis):
rl_cb.clicked.connect(rl_clicked)
hbox1 = QHBoxLayout()
hbox1.addWidget(lines_cb)
hbox1.addWidget(coords_cb)
hbox2 = QHBoxLayout()
hbox2.addWidget(center_cb)
hbox2.addWidget(focus_cb)
hbox3 = QHBoxLayout()
hbox3.addWidget(rl_cb)
hbox = QHBoxLayout()
hbox.addWidget(center_cb, alignment=Qt.AlignBaseline)
hbox.addWidget(focus_cb, alignment=Qt.AlignBaseline)
hbox.addWidget(rl_cb, alignment=Qt.AlignBaseline)
return hbox
vbox = QVBoxLayout()
vbox.addLayout(hbox1)
vbox.addLayout(hbox2)
vbox.addLayout(hbox3)
return vbox
def get_show_checkboxes(world, vis):
lines_cb = QCheckBox()
lines_cb.setText("show lines")
lines_cb.setChecked(vis.get_show_lines())
def lines_clicked():
vis.set_show_lines(lines_cb.isChecked())
lines_cb.clicked.connect(lines_clicked)
coords_cb = QCheckBox()
coords_cb.setText("show coordinates")
coords_cb.setChecked(vis.get_show_coordinates())
def coords_clicked():
vis.set_show_coordinates(coords_cb.isChecked())
coords_cb.clicked.connect(coords_clicked)
if world.config_data.border:
border_cb = QCheckBox()
border_cb.setText("show border")
border_cb.setChecked(vis.get_show_border())
def border_clicked():
vis.set_show_border(border_cb.isChecked())
border_cb.clicked.connect(border_clicked)
hbox = QHBoxLayout()
hbox.addWidget(lines_cb, alignment=Qt.AlignBaseline)
hbox.addWidget(coords_cb, alignment=Qt.AlignBaseline)
if world.config_data.border:
hbox.addWidget(border_cb, alignment=Qt.AlignBaseline)
return hbox
def get_grid_lines_scale_slider(vis):
......
......@@ -68,6 +68,9 @@ class ConfigData:
self.cursor_offset = config.getint("Visualization", "cursor_offset")
self.render_distance = config.getint("Visualization", "render_distance")
self.show_border = config.getboolean("Visualization", "show_border")
self.border_color = make_tuple(config.get("Visualization", "border_color"))
self.size_x = config.getfloat("World", "size_x")
self.size_y = config.getfloat("World", "size_y")
self.size_z = config.getfloat("World", "size_z")
......
......@@ -326,6 +326,12 @@ class Visualization:
def set_grid_line_color(self, color):
self._viewer.programs["grid"].set_line_color(color)
def get_grid_border_color(self):
return self._viewer.programs["grid"].get_border_color()
def set_grid_border_color(self, color):
self._viewer.programs["grid"].set_border_color(color)
def get_grid_line_width(self):
return self._viewer.programs["grid"].width
......@@ -369,6 +375,13 @@ class Visualization:
self._viewer.programs["grid"].show_lines = show_lines
self._viewer.glDraw()
def get_show_border(self):
return self._viewer.programs["grid"].show_border
def set_show_border(self, show_border: bool):
self._viewer.programs["grid"].show_border = show_border
self._viewer.glDraw()
def get_show_coordinates(self):
return self._viewer.programs["grid"].show_coordinates
......
......@@ -9,7 +9,8 @@ from lib.visualization.programs.offset_color_carry_program import OffsetColorCar
from lib.visualization.programs.offset_color_program import OffsetColorProgram
from lib.visualization.programs.grid_program import GridProgram
import numpy as np
import time
import os
import datetime
class OGLWidget(QtOpenGL.QGLWidget):
......@@ -142,19 +143,20 @@ class OGLWidget(QtOpenGL.QGLWidget):
self.programs["grid"] = GridProgram(self.world.grid, self.world.config_data.line_color,
self.world.config_data.coordinates_color,
self.world.config_data.tile_model_file)
self.world.config_data.tile_model_file,
(self.world.get_world_x_size(),
self.world.get_world_y_size(),
self.world.get_world_z_size()))
self.programs["grid"].set_world_scaling(self.world.grid.get_scaling())
self.programs["grid"].set_line_scaling(self.world.config_data.line_scaling)
self.programs["grid"].show_lines = self.world.config_data.show_lines
self.programs["grid"].set_model_scaling(self.world.config_data.coordinates_scaling)
self.programs["grid"].show_coordinates = self.world.config_data.show_coordinates
if self.world.config_data.border:
self.programs["grid"].show_border = self.world.config_data.show_border
self.programs["grid"].set_border_color(self.world.config_data.border_color)
self.programs["grid"].update_offsets(self.world.grid.get_box(self.world.grid.size))
# showing coordinates in 2D is not really necessary, since all coordinates are easy to spot on the grid
# and there's no depth
if self.world.grid.get_dimension_count() == 2:
self.programs["grid"].show_coordinates = False
self.programs["center"] = OffsetColorProgram(self.world.config_data.particle_model_file)
self.programs["center"].set_world_scaling(self.world.grid.get_scaling())
self.programs["center"].set_model_scaling((0.3, 0.3, 0.3))
......@@ -422,18 +424,30 @@ class OGLWidget(QtOpenGL.QGLWidget):
def take_screenshot(self):
"""
takes a screenshot of the OpenGLWidget. saves it with a random name in the screenshots folder.
takes a screenshot of the OpenGLWidget. saves it in the screenshots folder with .
:return:
"""
GL.glReadBuffer(GL.GL_FRONT)
pixels = GL.glReadPixels(0, 0, self.width(), self.height(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE)
i = Image.frombytes('RGB', (self.width(), self.height()), pixels, 'raw')
import os
# if screenshot folder doesn't exist -> create it
if not os.path.exists("screenshots") or not os.path.isdir("screenshots"):
os.mkdir("screenshots")
# if the screenshot folder exists save it, else print an error.
if os.path.exists("screenshots") and os.path.isdir("screenshots"):
i.save("screenshots/screenshot%s.jpg" % str(time.perf_counter_ns()), "JPEG")
now = datetime.datetime.now()
filename = str("screenshots/%d-%d-%d_%d-%d-%d_screenshot.jpg"
% (now.year, now.month, now.day, now.hour, now.minute, now.second))
i.save(filename, "JPEG")
# checks if the file exists. If not, some unknown error occured in the Image library.
if not os.path.exists(filename) or not os.path.isfile(filename):
eprint("Error: screenshot couldn't be saved due to unknown reasons.")
else:
eprint("\"screenshots\" folder doesn't exist. "
"Please create it in the running directory before taking screenshots.")
eprint("Error: couldn't create the screenshot folder.")
def set_background_color(self, color):
GL.glClearColor(*color, 1.0)
......
......@@ -12,7 +12,7 @@ class GridProgram(Program):
vertex_shader_file = "lib/visualization/shader/grid_vertex.glsl"
fragment_shader_file = "lib/visualization/shader/frag.glsl"
def __init__(self, grid, line_color, model_color, coordinate_model_file):
def __init__(self, grid, line_color, model_color, coordinate_model_file, border_size):
"""
initializes/loads/creates all necessary data/buffers/shaders for drawing the Grid
:param grid: the grid object to be visualized
......@@ -24,10 +24,14 @@ class GridProgram(Program):
self.width = 1
self.line_offset = 0
self.line_length = 0
self.border_offset = 0
self.border_length = 0
self.amount = 0
self.show_coordinates = True
self.show_lines = True
self.show_border = False
self.vbos = list()
self.border_size = border_size
super().__init__(self.vertex_shader_file, self.fragment_shader_file, coordinate_model_file)
self.set_line_color(line_color)
self.set_model_color(model_color)
......@@ -39,8 +43,19 @@ class GridProgram(Program):
self.line_offset = len(verts)
self.line_length = len(lines)
print(self.border_size)
border = self._calculate_border()
print(1)
self.border_offset = self.line_offset + self.line_length
print(1)
print(border)
self.border_length = len(border)
print(len(verts))
# prepare data for the gpu
gpu_data = np.array(verts + lines + normals, dtype=np.float32)
print(1)
gpu_data = np.array(verts + lines + border + normals, dtype=np.float32)
print(1)
# create VBO
self.vbos = list(gl.glGenBuffers(2))
......@@ -52,7 +67,8 @@ class GridProgram(Program):
loc = self.get_attribute_location("normal")
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, ctypes.c_void_p((len(verts) + len(lines)) * 12))
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, gl.GL_FALSE, 0,
ctypes.c_void_p((len(verts) + len(lines) + len(border)) * 12))
gl.glBufferData(gl.GL_ARRAY_BUFFER, 12 * len(gpu_data), gpu_data, gl.GL_STATIC_DRAW)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
......@@ -65,13 +81,54 @@ class GridProgram(Program):
gl.glBufferData(gl.GL_ARRAY_BUFFER, 0, np.array([], dtype=np.float32), gl.GL_DYNAMIC_DRAW)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
def _calculate_border(self):
lines = []
if self.grid.get_dimension_count() == 3:
lines = [(-self.border_size[0], -self.border_size[1], -self.border_size[2]),
(-self.border_size[0], -self.border_size[1], self.border_size[2]),
(-self.border_size[0], -self.border_size[1], self.border_size[2]),
(-self.border_size[0], self.border_size[1], self.border_size[2]),
(-self.border_size[0], self.border_size[1], self.border_size[2]),
(-self.border_size[0], self.border_size[1], -self.border_size[2]),
(-self.border_size[0], self.border_size[1], -self.border_size[2]),
(-self.border_size[0], -self.border_size[1], -self.border_size[2]),
(self.border_size[0], -self.border_size[1], -self.border_size[2]),
(self.border_size[0], -self.border_size[1], self.border_size[2]),
(self.border_size[0], -self.border_size[1], self.border_size[2]),
(self.border_size[0], self.border_size[1], self.border_size[2]),
(self.border_size[0], self.border_size[1], self.border_size[2]),
(self.border_size[0], self.border_size[1], -self.border_size[2]),
(self.border_size[0], self.border_size[1], -self.border_size[2]),
(self.border_size[0], -self.border_size[1], -self.border_size[2]),
(-self.border_size[0], self.border_size[1], self.border_size[2]),
(self.border_size[0], self.border_size[1], self.border_size[2]),
(-self.border_size[0], -self.border_size[1], self.border_size[2]),
(self.border_size[0], -self.border_size[1], self.border_size[2]),
(-self.border_size[0], self.border_size[1], -self.border_size[2]),
(self.border_size[0], self.border_size[1], -self.border_size[2]),
(-self.border_size[0], -self.border_size[1], -self.border_size[2]),
(self.border_size[0], -self.border_size[1], -self.border_size[2])]
if self.grid.get_dimension_count() <= 2:
lines = [(-self.border_size[0], -self.border_size[1], 0),
(-self.border_size[0], self.border_size[1], 0),
(-self.border_size[0], self.border_size[1], 0),
(self.border_size[0], self.border_size[1], 0),
(self.border_size[0], self.border_size[1], 0),
(self.border_size[0], -self.border_size[1], 0),
(self.border_size[0], -self.border_size[1], 0),
(-self.border_size[0], -self.border_size[1], 0)]
return lines
def _init_uniforms(self):
"""
initializes the shader uniforms
:return:
"""
super()._init_uniforms()
self.set_line_color((0.0, 0.0, 0.0, 0.0))
self.set_line_color((0.0, 0.0, 0.0, 1.0))
self.set_border_color((1.0, 0.0, 0.0, 1.0))
self.set_model_color((0.0, 0.0, 0.0, 0.0))
self.set_line_scaling((1.0, 1.0, 1.0))
......@@ -81,13 +138,17 @@ class GridProgram(Program):
:return:
"""
self.use()
if self.show_border:
self._draw_part(2)
gl.glDrawArrays(gl.GL_LINES, self.border_offset, self.border_length)
if self.show_lines:
self._drawing_lines(True)
self._draw_part(0)
gl.glDrawArraysInstanced(gl.GL_LINES, self.line_offset, self.line_length, self.amount)
if self.show_coordinates:
self._drawing_lines(False)
self._draw_part(1)
gl.glDrawArraysInstanced(gl.GL_TRIANGLES, 0, self.size, self.amount)
def set_width(self, width):
"""
sets the width of the grid lines (updates the glLineWidth globally!!!)
......@@ -119,6 +180,28 @@ class GridProgram(Program):
"""
return self.get_uniform("line_color", 4)
def set_border_color(self, color):
"""
sets the border_color uniform in the grid vertex shader
:param color: the color (rgba)
:return:
"""
self.use()
gpu_data = np.array(color, dtype=np.float32).flatten()
if len(gpu_data) != 4:
eprint("ERROR: length of set_border_color parameter not correct, expected 4 got %d " % len(gpu_data))
else:
loc = self.get_uniform_location("border_color")
gl.glUniform4f(loc, *gpu_data)
def get_border_color(self):
"""
reads the border color from the vertex shader
:return:
"""
return self.get_uniform("border_color", 4)
def set_model_color(self, color):
"""
sets the model_color uniform in the grid vertex shader
......@@ -140,9 +223,9 @@ class GridProgram(Program):
"""
return self.get_uniform("model_color", 4)
def _drawing_lines(self, line_flag: bool):
loc = self.get_uniform_location("drawing_lines")
gl.glUniform1i(loc, gl.GL_TRUE if line_flag else gl.GL_FALSE)
def _draw_part(self, part: int):
loc = self.get_uniform_location("drawing_part")
gl.glUniform1i(loc, part)
def update_offsets(self, data):
"""
......
......@@ -14,6 +14,8 @@ uniform mat4 view;
uniform mat4 world;
// color of the grid lines
uniform vec4 line_color;
// color of the border
uniform vec4 border_color;
// color of the locaiton model
uniform vec4 model_color;
// scaling of the world
......@@ -28,18 +30,17 @@ uniform float ambient_light;
uniform vec3 light_direction;
// color of the parallel lightsource
uniform vec4 light_color;
// flag if drawing the lines or the location model
uniform bool drawing_lines;
// flag for distinction of drawing the grid's connections (0), the location model (1) or the border (2)
uniform int drawing_part;
// varying color for fragment shader
out vec4 v_color;
void main(void)
{
if(drawing_lines){
if(drawing_part == 0){
v_color = line_color;
gl_Position = projection * view * world * vec4((position * line_scaling + offset) * world_scaling, 1.0);
}else{
}else if(drawing_part == 1){
vec3 nn = normalize(normal);
vec3 diffuseReflection = vec3(light_color) * vec3(model_color)
* max(max(ambient_light, dot(nn, light_direction)), dot(-nn, light_direction));
......@@ -48,5 +49,8 @@ void main(void)
mat4 use_world = world;
use_world[3] += vec4(offset * world_scaling, 0);
gl_Position = projection * view * use_world * vec4(position * model_scaling, 1.0);
}else if(drawing_part == 2){
v_color = border_color;
gl_Position = projection * view * world * vec4(position * world_scaling, 1.0);
}
}
......@@ -9,6 +9,7 @@ import logging
import random
import threading
import os
import datetime
import time
from lib import csv_generator, particle, tile, location, vis3d
......@@ -132,10 +133,18 @@ class World:
def save_scenario(self):
# create scenario folder, if it doesn't already exist.
if not os.path.exists("scenario") or not os.path.isdir("scenario"):
os.mkdir("scenario")
# if the scenario folder exists, try to create and save the new scenario file, if it fails print the error.
if os.path.exists("scenario") and os.path.isdir("scenario"):
now = datetime.datetime.now()
filename = str("scenario/%d-%d-%d_%d-%d-%d_scenario.py"
% (now.year, now.month, now.day, now.hour, now.minute, now.second))
try:
f = open("scenario/scenario_%s.py" % str(time.perf_counter_ns()), "w+")
f.write("def solution(world):\n")
f = open(filename, "w+")
f.write("def scenario(world):\n")
for p in self.particle_map_coordinates.values():
f.write("\tworld.add_particle(%s, color=%s)\n" % (str(p.coordinates), str(p.get_color())))
for t in self.tile_map_coordinates.values():
......@@ -146,10 +155,12 @@ class World:
f.close()
except IOError as e:
eprint(e)
else:
eprint("\"scenario\" folder doesn't exist. "
"Please create it in the running directory before saving scenarios.")
# checks if the file exists. If not, some unknown error occured while saving.
if not os.path.exists(filename) or not os.path.isfile(filename):
eprint("Error: scenario couldn't be saved due to unknown reasons.")
else:
eprint("\"scenario\" folder couldn't be created.")
def csv_aggregator(self):
self.csv_round.aggregate_metrics()
......@@ -161,7 +172,7 @@ class World:
def set_successful_end(self):
self.csv_round.success()
# self.set_end()
def get_max_round(self):
"""
The max round number
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment