thermodynamic v1
This commit is contained in:
parent
5168061d1b
commit
41761b7b56
16 changed files with 1025 additions and 212 deletions
386
Client/Client.py
Normal file
386
Client/Client.py
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
from OpenGL.GL import *
|
||||||
|
import numpy as np
|
||||||
|
from OpenGL.GL.ARB.vertex_array_object import glDeleteVertexArrays
|
||||||
|
from OpenGL.GL.framebufferobjects import glBindRenderbuffer
|
||||||
|
from OpenGL.GLUT import *
|
||||||
|
import OpenGL.GLUT.freeglut
|
||||||
|
from OpenGL.GLU import *
|
||||||
|
from OpenGL.GL import *
|
||||||
|
from ctypes import sizeof, c_float, c_void_p, c_uint
|
||||||
|
|
||||||
|
from Lights.Spotlight.Spotlight import Spotlight
|
||||||
|
from WorldProvider.WorldProvider import WorldProvider
|
||||||
|
from MatrixStuff.Transformations import perspectiveMatrix, lookAt, translate, rotate
|
||||||
|
from Objects.Cube.Cube import Cube
|
||||||
|
from Objects.Cuboid.Cuboid import Cuboid
|
||||||
|
from Objects.World import World
|
||||||
|
import json
|
||||||
|
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
from scipy.signal import convolve
|
||||||
|
|
||||||
|
MAX_DISTANCE = 200.0
|
||||||
|
FRICTION_COEFFICENT = 0.9
|
||||||
|
EPSILON = 0.00001
|
||||||
|
|
||||||
|
def value_to_color(v, min_value, max_value):
|
||||||
|
r = g = b = 0.0
|
||||||
|
scope = max_value - min_value
|
||||||
|
normalized = (v - min_value) / (max_value - min_value)
|
||||||
|
if 0.5 * scope + min_value != 0:
|
||||||
|
b = max(0, 1.0 - abs(2.0 * normalized))
|
||||||
|
g = max(0, 1.0 - abs(2.0 * normalized - 1.0))
|
||||||
|
r = max(0, 1.0 - abs(2.0 * normalized - 2.0))
|
||||||
|
l = np.sqrt((r*r + b*b + g*g))
|
||||||
|
r /= l
|
||||||
|
g /= l
|
||||||
|
b /= l
|
||||||
|
return r, g, b
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
def __init__(self, test=False, pos=[0, 0, 0]):
|
||||||
|
with open('./config.json', 'r') as f:
|
||||||
|
self.config = json.load(f)
|
||||||
|
glutInit(sys.argv)
|
||||||
|
self.width = 1920
|
||||||
|
self.height = 1080
|
||||||
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
|
||||||
|
glutInitWindowSize(self.width, self.height)
|
||||||
|
glutCreateWindow(b'Voxelengine')
|
||||||
|
|
||||||
|
with open('passthroughvertex.glsl', 'r') as f:
|
||||||
|
vertex_shader_string = f.read()
|
||||||
|
self.passthrough_vertex_shader_id = glCreateShader(GL_VERTEX_SHADER)
|
||||||
|
glShaderSource(self.passthrough_vertex_shader_id, vertex_shader_string)
|
||||||
|
glCompileShader(self.passthrough_vertex_shader_id)
|
||||||
|
if glGetShaderiv(self.passthrough_vertex_shader_id, GL_COMPILE_STATUS) != GL_TRUE:
|
||||||
|
raise RuntimeError(glGetShaderInfoLog(self.passthrough_vertex_shader_id))
|
||||||
|
|
||||||
|
with open('vertex.glsl', 'r') as f:
|
||||||
|
vertex_shader_string = f.read()
|
||||||
|
self.vertex_shader_id = glCreateShader(GL_VERTEX_SHADER)
|
||||||
|
glShaderSource(self.vertex_shader_id, vertex_shader_string)
|
||||||
|
glCompileShader(self.vertex_shader_id)
|
||||||
|
if glGetShaderiv(self.vertex_shader_id, GL_COMPILE_STATUS) != GL_TRUE:
|
||||||
|
raise RuntimeError(glGetShaderInfoLog(self.vertex_shader_id))
|
||||||
|
|
||||||
|
with open('fragment.glsl', 'r') as f:
|
||||||
|
fragment_shader_string = f.read()
|
||||||
|
self.fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
|
||||||
|
glShaderSource(self.fragment_shader_id, fragment_shader_string)
|
||||||
|
glCompileShader(self.fragment_shader_id)
|
||||||
|
if glGetShaderiv(self.fragment_shader_id, GL_COMPILE_STATUS) != GL_TRUE:
|
||||||
|
raise RuntimeError(glGetShaderInfoLog(self.fragment_shader_id))
|
||||||
|
|
||||||
|
Cube.initializeShader()
|
||||||
|
Cuboid.initializeShader()
|
||||||
|
self.geometry_shaders = {
|
||||||
|
Cube: Cube.GeometryShaderId,
|
||||||
|
Cuboid: Cuboid.GeometryShaderId
|
||||||
|
}
|
||||||
|
|
||||||
|
self.normal_program = {}
|
||||||
|
self.depth_program = {}
|
||||||
|
|
||||||
|
for key in self.geometry_shaders.keys():
|
||||||
|
self.normal_program[key] = glCreateProgram()
|
||||||
|
glAttachShader(self.normal_program[key], self.vertex_shader_id)
|
||||||
|
glAttachShader(self.normal_program[key], key.GeometryShaderId)
|
||||||
|
glAttachShader(self.normal_program[key], self.fragment_shader_id)
|
||||||
|
glLinkProgram(self.normal_program[key])
|
||||||
|
|
||||||
|
self.depth_program[self.normal_program[key]] = Spotlight.getDepthProgram(self.vertex_shader_id, key.GeometryShaderId)
|
||||||
|
|
||||||
|
self.world_provider = WorldProvider(self.normal_program)
|
||||||
|
for x_pos in range(0, 100):
|
||||||
|
for y_pos in range(0, 100):
|
||||||
|
for z_pos in range(0, 1):
|
||||||
|
self.world_provider.world.put_object(x_pos, y_pos, z_pos, Cuboid().setColor(
|
||||||
|
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0))
|
||||||
|
|
||||||
|
self.projMatrix = perspectiveMatrix(45.0, 400 / 400, 0.01, MAX_DISTANCE)
|
||||||
|
|
||||||
|
self.rx = self.cx = self.cy = 0
|
||||||
|
self.opening = 45
|
||||||
|
|
||||||
|
glutReshapeFunc(self.resize)
|
||||||
|
glutDisplayFunc(self.display)
|
||||||
|
glutKeyboardFunc(self.keyboardHandler)
|
||||||
|
glutSpecialFunc(self.funcKeydHandler)
|
||||||
|
|
||||||
|
self.pos = pos
|
||||||
|
|
||||||
|
self.time = time.time()
|
||||||
|
|
||||||
|
self.heat_map = np.zeros((100, 100, 1))
|
||||||
|
|
||||||
|
self.v_map_x = np.zeros((100, 100, 1))
|
||||||
|
self.v_map_y = np.zeros((100, 100, 1))
|
||||||
|
self.v_map_z = np.zeros((100, 100, 1))
|
||||||
|
|
||||||
|
if not test:
|
||||||
|
glutMainLoop()
|
||||||
|
else:
|
||||||
|
self.display()
|
||||||
|
self.resize(100, 100)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
glClearColor(0, 0, 0, 0)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||||
|
projMatrix = perspectiveMatrix(45, float(self.width) / float(self.height), 0.01, MAX_DISTANCE)
|
||||||
|
|
||||||
|
world: World = self.world_provider.world
|
||||||
|
lights = world.get_lights_to_render(self.pos, self.config['render_light_distance'])
|
||||||
|
for light in lights:
|
||||||
|
light.prepareForDepthMapping()
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||||
|
light_mat = translate(light.pos[0], light.pos[1], light.pos[2]) * \
|
||||||
|
lookAt(0, 0, 0, -light.pos[0], -light.pos[1], -light.pos[2], 0, 1, 0) * \
|
||||||
|
perspectiveMatrix(90, float(light.map_size) / float(light.map_size), 0.01, MAX_DISTANCE)
|
||||||
|
|
||||||
|
for obj_type, program_id in self.depth_program.items():
|
||||||
|
glUseProgram(program_id)
|
||||||
|
widthid = glGetUniformLocation(program_id, 'width')
|
||||||
|
heightid = glGetUniformLocation(program_id, 'height')
|
||||||
|
nearid = glGetUniformLocation(program_id, 'near')
|
||||||
|
farid = glGetUniformLocation(program_id, 'far')
|
||||||
|
glUniform1f(nearid, 0.01)
|
||||||
|
glUniform1f(farid, 100)
|
||||||
|
glUniform1f(widthid, light.map_size)
|
||||||
|
glUniform1f(heightid, light.map_size)
|
||||||
|
|
||||||
|
world.render(light_mat, rotate(0, 0, 0), self.depth_program)
|
||||||
|
glFlush()
|
||||||
|
light.finishDepthMapping()
|
||||||
|
glClearColor(0, 0, 0, 0)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
|
glClearColor(0, 0, 0, 0)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
|
for obj_type, program_id in self.normal_program.items():
|
||||||
|
glUseProgram(program_id)
|
||||||
|
widthid = glGetUniformLocation(program_id, 'width')
|
||||||
|
heightid = glGetUniformLocation(program_id, 'height')
|
||||||
|
nearid = glGetUniformLocation(program_id, 'near')
|
||||||
|
farid = glGetUniformLocation(program_id, 'far')
|
||||||
|
glUniform1f(nearid, 0.01)
|
||||||
|
glUniform1f(farid, 100)
|
||||||
|
glUniform1f(widthid, self.width)
|
||||||
|
glUniform1f(heightid, self.height)
|
||||||
|
|
||||||
|
world.render(translate(self.pos[0], self.pos[1], self.pos[2]) * lookAt(0, 0, 0, 0, 0, -self.pos[2], 0, 1, 0) * projMatrix, rotate(0, 0, 0))
|
||||||
|
glFlush()
|
||||||
|
|
||||||
|
glutSwapBuffers()
|
||||||
|
|
||||||
|
max_value = np.max(self.heat_map)
|
||||||
|
# min_value = np.min(self.heat_map)
|
||||||
|
min_value = 0
|
||||||
|
|
||||||
|
vel = np.sqrt(np.square(self.v_map_x) + np.square(self.v_map_y) + np.square(self.v_map_z))
|
||||||
|
max_value = np.max(vel)
|
||||||
|
min_value = np.min(vel)
|
||||||
|
|
||||||
|
for x_pos in range(0, 100):
|
||||||
|
for y_pos in range(0, 100):
|
||||||
|
for z_pos in range(0, 1):
|
||||||
|
# r, g, b = value_to_color(self.heat_map[x_pos, y_pos, z_pos], min_value, max_value)
|
||||||
|
r, g, b = value_to_color(vel[x_pos, y_pos, z_pos], min_value, max_value)
|
||||||
|
|
||||||
|
self.world_provider.world.set_color(x_pos, y_pos, z_pos, r, g, b)
|
||||||
|
# friction
|
||||||
|
# self.heat_map += np.sqrt(np.square(self.v_map_x * (1.0 - FRICTION_COEFFICENT)) +
|
||||||
|
# np.square(self.v_map_y * (1.0 - FRICTION_COEFFICENT)) +
|
||||||
|
# np.square(self.v_map_z * (1.0 - FRICTION_COEFFICENT)))
|
||||||
|
self.v_map_x *= FRICTION_COEFFICENT
|
||||||
|
self.v_map_y *= FRICTION_COEFFICENT
|
||||||
|
self.v_map_z *= FRICTION_COEFFICENT
|
||||||
|
# hot stuff rises / cool stuff sinks
|
||||||
|
rise = self.heat_map[:, :-1, :] > (self.heat_map[:, 1:, :] + EPSILON)
|
||||||
|
self.v_map_y[:, :-1, :] += 1.0 * rise
|
||||||
|
sink = self.heat_map[:, :-1, :] < (self.heat_map[:, 1:, :] - EPSILON)
|
||||||
|
self.v_map_y[:, 1:, :] -= 1.0 * sink
|
||||||
|
#flow
|
||||||
|
new_v_map_x = np.zeros(self.v_map_x.shape)
|
||||||
|
new_v_map_y = np.zeros(self.v_map_x.shape)
|
||||||
|
new_v_map_z = np.zeros(self.v_map_x.shape)
|
||||||
|
for x_pos in range(self.v_map_x.shape[0]):
|
||||||
|
for y_pos in range(self.v_map_x.shape[1]):
|
||||||
|
for z_pos in range(self.v_map_x.shape[2]):
|
||||||
|
target_x = min(self.v_map_x.shape[0] - 1,
|
||||||
|
max(0, int(round(x_pos + self.v_map_x[x_pos, y_pos, z_pos]))))
|
||||||
|
target_y = min(self.v_map_x.shape[1] - 1,
|
||||||
|
max(0, int(round(y_pos + self.v_map_y[x_pos, y_pos, z_pos]))))
|
||||||
|
target_z = min(self.v_map_x.shape[2] - 1,
|
||||||
|
max(0, int(round(z_pos + self.v_map_z[x_pos, y_pos, z_pos]))))
|
||||||
|
|
||||||
|
friction_dispersion = (1.0 -FRICTION_COEFFICENT) / 4
|
||||||
|
# velocity dispersion
|
||||||
|
# x
|
||||||
|
new_v_map_x[target_x, target_y, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * FRICTION_COEFFICENT
|
||||||
|
if target_y + 1 < self.v_map_x.shape[1] - 1:
|
||||||
|
new_v_map_y[target_x, target_y + 1, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_x[target_x, target_y, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_y - 1 > 0:
|
||||||
|
new_v_map_y[target_x, target_y - 1, target_z] -= self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_x[target_x, target_y, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
|
||||||
|
if target_z + 1 < self.v_map_x.shape[2] - 1:
|
||||||
|
new_v_map_z[target_x, target_y, target_z + 1] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_x[target_x, target_y, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_z - 1 > 0:
|
||||||
|
new_v_map_z[target_x, target_y, target_z - 1] -= self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_x[target_x, target_y, target_z] += self.v_map_x[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
# y
|
||||||
|
new_v_map_y[target_x, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * FRICTION_COEFFICENT
|
||||||
|
if target_x + 1 < self.v_map_x.shape[0] - 1:
|
||||||
|
new_v_map_x[target_x + 1, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_y[target_x, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_x - 1 > 0:
|
||||||
|
new_v_map_x[target_x - 1, target_y, target_z] -= self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_y[target_x, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
|
||||||
|
if target_z + 1 < self.v_map_x.shape[2] - 1:
|
||||||
|
new_v_map_z[target_x, target_y, target_z + 1] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_y[target_x, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_z - 1 > 0:
|
||||||
|
new_v_map_z[target_x, target_y, target_z - 1] -= self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_y[target_x, target_y, target_z] += self.v_map_y[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
# z
|
||||||
|
new_v_map_z[target_x, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * FRICTION_COEFFICENT
|
||||||
|
if target_x + 1 < self.v_map_x.shape[0] - 1:
|
||||||
|
new_v_map_x[target_x + 1, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_z[target_x, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_x - 1 > 0:
|
||||||
|
new_v_map_x[target_x - 1, target_y, target_z] -= self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_z[target_x, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
|
||||||
|
if target_y + 1 < self.v_map_x.shape[1] - 1:
|
||||||
|
new_v_map_y[target_x, target_y + 1, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_z[target_x, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
if target_y - 1 > 0:
|
||||||
|
new_v_map_y[target_x, target_y - 1, target_z] -= self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
else:
|
||||||
|
new_v_map_z[target_x, target_y, target_z] += self.v_map_z[x_pos, y_pos, z_pos] * friction_dispersion
|
||||||
|
# handle boundaries
|
||||||
|
filter_mat = np.array([[-1.0], [0], [1.0]]) / 2.0
|
||||||
|
new_v_map_y[0, :, :] += convolve(new_v_map_x[0, :, :], filter_mat, 'same')
|
||||||
|
new_v_map_x[0, :, :] = 0
|
||||||
|
new_v_map_y[new_v_map_x.shape[0] - 1, :, :] +=\
|
||||||
|
convolve(new_v_map_x[new_v_map_x.shape[0] - 1, :, :], filter_mat, 'same')
|
||||||
|
new_v_map_x[new_v_map_x.shape[0] - 1, :, :] = 0
|
||||||
|
|
||||||
|
filter_mat = np.array([[-1.0], [0], [1.0]]) / 2.0
|
||||||
|
new_v_map_x[:, 0, :] += convolve(new_v_map_y[:, 0, :], filter_mat, 'same')
|
||||||
|
new_v_map_y[:, 0, :] = 0
|
||||||
|
new_v_map_x[:, new_v_map_x.shape[1] - 1, :] +=\
|
||||||
|
convolve(new_v_map_y[:, new_v_map_x.shape[1] - 1, :], filter_mat, 'same')
|
||||||
|
new_v_map_y[:, new_v_map_x.shape[1] - 1, :] = 0
|
||||||
|
|
||||||
|
# corners
|
||||||
|
new_v_map_x[0, 0, 0] = new_v_map_y[0, 0, 0] = new_v_map_z[0, 0, 0] = 0
|
||||||
|
new_v_map_x[-1, 0, 0] = new_v_map_y[-1, 0, 0] = new_v_map_z[-1, 0, 0] = 0
|
||||||
|
new_v_map_x[-1, -1, 0] = new_v_map_y[-1, -1, 0] = new_v_map_z[-1, -1, 0] = 0
|
||||||
|
new_v_map_x[-1, -1, -1] = new_v_map_y[-1, -1, -1] = new_v_map_z[-1, -1, -1] = 0
|
||||||
|
new_v_map_x[0, -1, -1] = new_v_map_y[0, -1, -1] = new_v_map_z[0, -1, -1] = 0
|
||||||
|
new_v_map_x[0, -1, 0] = new_v_map_y[0, -1, 0] = new_v_map_z[0, -1, 0] = 0
|
||||||
|
new_v_map_x[-1, -1, 0] = new_v_map_y[-1, -1, 0] = new_v_map_z[-1, -1, 0] = 0
|
||||||
|
new_v_map_x[-1, 0, -1] = new_v_map_y[-1, 0, -1] = new_v_map_z[-1, 0, -1] = 0
|
||||||
|
|
||||||
|
self.v_map_x = new_v_map_x
|
||||||
|
self.v_map_y = new_v_map_y
|
||||||
|
self.v_map_z = new_v_map_z
|
||||||
|
|
||||||
|
filter_mat = (np.zeros((3, 3, 1)) + 1.0) / 9.0
|
||||||
|
|
||||||
|
v_map = np.pad(self.v_map_x, 1, 'edge')
|
||||||
|
self.v_map_x = convolve(v_map, filter_mat, mode='same')[1:-1, 1:-1, 1:2]
|
||||||
|
v_map = np.pad(self.v_map_y, 1, 'edge')
|
||||||
|
self.v_map_y = convolve(v_map, filter_mat, mode='same')[1:-1, 1:-1, 1:2]
|
||||||
|
v_map = np.pad(self.v_map_z, 1, 'edge')
|
||||||
|
self.v_map_z = convolve(v_map, filter_mat, mode='same')[1:-1, 1:-1, 1:2]
|
||||||
|
# moving heat
|
||||||
|
heat_map = np.zeros(self.heat_map.shape)
|
||||||
|
for x_pos in range(self.v_map_x.shape[0]):
|
||||||
|
for y_pos in range(self.v_map_x.shape[1]):
|
||||||
|
for z_pos in range(self.v_map_x.shape[2]):
|
||||||
|
target_x = min(self.v_map_x.shape[0] - 1,
|
||||||
|
max(0, int(round(x_pos + self.v_map_x[x_pos, y_pos, z_pos]))))
|
||||||
|
target_y = min(self.v_map_x.shape[1] - 1,
|
||||||
|
max(0, int(round(y_pos + self.v_map_y[x_pos, y_pos, z_pos]))))
|
||||||
|
target_z = min(self.v_map_x.shape[2] - 1,
|
||||||
|
max(0, int(round(z_pos + self.v_map_z[x_pos, y_pos, z_pos]))))
|
||||||
|
heat_map[target_x, target_y, target_z] += self.heat_map[x_pos, y_pos, z_pos]
|
||||||
|
|
||||||
|
self.heat_map = heat_map
|
||||||
|
# dispersing heat
|
||||||
|
heat_map = np.pad(self.heat_map, 1, 'edge')
|
||||||
|
self.heat_map = convolve(heat_map, filter_mat, mode='same')[1:-1, 1:-1, 1:2]
|
||||||
|
# heat source keeps source block on constant heat
|
||||||
|
self.heat_map[50-5:50+5, 0, 0] = 100.0
|
||||||
|
# roof gets cooled off to min temp
|
||||||
|
self.heat_map[:, 99, :] = np.maximum(self.heat_map[:, 99, :] * 0.8, 0.0)
|
||||||
|
|
||||||
|
print(1.0 / (time.time() - self.time))
|
||||||
|
self.time = time.time()
|
||||||
|
glutPostRedisplay()
|
||||||
|
|
||||||
|
def resize(self, w, h):
|
||||||
|
w = max(w, 1)
|
||||||
|
h = max(h, 1)
|
||||||
|
glViewport(0, 0, w, h)
|
||||||
|
self.projMatrix = perspectiveMatrix(45.0, float(w) / float(h), 0.01, MAX_DISTANCE)
|
||||||
|
self.width = w
|
||||||
|
self.height = h
|
||||||
|
|
||||||
|
def keyboardHandler(self, key: int, x: int, y: int):
|
||||||
|
if key == b'\x1b':
|
||||||
|
exit()
|
||||||
|
|
||||||
|
if key == b'+':
|
||||||
|
self.rx += 0.25
|
||||||
|
if key == b'-':
|
||||||
|
self.rx -= 0.25
|
||||||
|
|
||||||
|
if key == b'w':
|
||||||
|
self.cy += 0.25
|
||||||
|
if key == b's':
|
||||||
|
self.cy -= 0.25
|
||||||
|
|
||||||
|
if key == b'a':
|
||||||
|
self.cx -= 0.25
|
||||||
|
if key == b'd':
|
||||||
|
self.cx += 0.25
|
||||||
|
|
||||||
|
if key == b'q':
|
||||||
|
self.opening -= 0.25
|
||||||
|
if key == b'e':
|
||||||
|
self.opening += 0.25
|
||||||
|
|
||||||
|
if key == b'r':
|
||||||
|
print(self.cx, self.cy, self.opening)
|
||||||
|
# glutPostRedisplay()
|
||||||
|
# print(key,x,y)
|
||||||
|
|
||||||
|
def funcKeydHandler(self, key: int, x: int, y: int):
|
||||||
|
if key == 11:
|
||||||
|
glutFullScreenToggle()
|
||||||
|
# print(key)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
client = Client(pos=[-50, -50, -200])
|
0
Client/__init__.py
Normal file
0
Client/__init__.py
Normal file
|
@ -1,44 +1,16 @@
|
||||||
from OpenGL.GL import *
|
|
||||||
import numpy as np
|
|
||||||
from OpenGL.GL.ARB.vertex_array_object import glDeleteVertexArrays
|
|
||||||
from OpenGL.GL.framebufferobjects import glBindRenderbuffer
|
|
||||||
from OpenGL.GLUT import *
|
|
||||||
import OpenGL.GLUT.freeglut
|
|
||||||
from OpenGL.GLU import *
|
|
||||||
from OpenGL.GL import *
|
|
||||||
from ctypes import sizeof, c_float, c_void_p, c_uint
|
|
||||||
from MatrixStuff.Transformations import *
|
from MatrixStuff.Transformations import *
|
||||||
|
from Objects.Identifiable import Identifiable
|
||||||
|
|
||||||
|
|
||||||
class Light:
|
class Light(Identifiable):
|
||||||
programId = {}
|
programId = {}
|
||||||
depthshaderId = -1
|
depthshaderId = -1
|
||||||
|
|
||||||
def getDepthProgram(self, vertexshader=-1, geometryshader=-1):
|
def getDepthProgram(self, vertexshader=-1, geometryshader=-1):
|
||||||
if ((
|
pass
|
||||||
vertexshader, geometryshader) not in self.programId.keys() and vertexshader != -1 and geometryshader != -1):
|
|
||||||
if self.depthshaderId == -1:
|
|
||||||
with open('./Lights/depthfragment.glsl', 'r') as f:
|
|
||||||
fragment_shader_string = f.read()
|
|
||||||
fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
|
|
||||||
glShaderSource(fragment_shader_id, fragment_shader_string)
|
|
||||||
glCompileShader(fragment_shader_id)
|
|
||||||
if glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS) != GL_TRUE:
|
|
||||||
raise RuntimeError(glGetShaderInfoLog(fragment_shader_id))
|
|
||||||
|
|
||||||
program_id = glCreateProgram()
|
|
||||||
glAttachShader(program_id, vertexshader)
|
|
||||||
glAttachShader(program_id, geometryshader)
|
|
||||||
glAttachShader(program_id, fragment_shader_id)
|
|
||||||
glLinkProgram(program_id)
|
|
||||||
self.programId[(vertexshader, geometryshader)] = program_id
|
|
||||||
return program_id
|
|
||||||
else:
|
|
||||||
if (vertexshader, geometryshader) not in self.programId.keys():
|
|
||||||
return -1
|
|
||||||
return self.programId[(vertexshader, geometryshader)]
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
super(Light, self).__init__()
|
||||||
self._ModelviewProjectionMatrix = np.identity(4)
|
self._ModelviewProjectionMatrix = np.identity(4)
|
||||||
self._pos = [0, 0, 0]
|
self._pos = [0, 0, 0]
|
||||||
self._lightColor = [1, 1, 1]
|
self._lightColor = [1, 1, 1]
|
||||||
|
@ -71,36 +43,7 @@ class Light:
|
||||||
self._pos = value
|
self._pos = value
|
||||||
|
|
||||||
def prepareForDepthMapping(self):
|
def prepareForDepthMapping(self):
|
||||||
new = False
|
pass
|
||||||
if self.FramebufferId == -1:
|
|
||||||
self.FramebufferId = glGenFramebuffers(1)
|
|
||||||
new = True
|
|
||||||
glClearColor(1.0, 1.0, 1.0, 1.0)
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, self.FramebufferId)
|
|
||||||
glCullFace(GL_FRONT)
|
|
||||||
glViewport(0, 0, self.map_size, self.map_size)
|
|
||||||
if new:
|
|
||||||
if self.DepthBuffer == -1:
|
|
||||||
self.DepthBuffer = glGenTextures(1)
|
|
||||||
glBindTexture(GL_TEXTURE_2D, self.DepthBuffer)
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, self.map_size, self.map_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
|
|
||||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, np.array([0, 0, 0], dtype=np.float32))
|
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.FramebufferId, 0)
|
|
||||||
|
|
||||||
DrawBuffers = [GL_NONE]
|
|
||||||
glDrawBuffers(DrawBuffers)
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def finishDepthMapping(self):
|
def finishDepthMapping(self):
|
||||||
glCullFace(GL_BACK)
|
pass
|
||||||
DrawBuffers = [GL_COLOR_ATTACHMENT0]
|
|
||||||
glDrawBuffers(DrawBuffers)
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0)
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0)
|
|
||||||
|
|
|
@ -3,4 +3,95 @@ from OpenGL.GL import *
|
||||||
from MatrixStuff.Transformations import *
|
from MatrixStuff.Transformations import *
|
||||||
|
|
||||||
class Spotlight(Light):
|
class Spotlight(Light):
|
||||||
pass
|
programId = {}
|
||||||
|
depthshaderId = -1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getDepthProgram(cls, vertexshader=-1, geometryshader=-1):
|
||||||
|
if ((
|
||||||
|
vertexshader, geometryshader) not in cls.programId.keys() and vertexshader != -1 and geometryshader != -1):
|
||||||
|
fragment_shader_id = -1
|
||||||
|
if cls.depthshaderId == -1:
|
||||||
|
with open('./Lights/depthfragment.glsl', 'r') as f:
|
||||||
|
fragment_shader_string = f.read()
|
||||||
|
fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
|
||||||
|
glShaderSource(fragment_shader_id, fragment_shader_string)
|
||||||
|
glCompileShader(fragment_shader_id)
|
||||||
|
if glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS) != GL_TRUE:
|
||||||
|
raise RuntimeError(glGetShaderInfoLog(fragment_shader_id))
|
||||||
|
|
||||||
|
program_id = glCreateProgram()
|
||||||
|
glAttachShader(program_id, vertexshader)
|
||||||
|
glAttachShader(program_id, geometryshader)
|
||||||
|
glAttachShader(program_id, fragment_shader_id)
|
||||||
|
glLinkProgram(program_id)
|
||||||
|
cls.programId[(vertexshader, geometryshader)] = program_id
|
||||||
|
return program_id
|
||||||
|
else:
|
||||||
|
if (vertexshader, geometryshader) not in cls.programId.keys():
|
||||||
|
return -1
|
||||||
|
return cls.programId[(vertexshader, geometryshader)]
|
||||||
|
|
||||||
|
def __init__(self, target=[0, 0, 0], opening=45):
|
||||||
|
super(Spotlight, self).__init__()
|
||||||
|
self.target = target
|
||||||
|
self.opening = opening
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lightColor(self):
|
||||||
|
return self._lightColor
|
||||||
|
|
||||||
|
@lightColor.setter
|
||||||
|
def lightColor(self, value):
|
||||||
|
self._lightColor = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ModelviewProjectionMatrix(self):
|
||||||
|
return self._ModelviewProjectionMatrix
|
||||||
|
|
||||||
|
@ModelviewProjectionMatrix.setter
|
||||||
|
def ModelviewProjectionMatrix(self, value):
|
||||||
|
self._ModelviewProjectionMatrix = np.matrix(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pos(self):
|
||||||
|
return self._pos
|
||||||
|
|
||||||
|
@pos.setter
|
||||||
|
def pos(self, value):
|
||||||
|
self._pos = value
|
||||||
|
|
||||||
|
def prepareForDepthMapping(self):
|
||||||
|
new = False
|
||||||
|
if self.FramebufferId == -1:
|
||||||
|
self.FramebufferId = glGenFramebuffers(1)
|
||||||
|
new = True
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 1.0)
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, self.FramebufferId)
|
||||||
|
glCullFace(GL_FRONT)
|
||||||
|
glViewport(0, 0, self.map_size, self.map_size)
|
||||||
|
if new:
|
||||||
|
if self.DepthBuffer == -1:
|
||||||
|
self.DepthBuffer = glGenTextures(1)
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.DepthBuffer)
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, self.map_size, self.map_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
|
||||||
|
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, np.array([0, 0, 0], dtype=np.float32))
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.FramebufferId, 0)
|
||||||
|
|
||||||
|
DrawBuffers = [GL_NONE]
|
||||||
|
glDrawBuffers(DrawBuffers)
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def finishDepthMapping(self):
|
||||||
|
glCullFace(GL_BACK)
|
||||||
|
DrawBuffers = [GL_COLOR_ATTACHMENT0]
|
||||||
|
glDrawBuffers(DrawBuffers)
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 1.0)
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0)
|
|
@ -3,7 +3,7 @@ import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def lookAt(eyeX, eyeY, eyeZ, cX, cY, cZ, upX, upY, upZ):
|
def lookAt(eyeX, eyeY, eyeZ, cX, cY, cZ, upX, upY, upZ):
|
||||||
F = np.matrix([cX - eyeX, cY - eyeY, cZ - eyeZ])
|
F = np.matrix([eyeX - cX, eyeY -cY, eyeZ - cZ])
|
||||||
UP = np.matrix([upX, upY, upZ])
|
UP = np.matrix([upX, upY, upZ])
|
||||||
f = F / math.sqrt(np.sum(np.square(F)))
|
f = F / math.sqrt(np.sum(np.square(F)))
|
||||||
UP = UP / math.sqrt(np.sum(np.square(UP)))
|
UP = UP / math.sqrt(np.sum(np.square(UP)))
|
||||||
|
|
|
@ -6,7 +6,6 @@ import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class Cube(Object):
|
class Cube(Object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Cube, self).__init__()
|
super(Cube, self).__init__()
|
||||||
if (Cube.GeometryShaderId == -1):
|
if (Cube.GeometryShaderId == -1):
|
||||||
|
|
15
Objects/Identifiable.py
Normal file
15
Objects/Identifiable.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from multiprocessing import Semaphore
|
||||||
|
|
||||||
|
creatingID = Semaphore()
|
||||||
|
|
||||||
|
class Identifiable:
|
||||||
|
lastID: int = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
creatingID.acquire()
|
||||||
|
self.lastID += 1
|
||||||
|
self.id = self.lastID
|
||||||
|
creatingID.release()
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.id == other.id and type(self) == type(other)
|
18
Objects/Renderable.py
Normal file
18
Objects/Renderable.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from OpenGL.GLU import gluErrorString
|
||||||
|
from OpenGL.GL import glGetError, GL_NO_ERROR
|
||||||
|
|
||||||
|
class Renderable:
|
||||||
|
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_error(message):
|
||||||
|
gl_error = glGetError()
|
||||||
|
if (gl_error != GL_NO_ERROR):
|
||||||
|
print("Error: " + message)
|
||||||
|
if (gluErrorString(gl_error)):
|
||||||
|
print(gluErrorString(gl_error))
|
||||||
|
else:
|
||||||
|
print(hex(gl_error))
|
||||||
|
return True
|
||||||
|
return False
|
|
@ -11,31 +11,13 @@ import numpy as np
|
||||||
from OpenGL.extensions import alternate
|
from OpenGL.extensions import alternate
|
||||||
|
|
||||||
from Objects.Objects import Object
|
from Objects.Objects import Object
|
||||||
from MatrixStuff.Transformations import translate
|
from Objects.Renderable import Renderable
|
||||||
|
|
||||||
|
|
||||||
def check_error(message):
|
|
||||||
gl_error = glGetError()
|
|
||||||
if (gl_error != GL_NO_ERROR):
|
|
||||||
print("Error: " + message)
|
|
||||||
if (gluErrorString(gl_error)):
|
|
||||||
print(gluErrorString(gl_error))
|
|
||||||
else:
|
|
||||||
print(hex(gl_error))
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class Renderable:
|
|
||||||
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Structure(Renderable):
|
class Structure(Renderable):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.Objects = {}
|
self.Objects = {}
|
||||||
self.vais = {}
|
self.vais = {}
|
||||||
self.Matrix = np.identity(4, np.float32)
|
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
|
|
||||||
def addShape(self, program, shape):
|
def addShape(self, program, shape):
|
||||||
|
@ -65,6 +47,7 @@ class Structure(Renderable):
|
||||||
tpbi = GLuint(0)
|
tpbi = GLuint(0)
|
||||||
tcbi = GLuint(0)
|
tcbi = GLuint(0)
|
||||||
tsbi = GLuint(0)
|
tsbi = GLuint(0)
|
||||||
|
num = len(objects)
|
||||||
|
|
||||||
glGenVertexArrays(1, tvai)
|
glGenVertexArrays(1, tvai)
|
||||||
glBindVertexArray(tvai)
|
glBindVertexArray(tvai)
|
||||||
|
@ -81,7 +64,7 @@ class Structure(Renderable):
|
||||||
positions.append(o.pos[2])
|
positions.append(o.pos[2])
|
||||||
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
|
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
|
||||||
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
|
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
check_error("Could not create position buffer")
|
self.check_error("Could not create position buffer")
|
||||||
|
|
||||||
colors = []
|
colors = []
|
||||||
for o in objects:
|
for o in objects:
|
||||||
|
@ -95,7 +78,7 @@ class Structure(Renderable):
|
||||||
if vc != -1:
|
if vc != -1:
|
||||||
glEnableVertexAttribArray(vc)
|
glEnableVertexAttribArray(vc)
|
||||||
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
|
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
check_error("Could not create color buffer")
|
self.check_error("Could not create color buffer")
|
||||||
|
|
||||||
if hasattr(objects[0], 'size'):
|
if hasattr(objects[0], 'size'):
|
||||||
sizes = []
|
sizes = []
|
||||||
|
@ -110,36 +93,38 @@ class Structure(Renderable):
|
||||||
if vs != -1:
|
if vs != -1:
|
||||||
glEnableVertexAttribArray(vs)
|
glEnableVertexAttribArray(vs)
|
||||||
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
|
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
check_error("Could not create size buffer")
|
self.check_error("Could not create size buffer")
|
||||||
|
|
||||||
glBindVertexArray(0)
|
glBindVertexArray(0)
|
||||||
self.vais[key] = (tvai, tpbi, tcbi, tsbi)
|
self.vais[key] = (tvai, tpbi, tcbi, tsbi, num)
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
|
|
||||||
def clearVertexArrays(self):
|
def clearVertexArrays(self):
|
||||||
for key, (a, p, c, s) in self.vais.items():
|
temp = dict(self.vais)
|
||||||
if p != -1:
|
self.vais = {}
|
||||||
glDisableVertexAttribArray(p)
|
for key, vertex_array_ids in temp.items():
|
||||||
glDeleteBuffers(1, [p])
|
if vertex_array_ids[1] != -1 and vertex_array_ids[1] != GLuint(-1):
|
||||||
if c != -1:
|
glDeleteBuffers(1, [vertex_array_ids[1]])
|
||||||
glDisableVertexAttribArray(c)
|
self.check_error("Could not destroy buffer")
|
||||||
glDeleteBuffers(1, [c])
|
if vertex_array_ids[2] != -1 and vertex_array_ids[2] != GLuint(-1):
|
||||||
if s != -1 and s != GLuint(-1):
|
glDeleteBuffers(1, [vertex_array_ids[2]])
|
||||||
glDisableVertexAttribArray(s)
|
self.check_error("Could not destroy buffer")
|
||||||
glDeleteBuffers(1, [s])
|
if vertex_array_ids[3] != -1 and vertex_array_ids[3] != GLuint(-1):
|
||||||
glDeleteVertexArrays(1, a)
|
glDeleteBuffers(1, [vertex_array_ids[3]])
|
||||||
check_error("Could not destroy vertex array")
|
self.check_error("Could not destroy buffer")
|
||||||
|
glDeleteVertexArrays(1, vertex_array_ids[0])
|
||||||
|
self.check_error("Could not destroy vertex array")
|
||||||
|
|
||||||
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
||||||
|
self.buildvertexArrays()
|
||||||
for key, tupel in self.vais.items():
|
for key, vertex_array_ids in self.vais.items():
|
||||||
if alternateprograms == None:
|
if alternateprograms == None:
|
||||||
program_id = key
|
program_id = key
|
||||||
else:
|
else:
|
||||||
assert key in alternateprograms
|
assert key in alternateprograms
|
||||||
program_id = alternateprograms[key]
|
program_id = alternateprograms[key]
|
||||||
glUseProgram(program_id)
|
glUseProgram(program_id)
|
||||||
check_error("Renderingprogram is not initialized!")
|
self.check_error("Renderingprogram is not initialized!")
|
||||||
|
|
||||||
projection = glGetUniformLocation(program_id, 'projModelViewMatrix')
|
projection = glGetUniformLocation(program_id, 'projModelViewMatrix')
|
||||||
rot = glGetUniformLocation(program_id, 'rotMatrix')
|
rot = glGetUniformLocation(program_id, 'rotMatrix')
|
||||||
|
@ -147,9 +132,9 @@ class Structure(Renderable):
|
||||||
glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix))
|
glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix))
|
||||||
glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix))
|
glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix))
|
||||||
|
|
||||||
glBindVertexArray(tupel[0])
|
glBindVertexArray(vertex_array_ids[0])
|
||||||
glDrawArrays(GL_POINTS, 0, len(self.Objects[key]))
|
glDrawArrays(GL_POINTS, 0, vertex_array_ids[4])
|
||||||
check_error("Rendering problem")
|
self.check_error("Rendering problem")
|
||||||
|
|
||||||
glBindVertexArray(0)
|
glBindVertexArray(0)
|
||||||
glUseProgram(0)
|
glUseProgram(0)
|
||||||
|
@ -171,7 +156,6 @@ class CompoundStructure(Renderable):
|
||||||
|
|
||||||
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
||||||
for (structure, M, R) in self.Structures:
|
for (structure, M, R) in self.Structures:
|
||||||
structure.buildvertexArrays()
|
|
||||||
structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms)
|
structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
@ -179,75 +163,3 @@ class CompoundStructure(Renderable):
|
||||||
return self.Structures == other.Structures
|
return self.Structures == other.Structures
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class WorldChunk(Renderable):
|
|
||||||
def __init__(self, width, length, height):
|
|
||||||
assert width > 0, 'Width must be greater than 0'
|
|
||||||
assert length > 0, 'length must be greater than 0'
|
|
||||||
assert height > 0, 'height must be greater than 0'
|
|
||||||
self.visible = []
|
|
||||||
self.content = []
|
|
||||||
self.entities = []
|
|
||||||
|
|
||||||
self.width = width
|
|
||||||
self.length = length
|
|
||||||
self.height = height
|
|
||||||
|
|
||||||
for x in range(width):
|
|
||||||
self.content.append([])
|
|
||||||
self.visible.append([])
|
|
||||||
for y in range(length):
|
|
||||||
self.content[x].append([])
|
|
||||||
self.visible[x].append([])
|
|
||||||
for z in range(height):
|
|
||||||
self.content[x][y].append(None)
|
|
||||||
self.visible[x][y].append(4)
|
|
||||||
|
|
||||||
def put_object(self, x: int, y: int, z: int, new_object: Object):
|
|
||||||
assert 0 <= x < self.width, 'Put out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
|
||||||
assert 0 <= y < self.length, 'Put out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
|
||||||
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
|
||||||
self.content[x][y][z] = new_object
|
|
||||||
|
|
||||||
change = -1 if new_object is not None else 1
|
|
||||||
visible_carry_over = []
|
|
||||||
if x + 1 >= self.width:
|
|
||||||
visible_carry_over.append((1, 0, 0, change))
|
|
||||||
else:
|
|
||||||
self.visible[x + 1][y][z] += change
|
|
||||||
if x - 1 < 0:
|
|
||||||
visible_carry_over.append((-1, 0, 0, change))
|
|
||||||
else:
|
|
||||||
self.visible[x - 1][y][z] += change
|
|
||||||
|
|
||||||
if y + 1 >= self.length:
|
|
||||||
visible_carry_over.append((0, 1, 0, change))
|
|
||||||
else:
|
|
||||||
self.visible[x][y + 1][z] += change
|
|
||||||
if y - 1 < 0:
|
|
||||||
visible_carry_over.append((0, -1, 0, change))
|
|
||||||
else:
|
|
||||||
self.visible[x][y - 1][z] += change
|
|
||||||
|
|
||||||
if z + 1 >= self.height:
|
|
||||||
visible_carry_over.append((0, 0, 1, change))
|
|
||||||
else:
|
|
||||||
self.visible[x][y][z + 1] += change
|
|
||||||
if z - 1 < 0:
|
|
||||||
visible_carry_over.append((0, 0, -1, change))
|
|
||||||
else:
|
|
||||||
self.visible[x][y][z - 1] += change
|
|
||||||
|
|
||||||
return visible_carry_over
|
|
||||||
|
|
||||||
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
|
|
||||||
for x in range(self.width):
|
|
||||||
for y in range(self.length):
|
|
||||||
for z in range(self.height):
|
|
||||||
if self.visible[x][y][z] > 0 and self.content[x][y][z] is not None:
|
|
||||||
self.content[x][y][z].render(translate(x, y, z) * projMatrix,
|
|
||||||
geometryRotMatrix, alternateprograms)
|
|
||||||
|
|
||||||
for entity in self.entities:
|
|
||||||
entity.render(projMatrix, geometryRotMatrix, alternateprograms)
|
|
||||||
|
|
363
Objects/World.py
Normal file
363
Objects/World.py
Normal file
|
@ -0,0 +1,363 @@
|
||||||
|
from Lights.Lights import Light
|
||||||
|
from Objects.Objects import Object
|
||||||
|
from Objects.Renderable import Renderable
|
||||||
|
from Objects.Structure import Structure
|
||||||
|
from MatrixStuff.Transformations import translate
|
||||||
|
from OpenGL.GLU import *
|
||||||
|
from OpenGL.GL import *
|
||||||
|
import math
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class WorldChunk(Structure):
|
||||||
|
def __init__(self, width: int, length: int, height: int, programs: dict):
|
||||||
|
assert width > 0, 'Width must be greater than 0'
|
||||||
|
assert length > 0, 'length must be greater than 0'
|
||||||
|
assert height > 0, 'height must be greater than 0'
|
||||||
|
super(WorldChunk, self).__init__()
|
||||||
|
self.visible = []
|
||||||
|
self.content = []
|
||||||
|
self.entities = []
|
||||||
|
self.lights = []
|
||||||
|
|
||||||
|
self.width = width
|
||||||
|
self.length = length
|
||||||
|
self.height = height
|
||||||
|
self.programs = programs
|
||||||
|
|
||||||
|
for x in range(width):
|
||||||
|
self.content.append([])
|
||||||
|
self.visible.append([])
|
||||||
|
for y in range(length):
|
||||||
|
self.content[x].append([])
|
||||||
|
self.visible[x].append([])
|
||||||
|
for z in range(height):
|
||||||
|
self.content[x][y].append(None)
|
||||||
|
self.visible[x][y].append(4)
|
||||||
|
|
||||||
|
def put_object(self, x: int, y: int, z: int, new_object: Object):
|
||||||
|
assert 0 <= x < self.width, 'Put out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
||||||
|
assert 0 <= y < self.length, 'Put out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
||||||
|
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
||||||
|
no_visibility_changes = (self.content[x][y][z] is None) == (new_object is None)
|
||||||
|
|
||||||
|
self.content[x][y][z] = new_object
|
||||||
|
new_object.translate(translate(x, y, z))
|
||||||
|
|
||||||
|
change = -1 if new_object is not None else 1
|
||||||
|
visible_carry_over = []
|
||||||
|
if not no_visibility_changes:
|
||||||
|
if x + 1 >= self.width:
|
||||||
|
visible_carry_over.append((1, 0, 0, change))
|
||||||
|
else:
|
||||||
|
self.visible[x + 1][y][z] += change
|
||||||
|
if x - 1 < 0:
|
||||||
|
visible_carry_over.append((-1, 0, 0, change))
|
||||||
|
else:
|
||||||
|
self.visible[x - 1][y][z] += change
|
||||||
|
|
||||||
|
if y + 1 >= self.length:
|
||||||
|
visible_carry_over.append((0, 1, 0, change))
|
||||||
|
else:
|
||||||
|
self.visible[x][y + 1][z] += change
|
||||||
|
if y - 1 < 0:
|
||||||
|
visible_carry_over.append((0, -1, 0, change))
|
||||||
|
else:
|
||||||
|
self.visible[x][y - 1][z] += change
|
||||||
|
|
||||||
|
if z + 1 >= self.height:
|
||||||
|
visible_carry_over.append((0, 0, 1, change))
|
||||||
|
else:
|
||||||
|
self.visible[x][y][z + 1] += change
|
||||||
|
if z - 1 < 0:
|
||||||
|
visible_carry_over.append((0, 0, -1, change))
|
||||||
|
else:
|
||||||
|
self.visible[x][y][z - 1] += change
|
||||||
|
|
||||||
|
return visible_carry_over
|
||||||
|
|
||||||
|
def get_object(self, x: int, y: int, z: int):
|
||||||
|
assert 0 <= x < self.width, 'Put out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
||||||
|
assert 0 <= y < self.length, 'Put out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
||||||
|
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
||||||
|
|
||||||
|
return self.content[x][y][z]
|
||||||
|
|
||||||
|
def apply_visible_carry_over(self, x: int, y: int, z: int, change: int):
|
||||||
|
assert 0 <= x < self.width, 'Apply visible out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
||||||
|
assert 0 <= y < self.length, 'Apply visible out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
||||||
|
assert 0 <= z < self.height, 'Apply visible out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
||||||
|
|
||||||
|
self.visible[x][y][z] += change
|
||||||
|
|
||||||
|
def set_visibility(self, x: int, y: int, z: int, visibility: int):
|
||||||
|
assert 0 <= x < self.width, 'Apply visible out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
||||||
|
assert 0 <= y < self.length, 'Apply visible out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
||||||
|
assert 0 <= z < self.height, 'Apply visible out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
||||||
|
|
||||||
|
self.visible[x][y][z] = visibility
|
||||||
|
|
||||||
|
def buildvertexArrays(self):
|
||||||
|
if self.dirty:
|
||||||
|
self.clearVertexArrays()
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY)
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY)
|
||||||
|
self.vais = {}
|
||||||
|
|
||||||
|
objects = {}
|
||||||
|
counts = {}
|
||||||
|
for x in range(self.width):
|
||||||
|
for y in range(self.length):
|
||||||
|
for z in range(self.height):
|
||||||
|
if self.content[x][y][z] is not None: # and self.visible[x][y][z] > 0: TODO: check visibility...
|
||||||
|
if self.programs[type(self.content[x][y][z])] not in objects.keys():
|
||||||
|
objects[self.programs[type(self.content[x][y][z])]] = []
|
||||||
|
counts[self.programs[type(self.content[x][y][z])]] = 0
|
||||||
|
objects[self.programs[type(self.content[x][y][z])]].append(self.content[x][y][z])
|
||||||
|
counts[self.programs[type(self.content[x][y][z])]] += 1
|
||||||
|
|
||||||
|
for key, object_list in objects.items():
|
||||||
|
tvai = GLuint(0)
|
||||||
|
tpbi = GLuint(0)
|
||||||
|
tcbi = GLuint(0)
|
||||||
|
tsbi = GLuint(0)
|
||||||
|
|
||||||
|
glGenVertexArrays(1, tvai)
|
||||||
|
glBindVertexArray(tvai)
|
||||||
|
|
||||||
|
vid = glGetAttribLocation(key, "in_position")
|
||||||
|
glEnableVertexAttribArray(vid)
|
||||||
|
|
||||||
|
tpbi = glGenBuffers(1)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, tpbi)
|
||||||
|
positions = []
|
||||||
|
for o in object_list:
|
||||||
|
positions.append(o.pos[0])
|
||||||
|
positions.append(o.pos[1])
|
||||||
|
positions.append(o.pos[2])
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
|
||||||
|
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
|
self.check_error("Could not create position buffer")
|
||||||
|
|
||||||
|
colors = []
|
||||||
|
for o in object_list:
|
||||||
|
colors.append(o.color[0])
|
||||||
|
colors.append(o.color[1])
|
||||||
|
colors.append(o.color[2])
|
||||||
|
tcbi = glGenBuffers(1)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, tcbi)
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, np.array(colors, dtype=np.float32), GL_STATIC_DRAW)
|
||||||
|
vc = glGetAttribLocation(key, "MyInColor")
|
||||||
|
if vc != -1:
|
||||||
|
glEnableVertexAttribArray(vc)
|
||||||
|
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
|
self.check_error("Could not create color buffer")
|
||||||
|
|
||||||
|
if hasattr(object_list[0], 'size'):
|
||||||
|
sizes = []
|
||||||
|
for o in object_list:
|
||||||
|
sizes.append(o.size[0])
|
||||||
|
sizes.append(o.size[1])
|
||||||
|
sizes.append(o.size[2])
|
||||||
|
tsbi = glGenBuffers(1)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, tsbi)
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, np.array(sizes, dtype=np.float32), GL_STATIC_DRAW)
|
||||||
|
vs = glGetAttribLocation(key, "MyInSize")
|
||||||
|
if vs != -1:
|
||||||
|
glEnableVertexAttribArray(vs)
|
||||||
|
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
|
||||||
|
self.check_error("Could not create size buffer")
|
||||||
|
|
||||||
|
glBindVertexArray(0)
|
||||||
|
self.vais[key] = (tvai, tpbi, tcbi, tsbi, counts[key])
|
||||||
|
self.dirty = False
|
||||||
|
|
||||||
|
def render(self, proj_matrix, geometry_rot_matrix, alternate_programs=None):
|
||||||
|
super(WorldChunk, self).render(proj_matrix, geometry_rot_matrix, alternate_programs)
|
||||||
|
|
||||||
|
for entity in self.entities:
|
||||||
|
entity.render(proj_matrix, geometry_rot_matrix, alternate_programs)
|
||||||
|
|
||||||
|
def set_color(self, x: int, y: int, z: int, r: float, g: float, b: float):
|
||||||
|
assert 0 <= x < self.width, 'Put out of bounds for x coordinate! Must be between 0 and %i' % self.width
|
||||||
|
assert 0 <= y < self.length, 'Put out of bounds for y coordinate! Must be between 0 and %i' % self.length
|
||||||
|
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
|
||||||
|
|
||||||
|
if self.content[x][y][z] is not None:
|
||||||
|
self.content[x][y][z].setColor(r, g, b)
|
||||||
|
self.dirty = True
|
||||||
|
|
||||||
|
class World(Renderable):
|
||||||
|
def __init__(self, chunk_size_x: int, chunk_size_y: int, chunk_size_z: int,
|
||||||
|
chunk_n_x: int, chunk_n_y: int, chunk_n_z: int, programs: dict):
|
||||||
|
super(World, self).__init__()
|
||||||
|
self.chunk_size_x = chunk_size_x
|
||||||
|
self.chunk_size_y = chunk_size_y
|
||||||
|
self.chunk_size_z = chunk_size_z
|
||||||
|
self.chunk_n_x = chunk_n_x
|
||||||
|
self.chunk_n_y = chunk_n_y
|
||||||
|
self.chunk_n_z = chunk_n_z
|
||||||
|
self.programs = programs
|
||||||
|
|
||||||
|
self.chunks: [[[WorldChunk]]] = []
|
||||||
|
for x in range(chunk_n_x):
|
||||||
|
self.chunks.append([])
|
||||||
|
for y in range(chunk_n_y):
|
||||||
|
self.chunks[x].append([])
|
||||||
|
for z in range(chunk_n_z):
|
||||||
|
self.chunks[x][y].append(None)
|
||||||
|
|
||||||
|
def set_color(self, x: int, y: int, z: int, r: float, g: float, b: float):
|
||||||
|
x = x % (self.chunk_size_x * self.chunk_n_x)
|
||||||
|
y = y % (self.chunk_size_y * self.chunk_n_y)
|
||||||
|
z = z % (self.chunk_size_z * self.chunk_n_z)
|
||||||
|
|
||||||
|
chunk_x = int(x / self.chunk_size_x)
|
||||||
|
chunk_y = int(y / self.chunk_size_y)
|
||||||
|
chunk_z = int(z / self.chunk_size_z)
|
||||||
|
if self.chunks[chunk_x][chunk_y][chunk_z] is not None:
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z].set_color(x % self.chunk_size_x,
|
||||||
|
y % self.chunk_size_y,
|
||||||
|
z % self.chunk_size_z,
|
||||||
|
r, g, b)
|
||||||
|
|
||||||
|
def put_object(self, x: int, y: int, z: int, new_object: Object):
|
||||||
|
x = x % (self.chunk_size_x * self.chunk_n_x)
|
||||||
|
y = y % (self.chunk_size_y * self.chunk_n_y)
|
||||||
|
z = z % (self.chunk_size_z * self.chunk_n_z)
|
||||||
|
|
||||||
|
chunk_x = int(x / self.chunk_size_x)
|
||||||
|
chunk_y = int(y / self.chunk_size_y)
|
||||||
|
chunk_z = int(z / self.chunk_size_z)
|
||||||
|
|
||||||
|
if self.chunks[chunk_x][chunk_y][chunk_z] is None:
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z] = WorldChunk(self.chunk_size_x, self.chunk_size_y, self.chunk_size_z, self.programs)
|
||||||
|
|
||||||
|
carry_overs = self.chunks[chunk_x][chunk_y][chunk_z].put_object(x % self.chunk_size_x,
|
||||||
|
y % self.chunk_size_y,
|
||||||
|
z % self.chunk_size_z,
|
||||||
|
new_object)
|
||||||
|
for carry_over in carry_overs:
|
||||||
|
if self.chunks[(chunk_x + carry_over[0]) % self.chunk_n_x][(chunk_y + carry_over[1]) % self.chunk_n_y][(chunk_z + carry_over[2]) % self.chunk_n_z] is not None:
|
||||||
|
self.chunks[
|
||||||
|
(chunk_x + carry_over[0]) % self.chunk_n_x][
|
||||||
|
(chunk_y + carry_over[1]) % self.chunk_n_y][
|
||||||
|
(chunk_z + carry_over[2]) % self.chunk_n_z].apply_visible_carry_over(
|
||||||
|
(x + carry_over[0]) % self.chunk_size_x,
|
||||||
|
(y + carry_over[1]) % self.chunk_size_y,
|
||||||
|
(z + carry_over[2]) % self.chunk_size_z,
|
||||||
|
carry_over[3])
|
||||||
|
self.chunks[
|
||||||
|
(chunk_x + carry_over[0]) % self.chunk_n_x][
|
||||||
|
(chunk_y + carry_over[1]) % self.chunk_n_y][
|
||||||
|
(chunk_z + carry_over[2]) % self.chunk_n_z].dirty = True
|
||||||
|
|
||||||
|
visibility = 6
|
||||||
|
neighbour = self.get_object(x - 1, y, z)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
neighbour = self.get_object(x + 1, y, z)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
neighbour = self.get_object(x, y - 1, z)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
neighbour = self.get_object(x, y + 1, z)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
neighbour = self.get_object(x, y, z - 1)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
neighbour = self.get_object(x, y, z + 1)
|
||||||
|
if neighbour is not None:
|
||||||
|
visibility -= 1
|
||||||
|
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z].set_visibility(x % self.chunk_size_x,
|
||||||
|
y % self.chunk_size_y,
|
||||||
|
z % self.chunk_size_z,
|
||||||
|
visibility)
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z].dirty = True
|
||||||
|
|
||||||
|
def get_object(self, x: int, y: int, z: int):
|
||||||
|
x = x % (self.chunk_size_x * self.chunk_n_x)
|
||||||
|
y = y % (self.chunk_size_y * self.chunk_n_y)
|
||||||
|
z = z % (self.chunk_size_z * self.chunk_n_z)
|
||||||
|
|
||||||
|
chunk_x = int(x / self.chunk_size_x)
|
||||||
|
chunk_y = int(y / self.chunk_size_y)
|
||||||
|
chunk_z = int(z / self.chunk_size_z)
|
||||||
|
|
||||||
|
if self.chunks[chunk_x][chunk_y][chunk_z] is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.chunks[chunk_x][chunk_y][chunk_z].get_object(x % self.chunk_size_x,
|
||||||
|
y % self.chunk_size_y,
|
||||||
|
z % self.chunk_size_z)
|
||||||
|
|
||||||
|
def render(self, proj_matrix, geometry_rot_matrix, alternate_programs=None):
|
||||||
|
for x in range(self.chunk_n_x):
|
||||||
|
for y in range(self.chunk_n_y):
|
||||||
|
for z in range(self.chunk_n_z):
|
||||||
|
if self.chunks[x][y][z] is not None:
|
||||||
|
self.chunks[x][y][z].render(translate(x * self.chunk_size_x,
|
||||||
|
y * self.chunk_size_y,
|
||||||
|
z * self.chunk_size_z) * proj_matrix,
|
||||||
|
geometry_rot_matrix, alternate_programs)
|
||||||
|
|
||||||
|
def add_light(self, x: float, y: float, z: float, l: Light):
|
||||||
|
x = x % (self.chunk_size_x * self.chunk_n_x)
|
||||||
|
y = y % (self.chunk_size_y * self.chunk_n_y)
|
||||||
|
z = z % (self.chunk_size_z * self.chunk_n_z)
|
||||||
|
|
||||||
|
chunk_x = int(x / self.chunk_size_x)
|
||||||
|
chunk_y = int(y / self.chunk_size_y)
|
||||||
|
chunk_z = int(z / self.chunk_size_z)
|
||||||
|
|
||||||
|
if self.chunks[chunk_x][chunk_y][chunk_z] is None:
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z] = WorldChunk(self.chunk_size_x, self.chunk_size_y, self.chunk_size_z, self.programs)
|
||||||
|
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z].lights.append(l)
|
||||||
|
l.pos = [x, y, z]
|
||||||
|
|
||||||
|
def remove_light(self, l: Light):
|
||||||
|
chunk_x = int(l.pos[0] / self.chunk_size_x)
|
||||||
|
chunk_y = int(l.pos[1] / self.chunk_size_y)
|
||||||
|
chunk_z = int(l.pos[2] / self.chunk_size_z)
|
||||||
|
|
||||||
|
if self.chunks[chunk_x][chunk_y][chunk_z] is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if l in self.chunks[chunk_x][chunk_y][chunk_z].lights:
|
||||||
|
self.chunks[chunk_x][chunk_y][chunk_z].lights.remove(l)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def move_light(self, l: Light, target_x: float, target_y: float, target_z: float):
|
||||||
|
self.remove_light(l)
|
||||||
|
self.add_light(target_x, target_y, target_z, l)
|
||||||
|
|
||||||
|
def get_lights_to_render(self, pos, distance):
|
||||||
|
distance_x = math.ceil(float(distance) / self.chunk_size_x)
|
||||||
|
distance_y = math.ceil(float(distance) / self.chunk_size_y)
|
||||||
|
distance_z = math.ceil(float(distance) / self.chunk_size_z)
|
||||||
|
|
||||||
|
pos_x = int(pos[0] / self.chunk_size_x)
|
||||||
|
pos_y = int(pos[1] / self.chunk_size_y)
|
||||||
|
pos_z = int(pos[2] / self.chunk_size_z)
|
||||||
|
|
||||||
|
lights = []
|
||||||
|
for x in range(distance_x):
|
||||||
|
for y in range(distance_y):
|
||||||
|
for z in range(distance_z):
|
||||||
|
chunk = self.chunks[(pos_x + x) % self.chunk_n_x][(pos_y + y) % self.chunk_n_y][(pos_z + z) % self.chunk_n_z]
|
||||||
|
if chunk is not None:
|
||||||
|
lights += chunk.lights
|
||||||
|
|
||||||
|
return lights
|
10
WorldProvider/WorldProvider.py
Normal file
10
WorldProvider/WorldProvider.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from Objects.World import World
|
||||||
|
|
||||||
|
|
||||||
|
class WorldProvider:
|
||||||
|
def __init__(self, programs):
|
||||||
|
self.world: World = World(10, 10, 10, 10, 10, 10, programs)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
3
config.json
Normal file
3
config.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"render_light_distance": 100
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ const float diffuseFactor = 0.5;
|
||||||
const float specFactor = 1.0;
|
const float specFactor = 1.0;
|
||||||
const float shininess = 16.0;
|
const float shininess = 16.0;
|
||||||
const float screenGamma = 2.2;
|
const float screenGamma = 2.2;
|
||||||
const float pitl = 2*3.14159265359 / 16.0;
|
const float pitl = 2.0*3.14159265359 / 24.0;
|
||||||
const float circlelength = 100000.0;
|
const float circlelength = 100000.0;
|
||||||
|
|
||||||
bool isVisible(int i, vec2 offs, float lambertian)
|
bool isVisible(int i, vec2 offs, float lambertian)
|
||||||
|
@ -44,17 +44,25 @@ void main()
|
||||||
vec3 halfDir = normalize(lightDir + viewDir);
|
vec3 halfDir = normalize(lightDir + viewDir);
|
||||||
float specAngle = max(dot(halfDir, normalize(normal)), 0.0);
|
float specAngle = max(dot(halfDir, normalize(normal)), 0.0);
|
||||||
specular = int(lambertian > 0)*pow(specAngle, shininess);
|
specular = int(lambertian > 0)*pow(specAngle, shininess);
|
||||||
//int visible = int(!(texture(ShadowMaps,lightpos[i].xy/2 + vec2(0.5,0.5)).z < (lightpos[i].z)));
|
|
||||||
float visible = 0;
|
float visible = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
vec2 texelSize = 1.0 / textureSize(ShadowMaps[i], 0);
|
vec2 texelSize = 1.0 / textureSize(ShadowMaps[i], 0);
|
||||||
for(int x = -2; x <= 2; x++){
|
|
||||||
for(int y = -2; y <= 2; y++){
|
// Grid sampling
|
||||||
vec2 offs = vec2(x, y) * texelSize;
|
// for(int x = -2; x <= 2; x++){
|
||||||
visible += float(int(isVisible(i, offs, lambertian))) * 1.0/25.0;
|
// for(int y = -2; y <= 2; y++){
|
||||||
}
|
// vec2 offs = vec2(x, y) * texelSize;
|
||||||
|
// visible += float(int(isVisible(i, offs, lambertian))) * 1.0/25.0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//Circle Sampling
|
||||||
|
visible += float(int(isVisible(i, vec2(0, 0), lambertian))) * 1.0/25.0;
|
||||||
|
for(int r = 0; r < 24; r++){
|
||||||
|
vec2 offs = vec2(sin(r * pitl), cos(r * pitl)) * texelSize;
|
||||||
|
visible += float(int(isVisible(i, offs, lambertian))) * 1.0/25.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool condition = visible >= (1.0/5.0);
|
bool condition = visible >= (1.0/5.0);
|
||||||
visible = float(condition) * 1.0 + float(!condition) * visible;
|
visible = float(condition) * 1.0 + float(!condition) * visible;
|
||||||
|
|
||||||
|
|
48
main.py
48
main.py
|
@ -1,24 +1,13 @@
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from WorldProvider.WorldProvider import WorldProvider
|
||||||
|
|
||||||
print('64' if sys.maxsize > 2 ** 32 else '32')
|
print('64' if sys.maxsize > 2 ** 32 else '32')
|
||||||
|
|
||||||
from wsgiref.validate import check_errors
|
from Objects.Cube.Cube import Cube
|
||||||
|
from Objects.Cuboid.Cuboid import Cuboid
|
||||||
from OpenGL.GL.ARB.vertex_array_object import glDeleteVertexArrays
|
from Objects.Structure import Structure, CompoundStructure
|
||||||
from OpenGL.GL.framebufferobjects import glBindFramebuffer
|
|
||||||
from OpenGL.GLUT import *
|
|
||||||
import OpenGL.GLUT.freeglut
|
|
||||||
from OpenGL.GLU import *
|
|
||||||
from OpenGL.GL import *
|
|
||||||
from ctypes import sizeof, c_float, c_void_p, c_uint
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import math as math
|
|
||||||
from Objects.Cube.Cube import *
|
|
||||||
from Objects.Cuboid.Cuboid import *
|
|
||||||
from Objects.Structure import *
|
|
||||||
from MatrixStuff.Transformations import *
|
|
||||||
from Lights.Spotlight.Spotlight import Spotlight
|
from Lights.Spotlight.Spotlight import Spotlight
|
||||||
from Lights.LightingManager import *
|
from Lights.LightingManager import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -38,6 +27,8 @@ height = 1080
|
||||||
opening = 45
|
opening = 45
|
||||||
l = Spotlight()
|
l = Spotlight()
|
||||||
|
|
||||||
|
wp = None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
lm = LightingManager()
|
lm = LightingManager()
|
||||||
|
@ -142,16 +133,24 @@ def main():
|
||||||
# struct.addShape(program_id, Cube().translate(translate(-1, 1, 0)).setColor(1, 1, 1))
|
# struct.addShape(program_id, Cube().translate(translate(-1, 1, 0)).setColor(1, 1, 1))
|
||||||
# struct.addShape(program_id, Cube().translate(translate(0, 1, 0)).setColor(0, 0, 1))
|
# struct.addShape(program_id, Cube().translate(translate(0, 1, 0)).setColor(0, 0, 1))
|
||||||
|
|
||||||
for x_pos in range(-10, 10, 1):
|
for x_pos in range(0, 10, 1):
|
||||||
for y_pos in range(-10, 10):
|
for y_pos in range(0, 10):
|
||||||
z = random.random() * 2 - 1
|
z = random.random() * 2 - 1
|
||||||
struct.addShape(program_id, Cuboid().translate(translate(x_pos, y_pos, z)).setColor(
|
struct.addShape(program_id, Cuboid().translate(translate(x_pos, y_pos, z)).setColor(
|
||||||
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0).setSize(
|
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0).setSize(
|
||||||
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0
|
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0
|
||||||
))
|
))
|
||||||
|
|
||||||
|
global wp
|
||||||
|
wp = WorldProvider({Cuboid: program_id})
|
||||||
|
|
||||||
struct.buildvertexArrays()
|
for x_pos in range(0, 10):
|
||||||
|
for y_pos in range(0, 10):
|
||||||
|
for z_pos in range(0, 10):
|
||||||
|
wp.world.put_object(x_pos, y_pos, z_pos, Cuboid().setColor(
|
||||||
|
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0).setSize(
|
||||||
|
random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0, random.randint(0, 100) / 100.0
|
||||||
|
))
|
||||||
|
|
||||||
# struct.clearVertexArrays()
|
# struct.clearVertexArrays()
|
||||||
|
|
||||||
|
@ -320,9 +319,10 @@ ry = 0
|
||||||
|
|
||||||
|
|
||||||
def render(program_id, projMatrix, vai, x, y, z, alternateprograms=None):
|
def render(program_id, projMatrix, vai, x, y, z, alternateprograms=None):
|
||||||
global struct, cstruct
|
global struct, cstruct, wp
|
||||||
|
|
||||||
cstruct.render(translate(x, y, z) * rotate(0, ry, 0, True) * projMatrix, rotate(rx, 0, 0), alternateprograms)
|
cstruct.render(translate(x, y, z) * rotate(0, ry, 0, True) * projMatrix, rotate(rx, 0, 0), alternateprograms)
|
||||||
|
wp.world.render(translate(x, y, z) * rotate(0, ry, 0, True) * projMatrix, rotate(rx, 0, 0), alternateprograms)
|
||||||
'''
|
'''
|
||||||
glUseProgram(program_id)
|
glUseProgram(program_id)
|
||||||
check_error("Renderingprogram is not initialized!")
|
check_error("Renderingprogram is not initialized!")
|
||||||
|
@ -365,7 +365,7 @@ def display():
|
||||||
global projMatrix
|
global projMatrix
|
||||||
projMatrix = perspectiveMatrix(45, float(width) / float(height), 0.01, 100.0)
|
projMatrix = perspectiveMatrix(45, float(width) / float(height), 0.01, 100.0)
|
||||||
|
|
||||||
newMat = translate(-cx, -cy, -5) * lookAt(cx, cy, 5, 0, 0, 0, 0, 1, 0) * perspectiveMatrix(opening,
|
newMat = translate(-cx, -cy, -5) * lookAt(0, 0, 0, cx, cy, 5, 0, 1, 0) * perspectiveMatrix(opening,
|
||||||
float(l.map_size) /
|
float(l.map_size) /
|
||||||
float(l.map_size),
|
float(l.map_size),
|
||||||
0.01, 100.0)
|
0.01, 100.0)
|
||||||
|
@ -380,8 +380,8 @@ def display():
|
||||||
farid = glGetUniformLocation(program3_id, 'far')
|
farid = glGetUniformLocation(program3_id, 'far')
|
||||||
glUniform1f(nearid, 0.01)
|
glUniform1f(nearid, 0.01)
|
||||||
glUniform1f(farid, 100)
|
glUniform1f(farid, 100)
|
||||||
glUniform1f(widthid, width)
|
glUniform1f(widthid, l.map_size)
|
||||||
glUniform1f(heightid, height)
|
glUniform1f(heightid, l.map_size)
|
||||||
|
|
||||||
altPrId = {}
|
altPrId = {}
|
||||||
altPrId[program_id] = program3_id
|
altPrId[program_id] = program3_id
|
||||||
|
@ -418,7 +418,7 @@ def display():
|
||||||
glUniform1iv(texID, 1, 0)
|
glUniform1iv(texID, 1, 0)
|
||||||
|
|
||||||
glViewport(0, 0, width, height)
|
glViewport(0, 0, width, height)
|
||||||
render(program_id, translate(0, 0, -10) * lookAt(0, 0, 10, 0, 0, 0, 0, 1, 0) * projMatrix, vai, 0, 0, 0)
|
render(program_id, translate(0, 0, -10) * lookAt(0, 0, 0, 0, 0, 10, 0, 1, 0) * projMatrix, vai, 0, 0, 0)
|
||||||
|
|
||||||
# temp, _, _ = create_vertex_buffers(np.array([cx, cy, 5], dtype=np.float32),
|
# temp, _, _ = create_vertex_buffers(np.array([cx, cy, 5], dtype=np.float32),
|
||||||
# np.array([1, 1, 0], dtype=np.float32), program_id)
|
# np.array([1, 1, 0], dtype=np.float32), program_id)
|
||||||
|
|
6
tests/test_Client.py
Normal file
6
tests/test_Client.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from Client.Client import Client
|
||||||
|
from WorldProvider.WorldProvider import WorldProvider
|
||||||
|
|
||||||
|
def test_client_init():
|
||||||
|
wp = WorldProvider()
|
||||||
|
client = Client(wp, test=True)
|
59
tests/test_Structures.py
Normal file
59
tests/test_Structures.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
from Lights.Lights import Light
|
||||||
|
from Objects.Objects import Object
|
||||||
|
from Objects.World import World
|
||||||
|
|
||||||
|
|
||||||
|
def test_world_put_object():
|
||||||
|
w = World(5, 5, 5, 3, 3, 3)
|
||||||
|
o = Object()
|
||||||
|
w.put_object(5, 5, 5, o)
|
||||||
|
|
||||||
|
assert w.chunks[1][1][1].content[0][0][0] == o, 'Put Object into world failed'
|
||||||
|
|
||||||
|
|
||||||
|
def test_world_get_object():
|
||||||
|
w = World(5, 5, 5, 3, 3, 3)
|
||||||
|
o = Object()
|
||||||
|
w.put_object(5, 5, 5, o)
|
||||||
|
|
||||||
|
assert w.get_object(5, 5, 5) == o, 'Put Object into world failed'
|
||||||
|
|
||||||
|
|
||||||
|
def test_world_put_visibility():
|
||||||
|
w = World(5, 5, 5, 3, 3, 3)
|
||||||
|
o = Object()
|
||||||
|
w.put_object(4, 5, 5, o)
|
||||||
|
w.put_object(6, 5, 5, o)
|
||||||
|
|
||||||
|
w.put_object(5, 4, 5, o)
|
||||||
|
w.put_object(5, 6, 5, o)
|
||||||
|
|
||||||
|
w.put_object(5, 5, 4, o)
|
||||||
|
w.put_object(5, 5, 6, o)
|
||||||
|
|
||||||
|
w.put_object(5, 5, 5, o)
|
||||||
|
|
||||||
|
assert w.chunks[1][1][1].visible[0][0][0] == 0, 'Initial visibility not set!'
|
||||||
|
|
||||||
|
assert w.chunks[1][1][1].visible[1][0][0] == 5, 'Neighbours visibility not set!'
|
||||||
|
assert w.chunks[1][1][1].visible[0][1][0] == 5, 'Neighbours visibility not set!'
|
||||||
|
assert w.chunks[1][1][1].visible[0][0][1] == 5, 'Neighbours visibility not set!'
|
||||||
|
|
||||||
|
assert w.chunks[0][1][1].visible[4][0][0] == 5, 'Neighbours visibility not set!'
|
||||||
|
assert w.chunks[1][0][1].visible[0][4][0] == 5, 'Neighbours visibility not set!'
|
||||||
|
assert w.chunks[1][1][0].visible[0][0][4] == 5, 'Neighbours visibility not set!'
|
||||||
|
|
||||||
|
|
||||||
|
def test_world_add_light():
|
||||||
|
w = World(5, 5, 5, 3, 3, 3)
|
||||||
|
l = Light()
|
||||||
|
|
||||||
|
w.add_light(1.5, 2, 3.7, l)
|
||||||
|
|
||||||
|
|
||||||
|
def test_world_remove_light():
|
||||||
|
w = World(5, 5, 5, 3, 3, 3)
|
||||||
|
l = Light()
|
||||||
|
|
||||||
|
w.add_light(1.5, 2, 3.7, l)
|
||||||
|
w.remove_light(l)
|
Loading…
Reference in a new issue