From 502550e204f1b53bf52a7a3c1c8af68ecb6597e2 Mon Sep 17 00:00:00 2001 From: Lawrence D'Oliveiro Date: Sat, 25 Apr 2020 04:20:20 +0000 Subject: [PATCH] Split off demo code to reduce size of addon proper. --- __init__.py | 2 +- demo.py | 154 +++++++++++++++++++++++++++++++++++++++++ spaceship_generator.py | 148 ++------------------------------------- 3 files changed, 160 insertions(+), 144 deletions(-) create mode 100644 demo.py diff --git a/__init__.py b/__init__.py index a558869..3437c54 100644 --- a/__init__.py +++ b/__init__.py @@ -2,7 +2,7 @@ { "name" : "Spaceship Generator", "author" : "Michael Davies, Lawrence D'Oliveiro", - "version" : (1, 3, 0), + "version" : (1, 3, 1), "blender" : (2, 82, 0), "location" : "View3D > Add > Mesh", "description" : "Procedurally generate 3D spaceships from a random seed.", diff --git a/demo.py b/demo.py new file mode 100644 index 0000000..3585cff --- /dev/null +++ b/demo.py @@ -0,0 +1,154 @@ +#+ +# Demo script that can generate a single spaceship, or a movie +# comprising multiple spaceships. Enable the add_mesh_SpaceshipGenerator +# addon, open/copy this script in/into Blender’s Text Editor, and +# press ALT-P to run it. +#- + +import bpy +from add_mesh_SpaceshipGenerator.spaceship_generator import \ + deg, \ + parms_defaults, \ + generate_spaceship + +# When true, this script will generate a single spaceship in the scene. +# When false, this script will render multiple movie frames showcasing lots of ships. +generate_single_spaceship = True + +import os +import math +import datetime +import bpy +from mathutils import \ + Vector + +# Deletes all existing spaceships and unused materials from the scene +def reset_scene() : + for item in bpy.data.objects : + item.select_set(item.name.startswith("Spaceship")) + #end for + bpy.ops.object.delete() + for material in bpy.data.materials : + if not material.users : + bpy.data.materials.remove(material) + #end if + #end for + for texture in bpy.data.textures : + if not texture.users : + bpy.data.textures.remove(texture) + #end if + #end for +#end reset_scene + +class parms(parms_defaults) : + geom_ranseed = "" + mat_ranseed = "" + # add anything here to generate the same spaceship +#end class + +if generate_single_spaceship : + # Reset the scene, generate a single spaceship and focus on it + reset_scene() + obj = generate_spaceship(parms) + + # View the selected object in all views + for area in bpy.context.screen.areas : + if area.type == "VIEW_3D" : + ctx = bpy.context.copy() + ctx["area"] = area + ctx["region"] = area.regions[-1] + bpy.ops.view3d.view_selected(ctx) + #end if + #end for + +else : + # Export a movie showcasing many different kinds of ships + + # Settings + output_path = "" # leave empty to use script folder + total_movie_duration = 16 + total_spaceship_duration = 1 + yaw_rate = 45 * deg # angle/sec + yaw_offset = 220 * deg # angle/sec + camera_pole_rate = 1 + camera_pole_pitch_min = 15 * deg + camera_pole_pitch_max = 30 * deg + camera_pole_pitch_offset = 0 * deg + camera_pole_length = 10 + camera_refocus_object_every_frame = False + fov = 60 * deg + fps = 30 + res_x = 1920 + res_y = 1080 + + # Batch render the movie frames + inv_fps = 1 / fps + movie_duration = 0 + spaceship_duration = total_spaceship_duration + scene = bpy.data.scenes["Scene"] + scene.render.resolution_x = res_x + scene.render.resolution_y = res_y + scene.camera.rotation_mode = "XYZ" + scene.camera.data.angle = fov + frame = 0 + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + while movie_duration < total_movie_duration : + movie_duration += inv_fps + spaceship_duration += inv_fps + if spaceship_duration >= total_spaceship_duration : + spaceship_duration -= total_spaceship_duration + + # Generate a new spaceship + reset_scene() + obj = generate_spaceship(parms) + + # look for a mirror plane in the scene, and position it + # just underneath the ship if found + lowest_z = centre = min((Vector(b).z for b in obj.bound_box)) + plane_obj = bpy.data.objects.get("Plane") + if plane_obj : + plane_obj.location.z = lowest_z - 0.3 + #end if + #end if + + # Position and orient the camera + yaw = yaw_offset + yaw_rate * movie_duration + camera_pole_pitch_lerp = 0.5 * (1 + math.cos(camera_pole_rate * movie_duration)) # 0-1 + camera_pole_pitch = \ + ( + camera_pole_pitch_max * camera_pole_pitch_lerp + + + camera_pole_pitch_min * (1 - camera_pole_pitch_lerp) + ) + scene.camera.rotation_euler = \ + ( + 90 * deg - camera_pole_pitch + camera_pole_pitch_offset, + 0, + yaw + ) + scene.camera.location = \ + ( + math.sin(yaw) * camera_pole_length, + math.cos(yaw) * -camera_pole_length, + math.sin(camera_pole_pitch) * camera_pole_length + ) + if camera_refocus_object_every_frame : + bpy.ops.view3d.camera_to_view_selected() + #end if + + # Render the scene to disk + script_path = bpy.context.space_data.text.filepath if bpy.context.space_data else __file__ + folder = output_path if output_path else os.path.split(os.path.realpath(script_path))[0] + filename = os.path.join \ + ( + "renders", + timestamp, + timestamp + "_" + str(frame).zfill(5) + ".png" + ) + bpy.data.scenes["Scene"].render.filepath = os.path.join(folder, filename) + print("Rendering frame " + str(frame) + "...") + bpy.ops.render.render(write_still = True) + frame += 1 + #end while movie_duration < total_movie_duration + +#end if generate_single_spaceship diff --git a/spaceship_generator.py b/spaceship_generator.py index 021b0cd..9cce7e1 100644 --- a/spaceship_generator.py +++ b/spaceship_generator.py @@ -1,12 +1,12 @@ -# +#+ # spaceship_generator.py # # This is a Blender script that uses procedural generation to create -# textured 3D spaceship models. Tested with Blender 2.79. -# -# michael@spaceduststudios.com -# https://github.com/a1studmuffin/SpaceshipGenerator +# textured 3D spaceship models. Tested with Blender 2.82. # +# michael@spaceduststudios.com, Lawrence D'Oliveiro +# https://github.com/ldo/SpaceshipGenerator +#- import os import bpy @@ -1097,141 +1097,3 @@ def add_disc_to_face(bm, face) : return obj #end generate_spaceship - -if __name__ == "__main__" : - - import datetime - - # Deletes all existing spaceships and unused materials from the scene - def reset_scene() : - for item in bpy.data.objects : - item.select = item.name.startswith("Spaceship") - #end for - bpy.ops.object.delete() - for material in bpy.data.materials : - if not material.users : - bpy.data.materials.remove(material) - #end if - #end for - for texture in bpy.data.textures : - if not texture.users : - bpy.data.textures.remove(texture) - #end if - #end for - #end reset_scene - - # When true, this script will generate a single spaceship in the scene. - # When false, this script will render multiple movie frames showcasing lots of ships. - generate_single_spaceship = True - - if generate_single_spaceship : - # Reset the scene, generate a single spaceship and focus on it - reset_scene() - parms_defaults.geom_ranseed = "" - parms_defaults.mat_ranseed = "" - # add anything here to generate the same spaceship - obj = generate_spaceship(parms_defaults) - - # View the selected object in all views - for area in bpy.context.screen.areas : - if area.type == "VIEW_3D" : - ctx = bpy.context.copy() - ctx["area"] = area - ctx["region"] = area.regions[-1] - bpy.ops.view3d.view_selected(ctx) - #end if - #end for - - else : - # Export a movie showcasing many different kinds of ships - - # Settings - output_path = "" # leave empty to use script folder - total_movie_duration = 16 - total_spaceship_duration = 1 - yaw_rate = 45 * deg # angle/sec - yaw_offset = 220 * deg # angle/sec - camera_pole_rate = 1 - camera_pole_pitch_min = 15 * deg - camera_pole_pitch_max = 30 * deg - camera_pole_pitch_offset = 0 * deg - camera_pole_length = 10 - camera_refocus_object_every_frame = False - fov = 60 * deg - fps = 30 - res_x = 1920 - res_y = 1080 - - # Batch render the movie frames - inv_fps = 1 / fps - movie_duration = 0 - spaceship_duration = total_spaceship_duration - scene = bpy.data.scenes["Scene"] - scene.render.resolution_x = res_x - scene.render.resolution_y = res_y - scene.camera.rotation_mode = "XYZ" - scene.camera.data.angle = fov - frame = 0 - timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") - while movie_duration < total_movie_duration : - movie_duration += inv_fps - spaceship_duration += inv_fps - if spaceship_duration >= total_spaceship_duration : - spaceship_duration -= total_spaceship_duration - - # Generate a new spaceship - reset_scene() - obj = generate_spaceship(parms_defaults) - - # look for a mirror plane in the scene, and position it - # just underneath the ship if found - lowest_z = centre = min((Vector(b).z for b in obj.bound_box)) - plane_obj = bpy.data.objects.get("Plane") - if plane_obj : - plane_obj.location.z = lowest_z - 0.3 - #end if - #end if - - # Position and orient the camera - yaw = yaw_offset + yaw_rate * movie_duration - camera_pole_pitch_lerp = 0.5 * (1 + math.cos(camera_pole_rate * movie_duration)) # 0-1 - camera_pole_pitch = \ - ( - camera_pole_pitch_max * camera_pole_pitch_lerp - + - camera_pole_pitch_min * (1 - camera_pole_pitch_lerp) - ) - scene.camera.rotation_euler = \ - ( - 90 * deg - camera_pole_pitch + camera_pole_pitch_offset, - 0, - yaw - ) - scene.camera.location = \ - ( - math.sin(yaw) * camera_pole_length, - math.cos(yaw) * -camera_pole_length, - math.sin(camera_pole_pitch) * camera_pole_length - ) - if camera_refocus_object_every_frame : - bpy.ops.view3d.camera_to_view_selected() - #end if - - # Render the scene to disk - script_path = bpy.context.space_data.text.filepath if bpy.context.space_data else __file__ - folder = output_path if output_path else os.path.split(os.path.realpath(script_path))[0] - filename = os.path.join \ - ( - "renders", - timestamp, - timestamp + "_" + str(frame).zfill(5) + ".png" - ) - bpy.data.scenes["Scene"].render.filepath = os.path.join(folder, filename) - print("Rendering frame " + str(frame) + "...") - bpy.ops.render.render(write_still = True) - frame += 1 - #end while movie_duration < total_movie_duration - - #end if generate_single_spaceship - -#end if __name__ == "__main__"