feat: stream chunks in-game, render 3D catalog props, and ground chunk coordinates
checkpoint / checkpoint (push) Successful in 5m54s
checkpoint / checkpoint (push) Successful in 5m54s
This commit is contained in:
@@ -29,16 +29,282 @@ func _ready() -> void:
|
||||
|
||||
## Load and attach the object's mesh.
|
||||
func _load_mesh() -> void:
|
||||
_mesh_instance = MeshInstance3D.new()
|
||||
_mesh_instance.name = "mesh"
|
||||
# 1. Try to load the asset directly if it exists on disk
|
||||
var asset_node := _try_load_asset(world_object.asset_id)
|
||||
if asset_node != null:
|
||||
add_child(asset_node)
|
||||
if asset_node is MeshInstance3D:
|
||||
_mesh_instance = asset_node as MeshInstance3D
|
||||
return
|
||||
|
||||
# Try to load the asset by its id (path). Fall back to a placeholder.
|
||||
var mesh := _load_asset_mesh(world_object.asset_id)
|
||||
if mesh == null:
|
||||
mesh = _make_placeholder_mesh()
|
||||
# 2. Build a stylized, recognizable 3D representation based on catalog ID / asset ID
|
||||
var cat_id := _get_catalog_id()
|
||||
_build_procedural_object(cat_id)
|
||||
|
||||
_mesh_instance.mesh = mesh
|
||||
add_child(_mesh_instance)
|
||||
|
||||
func _get_catalog_id() -> String:
|
||||
if world_object == null:
|
||||
return ""
|
||||
if world_object.properties is Dictionary and world_object.properties.has("catalog_id"):
|
||||
return str(world_object.properties["catalog_id"]).to_lower()
|
||||
return world_object.asset_id.get_file().get_basename().to_lower()
|
||||
|
||||
|
||||
func _try_load_asset(asset_id: String) -> Node:
|
||||
if asset_id.is_empty():
|
||||
return null
|
||||
var path := "res://assets/%s" % asset_id
|
||||
if ResourceLoader.exists(path):
|
||||
var res := load(path)
|
||||
if res is PackedScene:
|
||||
return (res as PackedScene).instantiate()
|
||||
elif res is Mesh:
|
||||
var mi := MeshInstance3D.new()
|
||||
mi.name = "mesh"
|
||||
mi.mesh = res as Mesh
|
||||
return mi
|
||||
return null
|
||||
|
||||
|
||||
func _build_procedural_object(cat_id: String) -> void:
|
||||
var container := Node3D.new()
|
||||
container.name = "visuals"
|
||||
add_child(container)
|
||||
|
||||
if "lamp" in cat_id:
|
||||
# Lamp post: dark iron vertical pole + glowing lantern + omni light
|
||||
var pole := MeshInstance3D.new()
|
||||
pole.name = "pole"
|
||||
var pole_mesh := CylinderMesh.new()
|
||||
pole_mesh.height = 3.2
|
||||
pole_mesh.top_radius = 0.07
|
||||
pole_mesh.bottom_radius = 0.1
|
||||
var iron_mat := StandardMaterial3D.new()
|
||||
iron_mat.albedo_color = Color(0.2, 0.22, 0.25)
|
||||
iron_mat.metallic = 0.85
|
||||
iron_mat.roughness = 0.35
|
||||
pole_mesh.material = iron_mat
|
||||
pole.mesh = pole_mesh
|
||||
pole.position = Vector3(0, 1.6, 0)
|
||||
container.add_child(pole)
|
||||
_mesh_instance = pole
|
||||
|
||||
var cap := MeshInstance3D.new()
|
||||
cap.name = "cap"
|
||||
var cap_mesh := CylinderMesh.new()
|
||||
cap_mesh.height = 0.15
|
||||
cap_mesh.top_radius = 0.05
|
||||
cap_mesh.bottom_radius = 0.3
|
||||
cap_mesh.material = iron_mat
|
||||
cap.mesh = cap_mesh
|
||||
cap.position = Vector3(0, 3.2, 0)
|
||||
container.add_child(cap)
|
||||
|
||||
var lantern := MeshInstance3D.new()
|
||||
lantern.name = "lantern"
|
||||
var lantern_mesh := BoxMesh.new()
|
||||
lantern_mesh.size = Vector3(0.32, 0.45, 0.32)
|
||||
var glow_mat := StandardMaterial3D.new()
|
||||
glow_mat.albedo_color = Color(1.0, 0.95, 0.7)
|
||||
glow_mat.emission_enabled = true
|
||||
glow_mat.emission = Color(1.0, 0.9, 0.4)
|
||||
glow_mat.emission_energy_multiplier = 4.0
|
||||
lantern_mesh.material = glow_mat
|
||||
lantern.mesh = lantern_mesh
|
||||
lantern.position = Vector3(0, 2.9, 0)
|
||||
container.add_child(lantern)
|
||||
|
||||
var light := OmniLight3D.new()
|
||||
light.name = "light"
|
||||
light.light_color = Color(1.0, 0.93, 0.72)
|
||||
light.light_energy = 1.6
|
||||
light.omni_range = 10.0
|
||||
light.position = Vector3(0, 2.9, 0)
|
||||
container.add_child(light)
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var cyl := CylinderShape3D.new()
|
||||
cyl.height = 3.2
|
||||
cyl.radius = 0.2
|
||||
col_shape.shape = cyl
|
||||
col_shape.position = Vector3(0, 1.6, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
elif "crate" in cat_id:
|
||||
var crate := MeshInstance3D.new()
|
||||
crate.name = "crate"
|
||||
var crate_mesh := BoxMesh.new()
|
||||
crate_mesh.size = Vector3(1.0, 1.0, 1.0)
|
||||
var wood_mat := StandardMaterial3D.new()
|
||||
wood_mat.albedo_color = Color(0.55, 0.36, 0.18)
|
||||
wood_mat.roughness = 0.8
|
||||
crate_mesh.material = wood_mat
|
||||
crate.mesh = crate_mesh
|
||||
crate.position = Vector3(0, 0.5, 0)
|
||||
container.add_child(crate)
|
||||
_mesh_instance = crate
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var box := BoxShape3D.new()
|
||||
box.size = Vector3(1.0, 1.0, 1.0)
|
||||
col_shape.shape = box
|
||||
col_shape.position = Vector3(0, 0.5, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
elif "rock" in cat_id:
|
||||
var rock := MeshInstance3D.new()
|
||||
rock.name = "rock"
|
||||
var rock_mesh := SphereMesh.new()
|
||||
rock_mesh.radius = 0.65
|
||||
rock_mesh.height = 1.0
|
||||
rock_mesh.radial_segments = 8
|
||||
rock_mesh.rings = 6
|
||||
var stone_mat := StandardMaterial3D.new()
|
||||
stone_mat.albedo_color = Color(0.42, 0.44, 0.46)
|
||||
stone_mat.roughness = 0.9
|
||||
rock_mesh.material = stone_mat
|
||||
rock.mesh = rock_mesh
|
||||
rock.position = Vector3(0, 0.5, 0)
|
||||
container.add_child(rock)
|
||||
_mesh_instance = rock
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var sphere := SphereShape3D.new()
|
||||
sphere.radius = 0.65
|
||||
col_shape.shape = sphere
|
||||
col_shape.position = Vector3(0, 0.5, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
elif "tree" in cat_id:
|
||||
var trunk := MeshInstance3D.new()
|
||||
trunk.name = "trunk"
|
||||
var trunk_mesh := CylinderMesh.new()
|
||||
trunk_mesh.height = 1.4
|
||||
trunk_mesh.top_radius = 0.2
|
||||
trunk_mesh.bottom_radius = 0.25
|
||||
var bark_mat := StandardMaterial3D.new()
|
||||
bark_mat.albedo_color = Color(0.35, 0.22, 0.12)
|
||||
trunk_mesh.material = bark_mat
|
||||
trunk.mesh = trunk_mesh
|
||||
trunk.position = Vector3(0, 0.7, 0)
|
||||
container.add_child(trunk)
|
||||
|
||||
var leaves1 := MeshInstance3D.new()
|
||||
leaves1.name = "leaves1"
|
||||
var leaves1_mesh := CylinderMesh.new()
|
||||
leaves1_mesh.height = 2.0
|
||||
leaves1_mesh.top_radius = 0.1
|
||||
leaves1_mesh.bottom_radius = 1.4
|
||||
var leaves_mat := StandardMaterial3D.new()
|
||||
leaves_mat.albedo_color = Color(0.12, 0.38, 0.15)
|
||||
leaves1_mesh.material = leaves_mat
|
||||
leaves1.mesh = leaves1_mesh
|
||||
leaves1.position = Vector3(0, 2.0, 0)
|
||||
container.add_child(leaves1)
|
||||
_mesh_instance = leaves1
|
||||
|
||||
var leaves2 := MeshInstance3D.new()
|
||||
leaves2.name = "leaves2"
|
||||
var leaves2_mesh := CylinderMesh.new()
|
||||
leaves2_mesh.height = 1.6
|
||||
leaves2_mesh.top_radius = 0.0
|
||||
leaves2_mesh.bottom_radius = 0.9
|
||||
leaves2_mesh.material = leaves_mat
|
||||
leaves2.mesh = leaves2_mesh
|
||||
leaves2.position = Vector3(0, 3.2, 0)
|
||||
container.add_child(leaves2)
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var cyl := CylinderShape3D.new()
|
||||
cyl.height = 4.0
|
||||
cyl.radius = 0.35
|
||||
col_shape.shape = cyl
|
||||
col_shape.position = Vector3(0, 2.0, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
elif "chest" in cat_id:
|
||||
var chest := MeshInstance3D.new()
|
||||
chest.name = "chest"
|
||||
var chest_mesh := BoxMesh.new()
|
||||
chest_mesh.size = Vector3(1.0, 0.8, 0.6)
|
||||
var chest_mat := StandardMaterial3D.new()
|
||||
chest_mat.albedo_color = Color(0.48, 0.26, 0.12)
|
||||
chest_mesh.material = chest_mat
|
||||
chest.mesh = chest_mesh
|
||||
chest.position = Vector3(0, 0.4, 0)
|
||||
container.add_child(chest)
|
||||
_mesh_instance = chest
|
||||
|
||||
var trim := MeshInstance3D.new()
|
||||
trim.name = "trim"
|
||||
var trim_mesh := BoxMesh.new()
|
||||
trim_mesh.size = Vector3(0.2, 0.25, 0.64)
|
||||
var gold_mat := StandardMaterial3D.new()
|
||||
gold_mat.albedo_color = Color(0.9, 0.75, 0.2)
|
||||
trim_mesh.material = gold_mat
|
||||
trim.mesh = trim_mesh
|
||||
trim.position = Vector3(0, 0.4, 0)
|
||||
container.add_child(trim)
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var box := BoxShape3D.new()
|
||||
box.size = Vector3(1.0, 0.8, 0.6)
|
||||
col_shape.shape = box
|
||||
col_shape.position = Vector3(0, 0.4, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
elif "spawn" in cat_id or (world_object != null and world_object.type == "spawn_point"):
|
||||
var pad := MeshInstance3D.new()
|
||||
pad.name = "pad"
|
||||
var pad_mesh := CylinderMesh.new()
|
||||
pad_mesh.height = 0.08
|
||||
pad_mesh.top_radius = 1.2
|
||||
pad_mesh.bottom_radius = 1.2
|
||||
var spawn_mat := StandardMaterial3D.new()
|
||||
spawn_mat.albedo_color = Color(0.2, 0.75, 0.95)
|
||||
spawn_mat.emission_enabled = true
|
||||
spawn_mat.emission = Color(0.1, 0.6, 0.85)
|
||||
spawn_mat.emission_energy_multiplier = 2.0
|
||||
pad_mesh.material = spawn_mat
|
||||
pad.mesh = pad_mesh
|
||||
pad.position = Vector3(0, 0.04, 0)
|
||||
container.add_child(pad)
|
||||
_mesh_instance = pad
|
||||
|
||||
else:
|
||||
var mi := MeshInstance3D.new()
|
||||
mi.name = "mesh"
|
||||
mi.mesh = _make_placeholder_mesh()
|
||||
mi.position = Vector3(0, 0.5, 0)
|
||||
container.add_child(mi)
|
||||
_mesh_instance = mi
|
||||
|
||||
var col := _create_static_collision()
|
||||
var col_shape := CollisionShape3D.new()
|
||||
var box := BoxShape3D.new()
|
||||
box.size = Vector3(1.0, 1.0, 1.0)
|
||||
col_shape.shape = box
|
||||
col_shape.position = Vector3(0, 0.5, 0)
|
||||
col.add_child(col_shape)
|
||||
container.add_child(col)
|
||||
|
||||
|
||||
func _create_static_collision() -> StaticBody3D:
|
||||
var sb := StaticBody3D.new()
|
||||
sb.name = "collision"
|
||||
sb.set_collision_layer_value(1, true)
|
||||
sb.set_collision_mask_value(1, true)
|
||||
return sb
|
||||
|
||||
|
||||
## Attempt to load a mesh from the asset path.
|
||||
@@ -49,7 +315,7 @@ func _load_asset_mesh(asset_id: String) -> Mesh:
|
||||
if ResourceLoader.exists(path):
|
||||
var res := load(path)
|
||||
if res is Mesh:
|
||||
return res
|
||||
return res as Mesh
|
||||
return null
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user