summaryrefslogtreecommitdiff
path: root/stage/blender
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 00:29:43 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 00:29:43 +0800
commitdc454966bcacabb7df032edfda51759ecd9d3d94 (patch)
tree8249ee79abe67734d87128f62b331e797b8c7feb /stage/blender
parent9ec32a2ae03aabdae2828aa87a6a7689fedb96a6 (diff)
downloadsomhairles-dream-fsharp-dc454966bcacabb7df032edfda51759ecd9d3d94.tar.gz
feat(ship): PLA Space Force livery (deep-space blue, twin gold stripes, red star), crew details, aft transition structure; remove workspace grid and axis readout
Diffstat (limited to 'stage/blender')
-rw-r--r--stage/blender/ship.py104
1 files changed, 95 insertions, 9 deletions
diff --git a/stage/blender/ship.py b/stage/blender/ship.py
index 8a67673..9ba04a4 100644
--- a/stage/blender/ship.py
+++ b/stage/blender/ship.py
@@ -125,12 +125,14 @@ STEP_OBJECTS = {
"hnx02.detail.antenna",
"hnx02.detail.glow",
"hnx02.detail.glass",
+ "hnx02.livery.stripes",
+ "hnx02.livery.insignia",
],
}
# Material keys per object id.
OBJECT_MATERIAL = {
- "hnx02.hull.core": "white",
+ "hnx02.hull.core": "hull",
"hnx02.spine.truss": "hull",
"hnx02.node.forward": "white",
"hnx02.hab.a": "white",
@@ -150,6 +152,8 @@ OBJECT_MATERIAL = {
"hnx02.detail.antenna": "hull",
"hnx02.detail.glow": "glow",
"hnx02.detail.glass": "glass",
+ "hnx02.livery.stripes": "gold",
+ "hnx02.livery.insignia": "insignia",
}
@@ -185,18 +189,20 @@ def make_material(bpy, name, color, *, metallic=0.0, roughness=0.45, emission=No
def build_materials(bpy):
return {
- "hull": make_material(bpy, "hnx02.hull", (0.62, 0.64, 0.66), metallic=0.88, roughness=0.38),
- "white": make_material(bpy, "hnx02.white", (0.86, 0.86, 0.84), metallic=0.18, roughness=0.52),
+ # PLA Space Force livery: "deep-space blue" hull (深空蓝) with gold accents.
+ "hull": make_material(bpy, "hnx02.hull", (0.035, 0.070, 0.230), metallic=0.60, roughness=0.44),
+ "white": make_material(bpy, "hnx02.white", (0.80, 0.82, 0.85), metallic=0.18, roughness=0.52),
"shield": make_material(bpy, "hnx02.shield", (0.44, 0.46, 0.50), metallic=0.30, roughness=0.72),
"dark": make_material(bpy, "hnx02.dark", (0.10, 0.11, 0.13), metallic=0.72, roughness=0.48),
"radiator": make_material(bpy, "hnx02.radiator", (0.90, 0.91, 0.92), metallic=0.08, roughness=0.30),
"pv": make_material(bpy, "hnx02.pv", (0.07, 0.10, 0.24), metallic=0.35, roughness=0.28),
- "gold": make_material(bpy, "hnx02.gold", (0.82, 0.58, 0.19), metallic=1.0, roughness=0.30),
+ "gold": make_material(bpy, "hnx02.gold", (0.86, 0.63, 0.16), metallic=1.0, roughness=0.28),
+ "insignia": make_material(bpy, "hnx02.insignia", (0.72, 0.09, 0.09), metallic=0.15, roughness=0.45),
"copper": make_material(bpy, "hnx02.copper", (0.70, 0.44, 0.19), metallic=1.0, roughness=0.34),
"glow": make_material(bpy, "hnx02.glow", (1.0, 0.35, 0.10), metallic=0.0, roughness=0.6,
emission=(1.0, 0.42, 0.14), emission_strength=9.0),
- "glass": make_material(bpy, "hnx02.glass", (0.55, 0.75, 0.95), metallic=0.0, roughness=0.25,
- emission=(0.55, 0.80, 1.0), emission_strength=4.5),
+ "glass": make_material(bpy, "hnx02.glass", (0.95, 0.84, 0.55), metallic=0.0, roughness=0.25,
+ emission=(0.98, 0.86, 0.52), emission_strength=5.0),
}
@@ -764,8 +770,8 @@ def b_hull_core(bm):
a = 2.0 * math.pi * k / count
radial = Vector((math.cos(a), 0.0, math.sin(a)))
wc = c0 + radial * r
- cyl(bm, wc - radial * 0.12, wc + radial * 0.18, 0.22, seg=12, cap1=False)
- torus(bm, wc + radial * 0.18, 0.245, 0.05, axis=radial, seg=14, rseg=5)
+ cyl(bm, wc - radial * 0.12, wc + radial * 0.20, 0.28, seg=12, cap1=False)
+ torus(bm, wc + radial * 0.20, 0.305, 0.055, axis=radial, seg=14, rseg=5)
panel_bank(bm, p1 + Vector((0.0, 3.5, 0.0)), p2 - Vector((0.0, 3.5, 0.0)),
r + 0.035, cols=72, rows=18, depth=0.05)
for (t0, count, seed) in ((0.10, 26, 601), (0.60, 30, 602), (0.90, 22, 603)):
@@ -892,6 +898,26 @@ def b_reactor(bm):
def b_thrust_cone(bm):
+ # Aft transition structure: heavy beams + ring frames that visibly tie the
+ # hull to the propulsion section instead of leaving a bare truss gap.
+ for k in range(4):
+ a = math.pi / 4.0 + k * math.pi / 2.0
+ radial = Vector((math.cos(a), 0.0, math.sin(a)))
+ cyl(bm, Vector((0.0, -3.0, 0.0)) + radial * (HULL_R * 0.92),
+ Vector((0.0, -30.0, 0.0)) + radial * 2.6, 0.26, seg=10)
+ for t in (0.12, 0.32, 0.52, 0.72, 0.9):
+ yy = -3.0 - 27.0 * t
+ rr = HULL_R * 0.92 + (2.6 - HULL_R * 0.92) * t
+ torus(bm, Vector((0.0, yy, 0.0)), rr, 0.11, axis=(0, 1, 0), seg=24, rseg=6)
+ # propellant feed lines: tanks -> reactor -> engines
+ for sx in (-1.0, 1.0):
+ for dz in (0.6, -0.6):
+ pipe_run(bm, [
+ (sx * TANK_X, -25.0, dz * TANK_R),
+ (sx * 4.6, -31.0, dz * 2.3),
+ (sx * 2.2, -36.0, dz * 1.5),
+ (sx * 1.3, -40.0, dz * 0.9),
+ ], 0.15)
thrust_cone(bm, (0.0, -33.5, 0.0), (0, -1, 0), 3.6, 2.9, 1.8, struts=14)
shadow_shield(bm, (0.0, -35.6, 0.0), (0, -1, 0), 4.4, seg=36, ribs=12)
@@ -974,6 +1000,51 @@ def b_orion(bm):
bell(bm, base - Vector((0, 0.6, 0)), (0, -1, 0), 1.5, 0.22, 0.68, seg=22, layers=9)
+def five_star(bm, center, normal, radius, depth=0.09):
+ """Filled five-pointed star stamped on the hull (PLA insignia)."""
+ n = Vector(normal).normalized()
+ x, y, _ = basis(n)
+ c = Vector(center)
+ front, back = [], []
+ for i in range(10):
+ a = math.pi / 2.0 + i * math.pi / 5.0
+ rr = radius if i % 2 == 0 else radius * 0.382
+ p = c + (x * math.cos(a) + y * math.sin(a)) * rr
+ front.append(bm.verts.new(p + n * depth * 0.5))
+ back.append(bm.verts.new(p - n * depth * 0.5))
+ cf = bm.verts.new(c + n * depth * 0.5)
+ cb = bm.verts.new(c - n * depth * 0.5)
+ for i in range(10):
+ j = (i + 1) % 10
+ bm.faces.new((cf, front[i], front[j]))
+ bm.faces.new((cb, back[j], back[i]))
+ bm.faces.new((front[i], back[i], back[j], front[j]))
+
+
+def b_stripes(bm):
+ """Twin gold stripes down both flanks — PLA Space Force colour band."""
+ p1, p2 = Vector(HULL_P1), Vector(HULL_P2)
+ length = (p2 - p1).length
+ for base_deg in (0.0, 180.0):
+ for offset in (-20.0, 20.0):
+ a = math.radians(base_deg + offset)
+ radial = Vector((math.cos(a), 0.0, math.sin(a)))
+ tangent = radial.cross(Vector((0.0, 1.0, 0.0))).normalized()
+ c = (p1 + p2) * 0.5 + radial * (HULL_R + 0.14)
+ box(bm, c, 0.035, length * 0.455, 0.26, radial, Vector((0.0, 1.0, 0.0)), tangent)
+
+
+def b_insignia(bm):
+ """Red star insignia placed where nothing occludes them."""
+ for sx in (-1.0, 1.0):
+ a = 0.0 if sx > 0.0 else math.pi
+ radial = Vector((math.cos(a), 0.0, math.sin(a)))
+ # forward hull, in the clear band between the water wall and the node
+ five_star(bm, Vector((0.0, 40.2, 0.0)) + radial * (HULL_R + 0.06), radial, 1.9, 0.13)
+ # outboard face of the side-mounted modules
+ five_star(bm, Vector((sx * (6.6 + 2.6 + 0.05), 21.0, 0.0)), (sx, 0.0, 0.0), 1.5, 0.11)
+
+
def b_glow(bm):
"""Heat glow rings inside the engine bells."""
for ex in (-2.4, 2.4):
@@ -995,7 +1066,7 @@ def b_glass(bm):
a = 2.0 * math.pi * k / count
radial = Vector((math.cos(a), 0.0, math.sin(a)))
wc = c0 + radial * (HULL_R + 0.18)
- cyl(bm, wc - radial * 0.02, wc + radial * 0.05, 0.17, seg=10)
+ cyl(bm, wc - radial * 0.02, wc + radial * 0.06, 0.23, seg=10)
def b_greeble(bm):
@@ -1020,6 +1091,19 @@ def b_greeble(bm):
cyl(bm, Vector(pos), Vector(pos) + d * 0.15, rad, seg=10)
cyl(bm, Vector(pos) + d * 0.15, Vector(pos) + d * 0.34, rad * 0.7, seg=10)
equipment_row(bm, (0.0, 34.0, r + 0.15), (0, 1, 0), (0, 0, 1), 12, 1.0, 0.10, 0.24, seed=501)
+ # EVA handrail runs (crew translation paths along the hull)
+ for sx in (-1.0, 1.0):
+ for (yy0, count) in ((24.0, 10), (4.0, 12)):
+ a = math.radians(-14.0 if sx > 0.0 else 194.0)
+ radial = Vector((math.cos(a), 0.0, math.sin(a)))
+ tangent = Vector((0.0, 1.0, 0.0))
+ for k in range(count):
+ yy = yy0 + k * 1.35
+ base = Vector((0.0, yy, 0.0)) + radial * HULL_R
+ tip = base + radial * 0.42
+ cyl(bm, base, tip, 0.045, seg=6)
+ if k < count - 1:
+ cyl(bm, tip, tip + tangent * 1.35, 0.035, seg=5)
equipment_row(bm, (0.0, 6.0, -r - 0.15), (0, 1, 0), (0, 0, -1), 14, 1.0, 0.10, 0.24, seed=502)
@@ -1052,6 +1136,8 @@ BUILDERS = {
"hnx02.detail.antenna": b_antenna,
"hnx02.detail.glow": b_glow,
"hnx02.detail.glass": b_glass,
+ "hnx02.livery.stripes": b_stripes,
+ "hnx02.livery.insignia": b_insignia,
}