Beispiel #1
0
	def init_skylight(self, pending_chunk):
		""" Initializes the skylight of each chunks
		To avoid unsufferable lag from propagating from the top of the chunks when
		most of the heights would be air, it instead runs a simple algorithm
		to check where the highest point of the chunk is and propagates skylight from
		this height"""

		chunk_pos = pending_chunk.chunk_position

		# Retrieve the highest chunk point
		height = 0
		for lx in range(chunk.CHUNK_WIDTH):
			for lz in range(chunk.CHUNK_LENGTH):
				for ly in range(chunk.CHUNK_HEIGHT-1, -1, -1):
					if pending_chunk.blocks[lx][ly][lz]:
						break
				if ly > height:
					height = ly

		# Initialize skylight to 15 until that point and then queue a skylight propagation increase
		for lx in range(chunk.CHUNK_WIDTH):
			for lz in range(chunk.CHUNK_LENGTH):
				for ly in range(chunk.CHUNK_HEIGHT - 1, height, -1):
					pending_chunk.set_sky_light(glm.ivec3(lx, ly, lz), 15)

				pos = glm.ivec3(chunk.CHUNK_WIDTH * chunk_pos[0] + lx,
						ly,
						chunk.CHUNK_LENGTH * chunk_pos[2] + lz
				)
				self.skylight_increase_queue.append((pos, 15))

		self.propagate_skylight_increase(False)
Beispiel #2
0
 def block_pos_to_id(cls, pos: glm.ivec3) -> int:
     pos = glm.ivec3(pos)
     assert (all(abs(pos) < glm.ivec3(0x800)))
     u64 = lambda x: x & 0xffff_ffff_ffff_ffff
     s64 = lambda x: (x & 0x7fff_ffff_ffff_ffff) - (x &
                                                    0x8000_0000_0000_0000)
     return s64(
       u64(pos.z) * 0x1_000_000 + \
       u64(pos.y) * 0x1_000 + \
       u64(pos.x)
       )
