# AI ATLAS original educational scene. Tested in Blender 4.3.2.
# Opens a new scene. Save existing work before running. No network calls.
import bpy, math, json
from pathlib import Path
from mathutils import Vector
OUT = Path(__file__).resolve().parent
bpy.ops.wm.read_factory_settings(use_empty=True)
scene=bpy.context.scene
scene.unit_settings.system='METRIC';scene.unit_settings.scale_length=1.0

def mat(name,color):
 m=bpy.data.materials.new(name);m.diffuse_color=(*color,1);m.use_nodes=True
 m.node_tree.nodes['Principled BSDF'].inputs['Base Color'].default_value=(*color,1)
 m.node_tree.nodes['Principled BSDF'].inputs['Roughness'].default_value=.65
 return m
wood=mat('Warm birch',(.57,.31,.13));green=mat('Sage',(.28,.48,.37));blue=mat('Blue',(.20,.39,.58));paper=mat('Paper',(.86,.79,.60));floor=mat('Floor',(.69,.70,.60));white=mat('Warm white',(.85,.83,.74))
def box(name,loc,size,material):
 bpy.ops.mesh.primitive_cube_add(size=1, location=loc)
 o=bpy.context.object;o.name=name;o.dimensions=size
 bpy.ops.object.transform_apply(location=False,rotation=False,scale=True)
 o.data.materials.append(material)
 return o
box('Floor_3m_x_2m',(0,0,-.06),(3,2,.12),floor)
# Back and left walls are presentation cutaways, not construction design.
box('Back_wall',(0,.98,1.05),(3,.06,2.1),white)
box('Left_wall',(-1.48,0,1.05),(.06,2,2.1),white)
# Shelf placed at rear: 1.2m wide, 0.3m deep, 1.2m tall.
box('Shelf_left',(-1.22,.72,.6),(.06,.3,1.2),wood)
box('Shelf_right',(-.08,.72,.6),(.06,.3,1.2),wood)
for i,z in enumerate([.03,.42,.81,1.17]):box('Shelf_board_'+str(i),(-.65,.72,z),(1.08,.3,.06),wood)
for row,z in enumerate([.22,.61,1.0]):
 for j in range(8):
  box(f'Book_{row}_{j}',(-1.11+j*.12,.72,z),(.08,.19,.30),[green,blue,paper][(j+row)%3])
# Low reading bench and circular side table.
box('Bench_seat',(.70,.64,.42),(1.0,.45,.12),green)
for x in [.31,1.09]:
 for y in [.49,.79]:box(f'Bench_leg_{x}_{y}',(x,y,.18),(.07,.07,.36),wood)
bpy.ops.mesh.primitive_cylinder_add(vertices=32,radius=.30,depth=.06,location=(.65,-.22,.56));bpy.context.object.name='Table_top';bpy.context.object.data.materials.append(paper)
bpy.ops.mesh.primitive_cylinder_add(vertices=16,radius=.055,depth=.53,location=(.65,-.22,.265));bpy.context.object.name='Table_leg';bpy.context.object.data.materials.append(wood)
bpy.ops.mesh.primitive_cylinder_add(vertices=24,radius=.20,depth=.04,location=(.65,-.22,.02));bpy.context.object.name='Table_base';bpy.context.object.data.materials.append(wood)
box('Rug',(-.35,-.30,.01),(1.25,.85,.02),blue)
# Wall artwork uses geometry, no downloaded textures or logos.
box('Poster_frame',(.65,.935,1.5),(.65,.02,.45),wood)
box('Poster_paper',(.65,.919,1.5),(.59,.012,.39),paper)
box('Poster_line_1',(.65,.905,1.55),(.37,.01,.025),green)
box('Poster_line_2',(.65,.905,1.45),(.25,.01,.025),green)
# Export model only. Camera and lights are not part of the GLB.
model_objects=list(scene.objects)
for o in model_objects:o.select_set(True)
bpy.ops.export_scene.gltf(filepath=str(OUT/'reading-corner.glb'),export_format='GLB',use_selection=True)
triangles=sum(sum(len(p.vertices)-2 for p in o.data.polygons) for o in model_objects if o.type=='MESH')
measurements={'blenderVersion':bpy.app.version_string,'meshes':len(model_objects),'triangles':triangles,'floorDimensionsM':list(bpy.data.objects['Floor_3m_x_2m'].dimensions),'benchSeatDimensionsM':list(bpy.data.objects['Bench_seat'].dimensions),'glbBytes':(OUT/'reading-corner.glb').stat().st_size,'note':'Original procedural educational model, not an AI service output or construction design.'}
(OUT/'measurements.json').write_text(json.dumps(measurements,indent=2))
# Orthographic render for a clear comparison of scale and placement.
bpy.ops.object.camera_add(location=(4.2,-6.1,4.6));cam=bpy.context.object;cam.name='Camera';cam.rotation_euler=(Vector((0,0,.7))-cam.location).to_track_quat('-Z','Y').to_euler();cam.data.type='ORTHO';cam.data.ortho_scale=4.9;scene.camera=cam
bpy.ops.object.light_add(type='AREA',location=(0,-1,6));bpy.context.object.data.energy=500;bpy.context.object.data.shape='DISK';bpy.context.object.data.size=5
scene.world=bpy.data.worlds.new('World');scene.world.use_nodes=True;scene.world.node_tree.nodes['Background'].inputs['Color'].default_value=(.8,.85,.8,1);scene.world.node_tree.nodes['Background'].inputs['Strength'].default_value=.45
scene.render.engine='CYCLES';scene.cycles.samples=96;scene.cycles.use_denoising=False;scene.cycles.device='CPU';scene.render.threads_mode='FIXED';scene.render.threads=2
scene.render.resolution_x=960;scene.render.resolution_y=720;scene.render.resolution_percentage=100
scene.render.image_settings.file_format='PNG';scene.render.filepath=str(OUT/'reading-corner.png');scene.render.film_transparent=False
bpy.ops.wm.save_as_mainfile(filepath=str(OUT/'reading-corner.blend'))
bpy.ops.render.render(write_still=True)
print('ATLAS_MEASUREMENTS',json.dumps(measurements))
