141 lines
4.7 KiB
GDScript
141 lines
4.7 KiB
GDScript
extends Spatial
|
|
|
|
var timer = 0
|
|
var chunks_in_progress = {}
|
|
var progress2del = {}
|
|
|
|
func _init():
|
|
core.chunk=self
|
|
|
|
#creates a new chunk array
|
|
#adds air to it so the player not reaching a empty space and things craches
|
|
func new_chunk(pos):
|
|
var id = pos_to_chunkid(pos)
|
|
var chunk_pos = to_chunk_pos(pos)
|
|
var air = core.get_node_reg("air").id
|
|
for x in range(-core.chunk_size/2,core.chunk_size/2):
|
|
for y in range(-core.chunk_size/2,core.chunk_size/2):
|
|
for z in range(-core.chunk_size/2,core.chunk_size/2):
|
|
core.inset_map_node_id(air,chunk_pos+Vector3(x,y,z))
|
|
core.chunks[id] = MeshInstance.new()
|
|
var chunk = core.chunks[id]
|
|
chunk.transform.origin = chunk_pos
|
|
add_child(chunk)
|
|
var staticbody = StaticBody.new()
|
|
staticbody.name = "body"
|
|
chunk.add_child(staticbody)
|
|
var collision = CollisionShape.new()
|
|
collision.name = "collision"
|
|
staticbody.add_child(collision)
|
|
|
|
func to_chunk_pos(pos):
|
|
var c = core.chunk_size
|
|
var s = core.chunk_size/2
|
|
return ((pos+Vector3(s,s,s))/c).floor()*c
|
|
|
|
func get_chunk_at_pos(pos):
|
|
var c = core.chunk_size
|
|
var s = core.chunk_size/2
|
|
var c_pos = ((pos+Vector3(s,s,s))/c).floor()
|
|
return core.chunks.get(c_pos)
|
|
|
|
func pos_to_chunkid(pos):
|
|
var c = core.chunk_size
|
|
var s = core.chunk_size/2
|
|
return ((pos+Vector3(s,s,s))/c).floor()
|
|
|
|
func get_chunk(id):
|
|
return core.chunks.get(id)
|
|
|
|
#sends chunks to update in a list to process
|
|
#this keeps performance well, even we can expect somewhat slower loading
|
|
func _process(delta):
|
|
timer += delta
|
|
if timer > 0.0:
|
|
timer = 0
|
|
|
|
for i in progress2del:
|
|
chunks_in_progress.erase(i)
|
|
progress2del.clear()
|
|
var max_nodes = core.settings.max_update_nodes
|
|
for di in chunks_in_progress:
|
|
var data = chunks_in_progress.get(di)
|
|
var chunk_mesh = get_chunk(data.chunkid)
|
|
for x in range(data.range_x.a,data.range_x.b):
|
|
for y in range(data.range_y.a,data.range_y.b):
|
|
for z in range(data.range_z.a,data.range_z.b):
|
|
|
|
max_nodes -= 1
|
|
if max_nodes < 0:
|
|
data.range_x.a = x
|
|
data.range_y.a = y
|
|
data.range_z.a = z
|
|
return
|
|
|
|
var lpos = Vector3(x,y,z)
|
|
var id = core.map.get(lpos+data.chunk_pos)
|
|
|
|
if id:
|
|
var n = core.register.id.get(id) if id != null else "default"
|
|
var reg = core.register.nodes.get(n)
|
|
var tile = core.default_texture if reg.tiles.size() < 1 else reg.tiles[0]
|
|
if reg.drawtype != "none":
|
|
for f in core.default_node.faces.size():
|
|
var neighbour_id = core.map.get(lpos+core.default_node.dir[f]+data.chunk_pos)
|
|
var neighbour_name = core.register.id.get(neighbour_id) if neighbour_id != null else "none"
|
|
var neighbour_reg = core.register.nodes.get(neighbour_name)
|
|
|
|
if (data.full_cubes and neighbour_id == null) or (neighbour_id != id and neighbour_reg.get("solid_surface") == false):
|
|
data.st.begin(Mesh.PRIMITIVE_TRIANGLE_FAN)
|
|
var mat = SpatialMaterial.new()
|
|
var transparent = reg.get("transparent") == true
|
|
if f < reg.tiles.size():
|
|
tile = reg.tiles[f]
|
|
mat.albedo_texture = tile
|
|
mat.flags_transparent = transparent
|
|
data.st.set_material(mat)
|
|
data.st.add_color(Color(0,1,1))
|
|
var cmf = []
|
|
for v in range(0,4):
|
|
data.st.add_uv(core.default_node.uv[v])
|
|
data.st.add_vertex(core.default_node.faces[f][v]+lpos)
|
|
cmf.push_back(core.default_node.faces[f][v]+lpos)
|
|
|
|
data.st.commit(data.mesh)
|
|
# the faces is added, now add to the collision
|
|
# the TRIANGLE_FAN allows us to be more flexible models, but the trimesh do not work with it
|
|
# so we are using TRIANGLES for that
|
|
if reg.get("collidable") != false:
|
|
data.cst.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
data.cst.add_triangle_fan(cmf)
|
|
data.cst.commit(data.collision_mesh)
|
|
data.st.clear()
|
|
data.cst.clear()
|
|
chunk_mesh.mesh = data.mesh
|
|
chunk_mesh.get_node_or_null("body/collision").shape = data.collision_mesh.create_trimesh_shape()
|
|
chunks_in_progress.erase(di)
|
|
progress2del[di] = di
|
|
# the chunk is done, now work on next update
|
|
func update(pos):
|
|
if get_chunk_at_pos(pos) == null:
|
|
new_chunk(pos)
|
|
#no chunk here, generate it quickly
|
|
core.current_mapgen.call_func(to_chunk_pos(pos))
|
|
return
|
|
|
|
var chunkid = pos_to_chunkid(pos)
|
|
var data = {
|
|
vertex = {},
|
|
full_cubes = core.settings.full_3d_cubes,
|
|
mesh = Mesh.new(),
|
|
collision_mesh = Mesh.new(),
|
|
chunkid = chunkid,
|
|
chunk_pos = get_chunk(chunkid).transform.origin,
|
|
st = SurfaceTool.new(),
|
|
cst = SurfaceTool.new(),
|
|
range_x = {a=-core.chunk_size/2,b=core.chunk_size/2},
|
|
range_y = {a=-core.chunk_size/2,b=core.chunk_size/2},
|
|
range_z = {a=-core.chunk_size/2,b=core.chunk_size/2},
|
|
}
|
|
chunks_in_progress[chunkid] = data
|