feat: evolve portfolio into an authored midnight grand tour
This commit is contained in:
66
assets/blender/evolution/add-personality.py
Normal file
66
assets/blender/evolution/add-personality.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""Second design pass; run inside Blender with Portfolio Evolution loaded.
|
||||
Re-running replaces only this pass's objects. Keeps the eight material groups.
|
||||
"""
|
||||
import bpy
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
root_path = Path(__file__).resolve().parents[3]
|
||||
scene = bpy.data.scenes['Portfolio Evolution']
|
||||
bpy.context.window.scene = scene
|
||||
car = next(o for o in scene.objects if o.name.split('.')[0] == 'chase-car')
|
||||
materials = {m.name.split('.')[0]: m for o in scene.objects if o.type == 'MESH' for m in o.data.materials}
|
||||
for obj in list(scene.objects):
|
||||
if obj.name.startswith('signature-'):
|
||||
bpy.data.objects.remove(obj, do_unlink=True)
|
||||
|
||||
def finish(obj, name, material, bevel=0.008):
|
||||
obj.name = 'signature-' + name
|
||||
obj.parent = car
|
||||
obj.data.materials.append(materials[material])
|
||||
if bevel:
|
||||
mod = obj.modifiers.new('Soft machined edge', 'BEVEL')
|
||||
mod.width = bevel
|
||||
mod.segments = 2
|
||||
obj.modifiers.new('Weighted normals', 'WEIGHTED_NORMAL')
|
||||
return obj
|
||||
|
||||
def box(name, location, dimensions, material, bevel=0.008):
|
||||
bpy.ops.mesh.primitive_cube_add(size=1, location=location)
|
||||
obj = bpy.context.object
|
||||
obj.dimensions = dimensions
|
||||
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
|
||||
return finish(obj, name, material, bevel)
|
||||
|
||||
# A swept floating wing. Its high tips and low center echo the body haunches.
|
||||
outline = [(-1.22, 2.28), (-0.98, 2.08), (-0.72, 2.13),
|
||||
(0.72, 2.13), (0.98, 2.08), (1.22, 2.28),
|
||||
(1.18, 2.51), (0.72, 2.42), (-0.72, 2.42), (-1.18, 2.51)]
|
||||
n = len(outline)
|
||||
verts = [(x, y, 1.20 + (0.06 if abs(x) > 0.95 else 0) + dz)
|
||||
for dz in [0, 0.065] for x, y in outline]
|
||||
faces = [tuple(reversed(range(n))), tuple(range(n, 2*n))]
|
||||
faces += [(i, (i+1)%n, (i+1)%n+n, i+n) for i in range(n)]
|
||||
mesh = bpy.data.meshes.new('Swept aerofoil')
|
||||
mesh.from_pydata(verts, [], faces)
|
||||
mesh.update()
|
||||
wing = bpy.data.objects.new('Swept wing', mesh)
|
||||
scene.collection.objects.link(wing)
|
||||
finish(wing, 'floating-wing', 'M_Body_Haunch', 0.018)
|
||||
for side in [-1, 1]:
|
||||
box('wing-pylon', (side*0.66, 2.27, 1.045), (0.075, 0.14, 0.35), 'M_Lower_Graphite')
|
||||
box('wing-endplate', (side*1.185, 2.35, 1.245), (0.045, 0.30, 0.20), 'M_Body_Gunmetal')
|
||||
box('wing-marker', (side*1.212, 2.37, 1.28), (0.014, 0.19, 0.025), 'M_Cyan_Accent', 0.003)
|
||||
# Illuminated outer guides frame the dark diffuser, below the coral lamp.
|
||||
box('rear-guide-housing', (side*0.88, 2.56, 0.50), (0.07, 0.23, 0.235), 'M_Lower_Graphite')
|
||||
box('rear-guide', (side*0.88, 2.678, 0.50), (0.022, 0.02, 0.19), 'M_Cyan_Accent', 0.004)
|
||||
for y, z in [(-1.62, 0.42), (1.62, 0.46)]:
|
||||
# Eight swept metallic vanes sit inside each original rim ring.
|
||||
for index in range(8):
|
||||
angle = index * math.tau / 8
|
||||
obj = box('turbine-vane', (side*1.186, y+math.sin(angle)*0.19, z+math.cos(angle)*0.19),
|
||||
(0.022, 0.064, 0.19), 'M_Wheel', 0.005)
|
||||
obj.rotation_euler.x = -angle + side*0.3
|
||||
|
||||
bpy.data.libraries.write(str(root_path / 'assets/blender/evolution/nightdrive-evolution.blend'), {scene}, fake_user=True, compress=True)
|
||||
exec(compile((root_path / 'assets/blender/evolution/export-grand-tourer.py').read_text(), str(root_path / 'assets/blender/evolution/export-grand-tourer.py'), 'exec'))
|
||||
Reference in New Issue
Block a user