From 6c5cae958b6d5a7cb609b57c38f69794d731ca33 Mon Sep 17 00:00:00 2001 From: zomseffen Date: Sat, 15 Jan 2022 14:31:19 +0100 Subject: [PATCH] starts plate movement and frame improvements --- Client/Client.py | 46 ++++++++--------- Objects/Renderable.py | 12 +++-- Objects/Structure.py | 75 +++++++++++++++++++++------ Objects/World.py | 117 +++++++++++++++++++++++++++++++++--------- 4 files changed, 182 insertions(+), 68 deletions(-) diff --git a/Client/Client.py b/Client/Client.py index d87efc3..2f6699d 100644 --- a/Client/Client.py +++ b/Client/Client.py @@ -118,28 +118,28 @@ class Client: r, g, b = colors[int(self.world_provider.world.plates[x_pos, y_pos])] self.world_provider.world.set_color(x_pos, y_pos, z_pos, r, g, b) - total_x = self.world_provider.world.chunk_n_x * self.world_provider.world.chunk_size_x - total_y = self.world_provider.world.chunk_n_y * self.world_provider.world.chunk_size_y - for x_pos in range(0, 100): - for y_pos in range(0, 100): - if self.world_provider.world.faults[x_pos, y_pos] == -2: - self.world_provider.world.set_color(x_pos, y_pos, 0, 0, 0, 0) - - for line_index, line in enumerate(self.world_provider.world.fault_lines): - for x_pos in range(0, 100): - for y_pos in range(0, 100): - if self.world_provider.world.faults[x_pos, y_pos] == line_index: - if line_index != 9: - self.world_provider.world.set_color(x_pos, y_pos, 0, 0, 0, 1) - else: - self.world_provider.world.set_color(x_pos, y_pos, 0, 1, 1, 1) - - for x_pos in range(0, 100): - for y_pos in range(0, 100): - for z_pos in range(0, 1): - if [x_pos, y_pos] in self.world_provider.world.fault_nodes: - r, g, b = 1, 0, 0 - self.world_provider.world.set_color(x_pos, y_pos, z_pos, r, g, b) + # total_x = self.world_provider.world.chunk_n_x * self.world_provider.world.chunk_size_x + # total_y = self.world_provider.world.chunk_n_y * self.world_provider.world.chunk_size_y + # for x_pos in range(0, 100): + # for y_pos in range(0, 100): + # if self.world_provider.world.faults[x_pos, y_pos] == -2: + # self.world_provider.world.set_color(x_pos, y_pos, 0, 0, 0, 0) + # + # for line_index, line in enumerate(self.world_provider.world.fault_lines): + # for x_pos in range(0, 100): + # for y_pos in range(0, 100): + # if self.world_provider.world.faults[x_pos, y_pos] == line_index: + # if line_index != 9: + # self.world_provider.world.set_color(x_pos, y_pos, 0, 0, 0, 1) + # else: + # self.world_provider.world.set_color(x_pos, y_pos, 0, 1, 1, 1) + # + # for x_pos in range(0, 100): + # for y_pos in range(0, 100): + # for z_pos in range(0, 1): + # if [x_pos, y_pos] in self.world_provider.world.fault_nodes: + # r, g, b = 1, 0, 0 + # self.world_provider.world.set_color(x_pos, y_pos, z_pos, r, g, b) # # visualize direction lengths # lengths = np.sqrt(np.sum(np.square(self.world_provider.world.directions), axis=2)) @@ -295,7 +295,7 @@ class Client: # int(round(self.test_pixel[1])), # int(round(self.test_pixel[2])), 1.0, 1.0, 1.0) - # print(1.0 / (time.time() - self.time)) + print(1.0 / (time.time() - self.time)) self.time = time.time() glutPostRedisplay() diff --git a/Objects/Renderable.py b/Objects/Renderable.py index a24d804..fa1f9b8 100644 --- a/Objects/Renderable.py +++ b/Objects/Renderable.py @@ -1,8 +1,12 @@ -from OpenGL.GLU import gluErrorString -from OpenGL.GL import glGetError, GL_NO_ERROR +from OpenGL.GLU import * +from OpenGL.GL import * + +import numpy as np + class Renderable: - def render(self, projMatrix, geometryRotMatrix, alternateprograms=None): + def render(self, projMatrix, geometryRotMatrix, alternateprograms=None, + preselected_program=None, projection_pos=None, rot_pos=None): pass @staticmethod @@ -15,4 +19,4 @@ class Renderable: else: print(hex(gl_error)) return True - return False \ No newline at end of file + return False diff --git a/Objects/Structure.py b/Objects/Structure.py index 5b71802..5c49893 100644 --- a/Objects/Structure.py +++ b/Objects/Structure.py @@ -15,10 +15,41 @@ from Objects.Renderable import Renderable class Structure(Renderable): - def __init__(self): + def __init__(self, x_offset=0, y_offset=1, z_offset=0): self.Objects = {} self.vais = {} - self.dirty = False + self.dirty = True + + self.x_offset = x_offset + self.y_offset = y_offset + self.z_offset = z_offset + + @property + def x_offset(self): + return self._x_offset + + @x_offset.setter + def x_offset(self, value): + self.dirty = True + self._x_offset = value + + @property + def y_offset(self): + return self._y_offset + + @y_offset.setter + def y_offset(self, value): + self.dirty = True + self._y_offset = value + + @property + def z_offset(self): + return self._z_offset + + @z_offset.setter + def z_offset(self, value): + self.dirty = True + self._z_offset = value def addShape(self, program, shape): if not program in self.Objects.keys(): @@ -59,9 +90,9 @@ class Structure(Renderable): glBindBuffer(GL_ARRAY_BUFFER, tpbi) positions = [] for o in objects: - positions.append(o.pos[0]) - positions.append(o.pos[1]) - positions.append(o.pos[2]) + positions.append(o.pos[0] + self.x_offset) + positions.append(o.pos[1] + self.y_offset) + positions.append(o.pos[2] + self.z_offset) 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") @@ -115,29 +146,39 @@ class Structure(Renderable): 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, + preselected_program=None, projection_pos=None, rot_pos=None): self.buildvertexArrays() for key, vertex_array_ids in self.vais.items(): if alternateprograms == None: program_id = key else: - assert key in alternateprograms + assert key in alternateprograms.keys() program_id = alternateprograms[key] - glUseProgram(program_id) - self.check_error("Renderingprogram is not initialized!") + # check if a program was preloaded + if preselected_program is not None: + # if preloaded we only want to render the matching vertex arrays + if preselected_program != program_id: + continue + else: + glUseProgram(program_id) + self.check_error("Renderingprogram is not initialized!") - projection = glGetUniformLocation(program_id, 'projModelViewMatrix') - rot = glGetUniformLocation(program_id, 'rotMatrix') + if rot_pos is None: + rot = glGetUniformLocation(program_id, 'rotMatrix') + glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix)) - glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix)) - glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix)) + if projection_pos is None: + projection = glGetUniformLocation(program_id, 'projModelViewMatrix') + glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix)) glBindVertexArray(vertex_array_ids[0]) glDrawArrays(GL_POINTS, 0, vertex_array_ids[4]) self.check_error("Rendering problem") glBindVertexArray(0) - glUseProgram(0) + if preselected_program is None: + glUseProgram(0) def __eq__(self, other): if type(other) is type(self): @@ -154,9 +195,11 @@ class CompoundStructure(Renderable): R: np.matrix = np.identity(3, np.float)): self.Structures.append((structure, M, R)) - def render(self, projMatrix, geometryRotMatrix, alternateprograms=None): + def render(self, projMatrix, geometryRotMatrix, alternateprograms=None, + preselected_program=None, projection_pos=None, rot_pos=None): for (structure, M, R) in self.Structures: - structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms) + structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms, + preselected_program, projection_pos, rot_pos) def __eq__(self, other): if type(other) is type(self): diff --git a/Objects/World.py b/Objects/World.py index e21bdfe..473ccf2 100644 --- a/Objects/World.py +++ b/Objects/World.py @@ -10,6 +10,18 @@ import numpy as np import random import sys +# Plate Types +SEA_PLATE = 0 +CONTINENTAL_PLATE = 1 + +# Rock types +EMPTY = 0 +SEA_PLATE_STONE = 1 +MAGMATIC_STONE = 2 +METAMORPH_STONE = 3 +SEDIMENTAL_STONE = 4 +SEDIMENT = 5 + class WorldChunk(Structure): def __init__(self, width: int, length: int, height: int, programs: dict): assert width > 0, 'Width must be greater than 0' @@ -135,9 +147,9 @@ class WorldChunk(Structure): 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]) + positions.append(o.pos[0] + self.x_offset) + positions.append(o.pos[1] + self.y_offset) + positions.append(o.pos[2] + self.z_offset) 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") @@ -175,11 +187,14 @@ class WorldChunk(Structure): 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) + def render(self, proj_matrix, geometry_rot_matrix, alternate_programs=None, + preselected_program=None, projection_pos=None, rot_pos=None): + super(WorldChunk, self).render(proj_matrix, geometry_rot_matrix, alternate_programs, + preselected_program, projection_pos, rot_pos) for entity in self.entities: - entity.render(proj_matrix, geometry_rot_matrix, alternate_programs) + entity.render(proj_matrix, geometry_rot_matrix, alternate_programs, + preselected_program, projection_pos, rot_pos) 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 @@ -206,6 +221,9 @@ class World(Renderable): self.fault_lines = [] self.plates = None self.directions = None + self.num_plates = 0 + self.stone = None + self.faults = None self.chunks: [[[WorldChunk]]] = [] for x in range(chunk_n_x): @@ -215,7 +233,7 @@ class World(Renderable): for z in range(chunk_n_z): self.chunks[x][y].append(None) - def generate(self, seed=None, sea_height=50, continental_height=200): + def generate(self, seed: int=None, sea_plate_height: int = 50, continental_plate_height: int = 200): if seed is None: seed = random.randrange(2**32) seed = 229805811 @@ -381,12 +399,6 @@ class World(Renderable): item.remove(plate) directions = np.zeros((total_x, total_y, 3)) - heights = np.zeros((total_x, total_y)) - for plate in range(1, plate_num): - if random.randint(1, 2) == 1: - heights[plates == plate] = sea_height - else: - heights[plates == plate] = continental_height coords = np.zeros((total_x, total_y, 2)) for x in range(total_x): @@ -431,11 +443,37 @@ class World(Renderable): directions[plates == plate, :2] += perpendicular * (scalar / abs(scalar)) pass - - + for x in range(total_x): + for y in range(total_y): + if plates[x, y] == -1: + plate = np.max(plates[x - 1: x + 1, y - 1: y + 1]) + plates[x, y] = plate self.plates = plates self.directions = directions + self.num_plates = plate_num + + # max height will be three times the continental height + # sea level will be at one and a half time continental height + # with the continental plates top end ending there + # sea plates will be flush at the bottom end + max_height = 3 * continental_plate_height + sea_level = int(1.5 * continental_plate_height) + lower_level = sea_level - continental_plate_height + upper_sea_plate_level = lower_level + sea_plate_height + + # stone kinds: 0: lava/air, 1: sea_plate, 2: magmatic_continental, 3: metamorph, 4: sedimental_rock, 5: sediment + self.stone = np.zeros((total_x, total_y, max_height), np.int) + plate_to_type = {} + for plate in range(1, plate_num): + if random.randint(1, 2) == 1: + self.stone[plates == plate, lower_level:upper_sea_plate_level] = SEA_PLATE_STONE + plate_to_type[plate] = SEA_PLATE + else: + self.stone[plates == plate, lower_level:sea_level] = MAGMATIC_STONE + plate_to_type[plate] = CONTINENTAL_PLATE + + pass 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) @@ -462,6 +500,9 @@ class World(Renderable): 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].x_offset = chunk_x * self.chunk_size_x + self.chunks[chunk_x][chunk_y][chunk_z].y_offset = chunk_y * self.chunk_size_z + self.chunks[chunk_x][chunk_y][chunk_z].z_offset = chunk_z * self.chunk_size_y carry_overs = self.chunks[chunk_x][chunk_y][chunk_z].put_object(x % self.chunk_size_x, y % self.chunk_size_y, @@ -529,17 +570,38 @@ class World(Renderable): 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 render(self, proj_matrix, geometry_rot_matrix, alternate_programs=None, + preselected_program=None, projection_pos=None, rot_pos=None): + if preselected_program is not 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(proj_matrix, + geometry_rot_matrix, alternate_programs, + preselected_program, projection_pos, rot_pos) + else: + for _, program_id in self.programs.items(): + if alternate_programs == None: + used_program_id = program_id + else: + assert program_id in alternate_programs.keys() + used_program_id = alternate_programs[program_id] + glUseProgram(used_program_id) + self.check_error("Renderingprogram is not initialized!") + projection = glGetUniformLocation(used_program_id, 'projModelViewMatrix') + rot = glGetUniformLocation(used_program_id, 'rotMatrix') + glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometry_rot_matrix)) + glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(proj_matrix)) + 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(proj_matrix, + geometry_rot_matrix, alternate_programs, + used_program_id, projection, rot) - def add_light(self, x: float, y: float, z: float, l: Light): + def add_light(self, x: float, y: float, z: float, l: Light)-> 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) @@ -550,10 +612,15 @@ class World(Renderable): 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].x_offset = chunk_x * self.chunk_size_x + self.chunks[chunk_x][chunk_y][chunk_z].y_offset = chunk_y * self.chunk_size_z + self.chunks[chunk_x][chunk_y][chunk_z].z_offset = chunk_z * self.chunk_size_y self.chunks[chunk_x][chunk_y][chunk_z].lights.append(l) l.pos = [x, y, z] + return l + 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)