66 lines
4.3 KiB
Python
66 lines
4.3 KiB
Python
import bpy, random, math, os
|
|
from mathutils import Vector
|
|
random.seed(119)
|
|
OUT=os.path.dirname(os.path.abspath(__file__))
|
|
s=bpy.context.scene
|
|
# Layer individual leaves into substantial evergreen canopies instead of sparse twigs.
|
|
for ob in list(bpy.data.objects):
|
|
if 'individual canopy leaves' not in ob.name: continue
|
|
old=ob.data
|
|
verts=[tuple(v.co) for v in old.vertices]; faces=[tuple(p.vertices) for p in old.polygons]; inds=[p.material_index for p in old.polygons]
|
|
original=list(verts)
|
|
for k in range(0,len(original),5):
|
|
center=Vector(original[k+4]); index=inds[(k//5)*4]
|
|
for repeat in range(6):
|
|
offset=Vector((random.uniform(-.36,.36),random.uniform(-.36,.36),random.uniform(-.23,.23)))
|
|
a=random.uniform(-1,1); scale=random.uniform(.95,1.35); j=len(verts)
|
|
for v in original[k:k+5]:
|
|
d=(Vector(v)-center)*scale
|
|
d=Vector((d.x*math.cos(a)-d.y*math.sin(a),d.x*math.sin(a)+d.y*math.cos(a),d.z))
|
|
verts.append(tuple(center+offset+d))
|
|
faces.extend([(j,j+1,j+4),(j+1,j+2,j+4),(j+2,j+3,j+4),(j+3,j,j+4)]); inds.extend([index]*4)
|
|
me=bpy.data.meshes.new(ob.name+' full layered foliage'); me.from_pydata(verts,[],faces); me.update()
|
|
for m in old.materials: me.materials.append(m)
|
|
for p,mi in zip(me.polygons,inds): p.material_index=mi
|
|
ob.data=me; bpy.data.meshes.remove(old)
|
|
print('CANOPY',ob.name,len(verts),flush=True)
|
|
# Move two foreground eucalyptus trees aside to leave greenhouse and beds visible.
|
|
for ob in bpy.data.collections['09 Eucalyptus and fruit trees'].objects:
|
|
if not ob.data or ob.type!='MESH': continue
|
|
center=sum((Vector(b) for b in ob.bound_box),Vector())/8
|
|
center=ob.matrix_world@center
|
|
if center.x>26 and center.y>5: ob.location.x+=17
|
|
# Soft blue ambient sky with a warm north-east morning sun.
|
|
world=s.world; nodes=world.node_tree.nodes; bg=nodes.get('Background')
|
|
for link in list(bg.inputs['Color'].links): world.node_tree.links.remove(link)
|
|
bg.inputs['Color'].default_value=(.38,.49,.64,1); bg.inputs['Strength'].default_value=.45
|
|
s.view_settings.exposure=0
|
|
sun=bpy.data.objects['Warm early morning sun from north-east']; sun.data.energy=2.3; sun.data.color=(1,.78,.53)
|
|
sun.location=(35,40,23); sun.rotation_euler=(Vector((-15,-20,0))-sun.location).to_track_quat('-Z','Y').to_euler()
|
|
# Broad overlapping, wooded ridgelines complete the landscape beyond the site.
|
|
collection=bpy.data.collections['07 Terrain and paths']
|
|
for row,(y,base,color) in enumerate([(-58,9,(.13,.21,.16)),(-87,17,(.20,.29,.26)),(-125,23,(.29,.37,.36))]):
|
|
mat=bpy.data.materials.new('Distant wooded ridge '+str(row)); mat.diffuse_color=(*color,1); mat.use_nodes=True; p=mat.node_tree.nodes.get('Principled BSDF'); p.inputs['Base Color'].default_value=(*color,1); p.inputs['Roughness'].default_value=1
|
|
vs=[]; fs=[]
|
|
for j in range(9):
|
|
yy=y+(j-4)*7
|
|
for i in range(81):
|
|
x=-180+i*4.5; crest=base+4*math.sin(x*.048+row)+2.2*math.sin(x*.105+row*2)
|
|
z=crest*max(0,1-((j-4)/4.5)**2)-2
|
|
vs.append((x,yy,z))
|
|
for j in range(8):
|
|
for i in range(80):
|
|
k=j*81+i; fs.append((k,k+1,k+82,k+81))
|
|
me=bpy.data.meshes.new('Ridgeline terrain'); me.from_pydata(vs,[],fs); me.materials.append(mat); ob=bpy.data.objects.new('Layered subtropical ridgeline',me); collection.objects.link(ob)
|
|
for p in me.polygons: p.use_smooth=True
|
|
# Tone down new timber and roof glare; retain warm structure and silver-grey cladding.
|
|
for name in ['Silvered hardwood weatherboard - X grain','Silvered hardwood weatherboard - Y grain']:
|
|
m=bpy.data.materials[name]; ramp=next(n for n in m.node_tree.nodes if n.type=='VALTORGB')
|
|
ramp.color_ramp.elements[0].color=(.115,.12,.105,1); ramp.color_ramp.elements[1].color=(.30,.30,.26,1)
|
|
bpy.data.objects['NE aerial - complete adaptable compound'].data.lens=48
|
|
s.render.resolution_x=2560; s.render.resolution_y=1440; s.render.resolution_percentage=100; s.render.filepath=os.path.join(OUT,'samford-modular-final.png'); s.cycles.samples=96
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,'samford-modular-home.blend'))
|
|
s.cycles.device='CPU'; s.cycles.samples=12; s.render.resolution_percentage=40; s.render.filepath=os.path.join(OUT,'samford-modular-refined-draft.png')
|
|
bpy.ops.render.render(write_still=True)
|
|
print('REFINED_DRAFT_COMPLETE',flush=True)
|