thermodynamic v1

This commit is contained in:
zomseffen 2020-11-08 10:20:23 +01:00
parent 5168061d1b
commit 41761b7b56
16 changed files with 1025 additions and 212 deletions

386
Client/Client.py Normal file
View 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
View file

View 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 Objects.Identifiable import Identifiable
class Light:
class Light(Identifiable):
programId = {}
depthshaderId = -1
def getDepthProgram(self, vertexshader=-1, geometryshader=-1):
if ((
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)]
pass
def __init__(self):
super(Light, self).__init__()
self._ModelviewProjectionMatrix = np.identity(4)
self._pos = [0, 0, 0]
self._lightColor = [1, 1, 1]
@ -71,36 +43,7 @@ class Light:
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
pass
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)
pass

View file

@ -3,4 +3,95 @@ from OpenGL.GL import *
from MatrixStuff.Transformations import *
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)

View file

@ -3,7 +3,7 @@ import numpy as np
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])
f = F / math.sqrt(np.sum(np.square(F)))
UP = UP / math.sqrt(np.sum(np.square(UP)))

View file

@ -6,7 +6,6 @@ import numpy as np
class Cube(Object):
def __init__(self):
super(Cube, self).__init__()
if (Cube.GeometryShaderId == -1):

15
Objects/Identifiable.py Normal file
View 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
View 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

View file

@ -11,31 +11,13 @@ import numpy as np
from OpenGL.extensions import alternate
from Objects.Objects import Object
from MatrixStuff.Transformations import translate
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
from Objects.Renderable import Renderable
class Structure(Renderable):
def __init__(self):
self.Objects = {}
self.vais = {}
self.Matrix = np.identity(4, np.float32)
self.dirty = False
def addShape(self, program, shape):
@ -65,6 +47,7 @@ class Structure(Renderable):
tpbi = GLuint(0)
tcbi = GLuint(0)
tsbi = GLuint(0)
num = len(objects)
glGenVertexArrays(1, tvai)
glBindVertexArray(tvai)
@ -81,7 +64,7 @@ class Structure(Renderable):
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)
check_error("Could not create position buffer")
self.check_error("Could not create position buffer")
colors = []
for o in objects:
@ -95,7 +78,7 @@ class Structure(Renderable):
if vc != -1:
glEnableVertexAttribArray(vc)
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'):
sizes = []
@ -110,36 +93,38 @@ class Structure(Renderable):
if vs != -1:
glEnableVertexAttribArray(vs)
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)
self.vais[key] = (tvai, tpbi, tcbi, tsbi)
self.vais[key] = (tvai, tpbi, tcbi, tsbi, num)
self.dirty = False
def clearVertexArrays(self):
for key, (a, p, c, s) in self.vais.items():
if p != -1:
glDisableVertexAttribArray(p)
glDeleteBuffers(1, [p])
if c != -1:
glDisableVertexAttribArray(c)
glDeleteBuffers(1, [c])
if s != -1 and s != GLuint(-1):
glDisableVertexAttribArray(s)
glDeleteBuffers(1, [s])
glDeleteVertexArrays(1, a)
check_error("Could not destroy vertex array")
temp = dict(self.vais)
self.vais = {}
for key, vertex_array_ids in temp.items():
if vertex_array_ids[1] != -1 and vertex_array_ids[1] != GLuint(-1):
glDeleteBuffers(1, [vertex_array_ids[1]])
self.check_error("Could not destroy buffer")
if vertex_array_ids[2] != -1 and vertex_array_ids[2] != GLuint(-1):
glDeleteBuffers(1, [vertex_array_ids[2]])
self.check_error("Could not destroy buffer")
if vertex_array_ids[3] != -1 and vertex_array_ids[3] != GLuint(-1):
glDeleteBuffers(1, [vertex_array_ids[3]])
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):
for key, tupel in self.vais.items():
self.buildvertexArrays()
for key, vertex_array_ids in self.vais.items():
if alternateprograms == None:
program_id = key
else:
assert key in alternateprograms
program_id = alternateprograms[key]
glUseProgram(program_id)
check_error("Renderingprogram is not initialized!")
self.check_error("Renderingprogram is not initialized!")
projection = glGetUniformLocation(program_id, 'projModelViewMatrix')
rot = glGetUniformLocation(program_id, 'rotMatrix')
@ -147,9 +132,9 @@ class Structure(Renderable):
glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix))
glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix))
glBindVertexArray(tupel[0])
glDrawArrays(GL_POINTS, 0, len(self.Objects[key]))
check_error("Rendering problem")
glBindVertexArray(vertex_array_ids[0])
glDrawArrays(GL_POINTS, 0, vertex_array_ids[4])
self.check_error("Rendering problem")
glBindVertexArray(0)
glUseProgram(0)
@ -171,83 +156,10 @@ class CompoundStructure(Renderable):
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
for (structure, M, R) in self.Structures:
structure.buildvertexArrays()
structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms)
def __eq__(self, other):
if type(other) is type(self):
return self.Structures == other.Structures
else:
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)
return False

363
Objects/World.py Normal file
View 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

View 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
View file

@ -0,0 +1,3 @@
{
"render_light_distance": 100
}

View file

@ -21,7 +21,7 @@ const float diffuseFactor = 0.5;
const float specFactor = 1.0;
const float shininess = 16.0;
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;
bool isVisible(int i, vec2 offs, float lambertian)
@ -44,17 +44,25 @@ void main()
vec3 halfDir = normalize(lightDir + viewDir);
float specAngle = max(dot(halfDir, normalize(normal)), 0.0);
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;
int count = 0;
vec2 texelSize = 1.0 / textureSize(ShadowMaps[i], 0);
for(int x = -2; x <= 2; x++){
for(int y = -2; y <= 2; y++){
vec2 offs = vec2(x, y) * texelSize;
visible += float(int(isVisible(i, offs, lambertian))) * 1.0/25.0;
}
// Grid sampling
// for(int x = -2; x <= 2; x++){
// 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);
visible = float(condition) * 1.0 + float(!condition) * visible;

48
main.py
View file

@ -1,24 +1,13 @@
import random
import sys
from WorldProvider.WorldProvider import WorldProvider
print('64' if sys.maxsize > 2 ** 32 else '32')
from wsgiref.validate import check_errors
from OpenGL.GL.ARB.vertex_array_object import glDeleteVertexArrays
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 Objects.Cube.Cube import Cube
from Objects.Cuboid.Cuboid import Cuboid
from Objects.Structure import Structure, CompoundStructure
from Lights.Spotlight.Spotlight import Spotlight
from Lights.LightingManager import *
import numpy as np
@ -38,6 +27,8 @@ height = 1080
opening = 45
l = Spotlight()
wp = None
def main():
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(0, 1, 0)).setColor(0, 0, 1))
for x_pos in range(-10, 10, 1):
for y_pos in range(-10, 10):
for x_pos in range(0, 10, 1):
for y_pos in range(0, 10):
z = random.random() * 2 - 1
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
))
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()
@ -320,9 +319,10 @@ ry = 0
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)
wp.world.render(translate(x, y, z) * rotate(0, ry, 0, True) * projMatrix, rotate(rx, 0, 0), alternateprograms)
'''
glUseProgram(program_id)
check_error("Renderingprogram is not initialized!")
@ -365,7 +365,7 @@ def display():
global projMatrix
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),
0.01, 100.0)
@ -380,8 +380,8 @@ def display():
farid = glGetUniformLocation(program3_id, 'far')
glUniform1f(nearid, 0.01)
glUniform1f(farid, 100)
glUniform1f(widthid, width)
glUniform1f(heightid, height)
glUniform1f(widthid, l.map_size)
glUniform1f(heightid, l.map_size)
altPrId = {}
altPrId[program_id] = program3_id
@ -418,7 +418,7 @@ def display():
glUniform1iv(texID, 1, 0)
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),
# np.array([1, 1, 0], dtype=np.float32), program_id)

6
tests/test_Client.py Normal file
View 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
View 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)