61 lines
4.3 KiB
Python
61 lines
4.3 KiB
Python
import bpy, bmesh, math, json, os
|
|
from mathutils import Vector
|
|
OUT=os.path.dirname(os.path.abspath(__file__)); s=bpy.context.scene
|
|
# Clear grass from the new vehicle surfaces and garage interior.
|
|
route=[(36,-40),(28,-33),(22,-27),(8,-26),(5,-22),(5,-13),(1,-12),(-3,-12)]
|
|
segments=[]
|
|
for a,b in zip(route,route[1:]):
|
|
dx,dy=b[0]-a[0],b[1]-a[1]; segments.append((a[0],a[1],dx,dy,dx*dx+dy*dy))
|
|
def clear(x,y):
|
|
if -7.2<x<1.2 and -22.7<y<-15.3:return True
|
|
if -7.05<x<5.05 and -15.55<y<-9.45:return True
|
|
for ax,ay,dx,dy,l2 in segments:
|
|
t=max(0,min(1,((x-ax)*dx+(y-ay)*dy)/l2))
|
|
if (x-ax-t*dx)**2+(y-ay-t*dy)**2<2.08**2:return True
|
|
return False
|
|
removed=0
|
|
for o in s.objects:
|
|
if o.type=='MESH' and o.name.startswith('Native grasses'):
|
|
bm=bmesh.new(); bm.from_mesh(o.data); faces=[]
|
|
for f in bm.faces:
|
|
p=o.matrix_world@f.calc_center_median()
|
|
if clear(p.x,p.y):faces.append(f)
|
|
removed+=len(faces); bmesh.ops.delete(bm,geom=faces,context='FACES'); bm.to_mesh(o.data); bm.free()
|
|
# This broad panel is the vehicle entrance, not a permanent wall across the car bay.
|
|
o=bpy.data.objects.get('Garage north front panel')
|
|
if o:o.name='Garage 3.7m wide sectional vehicle door'; o['Operation']='Concept upward-opening vehicle door; transparent for presentation.'
|
|
o=bpy.data.objects.get('Garage roller door concept')
|
|
if o:o.name='Garage north service infill panel'
|
|
# Distinct static overview for inspecting the driveway without changing the Play camera.
|
|
camdata=bpy.data.cameras.new('VIEW - Road garage and retreat'); cam=bpy.data.objects.new(camdata.name,camdata); s.collection.objects.link(cam)
|
|
cam.location=(47,40,47); cam.rotation_euler=(Vector((0,-7,1))-cam.location).to_track_quat('-Z','Y').to_euler(); camdata.lens=38; camdata.clip_end=450
|
|
tour=bpy.data.objects['PLAY TOUR camera']; s.camera=tour; s.frame_set(1)
|
|
report=json.load(open(os.path.join(OUT,'design-checks.json'))); report['grass_faces_cleared_from_vehicle_surfaces']=removed
|
|
report['retained_child_beds']=sum(o.name.startswith('Child') and ('bed' in o.name or 'mattress' in o.name) for o in s.objects)
|
|
report['transparent_buildings']=['Living pavilion','Parents bedroom wing','Short corridor','Meditation room','Sauna','Greenhouse','Garage']
|
|
assert report['retained_child_beds']==0 and report['candles']==3
|
|
chapters=json.load(open(os.path.join(OUT,'tour-chapters.json')))
|
|
for ch in chapters:
|
|
s.frame_set(ch['start']); a=tour.location.copy(); s.frame_set(ch['end']); b=tour.location.copy(); assert (b-a).length>.01
|
|
report['all_23_chapters_animate']=True; json.dump(report,open(os.path.join(OUT,'design-checks.json'),'w'),indent=2)
|
|
s.camera=tour; s.frame_set(1)
|
|
for screen in bpy.data.screens:
|
|
for area in screen.areas:
|
|
if area.type=='VIEW_3D':
|
|
area.spaces.active.region_3d.view_perspective='CAMERA'; area.spaces.active.shading.type='SOLID'; area.spaces.active.shading.color_type='MATERIAL'; area.spaces.active.overlay.show_overlays=False
|
|
s.render.engine='CYCLES'; s.render.resolution_percentage=100; s.cycles.samples=48; s.cycles.use_denoising=True; s.cycles.adaptive_threshold=.035
|
|
prefs=bpy.context.preferences.addons['cycles'].preferences; prefs.compute_device_type='METAL'; prefs.get_devices()
|
|
for d in prefs.devices:d.use=d.type=='METAL'
|
|
s.cycles.device='GPU'; s.render.filepath=os.path.join(OUT,'retreat-garage-overview.png')
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,'samford-retreat-garage-tour.blend'))
|
|
# Captions are useful during playback, but photographs use clean architectural views.
|
|
titles=[o for o in bpy.data.collections['22 PLAY - guided camera tour'].objects if o.type=='FONT']
|
|
for o in titles:o.hide_render=True
|
|
s.camera=cam; bpy.ops.render.render(write_still=True); print('OVERVIEW_RENDERED',flush=True)
|
|
s.camera=tour; s.frame_set(2220); s.render.filepath=os.path.join(OUT,'meditation-room.png'); bpy.ops.render.render(write_still=True); print('MEDITATION_RENDERED',flush=True)
|
|
s.frame_set(2460); s.render.filepath=os.path.join(OUT,'garage-workstation-bikes.png'); bpy.ops.render.render(write_still=True); print('GARAGE_RENDERED',flush=True)
|
|
for o in titles:o.hide_render=False
|
|
s.camera=tour; s.frame_set(1); s.render.filepath=os.path.join(OUT,'retreat-garage-overview.png')
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,'samford-retreat-garage-tour.blend'))
|
|
print('FINAL_RETREAT_READY_TO_PLAY',flush=True)
|