def draw_models(self, batch: Batch, layer: OrderedGroup, models: List[Model], color: Color) -> Batch: """ Draw the models. :param batch: The batch which the vertices are written to for batch processing. :param layer: The layer to associate the batch rendered to, which defines the order of rendering. :param models: The list of models to render. :param color: The color in which to render the models. :returns batch: """ number_of_sides = len(models[0].coordinates) // 2 coordinates = [ coord for model in models for coord in model.coordinates ] coordinate_count = len(models) * number_of_sides indices = range(coordinate_count) # Determine the GL model to use based upon the number of sides. if number_of_sides == 3: mode = GL_TRIANGLES elif number_of_sides == 4: mode = GL_QUADS else: raise NotImplementedError colors = ('c3B', color * coordinate_count) batch.add_indexed(coordinate_count, mode, layer, indices, ('v2f', coordinates), colors) return batch
def draw_board(self, batch: Batch) -> Batch: """ Draw the game board (in a single batch). """ delta = (self.box_size // 2) - 1 offset = self.box_size def construct_cell(x: int, y: int): """ Returns the coordinates of a box centered at (x, y). """ x, y = (x + 1) * offset, (y + 1) * offset return ( x + delta, y + delta, x, y + delta, x, y, x + delta, y, ) # Construct all the cells in one batch. cell_coords = [ coord for x_index, y_index in self.board.alive for coord in construct_cell(x_index, y_index) ] cell_count = len(cell_coords) // 2 indices = range(cell_count) batch.add_indexed(cell_count, GL_QUADS, None, indices, ('v2i', cell_coords)) return batch
class Mesh(GameObject): def __init__(self, vertices=[], indices=[], normals=[], group=None, **args): self.vertices = [x for x in vertices] self.indices = [x for x in indices] self.normals = [x for x in normals] self.vertex_list = None self.batch = Batch() self.group = group super(Mesh, self).__init__(**args) self.update_mesh() def update_mesh(self): if self.vertex_list: self.vertex_list.delete() self.vertex_list = self.batch.add_indexed( len(self.vertices) // 3, GL_TRIANGLES, self.group, self.indices, ('v3f/static', self.vertices), ('n3f/static', self.normals)) def __del__(self): if self.vertex_list is not None: self.vertex_list.delete() def onDraw(self): super(Mesh, self).onDraw() self.batch.draw()
class World: def __init__(self): self.current_lists = {} self.old_lists = {} self.zone_size = 30.0 self.patch_size = 0.5 self.zone_x = None self.zone_z = None self.terrain_batch = Batch() self.sea_batch = Batch() self.tree_batch = Batch() def gen_terrain(self, mutex, x, z): zone_size = self.zone_size patch_size = self.patch_size w = zone_size / patch_size + 1 assert w == int(w) w = int(w) xmin = (x - 0.5) * zone_size xmax = (x + 0.5) * zone_size zmin = (z - 0.5) * zone_size zmax = (z + 0.5) * zone_size v = [] v_sea = [] n = [] c = [] t = [] for i in np.linspace(xmin, xmax, w): time.sleep(0.2) for j in np.linspace(zmin, zmax, w): y = self.get_v(i, j) vv = [i, y, j] vv_sea = [i, 0.0, j] nn = self.get_n(i, j) v += vv v_sea += vv_sea n += nn if y > 10.0: c += [255, 255, 255] elif y > 7.0: c += [255, 120, 0] elif y > 1.0: c += [0, 255, 0] if random.random() > 0.5: t.append([i, y, j]) elif y > 0.0: c += [255, 255, 150] else: c += [0, 0, 255] index = [] for i in range(0, w-1): for j in range(0, w-1): index += [ i + j * w, i + j * w + 1, i + j * w + 1 + w, i + j * w + w] data = [index, v, n, c, v_sea, t] mutex.acquire() self.current_lists[(x, z)] = data mutex.release() #np.savez('save/{0}_{1}.npz'.format(x,z), data) def draw(self): self.terrain_batch.draw() self.sea_batch.draw() self.tree_batch.draw() def zone_lists_changed(self): tmp_lists = self.current_lists.copy() if tmp_lists != self.old_lists: self.old_lists = self.current_lists.copy() return True return False def zone_changed(self): size = self.zone_size player_x = int(np.floor(self.player.position[0] / size + 0.5)) player_z = int(np.floor(self.player.position[2] / size + 0.5)) return (player_x != self.zone_x or player_z != self.zone_z) def draw_terrain(self, l, w2): vlist = self.terrain_batch.add_indexed( w2, GL_QUADS, None, l[0], ('v3f/static', l[1]), ('n3f/static', l[2]), ('c3B/static', l[3])) def draw_sea(self, l, w2): n = [0, 0, 255] * w2 vlist = self.sea_batch.add_indexed( w2, GL_QUADS, None, l[0], ('v3f/static', l[4]), ('n3f/static', n), ('c3B/static', l[3])) def draw_tree(self, l, w2): for [x, y, z] in l[5]: self.add_tree(self.tree_batch, x, y, z) def draw_sea_simple(self): tmp_lists = self.current_lists.copy() v = [minx, 0, minz, minx, 0, maxz, maxx, 0, maxz, maxx, 0, minz] n = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0] c = [0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255] self.sea_batch = Batch() self.sea_batch.add(4, GL_QUADS, None, ('v3f/static', v), ('n3f/static', n), ('c3B/static', c)) def update_batch(self): self.terrain_batch = Batch() self.sea_batch = Batch() self.tree_batch = Batch() tmp_lists = self.current_lists.copy() for i in tmp_lists: l = tmp_lists[i] w2 = len(l[1]) / 3 self.draw_sea(l, w2) self.draw_terrain(l, w2) self.draw_tree(l, w2) def update_zone_lists(self): size = self.zone_size player_x = int(np.floor(self.player.position[0] / size + 0.5)) player_z = int(np.floor(self.player.position[2] / size + 0.5)) new_set = set() for i in range(player_x - 1, player_x + 2): for j in range(player_z - 1, player_z + 2): new_set.add((i, j)) to_be_deleted = set() for i in self.current_lists: if i not in new_set: to_be_deleted.add(i) mutex = threading.Lock() for i in new_set: if i not in self.current_lists: x, z = i print 'Generating:', i threading.Thread( target=self.gen_terrain, args=(mutex, x, z)).start() for i in to_be_deleted: self.current_lists.pop(i) self.zone_x = player_x self.zone_z = player_z def update(self, dt): if self.zone_lists_changed(): self.update_batch() if self.zone_changed(): self.update_zone_lists() return def get_v(self, x, z): ratio = 0.01 ratio2 = 50.0 #return 0.0 return pnoise2(x*ratio, z*ratio, 5, persistence=0.5)*ratio2 def get_n(self, x, z): d = self.patch_size / 50.0 dydx = (self.get_v(x+d, z) - self.get_v(x-d, z)) / (2 * d) dydz = (self.get_v(x, z+d) - self.get_v(x, z-d)) / (2 * d) n = -np.cross([1.0, dydx, 0.0], [0.0, dydz, 1.0]) return list(n) def add_tree(self, batch, x, y, z): batch.add( 6, GL_TRIANGLES, None, ('v3f/static', ( -0.2+x, y, 0.0+z, 0.0+x, y+0.4, 0.0+z, 0.2+x, y, 0.0+z, 0.0+x, y, -0.2+z, 0.0+x, y+0.4, 0.0+z, 0.0+x, y, 0.2+z,)), ('c3B/static', ( 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0,)), ('n3f/static', ( 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,)))