"""Original flat-cutout camera study for Blender 5
Run: blender --background --python render-depth-card-study.py -- /new/output
No downloaded art, model inference, physical volume or texture reconstruction.
"""
import bpy
import math
import sys
import json
from pathlib import Path
from mathutils import Vector

out=Path(sys.argv[sys.argv.index('--')+1]);out.mkdir(parents=True,exist_ok=False)
materials={}
def mat(name,color):
    if name in materials:return materials[name]
    m=bpy.data.materials.new(name);m.diffuse_color=(*color,1);m.use_nodes=True
    n=m.node_tree.nodes;n.clear();e=n.new('ShaderNodeEmission');e.inputs['Color'].default_value=(*color,1);e.inputs['Strength'].default_value=1
    o=n.new('ShaderNodeOutputMaterial');m.node_tree.links.new(e.outputs[0],o.inputs[0]);materials[name]=m;return m
palette={'wall':(.06,.10,.17),'window':(.25,.55,.66),'frame':(.13,.22,.30),'coat':(.38,.25,.55),'face':(.80,.62,.42),'desk':(.17,.26,.32),'paper':(.84,.75,.52)}
source=[]
def shape(name,verts,color):source.append((name,verts,color))
def rect(name,x1,x2,z1,z2,y,color):shape(name,[(x1,y,z1),(x2,y,z1),(x2,y,z2),(x1,y,z2)],color)
rect('back wall',-12,12,-1,8,5,'wall')
for i in range(3):
    x=-4+i*3.5
    rect('window '+str(i),x,x+2.2,2,5.6,4.99,'window')
    rect('window bar '+str(i),x+1.04,x+1.16,2,5.6,4.98,'frame')
rect('body',-.65,.65,1.1,3.5,2,'coat')
shape('head',[(.48*math.cos(2*math.pi*i/64),1.99,3.95+.48*math.sin(2*math.pi*i/64)) for i in range(64)],'face')
rect('left leg',-.58,-.12,.2,1.2,2,'coat');rect('right leg',.12,.58,.2,1.2,2,'coat')
rect('near desk',-8,8,-1,1.4,0,'desk');rect('desk top',-8,8,1.4,1.52,-.01,'paper')
rect('left near frame',-4.4,-3.65,1.52,7,0,'frame');rect('right near frame',3.65,4.4,1.52,7,0,'frame')
for mode in ['flat','depth']:
    bpy.ops.wm.read_factory_settings(use_empty=True);materials={}
    scene=bpy.context.scene;scene.render.engine='BLENDER_EEVEE';scene.render.resolution_x=1280;scene.render.resolution_y=720;scene.render.resolution_percentage=100
    scene.render.image_settings.file_format='PNG';scene.render.fps=24;scene.frame_start=1;scene.frame_end=48
    scene.view_settings.view_transform='Standard';scene.view_settings.look='None';scene.view_settings.exposure=0;scene.view_settings.gamma=1
    for name,verts,color in source:
        actual=[]
        for x,y,z in verts:
            if mode=='flat':
                new_y=y*.001;ratio=(8+new_y)/(8+y);actual.append((x*ratio,new_y,3+(z-3)*ratio))
            else:actual.append((x,y,z))
        mesh=bpy.data.meshes.new(name);mesh.from_pydata(actual,[],[list(range(len(actual)))]);mesh.update()
        ob=bpy.data.objects.new(name,mesh);scene.collection.objects.link(ob);ob.data.materials.append(mat(color,palette[color]))
    camera_data=bpy.data.cameras.new('Camera');camera=bpy.data.objects.new('Camera',camera_data);scene.collection.objects.link(camera);scene.camera=camera
    camera.location=(0,-8,3);camera.rotation_euler=Vector((0,1,0)).to_track_quat('-Z','Y').to_euler();camera_data.lens=35;camera_data.sensor_width=36
    camera.keyframe_insert(data_path='location',frame=1);camera.location.x=1.2;camera.keyframe_insert(data_path='location',frame=48)
    for fc in camera.animation_data.action.layers[0].strips[0].channelbag(camera.animation_data.action_slot).fcurves:
        for kp in fc.keyframe_points:kp.interpolation='LINEAR'
    scene.frame_set(1);bpy.ops.wm.save_as_mainfile(filepath=str(out/(mode+'-cards.blend')))
    folder=out/mode;folder.mkdir();scene.render.filepath=str(folder/'frame-')
    bpy.ops.render.render(animation=True)
(out/'depth-card-measurements.json').write_text(json.dumps({'width':1280,'height':720,'fps':24,'frames':48,'duration':2,'cameraStart':[0,-8,3],'cameraEnd':[1.2,-8,3],'lens_mm':35,'sensor_width_mm':36,'modes':['flat','depth'],'source':source,'meaning':'Original planar meshes with emission materials; flat mode adjusts each vertex to match the initial perspective, then brings depths almost together'},indent=2))
import bpy,json,sys
from pathlib import Path
from mathutils import Vector
from bpy_extras.object_utils import world_to_camera_view
out=Path(sys.argv[sys.argv.index('--')+1]);p=out/'depth-card-measurements.json';data=json.loads(p.read_text());projection={}
for mode in ['flat','depth']:
 bpy.ops.wm.open_mainfile(filepath=str(out/(mode+'-cards.blend')))
 scene=bpy.context.scene;head=bpy.data.objects['head'];center=sum((v.co for v in head.data.vertices),Vector())/len(head.data.vertices)
 points=[]
 for frame in [1,48]:
  scene.frame_set(frame);scene.view_layers.update();v=world_to_camera_view(scene,scene.camera,head.matrix_world@center)
  points.append({'frame':frame,'camera':list(scene.camera.location),'head_x_pixels':v.x*1280,'head_y_pixels':(1-v.y)*720})
 projection[mode]=points
assert abs(projection['flat'][0]['head_x_pixels']-projection['depth'][0]['head_x_pixels'])<.001
assert projection['depth'][1]['head_x_pixels']>projection['flat'][1]['head_x_pixels']+30
data['projection']=projection;p.write_text(json.dumps(data,indent=2));print(json.dumps(projection))
