feat: Blender-authored roadside districts that rise per chapter
This commit is contained in:
67
assets/blender/districts/export-districts.py
Normal file
67
assets/blender/districts/export-districts.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""Export the district kit to the runtime GLB (positions + indices only).
|
||||
|
||||
blender -b assets/blender/districts/nightdrive-districts.blend --python assets/blender/districts/export-districts.py [-- --preview out.png]
|
||||
|
||||
Normals are derived per fragment at runtime (flat shading from screen-space
|
||||
derivatives), so the GLB carries no normals, UVs or materials and shared box
|
||||
corners stay welded. Writes provenance next to this script.
|
||||
"""
|
||||
import bpy, json, hashlib, sys, math
|
||||
from pathlib import Path
|
||||
|
||||
here = Path(__file__).resolve().parent
|
||||
root = here.parents[2]
|
||||
scene = bpy.data.scenes['Roadside Districts']
|
||||
output = root / 'src/assets/nightdrive-districts.glb'
|
||||
|
||||
for obj in scene.objects:
|
||||
obj.select_set(True)
|
||||
bpy.ops.export_scene.gltf(
|
||||
filepath=str(output), export_format='GLB', use_selection=True, use_active_scene=True,
|
||||
export_apply=True, export_normals=False, export_texcoords=False, export_materials='NONE',
|
||||
export_animations=False, export_cameras=False, export_lights=False, export_yup=True,
|
||||
)
|
||||
triangles = 0
|
||||
for obj in scene.objects:
|
||||
obj.data.calc_loop_triangles()
|
||||
triangles += len(obj.data.loop_triangles)
|
||||
provenance = {
|
||||
'asset': 'Nightdrive roadside districts',
|
||||
'source': 'nightdrive-districts.blend',
|
||||
'authorship': 'Original procedural modelling in Blender for this portfolio (author-districts.py); no external assets.',
|
||||
'editable_scene': 'Roadside Districts',
|
||||
'pieces': sorted({o.name.rsplit('_', 1)[0] for o in scene.objects}),
|
||||
'triangles': triangles,
|
||||
'attributes': 'POSITION + indices; flat normals derived at runtime',
|
||||
'export': '../../../src/assets/nightdrive-districts.glb',
|
||||
'sha256': hashlib.sha256(output.read_bytes()).hexdigest(),
|
||||
}
|
||||
(here / 'nightdrive-districts.asset.json').write_text(json.dumps(provenance, indent=2) + '\n')
|
||||
print(json.dumps(provenance))
|
||||
|
||||
if '--preview' in sys.argv:
|
||||
target = sys.argv[sys.argv.index('--preview') + 1]
|
||||
names = provenance['pieces']
|
||||
for i, name in enumerate(names):
|
||||
for suffix in ('body', 'light'):
|
||||
obj = scene.objects[f'{name}_{suffix}']
|
||||
obj.location = ((i % 4) * 34 - 50, (i // 4) * 40, 0)
|
||||
mat = bpy.data.materials.new(f'preview-{suffix}')
|
||||
mat.diffuse_color = (0.05, 0.05, 0.08, 1) if suffix == 'body' else (0.1, 0.9, 1.0, 1)
|
||||
obj.data.materials.append(mat)
|
||||
cam = bpy.data.objects.new('preview-cam', bpy.data.cameras.new('preview-cam'))
|
||||
scene.collection.objects.link(cam)
|
||||
cam.location = (95, -95, 70)
|
||||
cam.rotation_euler = (math.radians(58), 0, math.radians(45))
|
||||
cam.data.lens = 30
|
||||
scene.camera = cam
|
||||
try:
|
||||
scene.render.engine = 'BLENDER_WORKBENCH'
|
||||
except TypeError as e:
|
||||
print(e)
|
||||
scene.display.shading.color_type = 'MATERIAL'
|
||||
scene.display.shading.light = 'STUDIO'
|
||||
scene.display.shading.show_cavity = True
|
||||
scene.render.resolution_x, scene.render.resolution_y = 1600, 1000
|
||||
scene.render.filepath = target
|
||||
bpy.ops.render.render(write_still=True)
|
||||
Reference in New Issue
Block a user