Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
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,)))