Beispiel #3
0
	def check_in_frustum(self, chunk_pos):
		"""Frustum check of each chunk. If the chunk is not in the view frustum, it is discarded"""
		planes = (Frustum.left, Frustum.right, Frustum.bottom, Frustum.top, Frustum.near, Frustum.far)
		result = 2
		center = glm.vec3(chunk_pos * glm.ivec3(chunk.CHUNK_WIDTH, 0, chunk.CHUNK_LENGTH)
									+ glm.ivec3(chunk.CHUNK_WIDTH / 2, 
												chunk.CHUNK_HEIGHT / 2,
												chunk.CHUNK_LENGTH / 2))


		for plane in planes:
			_in = 0
			_out = 0
			normal = plane.xyz
			w = plane.w
			if glm.dot(normal, center + glm.vec3(chunk.CHUNK_WIDTH / 2, chunk.CHUNK_HEIGHT / 2, chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(-chunk.CHUNK_WIDTH / 2, chunk.CHUNK_HEIGHT / 2, chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(chunk.CHUNK_WIDTH / 2, chunk.CHUNK_HEIGHT / 2, -chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(-chunk.CHUNK_WIDTH / 2, chunk.CHUNK_HEIGHT / 2, -chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(chunk.CHUNK_WIDTH / 2, -chunk.CHUNK_HEIGHT / 2, chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(-chunk.CHUNK_WIDTH / 2, -chunk.CHUNK_HEIGHT / 2, chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(chunk.CHUNK_WIDTH / 2, -chunk.CHUNK_HEIGHT / 2, -chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			if glm.dot(normal, center + glm.vec3(-chunk.CHUNK_WIDTH / 2, -chunk.CHUNK_HEIGHT / 2, -chunk.CHUNK_LENGTH / 2)) + w < 0:
				_out += 1
			else:
				_in += 1
			
			if not _in:
				return 0
			elif _out:
				result = 1
		return result
Beispiel #4
0
def get_local_position(position):
	x, y, z = position
	
	return glm.ivec3(
		int(x % chunk.CHUNK_WIDTH),
		int(y % chunk.CHUNK_HEIGHT),
		int(z % chunk.CHUNK_LENGTH))
Beispiel #5
0
def get_chunk_position(position):
	x, y, z = position

	return glm.ivec3(
		(x // chunk.CHUNK_WIDTH),
		(y // chunk.CHUNK_HEIGHT),
		(z // chunk.CHUNK_LENGTH))
Beispiel #6
0
    def load(self):
        logging.info("Loading world")

        # for x in range(-1, 15):
        # 	for y in range(-15, 1):
        # 		self.load_chunk((x, y))

        for x in range(-4, 4):
            for y in range(-4, 4):
                self.load_chunk((x, 0, y))

        #for x in range(-1, 1):
        #	for y in range(-1, 1):
        #		self.load_chunk((x, 0, y))

        for chunk_position, unlit_chunk in self.world.chunks.items():
            for x in range(chunk.CHUNK_WIDTH):
                for y in range(chunk.CHUNK_HEIGHT):
                    for z in range(chunk.CHUNK_LENGTH):
                        if unlit_chunk.blocks[x][y][
                                z] in self.world.light_blocks:
                            world_pos = glm.ivec3(
                                chunk_position[0] * chunk.CHUNK_WIDTH + x,
                                chunk_position[1] * chunk.CHUNK_HEIGHT + y,
                                chunk_position[2] * chunk.CHUNK_LENGTH + z)
                            self.world.increase_light(world_pos, 15, False)
Beispiel #7
0
 def block_id_to_pos(cls, id: int) -> glm.ivec3:
     unsigned_to_signed = lambda x: x if x < 0x800 else x - 0x1000
     i = id
     x = unsigned_to_signed(i % 0x1000)
     j = (i - x) // 0x1000
     y = unsigned_to_signed(j % 0x1000)
     k = (j - y) // 0x1000
     z = unsigned_to_signed(k % 0x1000)
     return glm.ivec3(x, y, z)
Beispiel #8
0
    def __init__(self, gl, width, height, volume_res):
        super(Context, self).__init__()
        self.gl = gl
        self._vaos = []

        self.u_res = glm.ivec2(width, height)
        self.u_vsize = glm.ivec3(volume_res)
        self.gx, self.gy, self.gz = (
            int(self.u_vsize.x / 4),
            int(self.u_vsize.y / 4),
            int(self.u_vsize.z / 4),
        )
Beispiel #9
0
	def update_mesh(self):
		self.mesh = []
		self.translucent_mesh = []

		for local_x in range(SUBCHUNK_WIDTH):
			for local_y in range(SUBCHUNK_HEIGHT):
				for local_z in range(SUBCHUNK_LENGTH):
					parent_lx = self.local_position[0] + local_x
					parent_ly = self.local_position[1] + local_y
					parent_lz = self.local_position[2] + local_z

					block_number = self.parent.blocks[parent_lx][parent_ly][parent_lz]

					parent_lpos = glm.ivec3(parent_lx, parent_ly, parent_lz)

					if block_number:
						block_type = self.world.block_types[block_number]

						x, y, z = pos = glm.ivec3(
							self.position[0] + local_x,
							self.position[1] + local_y,
							self.position[2] + local_z)
						

						# if block is cube, we want it to check neighbouring blocks so that we don't uselessly render faces
						# if block isn't a cube, we just want to render all faces, regardless of neighbouring blocks
						# since the vast majority of blocks are probably anyway going to be cubes, this won't impact performance all that much; the amount of useless faces drawn is going to be minimal

						if block_type.is_cube:
							for face, direction in enumerate(DIRECTIONS):
								npos = pos + direction
								if self.can_render_face(block_type, block_number, npos):
									self.add_face(face, pos, parent_lpos, block_number, block_type, npos)
														
						else:
							for i in range(len(block_type.vertex_positions)):
								self.add_face(i, pos, parent_lpos, block_number, block_type)
Beispiel #10
0
    def load_chunk(self, chunk_position):
        logging.debug(f"Loading chunk at position {chunk_position}")
        # load the chunk file

        chunk_path = self.chunk_position_to_path(chunk_position)

        try:
            chunk_blocks = nbt.load(chunk_path)["Level"]["Blocks"]

        except FileNotFoundError:
            return

        # create chunk and fill it with the blocks from our chunk file

        self.world.chunks[glm.ivec3(chunk_position)] = chunk.Chunk(
            self.world, glm.ivec3(chunk_position))

        for x in range(chunk.CHUNK_WIDTH):
            for y in range(chunk.CHUNK_HEIGHT):
                for z in range(chunk.CHUNK_LENGTH):
                    self.world.chunks[glm.ivec3(
                        chunk_position)].blocks[x][y][z] = chunk_blocks[
                            x * chunk.CHUNK_LENGTH * chunk.CHUNK_HEIGHT +
                            z * chunk.CHUNK_HEIGHT + y]
Beispiel #11
0
    def init(self):
        gl = self.gl

        WHD = glm.ivec3(self.u_vsize)
        self.volume_0 = gl.buffer(reserve=WHD.x * WHD.y * WHD.z * 4)

        self.vbo = gl.buffer(
            np.array([-1.0, -1.0, -1.0, +1.0, +1.0, -1.0, +1.0, +1.0])
            .astype(np.float32)
            .tobytes()
        )
        self.ibo = gl.buffer(np.array([0, 1, 2, 2, 1, 3]).astype(np.int32).tobytes())

        self.recompile()

        recompile_handler = FileSystemEventHandler()
        recompile_handler.on_modified = self.on_src_modified
        self.src_observer = Observer()
        self.src_observer.schedule(recompile_handler, "./gl")
        self.src_observer.start()
Beispiel #12
0
	def set_block(self, position, number): # set number to 0 (air) to remove block
		x, y, z = position
		chunk_position = get_chunk_position(position)

		if not chunk_position in self.chunks: # if no chunks exist at this position, create a new one
			if number == 0:
				return # no point in creating a whole new chunk if we're not gonna be adding anything

			self.create_chunk(chunk_position)

		
		if self.get_block_number(position) == number: # no point updating mesh if the block is the same
			return
		
		lx, ly, lz = get_local_position(position)

		self.chunks[chunk_position].blocks[lx][ly][lz] = number
		self.chunks[chunk_position].modified = True

		self.chunks[chunk_position].update_at_position((x, y, z))

		if number:
			if number in self.light_blocks:
				self.increase_light(position, 15)

			elif self.block_types[number].transparent != 2:
				self.decrease_light(position)
				self.decrease_skylight(position)
		
		elif not number:
			self.decrease_light(position)
			self.decrease_skylight(position)

		cx, cy, cz = chunk_position

		def try_update_chunk_at_position(chunk_position, position):
			if chunk_position in self.chunks:
				self.chunks[chunk_position].update_at_position(position)
		
		if lx == chunk.CHUNK_WIDTH - 1: try_update_chunk_at_position(glm.ivec3(cx + 1, cy, cz), (x + 1, y, z))
		if lx == 0: try_update_chunk_at_position(glm.ivec3(cx - 1, cy, cz), (x - 1, y, z))

		if ly == chunk.CHUNK_HEIGHT - 1: try_update_chunk_at_position(glm.ivec3(cx, cy + 1, cz), (x, y + 1, z))
		if ly == 0: try_update_chunk_at_position(glm.ivec3(cx, cy - 1, cz), (x, y - 1, z))

		if lz == chunk.CHUNK_LENGTH - 1: try_update_chunk_at_position(glm.ivec3(cx, cy, cz + 1), (x, y, z + 1))
		if lz == 0: try_update_chunk_at_position(glm.ivec3(cx, cy, cz - 1), (x, y, z - 1))
    def __init__(self, width, height):
        global m_vao
        global m_vbo

        i = 0
        j = 0

        load_shaders()

        initial_positions = [glm.vec4() for _ in range(POINTS_TOTAL)]
        initial_velocities = [glm.vec3() for _ in range(POINTS_TOTAL)]
        connection_vectors = [glm.ivec3() for _ in range(POINTS_TOTAL)]

        n = 0
        for j in range(0, POINTS_Y):
            fj = float(j) / float(POINTS_Y)

            for i in range(0, POINTS_X):

                fi = float(i) / float(POINTS_X)

                initial_positions[n] = glm.vec4((fi - 0.5) * float(POINTS_X),
                                                (fj - 0.5) * float(POINTS_Y),
                                                0.6 * sin(fi) * cos(fj), 1.0)
                initial_velocities[n] = glm.vec3(0.0)
                connection_vectors[n] = glm.ivec4(-1)

                if (j != (POINTS_Y - 1)):

                    if (i != 0):
                        connection_vectors[n][0] = n - 1

                    if (j != 0):
                        connection_vectors[n][1] = n - POINTS_X

                    if (i != (POINTS_X - 1)):
                        connection_vectors[n][2] = n + 1

                    if (j != (POINTS_Y - 1)):
                        connection_vectors[n][3] = n + POINTS_X
                n += 1

        for i in range(0, 2):
            glGenVertexArrays(1, m_vao[i])

        for i in range(0, 5):
            glGenBuffers(i + 1, m_vbo[i])

        for i in range(0, 2):

            glBindVertexArray(m_vao[i])

            glBindBuffer(GL_ARRAY_BUFFER, m_vbo[POSITION_A + i])

            # POSITION_A
            glBindBuffer(GL_ARRAY_BUFFER, m_vbo[POSITION_A + i])

            ar_position = np.empty([POINTS_TOTAL, 4], dtype='float32')
            for j, e in enumerate(initial_positions):
                ar_position[j] = e

            glBufferData(GL_ARRAY_BUFFER,
                         POINTS_TOTAL * glm.sizeof(glm.vec4()), ar_position,
                         GL_DYNAMIC_COPY)
            glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, None)
            glEnableVertexAttribArray(0)

            # VELOCITY_A
            glBindBuffer(GL_ARRAY_BUFFER, m_vbo[VELOCITY_A + i])

            ar_velocities = np.empty([POINTS_TOTAL, 3], dtype='float32')
            for j, e in enumerate(initial_velocities):
                ar_velocities[j] = e

            glBufferData(GL_ARRAY_BUFFER,
                         POINTS_TOTAL * glm.sizeof(glm.vec3()), ar_velocities,
                         GL_DYNAMIC_COPY)
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, None)
            glEnableVertexAttribArray(1)

            # CONNECTION
            glBindBuffer(GL_ARRAY_BUFFER, m_vbo[CONNECTION])

            ar_connection = np.empty([POINTS_TOTAL, 4], dtype='uint32')
            for j, e in enumerate(connection_vectors):
                ar_connection[j] = e

            glBufferData(GL_ARRAY_BUFFER,
                         POINTS_TOTAL * glm.sizeof(glm.ivec4()), ar_connection,
                         GL_STATIC_DRAW)
            glVertexAttribIPointer(2, 4, GL_INT, 0, None)
            glEnableVertexAttribArray(2)

        glGenTextures(2, m_pos_tbo)
        glBindTexture(GL_TEXTURE_BUFFER, m_pos_tbo[0])
        glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_vbo[POSITION_A])
        glBindTexture(GL_TEXTURE_BUFFER, m_pos_tbo[1])
        glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_vbo[POSITION_B])

        lines = (POINTS_X - 1) * POINTS_Y + (POINTS_Y - 1) * POINTS_X

        glGenBuffers(1, m_index_buffer)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     lines * 2 * ctypes.sizeof(ctypes.c_int), None,
                     GL_STATIC_DRAW)

        e = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0,
                             lines * 2 * ctypes.sizeof(ctypes.c_int),
                             GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)

        int_array = (ctypes.c_int * (4 * lines * 2)).from_address(e)
        n = 0
        for j in range(0, POINTS_Y):
            for i in range(0, POINTS_X - 1):
                int_array[n] = i + j * POINTS_X
                n += 1

                int_array[n] = 1 + i + j * POINTS_X
                n += 1

        for i in range(0, POINTS_X):

            for j in range(0, POINTS_Y - 1):
                int_array[n] = i + j * POINTS_X
                n += 1

                int_array[n] = POINTS_X + i + j * POINTS_X
                n += 1

        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)
    def intersect(self, ray_origin, ray_direction):

        size = glm.ivec3(*self.size)
        abs_d = glm.abs(ray_direction)
        max_d = max(abs_d.x, max(abs_d.y, abs_d.z))
        dir = ray_direction / max_d / glm.vec3(size)
        origin = ray_origin * glm.vec3(size)

        map = glm.ivec3(origin + 1) - 1
        side = 0
        stepAmount = glm.ivec3(0)
        tDelta = abs(1.0 / dir)
        tMax = glm.vec3(0)
        voxel = 0

        if dir.x < 0:
            stepAmount.x = -1
            tMax.x = (origin.x - map.x) * tDelta.x
        elif dir.x > 0:
            stepAmount.x = 1
            tMax.x = (map.x + 1 - origin.x) * tDelta.x
        else:
            stepAmount.x = 0
            tMax.x = 0

        if dir.y < 0:
            stepAmount.y = -1
            tMax.y = (origin.y - map.y) * tDelta.y
        elif dir.y > 0:
            stepAmount.y = 1
            tMax.y = (map.y + 1 - origin.y) * tDelta.y
        else:
            stepAmount.y = 0
            tMax.y = 0

        if dir.z < 0:
            stepAmount.z = -1
            tMax.z = (origin.z - map.z) * tDelta.z
        elif dir.z > 0:
            stepAmount.z = 1
            tMax.z = (map.z + 1.0 - origin.z) * tDelta.z
        else:
            stepAmount.z = 0
            tMax.z = 0

        while True:
            if tMax.x < tMax.y:
                if tMax.x < tMax.z:
                    map.x += stepAmount.x
                    if (stepAmount.x > 0
                            and map.x >= size.x) or (stepAmount.x < 0
                                                     and map.x < 0):
                        return (False, map, side)
                    tMax.x += tDelta.x
                    side = 0
                else:
                    map.z += stepAmount.z
                    if (stepAmount.z > 0
                            and map.z >= size.z) or (stepAmount.z < 0
                                                     and map.z < 0):
                        return (False, map, side)
                    tMax.z += tDelta.z
                    side = 2
            else:
                if tMax.y < tMax.z:
                    map.y += stepAmount.y
                    if (stepAmount.y > 0
                            and map.y >= size.y) or (stepAmount.y < 0
                                                     and map.y < 0):
                        return (False, map, side)
                    tMax.y += tDelta.y
                    side = 1
                else:
                    map.z += stepAmount.z
                    if (stepAmount.z > 0
                            and map.z >= size.z) or (stepAmount.z < 0
                                                     and map.z < 0):
                        return (False, map, side)
                    tMax.z += tDelta.z
                    side = 2
            voxel = self.lookup(map)
            if voxel != 0:
                break
        return (True, map, side)
Beispiel #15
0
 def value(self):
     v = b'\x00' * 12
     native.n_svivec3_value(self.m_cptr, ffi.from_buffer('int[]', v))
     return glm.ivec3(struct.unpack('3i', v))
Beispiel #16
0
def main():

    global delta_time, last_frame

    fps_list = []
    test_world = world_gen.world('__DELETEME__', '-o')
    window = utilities.window()
    camera.setup_window(window)
    ctx = mgl.create_context()

    window.bind_context(ctx)
    ctx.enable(mgl.DEPTH_TEST | mgl.BLEND)
    ctx.blend_func = mgl.SRC_ALPHA, mgl.ONE_MINUS_SRC_ALPHA

    scene = ctx.program(vertex_shader=vertex_source_3d,
                        fragment_shader=fragment_source_3d,
                        geometry_shader=geometry_source_3d,
                        varyings=("texture_coord", "texture_layer"))
    hud = ctx.program(vertex_shader=vertex_source_GUI,
                      fragment_shader=fragment_source_GUI)
    sky = ctx.program(vertex_shader=vertex_source_sky,
                      fragment_shader=fragment_source_sky)

    sky_data = np.array(
        [  # Sky
            -1.0, 1.0, 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0
        ],
        dtype='float32')

    sky_vbo = ctx.buffer(sky_data)
    sky_vao = ctx.vertex_array(sky, sky_vbo, "aPos")

    crosshair = np.array([0, 0, 0], dtype='float32')  # Crosshair

    vbo_2d = ctx.buffer(crosshair)
    vao_2d = ctx.vertex_array(hud, vbo_2d, "aPos")

    crosshair_file = Image.open(texturepath / "icons.png").crop((0, 0, 16, 16))
    crosshair_texture = ctx.texture((16, 16), 4, crosshair_file.tobytes())
    crosshair_texture.filter = (mgl.NEAREST, mgl.NEAREST)

    camera_direction = glm.vec3()
    second_counter = 0
    frame_counter = 0

    all_textures, layers = render.load_all_block_textures(
        blocktexturepath, ctx)
    all_models = model.load_all(rootpath)

    world_render = render.render(layers, all_models, all_textures, scene, ctx)
    all_chunks = test_world.return_all_chunks()
    chunk_arrays = world_render.create_buffers_from_chunks(all_chunks)

    while not window.check_if_closed():

        current_frame = glfw.get_time()
        delta_time = current_frame - last_frame
        last_frame = current_frame
        second_counter += delta_time
        frame_counter += 1

        window.refresh(0, ctx)

        sky['orientation'] = glm.radians(camera.pitch)
        ctx.disable(mgl.DEPTH_TEST)
        sky_vao.render(mode=mgl.TRIANGLE_STRIP)

        camera.process_input(window, delta_time)
        camera.testing_commands(window)

        pos, looking, up = camera.return_vectors()
        view = glm.lookAt(pos, looking, up)
        projection = glm.perspective(glm.radians(45),
                                     window.size[0] / window.size[1], 0.1, 256)
        scene['view'].write(view)
        scene['projection'].write(projection)
        scene['texture0'] = 0
        all_textures.use(location=0)

        if glfw.get_key(window.window, glfw.KEY_U) == glfw.PRESS:
            test_world.set_block(tuple(glm.ivec3(pos)), 3, world_render)
        ctx.enable(mgl.DEPTH_TEST)
        world_render.draw_from_chunks(chunk_arrays)

        hud['texture0'] = 0
        crosshair_texture.use(location=0)
        vao_2d.render(mode=mgl.POINTS)

        if second_counter >= 1:
            fps_list.append(frame_counter)
            second_counter, frame_counter = 0, 0
        window.refresh(1, ctx)

    window.close()
    print('\n===== End statistics =====')
    print("Average FPS: {}".format(np.mean(fps_list)))
    print("Render buffer creation: ", world_render.time_required)
    print(test_world.return_time())