######## UPDATE ##############
(BA upload :no:) ->>>
NEW: https://drive.google.com/open?id=0B8kZsmvJJIZlT28zZ1YxLVM3czg
So I got it basically game ready.
Now it is class based, and has proper functions handles to add voxels, remove voxels, bulk fill and optimize.
(example snippets, not actually composition!)
from pixel_meshing import Chunk, floor_to_chunk_key, load_csv_template, generate_chunk_keys
from perlin import Noise
CHUNK_SIZE = 16
MAP_RADIUS = 20
tree_template = load_csv_template('//tree.csv')
logic.spawn_positons = generate_chunk_keys(MAP_RADIUS, CHUNK_SIZE)
logic.tree_positions = logic.spawn_positons[:]
logic.to_update = set()
logic.chunks = {}
# Example: Extend the 'pixel_meshing.Chunk' class to overwrite the initial voxel generation method.
class PerlinChunk(Chunk):
COLORS = [(0,0,0,0),(0,0.41,0.1,1),(0.7,0.5,0.1,1),(0.25,0.1,0.0,1),(0.2,0.45,0,1),]
PERLIN_MAP = Noise(16, 'This string is the world seed')
# overload original fill function
def fill_voxels(self):
""" initial function that fills the chunk with random voxels """
global_x, global_y, global_z = self.position
chunk_size = self.chunk_size
voxels = self.voxels
for x in range(chunk_size):
for y in range(chunk_size):
z = int(abs(self.PERLIN_MAP.get_value(x+global_x, y+global_y) ) * 8 * 2 ) * 2
z = (min(z,chunk_size-1))
if z>=0:
self.change_voxel((x,y,z), 1)
while z>0:
z-=1
self.change_voxel((x,y,z), 2)
# spawn chunk, this includes the fill method in the init
pos = logic.spawn_positons.pop()
logic.chunks[pos] = PerlinChunk(position=pos, chunk_size=CHUNK_SIZE)
# how to add a single voxel (0 is air, 1 is dirt, 2 is grass, etc) based on local position
local_pos, grass = (5,5,5), 2
chunk.change_voxel(local_pos, grass)
# there is also chunk.change_global_voxel
# spawn a tree based on template
chunk = logic.chunks[pos]
for relative_vox in tree_template:
global_pos = relative_vox[0]+pos[0], relative_vox[1]+pos[1], relative_vox[2]+pos[2]
chunk_key = floor_to_chunk_key(global_pos, CHUNK_SIZE)
chunk = logic.chunks.get(chunk_key)
if chunk:
chunk.change_global_voxel(global_pos, 3+relative_vox[3])
logic.to_update.add(chunk_key)
# draw and optimize (relaod)
chunk.draw_voxels()
chunk.load_chunk()
(latter has 600 16x16x16 chunks )
############################
Behold the glory
I basically render all the faces of voxels that reside on the same plane as texture pixels.
Currently I am using 8x8x8 chunks with each having an 64x64 pixel texture, of which I can spawn around 2000 to 6000.
The map is basically the worst case scenario: a checkerboard chunks.
The libload->new texture->spawn voxels takes 4 ms per chunk.
There is tons of room for optimization. On more organic maps and such, there would be significant gains from culling unused planes and sharing textures.
It consumes marginal amounts of memory and performance:
Now the bad stuff:
The stars have to be aligned and horoscope favorable.
Many things will cause bugs, mainly because blender was not intended for such abuse.
Bug inducing factors:
- Use frame rate option
- Display lists
- Storage: Auto or Vertex buffer obj
- Alpha blend options ( will reset uv cordinates )
- multitexture mode (has about 3x the performance:()
- Your system
- basically everything to do with bgl or bge.render.
- unique libload
The basic issue is that the UV coordinates, texture or mipmaps get reset when the chunks are spawned not in view or its the wrong time of the day.
Oh, and also crashes…
What i plan:
- get some opinions
- get some help
- write culling and merging optimization
- decide whether to continue in blender or move on
So what you people think?
(Press space to spawn voxels.)
EDIT: fixed the file path and added slow auto spawn
OLD_VERSION: https://drive.google.com/file/d/0B8kZsmvJJIZlbXlaQTJlMTFYRGs/view