[DEV] porting to 2.80

pull/34/head
lendo 2020-06-01 12:47:33 +02:00
rodzic a8519b0329
commit e22758c801
3 zmienionych plików z 38 dodań i 34 usunięć

Wyświetl plik

@ -6,7 +6,7 @@ A Blender script to procedurally generate 3D spaceships from a random seed.
Usage Usage
----- -----
* Install Blender 2.76 or greater: http://blender.org/download/ * Install Blender 2.80 or greater: http://blender.org/download/
* Download newest `add_mesh_SpaceshipGenerator.zip` from the [Releases](https://github.com/a1studmuffin/SpaceshipGenerator/releases) section * Download newest `add_mesh_SpaceshipGenerator.zip` from the [Releases](https://github.com/a1studmuffin/SpaceshipGenerator/releases) section
* Under File > User Preferences... > Add-ons > Install From File... open the downloaded ZIP file * Under File > User Preferences... > Add-ons > Install From File... open the downloaded ZIP file
* Under File > User Preferences... > Add-ons enable this script (search for "spaceship") * Under File > User Preferences... > Add-ons enable this script (search for "spaceship")

Wyświetl plik

@ -2,7 +2,7 @@ bl_info = {
"name": "Spaceship Generator", "name": "Spaceship Generator",
"author": "Michael Davies", "author": "Michael Davies",
"version": (1, 1, 2), "version": (1, 1, 2),
"blender": (2, 76, 0), "blender": (2, 80, 0),
"location": "View3D > Add > Mesh", "location": "View3D > Add > Mesh",
"description": "Procedurally generate 3D spaceships from a random seed.", "description": "Procedurally generate 3D spaceships from a random seed.",
"wiki_url": "https://github.com/a1studmuffin/SpaceshipGenerator/blob/master/README.md", "wiki_url": "https://github.com/a1studmuffin/SpaceshipGenerator/blob/master/README.md",
@ -58,12 +58,12 @@ def menu_func(self, context):
self.layout.operator(GenerateSpaceship.bl_idname, text="Spaceship") self.layout.operator(GenerateSpaceship.bl_idname, text="Spaceship")
def register(): def register():
bpy.utils.register_module(__name__) bpy.utils.register_class(GenerateSpaceship)
bpy.types.INFO_MT_mesh_add.append(menu_func) bpy.types.VIEW3D_MT_mesh_add.append(menu_func)
def unregister(): def unregister():
bpy.utils.unregister_module(__name__) bpy.utils.unregister_class(GenerateSpaceship)
bpy.types.INFO_MT_mesh_add.remove(menu_func) bpy.types.VIEW3D_MT_mesh_add.remove(menu_func)
if __name__ == "__main__": if __name__ == "__main__":
register() register()

Wyświetl plik

@ -131,7 +131,7 @@ def is_rear_face(face):
def add_exhaust_to_face(bm, face): def add_exhaust_to_face(bm, face):
if not face.is_valid: if not face.is_valid:
return return
# The more square the face is, the more grid divisions it might have # The more square the face is, the more grid divisions it might have
num_cuts = randint(1, int(4 - get_aspect_ratio(face))) num_cuts = randint(1, int(4 - get_aspect_ratio(face)))
result = bmesh.ops.subdivide_edges(bm, result = bmesh.ops.subdivide_edges(bm,
@ -139,7 +139,7 @@ def add_exhaust_to_face(bm, face):
cuts=num_cuts, cuts=num_cuts,
fractal=0.02, fractal=0.02,
use_grid_fill=True) use_grid_fill=True)
exhaust_length = uniform(0.1, 0.2) exhaust_length = uniform(0.1, 0.2)
scale_outer = 1 / uniform(1.3, 1.6) scale_outer = 1 / uniform(1.3, 1.6)
scale_inner = 1 / uniform(1.05, 1.1) scale_inner = 1 / uniform(1.05, 1.1)
@ -195,7 +195,7 @@ def add_cylinders_to_face(bm, face):
face.verts[2].co, (h + 1) / float(horizontal_step + 1)) face.verts[2].co, (h + 1) / float(horizontal_step + 1))
for v in range(vertical_step): for v in range(vertical_step):
pos = top.lerp(bottom, (v + 1) / float(vertical_step + 1)) pos = top.lerp(bottom, (v + 1) / float(vertical_step + 1))
cylinder_matrix = get_face_matrix(face, pos) * \ cylinder_matrix = get_face_matrix(face, pos) @ \
Matrix.Rotation(radians(90), 3, 'X').to_4x4() Matrix.Rotation(radians(90), 3, 'X').to_4x4()
bmesh.ops.create_cone(bm, bmesh.ops.create_cone(bm,
cap_ends=True, cap_ends=True,
@ -225,7 +225,7 @@ def add_weapons_to_face(bm, face):
face.verts[2].co, (h + 1) / float(horizontal_step + 1)) face.verts[2].co, (h + 1) / float(horizontal_step + 1))
for v in range(vertical_step): for v in range(vertical_step):
pos = top.lerp(bottom, (v + 1) / float(vertical_step + 1)) pos = top.lerp(bottom, (v + 1) / float(vertical_step + 1))
face_matrix = get_face_matrix(face, pos + face.normal * weapon_depth * 0.5) * \ face_matrix = get_face_matrix(face, pos + face.normal * weapon_depth * 0.5) @ \
Matrix.Rotation(radians(uniform(0, 90)), 3, 'Z').to_4x4() Matrix.Rotation(radians(uniform(0, 90)), 3, 'Z').to_4x4()
# Turret foundation # Turret foundation
@ -239,8 +239,8 @@ def add_weapons_to_face(bm, face):
matrix=face_matrix) matrix=face_matrix)
# Turret left guard # Turret left guard
left_guard_mat = face_matrix * \ left_guard_mat = face_matrix @ \
Matrix.Rotation(radians(90), 3, 'Y').to_4x4() * \ Matrix.Rotation(radians(90), 3, 'Y').to_4x4() @ \
Matrix.Translation(Vector((0, 0, weapon_size * 0.6))).to_4x4() Matrix.Translation(Vector((0, 0, weapon_size * 0.6))).to_4x4()
bmesh.ops.create_cone(bm, bmesh.ops.create_cone(bm,
cap_ends=True, cap_ends=True,
@ -252,8 +252,8 @@ def add_weapons_to_face(bm, face):
matrix=left_guard_mat) matrix=left_guard_mat)
# Turret right guard # Turret right guard
right_guard_mat = face_matrix * \ right_guard_mat = face_matrix @ \
Matrix.Rotation(radians(90), 3, 'Y').to_4x4() * \ Matrix.Rotation(radians(90), 3, 'Y').to_4x4() @ \
Matrix.Translation(Vector((0, 0, weapon_size * -0.6))).to_4x4() Matrix.Translation(Vector((0, 0, weapon_size * -0.6))).to_4x4()
bmesh.ops.create_cone(bm, bmesh.ops.create_cone(bm,
cap_ends=True, cap_ends=True,
@ -266,8 +266,8 @@ def add_weapons_to_face(bm, face):
# Turret housing # Turret housing
upward_angle = uniform(0, 45) upward_angle = uniform(0, 45)
turret_house_mat = face_matrix * \ turret_house_mat = face_matrix @ \
Matrix.Rotation(radians(upward_angle), 3, 'X').to_4x4() * \ Matrix.Rotation(radians(upward_angle), 3, 'X').to_4x4() @ \
Matrix.Translation(Vector((0, weapon_size * -0.4, 0))).to_4x4() Matrix.Translation(Vector((0, weapon_size * -0.4, 0))).to_4x4()
bmesh.ops.create_cone(bm, bmesh.ops.create_cone(bm,
cap_ends=True, cap_ends=True,
@ -286,7 +286,7 @@ def add_weapons_to_face(bm, face):
diameter1=weapon_size * 0.1, diameter1=weapon_size * 0.1,
diameter2=weapon_size * 0.1, diameter2=weapon_size * 0.1,
depth=weapon_depth * 6, depth=weapon_depth * 6,
matrix=turret_house_mat * \ matrix=turret_house_mat @ \
Matrix.Translation(Vector((weapon_size * 0.2, 0, -weapon_size))).to_4x4()) Matrix.Translation(Vector((weapon_size * 0.2, 0, -weapon_size))).to_4x4())
bmesh.ops.create_cone(bm, bmesh.ops.create_cone(bm,
cap_ends=True, cap_ends=True,
@ -295,7 +295,7 @@ def add_weapons_to_face(bm, face):
diameter1=weapon_size * 0.1, diameter1=weapon_size * 0.1,
diameter2=weapon_size * 0.1, diameter2=weapon_size * 0.1,
depth=weapon_depth * 6, depth=weapon_depth * 6,
matrix=turret_house_mat * \ matrix=turret_house_mat @ \
Matrix.Translation(Vector((weapon_size * -0.2, 0, -weapon_size))).to_4x4()) Matrix.Translation(Vector((weapon_size * -0.2, 0, -weapon_size))).to_4x4())
# Given a face, adds a sphere on the surface, partially inset. # Given a face, adds a sphere on the surface, partially inset.
@ -411,12 +411,12 @@ def create_texture(name, tex_type, filename, use_alpha=True):
except: except:
raise IOError("Cannot load image: %s" % filename) raise IOError("Cannot load image: %s" % filename)
img.use_alpha = use_alpha # img.use_alpha = use_alpha
img.pack() img.pack()
# Cache the asset # Cache the asset
img_cache[(filename, use_alpha)] = img img_cache[(filename, use_alpha)] = img
# Create and return a new texture using img # Create and return a new texture using img
tex = bpy.data.textures.new(name, tex_type) tex = bpy.data.textures.new(name, tex_type)
tex.image = img tex.image = img
@ -444,7 +444,7 @@ def create_materials():
ret = [] ret = []
for material in Material: for material in Material:
ret.append(bpy.data.materials.new(material.name)) ret.append(bpy.data.materials.new(material.name))
# Choose a base color for the spaceship hull # Choose a base color for the spaceship hull
hull_base_color = hls_to_rgb( hull_base_color = hls_to_rgb(
random(), uniform(0.05, 0.5), uniform(0, 0.25)) random(), uniform(0.05, 0.5), uniform(0, 0.25))
@ -490,7 +490,7 @@ def create_materials():
# Choose a glow color for the exhaust + glow discs # Choose a glow color for the exhaust + glow discs
glow_color = hls_to_rgb(random(), uniform(0.5, 1), 1) glow_color = hls_to_rgb(random(), uniform(0.5, 1), 1)
# Build the exhaust_burn texture # Build the exhaust_burn texture
mat = ret[Material.exhaust_burn] mat = ret[Material.exhaust_burn]
mat.diffuse_color = glow_color mat.diffuse_color = glow_color
@ -607,7 +607,7 @@ def generate_spaceship(random_seed='',
# Skip any long thin faces as it'll probably look stupid # Skip any long thin faces as it'll probably look stupid
if get_aspect_ratio(face) > 3: if get_aspect_ratio(face) > 3:
continue continue
# Spin the wheel! Let's categorize + assign some materials # Spin the wheel! Let's categorize + assign some materials
val = random() val = random()
if is_rear_face(face): # rear face if is_rear_face(face): # rear face
@ -675,11 +675,11 @@ def generate_spaceship(random_seed='',
# Apply horizontal symmetry sometimes # Apply horizontal symmetry sometimes
if allow_horizontal_symmetry and random() > 0.5: if allow_horizontal_symmetry and random() > 0.5:
bmesh.ops.symmetrize(bm, input=bm.verts[:] + bm.edges[:] + bm.faces[:], direction=1) bmesh.ops.symmetrize(bm, input=bm.verts[:] + bm.edges[:] + bm.faces[:], direction="Y")
# Apply vertical symmetry sometimes - this can cause spaceship "islands", so disabled by default # Apply vertical symmetry sometimes - this can cause spaceship "islands", so disabled by default
if allow_vertical_symmetry and random() > 0.5: if allow_vertical_symmetry and random() > 0.5:
bmesh.ops.symmetrize(bm, input=bm.verts[:] + bm.edges[:] + bm.faces[:], direction=2) bmesh.ops.symmetrize(bm, input=bm.verts[:] + bm.edges[:] + bm.faces[:], direction="Z")
# Finish up, write the bmesh into a new mesh # Finish up, write the bmesh into a new mesh
me = bpy.data.meshes.new('Mesh') me = bpy.data.meshes.new('Mesh')
@ -689,11 +689,14 @@ def generate_spaceship(random_seed='',
# Add the mesh to the scene # Add the mesh to the scene
scene = bpy.context.scene scene = bpy.context.scene
obj = bpy.data.objects.new('Spaceship', me) obj = bpy.data.objects.new('Spaceship', me)
scene.objects.link(obj) # scene.objects.link(obj)
scene.collection.objects.link(obj)
# Select and make active # Select and make active
scene.objects.active = obj bpy.context.view_layer.objects.active = obj
obj.select = True obj.select_set(True)
# scene.objects.active = obj
# obj.select = True
# Recenter the object to its center of mass # Recenter the object to its center of mass
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS') bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
@ -711,21 +714,22 @@ def generate_spaceship(random_seed='',
# Add materials to the spaceship # Add materials to the spaceship
me = ob.data me = ob.data
materials = create_materials() # materials = create_materials()
materials = []
for mat in materials: for mat in materials:
if assign_materials: if assign_materials:
me.materials.append(mat) me.materials.append(mat)
else: else:
me.materials.append(bpy.data.materials.new(name="Material")) me.materials.append(bpy.data.materials.new(name="Material"))
return obj return obj
if __name__ == "__main__": if __name__ == "__main__":
# When true, this script will generate a single spaceship in the 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. # When false, this script will render multiple movie frames showcasing lots of ships.
generate_single_spaceship = True generate_single_spaceship = True
if generate_single_spaceship: if generate_single_spaceship:
# Reset the scene, generate a single spaceship and focus on it # Reset the scene, generate a single spaceship and focus on it
reset_scene() reset_scene()
@ -797,7 +801,7 @@ if __name__ == "__main__":
sin(radians(camera_pole_pitch))*camera_pole_length) sin(radians(camera_pole_pitch))*camera_pole_length)
if camera_refocus_object_every_frame: if camera_refocus_object_every_frame:
bpy.ops.view3d.camera_to_view_selected() bpy.ops.view3d.camera_to_view_selected()
# Render the scene to disk # Render the scene to disk
script_path = bpy.context.space_data.text.filepath if bpy.context.space_data else __file__ 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] folder = output_path if output_path else os.path.split(os.path.realpath(script_path))[0]