Elaborate Bloom favela and town detail

This commit is contained in:
Meta Vens 2026-05-05 01:22:25 +01:00
commit d930d28570
9 changed files with 257 additions and 13 deletions

View file

@ -47,6 +47,10 @@ The build follows the current Bloom model:
luxury spoke districts, urban mixed belts, suburban/industrial areas,
industrial/agricultural bands, beach rim, sea band, roads, rivers, cloud
patches, and service routes
- fractal favela wall detail: batched core shacks, child shacks, patched roofs,
stilts, diagonal braces, and catwalks climbing the hubward wall
- elaborated spoke plazas and town fields: plaza rings, kiosks, feeder walks,
nested town houses, and lane networks
- one small Service Ring Kappa marker among many maintenance systems, not the
compositional focus
@ -72,7 +76,7 @@ Result:
```text
AETHERIA_BLOOM_VERIFY ok
AETHERIA_BLOOM_VERIFY group VG Bloom Light Spine 21 31
AETHERIA_BLOOM_VERIFY objects 735
AETHERIA_BLOOM_VERIFY objects 1102
```
## Procedural Translation Notes
@ -85,8 +89,8 @@ This is intentionally hybrid:
geometry-node group used by a Nodes modifier in the scene.
- bpy builds the full shell surfaces, despun core, hub cap, docking port, spun
sheath, spiral spoke loops, endcaps, frame-transfer arteries, wrapped region
patches, city blocks, roads, rivers, clouds, utility lines, service markers,
and cameras.
patches, city blocks, batched favela/town/plaza detail, roads, rivers, clouds,
utility lines, service markers, and cameras.
The IRCSS pass paid off in three ways:
@ -104,6 +108,10 @@ The IRCSS pass paid off in three ways:
- **Golden-angle filling:** spoke placement uses the sunflower trick, stepping
by the golden angle along the axis so each new spoke avoids the previous
radial lanes while still reading as one organic exchange network.
- **Batched micro-detail:** rickety visual detail should not mean one Blender
object per plank. The favela/town pass batches many boxes into shared meshes
and many brace/catwalk paths into shared curve objects, preserving detail
without making scene generation stall.
- **Python as orchestration:** the cylinder layers, region maps, city blocks,
social-gradient bands, roads, rivers, forests, clouds, and spokes come from
small tables and named helpers rather than copied object placement.
@ -111,7 +119,8 @@ The IRCSS pass paid off in three ways:
## Current Limits
- The build is a spatial systems study, not final art.
- The civic surface is a symbolic map-layer world, not a lived city.
- The civic surface is still a symbolic map-layer world, but the hubward favela
now has enough nested structure to read as precarious built habitat.
- The current whole-Bloom view is less skeletal, but still a study. It needs
denser horizon city detail and better art-directed lighting before it earns
the word cinematic without fraud.

View file

