Panda3D Game Jam 2022!
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

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))