You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.8 KiB
136 lines
4.8 KiB
from random import choice, randint, uniform
|
|
from panda3d.core import PNMImage
|
|
from panda3d.core import Texture
|
|
from panda3d.core import TextureStage
|
|
from panda3d.core import ShaderTerrainMesh
|
|
from panda3d.core import Shader
|
|
from panda3d.core import TransformState
|
|
from panda3d.core import Fog
|
|
|
|
from panda3d.bullet import BulletHeightfieldShape
|
|
from panda3d.bullet import BulletRigidBodyNode
|
|
from panda3d.bullet import ZUp
|
|
|
|
from .models import place_models
|
|
|
|
# These need to be power of two, WORLD_SIZE > CHUNK_SIZE
|
|
WORLD_SIZE = 1024*8
|
|
CHUNK_SIZE = WORLD_SIZE//4
|
|
|
|
def make_perlin_dunes(seed=100, spread=42):
|
|
maxval = 65535
|
|
table_size = int(1024)
|
|
res = WORLD_SIZE
|
|
print('creating images')
|
|
pnm_image = PNMImage(res, res, num_channels=1, maxval=maxval)
|
|
noise = PNMImage(res, res, num_channels=1, maxval=maxval)
|
|
spot = PNMImage(res, res, num_channels=1, maxval=maxval)
|
|
|
|
pnm_image.fill(maxval)
|
|
sub = pnm_image.darken_sub_image
|
|
add = pnm_image.add_sub_image
|
|
mult = pnm_image.mult_sub_image
|
|
for a in [
|
|
(8.50, 5.00, 0.800, sub),
|
|
(2.00, 1.80, 0.800, add),
|
|
(0.80, 1.00, 0.500, sub),
|
|
(0.60, 0.50, 0.500, sub),
|
|
(0.40, 0.25, 0.005, add),
|
|
(0.45, 0.55, 0.400, sub),
|
|
(3.00, 2.80, 0.200, sub),
|
|
(0.26, 0.45, 0.005, add),
|
|
(2.00, 2.80, 1.000, mult),
|
|
]:
|
|
xscale, yscale, amount, func = a
|
|
xscale = (xscale/CHUNK_SIZE)*spread
|
|
yscale = (yscale/CHUNK_SIZE)*spread
|
|
noise.perlin_noise_fill(xscale,yscale, table_size=table_size, seed=seed)
|
|
func(noise, 0, 0, pixel_scale=amount)
|
|
|
|
#spot.render_spot(fg=(1,1,1,1), bg=(0,0,0,0), min_radius=0.8, max_radius=1)
|
|
#pnm_image.mult_sub_image(spot, 0, 0, pixel_scale=1)
|
|
print('blurring')
|
|
pnm_image.gaussian_filter(3)
|
|
print('writing out images')
|
|
shift = CHUNK_SIZE
|
|
pieces = WORLD_SIZE//CHUNK_SIZE
|
|
sub_image = PNMImage(shift, shift, num_channels=1, maxval=maxval)
|
|
sub_image.fill(maxval)
|
|
for y in range(pieces):
|
|
for x in range(pieces):
|
|
sub_image.copy_sub_image(pnm_image, xto=0, yto=0, xfrom=shift*x, yfrom=shift*y)
|
|
sub_image.write('assets/textures/heightmaps/{}-{}.png'.format(x, y))
|
|
|
|
|
|
def load_chunk(bullet_world, x, y, cloud_maker, override_texture=None):
|
|
res = CHUNK_SIZE
|
|
height = 200
|
|
if override_texture:
|
|
texture=override_texture
|
|
else:
|
|
texture = loader.load_texture('assets/textures/heightmaps/{}-{}.png'.format(x,y))
|
|
|
|
x = (x*res)-(WORLD_SIZE//2)-1
|
|
y = -((y*res)-(WORLD_SIZE//2)-1)
|
|
|
|
bullet_shape = BulletHeightfieldShape(texture, height, ZUp)
|
|
bullet_rigidbody = BulletRigidBodyNode('the_dunes')
|
|
bullet_rigidbody.add_shape(bullet_shape, TransformState.make_pos((x,y,0)))
|
|
bullet_rigidbody.set_ccd_motion_threshold(0.000000007)
|
|
bullet_rigidbody.set_ccd_swept_sphere_radius(0.30)
|
|
bullet_rigidbody.set_deactivation_enabled(False)
|
|
bullet_world.attach_rigid_body(bullet_rigidbody)
|
|
|
|
terrain = ShaderTerrainMesh()
|
|
terrain.set_heightfield(texture)
|
|
terrain.set_target_triangle_width(40) # or 16
|
|
terrain.set_chunk_size(128) # or 64
|
|
terrain.set_update_enabled(True)
|
|
terrain_root = render.attach_new_node(terrain)
|
|
terrain_shader = Shader.load(
|
|
Shader.SL_GLSL,
|
|
'assets/shaders/test_heightmap.vert',
|
|
'assets/shaders/test_heightmap.frag'
|
|
)
|
|
|
|
terrain_root.set_shader(terrain_shader)
|
|
terrain_root.set_shader_input("camera", base.cam)
|
|
terrain_root.set_scale(res, res, height)
|
|
offset = texture.get_x_size() / 2.0 - 0.5
|
|
terrain_root.set_pos(-offset+x, -offset+y, -height/2)
|
|
|
|
exponential_fog = Fog('world_fog')
|
|
exponential_fog.set_color(0.9, 0.7, 0)
|
|
exponential_fog.set_exp_density(0.00009)
|
|
base.render.set_fog(exponential_fog)
|
|
|
|
terrain.generate()
|
|
sand_tex = loader.load_texture('assets/textures/sand_01.png')
|
|
terrain_root.set_texture(sand_tex)
|
|
|
|
place_models(bullet_world, res, x, y)
|
|
cloud_maker.make_dust_clouds(16, res, x, y)
|
|
|
|
return terrain_root
|
|
|
|
|
|
class Dune():
|
|
def __init__(self, bullet_world, cloud_maker):
|
|
self.size = WORLD_SIZE
|
|
#make_perlin_dunes()
|
|
for y in range(4):
|
|
for x in range(4):
|
|
load_chunk(bullet_world, x, y, cloud_maker)
|
|
base.camLens.set_far(3200)
|
|
#base.cam.set_pos(WORLD_SIZE, WORLD_SIZE, WORLD_SIZE)
|
|
#base.cam.look_at(0,0,0)
|
|
|
|
|
|
class TestDune():
|
|
def __init__(self, bullet_world, cloud_maker):
|
|
self.size = WORLD_SIZE
|
|
load_chunk(bullet_world, 0, 0, cloud_maker, loader.load_texture('assets/textures/test_heightmap3.png'))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
make_perlin_dunes(seed = random.randint(0, 128000))
|
|
|