@ -177,6 +177,208 @@ def add_surface_block_field(name, x_values, angles, material, size, radial_lift=
)
def append_box_parts(verts, faces, loc, axes, size):
from mathutils import Vector
origin = Vector(loc)
ax = [Vector(axis).normalized() for axis in axes]
sx, sy, sz = (value * 0.5 for value in size)
base = len(verts)
for dx, dy, dz in [
(-sx, -sy, -sz),
(sx, -sy, -sz),
(sx, sy, -sz),
(-sx, sy, -sz),
(-sx, -sy, sz),
(sx, -sy, sz),
(sx, sy, sz),
(-sx, sy, sz),
]:
v = origin + ax[0] * dx + ax[1] * dy + ax[2] * dz
verts.append((v.x, v.y, v.z))
faces.extend(
[
(base + 0, base + 1, base + 2, base + 3),
(base + 4, base + 7, base + 6, base + 5),
(base + 0, base + 4, base + 5, base + 1),
(base + 1, base + 5, base + 6, base + 2),
(base + 2, base + 6, base + 7, base + 3),
(base + 3, base + 7, base + 4, base + 0),
]
)
def add_mesh_parts(name, verts, faces, material):
import bpy
mesh = bpy.data.meshes.new(name + "Mesh")
mesh.from_pydata(verts, [], faces)
mesh.update()
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
obj.data.materials.append(material)
return obj
def add_multi_polyline_curve(name, lines, bevel, material, resolution=2):
import bpy
curve = bpy.data.curves.new(name + "Curve", "CURVE")
curve.dimensions = "3D"
curve.resolution_u = resolution
curve.bevel_depth = bevel
curve.bevel_resolution = 2
for line in lines:
spline = curve.splines.new("POLY")
spline.points.add(len(line) - 1)
for point, co in zip(spline.points, line):
point.co = (co[0], co[1], co[2], 1.0)
obj = bpy.data.objects.new(name, curve)
bpy.context.collection.objects.link(obj)
obj.data.materials.append(material)
return obj
def add_surface_stilt(name, x, angle, inner_lift, outer_lift, material, radius=0.009):
start = surface_point(x, angle, INNER_RADIUS, lift=inner_lift)
end = surface_point(x, angle, INNER_RADIUS, lift=outer_lift)
return add_cylinder_between(name, start, end, radius, material, vertices=6)
def add_surface_brace(name, x0, angle0, x1, angle1, lift0, lift1, material, bevel=0.006):
return add_curve_polyline(
name,
[
surface_point(x0, angle0, INNER_RADIUS, lift=lift0),
surface_point((x0 + x1) * 0.5, (angle0 + angle1) * 0.5, INNER_RADIUS, lift=(lift0 + lift1) * 0.5 - 0.03),
surface_point(x1, angle1, INNER_RADIUS, lift=lift1),
],
bevel,
material,
resolution=3,
)
def add_favela_fractal_cluster(prefix, x_values, angles, mats):
shack_verts, shack_faces = [], []
roof_verts, roof_faces = [], []
brace_lines = []
for ix, x in enumerate(x_values):
for ia, angle in enumerate(angles):
lean = ((ix * 5 + ia * 3) % 5 - 2) * 0.018
root = f"{prefix}_{ix:02d}_{ia:02d}"
axes = ((1, 0, 0), tangent(angle + lean), radial(angle + lean))
append_box_parts(shack_verts, shack_faces, surface_point(x, angle + lean, INNER_RADIUS, lift=-0.38), axes, (0.2, 0.12, 0.24))
for level in range(2):
lift = -0.55 - level * 0.14
width = 0.13 - level * 0.015
for wing in (-1, 1):
dx = wing * (0.09 + 0.035 * level)
da = wing * (0.018 + 0.012 * level) + lean
local_axes = ((1, 0, 0), tangent(angle + da), radial(angle + da))
append_box_parts(
shack_verts,
shack_faces,
surface_point(x + dx, angle + da, INNER_RADIUS, lift=lift),
local_axes,
(width, 0.075, 0.11),
)
roof_axes = ((1, 0, 0), tangent(angle + da + 0.006 * wing), radial(angle + da + 0.006 * wing))
append_box_parts(
roof_verts,
roof_faces,
surface_point(x + dx + 0.012 * wing, angle + da + 0.006 * wing, INNER_RADIUS, lift=lift - 0.07),
roof_axes,
(width * 1.22, 0.095, 0.018),
)
brace_lines.append(
[
surface_point(x + dx - width * 0.25, angle + da - 0.006, INNER_RADIUS, lift=lift + 0.05),
surface_point(x + dx - width * 0.25, angle + da - 0.006, INNER_RADIUS, lift=-0.25),
]
)
brace_lines.append(
[
surface_point(x + dx - width * 0.42, angle + da - 0.012, INNER_RADIUS, lift=lift + 0.02),
surface_point(x + dx, angle + da, INNER_RADIUS, lift=lift - 0.04),
surface_point(x + dx + width * 0.42, angle + da + 0.012, INNER_RADIUS, lift=lift - 0.09),
]
)
for step in range(2):
brace_lines.append(
[
surface_point(x - 0.18, angle + lean + step * 0.028, INNER_RADIUS, lift=-0.62 - step * 0.08),
surface_point(x, angle + lean + 0.035 + step * 0.025, INNER_RADIUS, lift=-0.62 - step * 0.08),
surface_point(x + 0.2, angle + lean + step * 0.02, INNER_RADIUS, lift=-0.62 - step * 0.08),
]
)
add_mesh_parts(prefix + "_shack_mesh", shack_verts, shack_faces, mats["favela"])
add_mesh_parts(prefix + "_roof_mesh", roof_verts, roof_faces, mats["shack_roof"])
add_multi_polyline_curve(prefix + "_brace_and_catwalks", brace_lines, 0.005, mats["brace"], resolution=2)
def add_town_detail_cluster(prefix, x_values, angles, material, road_material):
verts, faces = [], []
lanes = []
for ix, x in enumerate(x_values):
for ia, angle in enumerate(angles):
root = f"{prefix}_{ix:02d}_{ia:02d}"
for lane in (-1, 0, 1):
local_angle = angle + lane * 0.024
lanes.append(
[
surface_point(x - 0.32, local_angle - 0.014, INNER_RADIUS, lift=-0.37),
surface_point(x, local_angle + 0.008, INNER_RADIUS, lift=-0.37),
surface_point(x + 0.32, local_angle - 0.006, INNER_RADIUS, lift=-0.37),
]
)
for b in range(3):
dx = -0.22 + b * 0.22 + ((ix + ia + b) % 3 - 1) * 0.018
da = lane * 0.026 + ((ix * 7 + ia * 5 + b) % 5 - 2) * 0.004
height = 0.12 + 0.035 * ((ix + ia + b) % 4)
append_box_parts(
verts,
faces,
surface_point(x + dx, angle + da, INNER_RADIUS, lift=-0.3 - height * 0.5),
((1, 0, 0), tangent(angle + da), radial(angle + da)),
(0.12, 0.07, height),
)
add_mesh_parts(prefix + "_nested_house_mesh", verts, faces, material)
add_multi_polyline_curve(prefix + "_lane_network", lanes, 0.006, road_material, resolution=2)
def add_spoke_plaza_detail(prefix, x, angle, mats, seed):
add_surface_curve(
f"{prefix}_plaza_ring",
[(x + 0.34 * pymath.cos(t), angle + 0.065 * pymath.sin(t)) for t in [TAU * i / 28 for i in range(29)]],
INNER_RADIUS,
0.01,
mats["road"],
lift=-0.42,
)
for i in range(10):
t = TAU * i / 10 + seed * 0.13
dx = 0.28 * pymath.cos(t)
da = 0.052 * pymath.sin(t)
add_surface_box(
f"{prefix}_kiosk_{i:02d}",
x + dx,
angle + da,
mats["luxury"],
size=(0.09, 0.055, 0.1 + 0.025 * (i % 3)),
radial_lift=-0.37,
)
for i, spoke_da in enumerate((-0.11, -0.055, 0.055, 0.11)):
add_surface_curve(
f"{prefix}_feeder_walk_{i:02d}",
[(x - 0.45, angle + spoke_da), (x, angle + spoke_da * 0.3), (x + 0.45, angle - spoke_da * 0.6)],
INNER_RADIUS,
0.008,
mats["pressure_line"],
lift=-0.43,
)
def add_rotating_spoke(name, x, angle, inner_radius, outer_radius, material, radius=0.045, vertices=10):
r = radial(angle)
return add_cylinder_between(
@ -374,6 +576,8 @@ def build_scene():
"farm": mat("TCS Root farms", (0.15, 0.55, 0.24), alpha=0.92),
"district": mat("surface districts", (0.55, 0.58, 0.62), alpha=0.95),
"favela": mat("hubcap terrace slums", (0.74, 0.48, 0.26), alpha=0.98),
"shack_roof": mat("patched favela sheet metal", (0.46, 0.39, 0.32), alpha=0.98),
"brace": mat("rickety brace dark steel", (0.12, 0.10, 0.085), alpha=0.98),
"luxury": mat("luxury spoke districts", (0.82, 0.78, 0.62), alpha=0.98),
"industrial": mat("industrial works", (0.32, 0.34, 0.36), alpha=0.98),
"suburban": mat("suburban mixed belt", (0.5, 0.64, 0.5), alpha=0.96),
@ -483,12 +687,33 @@ def build_scene():
dense_angles = [pymath.radians(a) for a in range(-165, 180, 15)]
add_surface_block_field("layered_hubcap_slum_stack", [-8.65, -8.25, -7.85, -7.45], dense_angles, mats["favela"], size=(0.16, 0.08, 0.22), radial_lift=-0.35, jitter=0.035)
add_surface_block_field("hyperurban_microtower", [-7.0, -6.55, -6.1, -5.7], dense_angles[::2], mats["city"], size=(0.2, 0.1, 0.36), radial_lift=-0.42, jitter=0.03)
add_favela_fractal_cluster(
"fractal_wall_favela",
[-8.78, -8.42, -8.06, -7.7, -7.34, -6.98, -6.62],
[pymath.radians(a) for a in range(-165, 181, 30)],
mats,
)
add_town_detail_cluster(
"hyperurban_nested_town",
[-7.1, -6.65, -6.2, -5.75],
[pymath.radians(a) for a in range(-150, 181, 45)],
mats["city"],
mats["road"],
)
for x in [-5.0, -4.2, -3.4]:
for a in prestige_angles[:8]:
for ia, a in enumerate(prestige_angles[:8]):
add_surface_box(f"luxury_spoke_plaza_{x:.1f}_{a:.2f}", x, a, mats["luxury"], size=(0.55, 0.34, 0.14), radial_lift=-0.31)
add_spoke_plaza_detail(f"luxury_spoke_plaza_detail_{x:.1f}_{ia:02d}", x, a, mats, ia)
for da in (-0.16, 0.16):
add_surface_box(f"luxury_spoke_tower_{x:.1f}_{a:.2f}_{da:.1f}", x + da, a + da, mats["city"], size=(0.18, 0.1, 0.42), radial_lift=-0.44)
add_surface_block_field("mixed_suburban_industrial_block", [-2.2, -1.4, -0.6, 0.2], [pymath.radians(a) for a in range(-150, 181, 30)], mats["suburban"], size=(0.42, 0.18, 0.12), radial_lift=-0.27, jitter=0.04)
add_town_detail_cluster(
"mixed_belt_nested_town",
[-2.35, -1.65, -0.95, -0.25, 0.45],
[pymath.radians(a) for a in range(-150, 181, 60)],
mats["suburban"],
mats["road"],
)
add_surface_block_field("factory_yard_block", [1.2, 2.0, 2.8, 3.6], [pymath.radians(a) for a in range(-150, 181, 45)], mats["industrial"], size=(0.62, 0.22, 0.16), radial_lift=-0.29, jitter=0.035)
add_surface_block_field("farm_service_shed", [4.2, 5.0, 5.6], [pymath.radians(a) for a in range(-165, 181, 45)], mats["farm"], size=(0.52, 0.16, 0.08), radial_lift=-0.24, jitter=0.04)
for i, deg in enumerate(range(-170, 181, 20)):

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

After

Width:  |  Height:  |  Size: 2 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Before After
Before After

View file

@ -60,11 +60,11 @@ generates an Aetheria Bloom whole-habitat study using Bloom lore plus Eric
Bruneton's Rama making-of as a cylindrical-world reference. It now emphasizes
whole-cylinder mapped spaces and frame interfaces: full shell layers, despun
hub cap and docking core, spun spire sheath, shared x/angle/radius coordinate
helpers, golden-angle spiral spoke and transfer-loop distribution, layered
endcaps, hub-cap terrace slums, favela/hyperurban belts, luxury spoke districts,
mixed urban/suburban/industrial belts, industrial/agricultural areas, beach and
sea bands, roads, rivers, airflow cloud patches, and surface service seams.
Kappa is only a small service marker. Build notes live at
helpers, golden-angle spoke/transfer loops, layered endcaps, mapped civic
bands, roads, rivers, cloud patches, and service seams. The hubward favela wall
uses batched fractal shack/roof/brace/catwalk detail; plazas and towns have
nested buildings, kiosks, feeder walks, and lane networks. Kappa is only a
small service marker. Build notes live at
`docs/research/builds/aetheria-bloom-habitat.md`; verification lives at
`tools/verify_aetheria_bloom_habitat.py`.

View file

@ -37,3 +37,4 @@
{"ts": "2026-05-04T23:10:37+00:00", "type": "implementation", "status": "accepted", "note": "Built a from-scratch Aetheria Bloom habitat study after reading Bloom lore and Bruneton Rama making-of references. Refocused from Kappa detail to whole-cylinder spaces: layered shell, axial hub/light spine, spokes, central water band, plains/farms, forests, city clusters, wrapped roads/rivers, cloud patches, utility routes, and one small service-ring marker. Blender verification passes with VG Bloom Light Spine at 21 nodes/31 links and 98 geometry/text objects."}
{"ts": "2026-05-04T23:38:17+00:00", "type": "implementation", "status": "accepted", "note": "Reworked the Aetheria Bloom build from a cutout/map-layer view into a full 360-degree whole-habitat composition: full shell layers, despun center-axis core and docking hub cap, spun spire sheath, multi-station major spokes, thin utility spokes, frame-transfer arteries, hub-cap terrace slums, favela/hyperurban belts, luxury spoke districts, mixed urban/suburban/industrial belts, industrial/agricultural areas, beach and sea bands, roads/rivers, and airflow cloud patches. Verification now passes with 481 geometry/text objects and VG Bloom Light Spine still 21 nodes/31 links."}
{"ts": "2026-05-04T23:59:24+00:00", "type": "implementation", "status": "accepted", "note": "Aetheria Bloom whole-habitat pass now uses shared cylindrical coordinate helpers, golden-angle spiral spoke/transfer loops, and explicit layered endcaps; Blender verifier passed with 735 geometry/text objects and light-spine Geometry Script group at 21 nodes/31 links."}
{"ts": "2026-05-05T00:21:08+00:00", "type": "implementation", "status": "accepted", "note": "Bloom detail pass added batched fractal favela wall detail, elaborated spoke plazas, and nested town fields; initial per-object version timed out, batching preserved visual detail and verifier passed with 1102 geometry/text objects."}

View file

@ -96,8 +96,8 @@ data_flow:
- If state grows faster than understanding, cut it back.
current_status:
summary: VibeGeometry has an initial persistence scaffold plus verified Geometry Script translations for local math/utility samples, a first official Blender demo tranche, IRCSS French Houses city-scale graph doctrine, and a from-scratch Aetheria Bloom whole-habitat build. The IRCSS pass verified MakeSpiral and PointyGothicCone, then mapped the 108-group town kit through a dependency map, all-node atlas, and node mechanism study. The Bloom pass used Aetheria lore plus Bruneton's Rama making-of to generate a full cylindrical world study with shell anatomy, despun hub cap and docking core, spun spire sheath, shared x/angle/radius coordinate helpers, golden-angle spiral spoke and transfer-loop distribution, layered endcaps, social-gradient inner geography from terrace slums to luxury spokes to industrial/agricultural/beach zones, roads/rivers, cloud-flow patches, surface service seams, and service markers. The remaining large-system blockers are repeat-zone feedback, repeat Top outputs, foreach zones, and gizmo nodes.
next_action: Continue the Aetheria Bloom build by moving the shared cylindrical coordinate helpers plus spiral spoke/transfer-artery network into reusable Geometry Script groups, then improve atmospheric/light readability from render evidence.
summary: VibeGeometry has an initial persistence scaffold plus verified Geometry Script translations for local math/utility samples, a first official Blender demo tranche, IRCSS French Houses city-scale graph doctrine, and a from-scratch Aetheria Bloom whole-habitat build. The IRCSS pass verified MakeSpiral and PointyGothicCone, then mapped the 108-group town kit through a dependency map, all-node atlas, and node mechanism study. The Bloom pass used Aetheria lore plus Bruneton's Rama making-of to generate a full cylindrical world study with shell anatomy, despun hub cap and docking core, spun spire sheath, shared x/angle/radius coordinate helpers, golden-angle spiral spoke and transfer-loop distribution, layered endcaps, social-gradient inner geography, batched fractal favela wall detail, elaborated spoke plazas/town fields, roads/rivers, cloud-flow patches, surface service seams, and service markers. The remaining large-system blockers are repeat-zone feedback, repeat Top outputs, foreach zones, and gizmo nodes.
next_action: Continue the Aetheria Bloom build by moving the shared cylindrical coordinate helpers plus batched favela/town/plaza and spiral spoke/transfer-artery networks into reusable Geometry Script groups, then improve atmospheric/light readability from render evidence.
remotes:
vibegeometry: https://github.com/GameCult/VibeGeometry
geometry_script_fork: https://github.com/GameCult/geometry-script

View file

@ -54,7 +54,16 @@ REQUIRED_OBJECTS = {
"wrapped_river_0",
"airflow_cloud_patch_0",
"layered_hubcap_slum_stack_00_00",
"fractal_wall_favela_shack_mesh",
"fractal_wall_favela_roof_mesh",
"fractal_wall_favela_brace_and_catwalks",
"hyperurban_nested_town_nested_house_mesh",
"hyperurban_nested_town_lane_network",
"luxury_spoke_plaza_-5.0_-3.14",
"luxury_spoke_plaza_detail_-5.0_00_plaza_ring",
"luxury_spoke_plaza_detail_-5.0_00_kiosk_00",
"luxury_spoke_plaza_detail_-5.0_00_feeder_walk_00",
"mixed_belt_nested_town_nested_house_mesh",
"factory_yard_block_00_00",
"axial_surface_service_lane_00",
"circumferential_market_seam_00",
@ -86,7 +95,7 @@ def verify_scene():
assert_true(path.stat().st_size > 10_000, f"Generated artifact is suspiciously small: {path}")
mesh_objects = [obj for obj in bpy.data.objects if obj.type in {"MESH", "CURVE", "FONT"}]
assert_true(len(mesh_objects) >= 500, f"Expected a populated whole-Bloom study scene, found {len(mesh_objects)} geometry/text objects")
assert_true(len(mesh_objects) >= 760, f"Expected a populated whole-Bloom study scene, found {len(mesh_objects)} geometry/text objects")
print("AETHERIA_BLOOM_VERIFY ok")
print("AETHERIA_BLOOM_VERIFY group", group.name, len(group.nodes), len(group.links))