First MODELBEAST prop: hunyuan3d charge station replaces the blue box

flux_local concept (orange enamel pylon, analog gauge, coil cable) ->
local flood-fill cutout -> hunyuan3d_mlx run directly on m3ultra (queue
dispatch is TCC-broken tonight, flagged separately). _fit_prop():
AABB-normalized scale, floor-seated, metallic clamped (gltf metal=1
renders black without IBL). Box fallback stays when the GLB is absent.
All 6 charge posts now use the model. Integration still passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-08-03 23:48:08 +10:00
parent 2ef9487284
commit 994208f6ac
19 changed files with 618 additions and 12 deletions

Binary file not shown.

View File

@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cg4g4pm5edef5"
path="res://.godot/imported/charge_post.glb-a4838dab6c9fd725a88e494931115c67.scn"
[deps]
source_file="res://assets/models/charge_post.glb"
dest_files=["res://.godot/imported/charge_post.glb-a4838dab6c9fd725a88e494931115c67.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b120kykvtyd5r"
path="res://.godot/imported/charge_post_0.png-4a07fa44caf8c8b7b6b135c512eef865.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "36d6f403b237498cee7da6430cacd89a"
}
[deps]
source_file="res://assets/models/charge_post_0.png"
dest_files=["res://.godot/imported/charge_post_0.png-4a07fa44caf8c8b7b6b135c512eef865.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cou3au5g65qvx"
path="res://.godot/imported/charge_post_1.png-ab3b445260591d89e38f93f6207e3cde.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "f4d3410600c44a6be54040bf253d54ba"
}
[deps]
source_file="res://assets/models/charge_post_1.png"
dest_files=["res://.godot/imported/charge_post_1.png-ab3b445260591d89e38f93f6207e3cde.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cmbanx380cgmk"
path="res://.godot/imported/bridge_floor.jpg-c04e97e3fa7c08954188c6e1d4ef4dd2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/bridge_floor.jpg"
dest_files=["res://.godot/imported/bridge_floor.jpg-c04e97e3fa7c08954188c6e1d4ef4dd2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://de0t6o8cl2uut"
path="res://.godot/imported/bridge_wall.jpg-7dbcb8cc32efa268bfd8ed0f41a6f9f4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/bridge_wall.jpg"
dest_files=["res://.godot/imported/bridge_wall.jpg-7dbcb8cc32efa268bfd8ed0f41a6f9f4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c7hwfo0a5vh7i"
path="res://.godot/imported/bridge_wall_src.jpg-bc71ecd61b847ba2ae80237e79a68098.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/bridge_wall_src.jpg"
dest_files=["res://.godot/imported/bridge_wall_src.jpg-bc71ecd61b847ba2ae80237e79a68098.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dmkrx4uq248m2"
path="res://.godot/imported/comms_greeble.jpg-871ab87790e40512a595ed85d1fa685b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/comms_greeble.jpg"
dest_files=["res://.godot/imported/comms_greeble.jpg-871ab87790e40512a595ed85d1fa685b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2xg2jbp7drbr"
path="res://.godot/imported/comms_wall.jpg-9c40339d42b1e204a02d8c30890f8d28.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/comms_wall.jpg"
dest_files=["res://.godot/imported/comms_wall.jpg-9c40339d42b1e204a02d8c30890f8d28.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dulied4ph47j2"
path="res://.godot/imported/hydro_floor.jpg-f67fcadf82bf93cdd5524add5f1df178.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/hydro_floor.jpg"
dest_files=["res://.godot/imported/hydro_floor.jpg-f67fcadf82bf93cdd5524add5f1df178.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://g2yowatxon8k"
path="res://.godot/imported/hydro_greeble.jpg-7c1497119e76deab386fba1e84581e2d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/hydro_greeble.jpg"
dest_files=["res://.godot/imported/hydro_greeble.jpg-7c1497119e76deab386fba1e84581e2d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bl4vosa5mwhe"
path="res://.godot/imported/hydro_wall.jpg-d8baf12f8efcbaa6ef7f7f39c8209017.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/hydro_wall.jpg"
dest_files=["res://.godot/imported/hydro_wall.jpg-d8baf12f8efcbaa6ef7f7f39c8209017.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cdndky6r0n8s5"
path="res://.godot/imported/reactor_floor.jpg-54102b75cf29ea9c1c8500203f06a137.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/reactor_floor.jpg"
dest_files=["res://.godot/imported/reactor_floor.jpg-54102b75cf29ea9c1c8500203f06a137.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://sd1wfhm5sqlv"
path="res://.godot/imported/reactor_greeble.jpg-3ed6858c4eb61466ed5acd257365928b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/reactor_greeble.jpg"
dest_files=["res://.godot/imported/reactor_greeble.jpg-3ed6858c4eb61466ed5acd257365928b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c6pte6oyvtfy6"
path="res://.godot/imported/reactor_wall.jpg-4cf10d3b623cc7a115768edfd1f5aa96.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/reactor_wall.jpg"
dest_files=["res://.godot/imported/reactor_wall.jpg-4cf10d3b623cc7a115768edfd1f5aa96.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -82,6 +82,7 @@ func _photo_tour() -> void:
[Vector3(11, 0.2, 53), -PI / 2.0], # hydroponics
[Vector3(-4.2, 0.2, 63.5), PI], # comms
[Vector3(4.5, 0.2, 65), PI], # bridge
[Vector3(-0.5, 0.2, 10.5), PI / 2.0], # charge post close-up
]
for i in spots.size():
droid.global_position = spots[i][0]
@ -267,9 +268,53 @@ func make_door(z: float) -> Node3D:
return d
var _post_scene: PackedScene = null
var _post_checked := false
func _fit_prop(p: Node3D, pos: Vector3, target_h: float) -> void:
## normalize a generated GLB: uniform scale to target height, feet on floor,
## metallic clamped (gltf metallic=1 renders black without IBL — MESHGOD gotcha)
add_child(p)
p.global_position = Vector3.ZERO
var aabb := AABB()
var first := true
for mi in p.find_children("*", "MeshInstance3D", true, false):
var b: AABB = mi.global_transform * mi.get_aabb()
aabb = b if first else aabb.merge(b)
first = false
if mi.mesh:
for si in mi.mesh.get_surface_count():
var mt = mi.mesh.surface_get_material(si)
if mt is BaseMaterial3D:
mt.metallic = minf(mt.metallic, 0.2)
if first:
return
var sc := target_h / maxf(aabb.size.y, 0.01)
p.scale = Vector3.ONE * sc
var c := aabb.get_center()
p.global_position = Vector3(pos.x - c.x * sc, pos.y - aabb.position.y * sc, pos.z - c.z * sc)
func charge_post(pos: Vector3) -> ElementField:
box(pos + Vector3(0, 0.9, 0), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var f := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12))
if not _post_checked:
_post_checked = true
if FileAccess.file_exists("res://assets/models/charge_post.glb"):
_post_scene = load("res://assets/models/charge_post.glb")
if _post_scene:
_fit_prop(_post_scene.instantiate(), pos, 1.7)
var sb := StaticBody3D.new()
var cs := CollisionShape3D.new()
var bs := BoxShape3D.new()
bs.size = Vector3(0.7, 1.7, 0.7)
cs.shape = bs
cs.position.y = 0.85
sb.add_child(cs)
sb.position = pos
add_child(sb)
else:
box(pos + Vector3(0, 0.9, 0), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var f := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.055))
f.position = pos + Vector3(0, 0.9, 0)
add_child(f)
sign3d("CHARGE POST", pos + Vector3(0, 2.3, -0.3))
@ -372,11 +417,7 @@ func _build_objects() -> void:
Vector3(-2.0, 2.2, 4.0), PI, 22, Color(1.0, 0.75, 0.3))
# --- segment B: charge post + be-the-wire gap ---
box(Vector3(-2.5, 0.9, 10.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var post1 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12))
post1.position = Vector3(-2.5, 0.9, 10.5)
add_child(post1)
sign3d("CHARGE POST", Vector3(-2.5, 2.3, 10.2))
charge_post(Vector3(-2.5, 0, 10.5))
for x in [-1.0, 1.0]:
box(Vector3(x, 1.0, 15.3), Vector3(0.25, 2.0, 0.25), Color(0.55, 0.55, 0.6)).material = glow(Color(0.8, 0.8, 0.5), 0.5)
@ -394,11 +435,7 @@ func _build_objects() -> void:
sign3d("SPARE MOBILITY UNIT — GC CAT. 6601-W", Vector3(2.5, 1.4, 17.8))
# --- segment C: post 2, drum bay, puddle + relay ---
box(Vector3(-2.8, 0.9, 20.5), Vector3(0.5, 1.8, 0.5), Color(0.2, 0.5, 0.6)).material = glow(Color(0.15, 0.7, 0.85))
var post2 := ElementField.make("electricity", 1.3, Color(0.3, 1.0, 1.0, 0.12))
post2.position = Vector3(-2.8, 0.9, 20.5)
add_child(post2)
sign3d("CHARGE POST", Vector3(-2.8, 2.3, 20.2))
charge_post(Vector3(-2.8, 0, 20.5))
# rotating drum, opening starts facing UP; +90° about z turns it to face the corridor
drum = Node3D.new()

1
src/zones.gd.uid Normal file
View File

@ -0,0 +1 @@
uid://bptk5ky2q0dht