| 1234567891011121314151617181920212223242526272829303132333435363738 |
- """Render actual exported pilot GLBs for offline asset review, not a browser screenshot."""
- import bpy, json, math
- from pathlib import Path
- from mathutils import Vector
- BASE = Path('.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/negative-estate-pilot').resolve()
- OUT = BASE/'offline-renders-v3'
- if OUT.exists(): raise RuntimeError('Use a fresh render directory')
- OUT.mkdir()
- plan = json.loads((BASE/'input-v2/seated-plan.json').read_text())
- manifest = json.loads((BASE/'export-v3/manifest.json').read_text())
- bpy.ops.wm.read_factory_settings(use_empty=True)
- for cell in manifest['cells']:
- bpy.ops.import_scene.gltf(filepath=str(BASE/'export-v3'/cell['lod0']['uri']))
- scene = bpy.context.scene
- scene.render.engine = 'CYCLES';scene.cycles.samples=16
- scene.render.resolution_x=512;scene.render.resolution_y=512;scene.render.resolution_percentage=100
- scene.render.image_settings.file_format='PNG'
- scene.world = bpy.data.worlds.new('Review world');scene.world.use_nodes=True
- scene.world.node_tree.nodes['Background'].inputs[0].default_value=(.65,.68,.72,1)
- scene.world.node_tree.nodes['Background'].inputs[1].default_value=.6
- scene.view_settings.view_transform='AgX'
- sun_data=bpy.data.lights.new('Review sun','SUN');sun_data.energy=2.5
- sun=bpy.data.objects.new('Review sun',sun_data);scene.collection.objects.link(sun);sun.rotation_euler=(math.radians(25),math.radians(-20),math.radians(-30))
- cam_data=bpy.data.cameras.new('Review camera');cam=bpy.data.objects.new('Review camera',cam_data);scene.collection.objects.link(cam);scene.camera=cam
- cam_data.type='ORTHO';cam_data.lens=50
- meshes = [o for o in scene.objects if o.type=='MESH']
- records=[]
- for building in plan['buildings']:
- target=next(o for o in meshes if o.name==building['id'])
- for o in meshes:o.hide_render=(o!=target)
- points=[target.matrix_world@Vector(c) for c in target.bound_box]
- low=Vector(tuple(min(p[i] for p in points) for i in range(3)));high=Vector(tuple(max(p[i] for p in points) for i in range(3)));center=(low+high)/2
- size=max(high-low);cam.location=center+Vector((1,-1,.85)).normalized()*size*3
- cam.rotation_euler=(center-cam.location).to_track_quat('-Z','Y').to_euler();cam_data.ortho_scale=size*1.5
- file=OUT/(building['id']+'.png');scene.render.filepath=str(file);bpy.ops.render.render(write_still=True)
- records.append({'id':building['id'],'image':str(file),'from':'export-v3 actual LOD0 glTF import','estimatedFloors':building['floors'],'estimatedHeightM':building['heightM']})
- (OUT/'manifest.json').write_text(json.dumps({'images':records,'browserUsed':False,'runtimeVisualAcceptance':False,'note':'Isolated authored asset view; world lighting differs from cockpit grade/fog, foundation shown below grade.'},indent=2),encoding='utf8')
- print('PILOT_REVIEW_RENDER',json.dumps({'images':len(records),'output':str(OUT)}))
|