Partially moved CPU-intensive code to C++ modules OpenSimplex and Voxel
parent
30305d5384
commit
f17f202609
|
@ -2,14 +2,13 @@
|
|||
|
||||
[ext_resource path="res://block_node.gd" type="Script" id=1]
|
||||
|
||||
|
||||
[node name="Block" type="MeshInstance"]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
layers = 1
|
||||
geometry/visible = true
|
||||
geometry/material_override = null
|
||||
geometry/cast_shadow = true
|
||||
geometry/cast_shadow = 1
|
||||
geometry/receive_shadows = true
|
||||
geometry/range_begin = 0.0
|
||||
geometry/range_end = 0.0
|
||||
|
|
|
@ -17,7 +17,7 @@ params/blend_mode = 0
|
|||
params/depth_draw = 1
|
||||
params/line_width = 0.0
|
||||
fixed_flags/use_alpha = false
|
||||
fixed_flags/use_color_array = false
|
||||
fixed_flags/use_color_array = true
|
||||
fixed_flags/use_point_size = false
|
||||
fixed_flags/discard_alpha = false
|
||||
fixed_flags/use_xy_normalmap = false
|
||||
|
@ -87,7 +87,7 @@ ambient_light/color = Color( 0.378906, 0.378906, 0.378906, 1 )
|
|||
ambient_light/energy = 1.0
|
||||
fxaa/enabled = false
|
||||
background/mode = 2
|
||||
background/color = Color( 0.539063, 0.525474, 0.414825, 1 )
|
||||
background/color = Color( 0.446167, 0.645425, 0.671875, 1 )
|
||||
background/energy = 1.0
|
||||
background/scale = 1.0
|
||||
background/glow = 0.0
|
||||
|
@ -115,7 +115,7 @@ hdr/exposure_adj_speed = 0.5
|
|||
fog/enabled = true
|
||||
fog/begin = 0.01
|
||||
fog/begin_color = Color( 0, 0, 0, 1 )
|
||||
fog/end_color = Color( 0.537255, 0.521569, 0.411765, 1 )
|
||||
fog/end_color = Color( 0.443137, 0.643137, 0.670588, 1 )
|
||||
fog/attenuation = 0.707107
|
||||
fog/bg = true
|
||||
bcs/enabled = false
|
||||
|
@ -129,7 +129,7 @@ srgb/enabled = false
|
|||
[node name="Camera" type="Camera" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform/local = Transform( 0.815509, -0.351713, 0.459612, 0, 0.794154, 0.607717, -0.578744, -0.495599, 0.64764, 18.1809, 4.88061, 25.3826 )
|
||||
transform/local = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0 )
|
||||
projection = 0
|
||||
fov = 80.0
|
||||
near = 0.1
|
||||
|
@ -154,7 +154,7 @@ _import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
|||
layers = 1
|
||||
geometry/visible = true
|
||||
geometry/material_override = null
|
||||
geometry/cast_shadow = false
|
||||
geometry/cast_shadow = 0
|
||||
geometry/receive_shadows = true
|
||||
geometry/range_begin = 0.0
|
||||
geometry/range_end = 0.0
|
||||
|
@ -228,7 +228,7 @@ environment = SubResource( 3 )
|
|||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform/local = Transform( 0.817159, -0.383981, 0.429895, 4.66628e-006, 0.745816, 0.666152, -0.576412, -0.54435, 0.609452, 1.36405, 1.98931, 7.37862 )
|
||||
transform/local = Transform( -0.761692, 0.482016, -0.432995, -0.609208, -0.305189, 0.731932, 0.220658, 0.821291, 0.526108, 1.11878, 2.33452, 7.6244 )
|
||||
layers = 1
|
||||
params/enabled = true
|
||||
params/editor_only = false
|
||||
|
@ -236,7 +236,7 @@ params/bake_mode = 0
|
|||
params/energy = 1.0
|
||||
colors/diffuse = Color( 1, 1, 1, 1 )
|
||||
colors/specular = Color( 1, 1, 1, 1 )
|
||||
shadow/shadow = true
|
||||
shadow/shadow = false
|
||||
shadow/darkening = 0.0
|
||||
shadow/z_offset = 0.05
|
||||
shadow/z_slope_scale = 0.0
|
||||
|
@ -245,7 +245,7 @@ shadow/blur_passes = 1.0
|
|||
projector = null
|
||||
operator = 0
|
||||
shadow/mode = 3
|
||||
shadow/max_distance = 100.0
|
||||
shadow/max_distance = 32.0
|
||||
shadow/split_weight = 0.5
|
||||
shadow/zoffset_scale = 2.0
|
||||
|
||||
|
|
|
@ -22,20 +22,9 @@ const SORT_TIME = 1
|
|||
|
||||
export(Material) var solid_material = null
|
||||
export(Material) var transparent_material = null
|
||||
var view_radius = 8
|
||||
var min_y = -2
|
||||
var max_y = 2
|
||||
|
||||
var VoxelType = preload("voxel_type.gd")
|
||||
|
||||
var _side_normals = [
|
||||
Vector3(-1,0,0),
|
||||
Vector3(1,0,0),
|
||||
Vector3(0,-1,0),
|
||||
Vector3(0,1,0),
|
||||
Vector3(0,0,-1),
|
||||
Vector3(0,0,1)
|
||||
]
|
||||
var view_radius = 4
|
||||
var min_y = -4
|
||||
var max_y = 4
|
||||
|
||||
var _blocks = {}
|
||||
var _generating_blocks = {}
|
||||
|
@ -50,11 +39,14 @@ var _priority_positions = []
|
|||
var _outer_positions = []
|
||||
var _precalc_neighboring = []
|
||||
|
||||
var _noise = OsnNoise.new()
|
||||
var _mesh_builder = VoxelMeshBuilder.new()
|
||||
var _library = VoxelLibrary.new()
|
||||
|
||||
|
||||
# BLOCK_SIZE * BLOCK_SIZE * BLOCK_SIZE voxel buffer used in VoxelMaps
|
||||
class Block:
|
||||
var voxel_map = null
|
||||
var voxels = []
|
||||
var voxels = VoxelBuffer.new()
|
||||
var pos = Vector3(0,0,0)
|
||||
var mesh = null
|
||||
var node = null
|
||||
|
@ -64,24 +56,7 @@ class Block:
|
|||
var need_update = false
|
||||
|
||||
func _init():
|
||||
pass
|
||||
#voxels = create_voxel_grid(BLOCK_SIZE+2,BLOCK_SIZE+2,BLOCK_SIZE+2)
|
||||
|
||||
static func create_voxel_grid(sx,sy,sz):
|
||||
var grid = []
|
||||
grid.resize(sz)
|
||||
for z in range(0, sz):
|
||||
var plane = []
|
||||
plane.resize(sy)
|
||||
grid[z] = plane
|
||||
for y in range(0, sy):
|
||||
var line = []
|
||||
#var line = IntArray()
|
||||
line.resize(sx)
|
||||
plane[y] = line
|
||||
for x in range(0, sx):
|
||||
line[x] = 0
|
||||
return grid
|
||||
voxels.create(BLOCK_SIZE+2,BLOCK_SIZE+2,BLOCK_SIZE+2)
|
||||
|
||||
func is_generated():
|
||||
return has_generated and has_structures
|
||||
|
@ -131,6 +106,10 @@ class BlockRequest:
|
|||
|
||||
|
||||
func _ready():
|
||||
_noise.set_seed(131183)
|
||||
|
||||
_library.set_atlas_size(4)
|
||||
|
||||
_camera = get_parent().get_node("Camera")
|
||||
|
||||
_load_voxel_types()
|
||||
|
@ -149,40 +128,16 @@ func _precalculate_neighboring():
|
|||
_precalc_neighboring.append(Vector3(x,y,z))
|
||||
|
||||
|
||||
func add_voxel_type(id, name):
|
||||
var vt = VoxelType.new(id, name)
|
||||
if id >= _voxel_types.size():
|
||||
_voxel_types.resize(id+1)
|
||||
_voxel_types[id] = vt
|
||||
return vt
|
||||
|
||||
|
||||
func _load_voxel_types():
|
||||
add_voxel_type(0, "air") \
|
||||
.set_geom(VoxelType.GEOM_EMPTY) \
|
||||
.set_transparent(true)
|
||||
_library.create_voxel(0, "air").set_transparent()
|
||||
_library.create_voxel(1, "grass_dirt").set_cube_geometry().set_cube_uv_tbs_sides(Vector2(0,0), Vector2(0,1), Vector2(1,0))
|
||||
_library.create_voxel(2, "dirt").set_cube_geometry().set_cube_uv_all_sides(Vector2(1,0))
|
||||
_library.create_voxel(3, "log").set_cube_geometry().set_cube_uv_tbs_sides(Vector2(3,0), Vector2(3,0), Vector2(2,0))
|
||||
_library.create_voxel(4, "water").set_transparent().set_cube_geometry(15.0/16.0).set_cube_uv_all_sides(Vector2(2,1)).set_material_id(1)
|
||||
|
||||
add_voxel_type(1, "grassy_dirt") \
|
||||
.set_tbs_atlas_pos(Vector2(0,0), Vector2(1,0), Vector2(0,1))
|
||||
|
||||
add_voxel_type(2, "bush") \
|
||||
.set_all_atlas_pos(Vector2(1,1)) \
|
||||
.set_geom(VoxelType.GEOM_XQUAD) \
|
||||
.set_transparent(true)
|
||||
|
||||
add_voxel_type(3, "log") \
|
||||
.set_tbs_atlas_pos(Vector2(3,0), Vector2(3,0), Vector2(2,0))
|
||||
|
||||
add_voxel_type(4, "dirt") \
|
||||
.set_all_atlas_pos(Vector2(1,0))
|
||||
|
||||
add_voxel_type(5, "water") \
|
||||
.set_all_atlas_pos(Vector2(2,1)) \
|
||||
.set_transparent(true) \
|
||||
.set_geom(VoxelType.GEOM_LIQUID)
|
||||
|
||||
for vt in _voxel_types:
|
||||
vt.compile()
|
||||
_mesh_builder.set_library(_library)
|
||||
_mesh_builder.set_material(solid_material, 0)
|
||||
_mesh_builder.set_material(transparent_material, 1)
|
||||
|
||||
|
||||
func _precalculate_priority_positions():
|
||||
|
@ -276,8 +231,11 @@ func _process(delta):
|
|||
# Closer blocks are loaded first
|
||||
var pos = _pending_blocks[_pending_blocks.size()-1]
|
||||
_pending_blocks.pop_back()
|
||||
_thread.start(self, "generate_block_thread", BlockRequest.new(pos, BlockRequest.TYPE_GENERATE))
|
||||
_generating_blocks[pos] = true
|
||||
var arg = BlockRequest.new(pos, BlockRequest.TYPE_GENERATE)
|
||||
#_thread.start(self, "generate_block_thread", arg)
|
||||
#print("generate " + str(pos))
|
||||
spawn_block(generate_block(arg.block_pos))
|
||||
|
||||
# Visible blocks are loaded first
|
||||
# var hbs = Vector3(0.5, 0.5, 0.5) * BLOCK_SIZE
|
||||
|
@ -296,6 +254,7 @@ func generate_block_thread(request):
|
|||
var block = generate_block(request.block_pos)
|
||||
# Call the main thread to wait
|
||||
call_deferred("thread_finished")
|
||||
#_generating_blocks.erase(block.pos) # Enable only without thread!
|
||||
return block
|
||||
else:
|
||||
print("Unknown request type " + str(request.type))
|
||||
|
@ -310,40 +269,22 @@ func thread_finished():
|
|||
func generate_block(pos):
|
||||
var time_before = OS.get_ticks_msec()
|
||||
|
||||
#var time_before = OS.get_ticks_msec()
|
||||
var voxels = Block.create_voxel_grid(BLOCK_SIZE+2, BLOCK_SIZE+2, BLOCK_SIZE+2)
|
||||
#print("Create: " + str(OS.get_ticks_msec() - time_before) + "ms")
|
||||
var block = Block.new()
|
||||
block.pos = pos
|
||||
|
||||
#time_before = OS.get_ticks_msec()
|
||||
var empty = generate_random(voxels, pos * BLOCK_SIZE)
|
||||
var empty = generate_3d(block.voxels, pos * BLOCK_SIZE)
|
||||
#print("Generate: " + str(OS.get_ticks_msec() - time_before) + "ms")
|
||||
|
||||
var mesh = null
|
||||
if empty:
|
||||
voxels = null
|
||||
block.voxels = null
|
||||
else:
|
||||
#time_before = OS.get_ticks_msec()
|
||||
var st_solid = SurfaceTool.new()
|
||||
var st_transparent = SurfaceTool.new()
|
||||
|
||||
st_solid.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st_transparent.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
|
||||
st_solid.set_material(solid_material)
|
||||
st_transparent.set_material(transparent_material)
|
||||
|
||||
make_mesh(voxels, st_solid, st_transparent)
|
||||
#st.index()
|
||||
|
||||
mesh = st_solid.commit()
|
||||
st_transparent.commit(mesh)
|
||||
|
||||
mesh = _mesh_builder.build(block.voxels)
|
||||
#print("Bake: " + str(OS.get_ticks_msec() - time_before) + "ms")
|
||||
|
||||
var block = Block.new()
|
||||
block.voxel_map = self
|
||||
block.voxels = voxels
|
||||
block.pos = pos
|
||||
block.mesh = mesh
|
||||
block.gen_time = OS.get_ticks_msec() - time_before
|
||||
|
||||
|
@ -353,17 +294,80 @@ func generate_block(pos):
|
|||
func spawn_block(block):
|
||||
if block.mesh != null:
|
||||
var mesh_instance = preload("res://block.tscn").instance()
|
||||
mesh_instance.set_mesh(block.mesh)
|
||||
mesh_instance.set_translation(block.pos * BLOCK_SIZE)
|
||||
mesh_instance.spawn()
|
||||
mesh_instance.set_mesh(block.mesh)
|
||||
mesh_instance.voxel_map = self
|
||||
add_child(mesh_instance)
|
||||
block.node = mesh_instance
|
||||
mesh_instance.spawn()
|
||||
_blocks[block.pos] = block
|
||||
print("Gen time: " + str(block.gen_time) + " (empty=" + str(block.mesh == null) + ")")
|
||||
#print("Gen time: " + str(block.gen_time) + " (empty=" + str(block.mesh == null) + ")")
|
||||
|
||||
|
||||
func generate_random(cubes, offset):
|
||||
func generate_test(cubes, offset):
|
||||
cubes.set_voxel(1, 1,1,1)
|
||||
|
||||
cubes.set_voxel(1, 3,1,1)
|
||||
cubes.set_voxel(1, 3,1,2)
|
||||
|
||||
cubes.set_voxel(1, 5,1,1)
|
||||
cubes.set_voxel(1, 5,1,2)
|
||||
cubes.set_voxel(1, 5,2,1)
|
||||
|
||||
cubes.set_voxel(1, 8,1,1)
|
||||
cubes.set_voxel(1, 8,2,1)
|
||||
cubes.set_voxel(1, 7,1,1)
|
||||
|
||||
cubes.set_voxel(1, 11,1,1)
|
||||
cubes.set_voxel(1, 11,2,1)
|
||||
cubes.set_voxel(1, 10,1,1)
|
||||
cubes.set_voxel(1, 10,1,2)
|
||||
|
||||
for x in range(4,7):
|
||||
for z in range(4,7):
|
||||
cubes.set_voxel(1, x, 2, z)
|
||||
cubes.set_voxel(1, x+5, 2, z)
|
||||
cubes.set_voxel(1, 5,3,5)
|
||||
cubes.set_voxel(1, 5,1,5)
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func generate_3d(cubes, offset):
|
||||
var ox = offset.x
|
||||
var oy = offset.y
|
||||
var oz = offset.z
|
||||
var empty = true
|
||||
var bs = cubes.get_size_x()
|
||||
|
||||
var noise1 = OsnFractalNoise.new()
|
||||
noise1.set_source_noise(_noise)
|
||||
noise1.set_period(100)
|
||||
noise1.set_octaves(4)
|
||||
|
||||
var dirt = 1
|
||||
if oy < 0:
|
||||
dirt = 2
|
||||
|
||||
for z in range(0, bs):
|
||||
for x in range(0, bs):
|
||||
for y in range(0, bs):
|
||||
var gy = y+oy
|
||||
var h = noise1.get_noise_3d(x+ox+2, gy, z+oz)
|
||||
if h < 1-gy*0.01 - 1:
|
||||
cubes.set_voxel(dirt, x, y, z)
|
||||
empty = false
|
||||
else:
|
||||
if gy < 0:
|
||||
cubes.set_voxel(4, x, y, z)
|
||||
else:
|
||||
cubes.set_voxel(0, x, y, z)
|
||||
empty = false
|
||||
|
||||
return empty
|
||||
|
||||
|
||||
func generate_heightmap(cubes, offset):
|
||||
var ox = offset.x
|
||||
var oy = offset.y
|
||||
var oz = offset.z
|
||||
|
@ -373,31 +377,33 @@ func generate_random(cubes, offset):
|
|||
|
||||
var dirt = 1
|
||||
if oy < 0:
|
||||
dirt = 4
|
||||
|
||||
var air = 0
|
||||
if oy < 0:
|
||||
air = 5
|
||||
dirt = 2
|
||||
|
||||
var bs = cubes.size()
|
||||
var bs = cubes.get_size_x()
|
||||
|
||||
var noise1 = OsnFractalNoise.new()
|
||||
noise1.set_source_noise(_noise)
|
||||
noise1.set_period(128)
|
||||
noise1.set_octaves(4)
|
||||
|
||||
for z in range(0, bs):
|
||||
for x in range(0, bs):
|
||||
#var h = 8.0*(cos((ox+x)/8.0) + sin((oz+z)/8.0)) + 8 - oy
|
||||
var n1 = preload("Simplex.gd").simplex2(ns1*(ox+x), ns1*(oz+z))
|
||||
var n2 = preload("Simplex.gd").simplex2(ns2*(ox+x+100.0), ns2*(oz+z))
|
||||
var h = 16.0*n1 + 4.0*n2 + 8 - oy
|
||||
|
||||
var h = 16.0 * noise1.get_noise_2d(ox+x, oz+z) - oy
|
||||
|
||||
if h >= 0:
|
||||
if h < bs:
|
||||
empty = false
|
||||
for y in range(0, h):
|
||||
cubes[z][y][x] = dirt
|
||||
cubes.set_voxel(dirt, x,y,z)
|
||||
#cubes[z][y][x] = dirt
|
||||
for y in range(h, bs):
|
||||
cubes[z][y][x] = air
|
||||
if oy == -BLOCK_SIZE:
|
||||
cubes[z][bs-1][x] = 0
|
||||
if oy >= 0 and randf() < 0.2:
|
||||
cubes[z][h][x] = 2
|
||||
cubes.set_voxel(0, x,y,z)
|
||||
#cubes[z][y][x] = air
|
||||
# if oy == -BLOCK_SIZE:
|
||||
# cubes[z][bs-1][x] = 0
|
||||
# if oy >= 0 and randf() < 0.2:
|
||||
# cubes[z][h][x] = 2
|
||||
# if randf() < 0.01:
|
||||
# var th = h+1+randi()%8
|
||||
# if th > bs:
|
||||
|
@ -407,67 +413,14 @@ func generate_random(cubes, offset):
|
|||
else:
|
||||
empty = false
|
||||
for y in range(0, bs):
|
||||
cubes[z][y][x] = 1
|
||||
cubes.set_voxel(dirt, x,y,z)
|
||||
else:
|
||||
for y in range(0, bs):
|
||||
cubes[z][y][x] = air
|
||||
cubes.set_voxel(0, x,y,z)
|
||||
|
||||
return empty
|
||||
|
||||
|
||||
func _is_face_visible(vt, other_vt):
|
||||
return other_vt.id == 0 or (other_vt.is_transparent and other_vt != vt)
|
||||
|
||||
|
||||
func make_mesh(cubes, st_solid, st_transparent):
|
||||
|
||||
# Note: the data must be padded with border voxels,
|
||||
# so iteration starts at 1 and there is no need to check boundaries.
|
||||
# This trades performance over a bit of memory.
|
||||
|
||||
for z in range(1, cubes.size()-1):
|
||||
var plane = cubes[z]
|
||||
for y in range(1, plane.size()-1):
|
||||
var line = plane[y]
|
||||
for x in range(1, line.size()-1):
|
||||
var voxel_id = line[x]
|
||||
if voxel_id != 0:
|
||||
var voxel_type = _voxel_types[voxel_id]
|
||||
|
||||
var st = st_solid
|
||||
if voxel_type.is_transparent:
|
||||
st = st_transparent
|
||||
|
||||
var ppos = Vector3(x,y,z)
|
||||
var pos = ppos-Vector3(1,1,1)
|
||||
|
||||
# Side faces (full cubes only have side faces)
|
||||
if voxel_type.model_side_vertices.size() != 0:
|
||||
for side in range(0,6):
|
||||
var npos = ppos + _side_normals[side]
|
||||
if _is_face_visible(voxel_type, _voxel_types[cubes[npos.z][npos.y][npos.x]]):
|
||||
st.add_normal(_side_normals[side])
|
||||
var uvs = voxel_type.model_side_uv[side]
|
||||
var vertices = voxel_type.model_side_vertices[side]
|
||||
for vi in range(0,vertices.size()):
|
||||
st.add_uv(uvs[vi])
|
||||
st.add_vertex(pos + vertices[vi])
|
||||
|
||||
if voxel_type.geom_type == VoxelType.GEOM_XQUAD:
|
||||
pos.x += rand_range(-0.15, 0.15)
|
||||
pos.z += rand_range(-0.15, 0.15)
|
||||
|
||||
# Model faces
|
||||
if voxel_type.model_vertices.size() != 0:
|
||||
var vertices = voxel_type.model_vertices
|
||||
var uvs = voxel_type.model_uv
|
||||
var normals = voxel_type.model_normals
|
||||
for vi in range(0, vertices.size()):
|
||||
st.add_uv(uvs[vi])
|
||||
st.add_normal(normals[vi])
|
||||
st.add_vertex(pos + vertices[vi])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue