-
-
Save wakarase/801343a4d98165be9bcb793b5a227dd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# BlenderユーザーのためのPython入門 | |
# 第26節 ギャグマシーンを作成する | |
import bpy | |
import math | |
import random | |
# 人体を構成する10個のオブジェクトです。 | |
objs = [] | |
# 身体の各部分に許容する回転角です。 | |
rot_range = (10, 45, 90, 90, 90, 90, 90, 90, 90, 90) | |
def make_cube(parent, loc, scale, pivot, name): | |
"""立方体を作ります。 | |
parent: 親にするオブジェクトです。 | |
loc: 立方体の中心の座標です。 | |
scale: 軸ごとの拡大縮小率です。 | |
pivot: 立方体の中心から相対的な、回転中心です。 | |
name: オブジェクトに与える名前です。 | |
""" | |
# scaleの値は半分にしたほうがよさそうです。 | |
x, y, z = scale | |
x, y, z = x / 2, y / 2, z / 2 | |
scale = x, y, z | |
bpy.ops.mesh.primitive_cube_add(location=loc, scale=scale) | |
obj = bpy.context.active_object | |
# 回転中心のローカル座標からワールド座標を得ます。 | |
x = obj.location.x + pivot[0] | |
y = obj.location.y + pivot[1] | |
z = obj.location.z + pivot[2] | |
bpy.context.scene.cursor.location = (x, y, z) | |
bpy.ops.object.origin_set(type='ORIGIN_CURSOR') | |
if parent is not None: | |
obj.parent = parent | |
if name: | |
obj.name = name | |
return obj | |
def set_animation(obj, frame, rotation): | |
"""objの第frameフレームに回転角rotationでキーフレームを登録します。""" | |
bpy.context.scene.frame_set(frame) | |
obj.rotation_euler = rotation | |
obj.keyframe_insert(data_path="rotation_euler") | |
for m in bpy.data.meshes: | |
"""既存のメッシュ、つまり以前に作った立方体などを削除します。""" | |
bpy.data.meshes.remove(m) | |
# 人体の各部となる立方体を配置します。 | |
loc = (0, 0, 0) | |
scale = (3, 1.5, 4) | |
pivot = (0, 0, -2) | |
objs.append(make_cube(None, loc, scale, pivot, 'Hip')) | |
loc = (0, 0, 5) | |
scale = (2, 2, 2) | |
pivot = (0, 0, -1) | |
objs.append(make_cube(objs[0], loc, scale, pivot, 'Head')) | |
loc = (2.5, 0, 3.5) | |
scale = (2, 1, 1) | |
pivot = (-1, 0, 0) | |
objs.append(make_cube(objs[0], loc, scale, pivot, 'UpperArm.L')) | |
loc = (3, 0, 0) | |
scale = (2, 1, 1) | |
pivot = (-1, 0, 0) | |
objs.append(make_cube(objs[2], loc, scale, pivot, 'LowerArm.L')) | |
loc = (-2.5, 0, 3.5) | |
scale = (2, 1, 1) | |
pivot = (1, 0, 0) | |
objs.append(make_cube(objs[0], loc, scale, pivot, 'UpperArm.R')) | |
loc = (-3, 0, 0) | |
scale = (2, 1, 1) | |
pivot = (1, 0, 0) | |
objs.append(make_cube(objs[4], loc, scale, pivot, 'LowerArm.R')) | |
loc = (0.8, 0, -1) | |
scale = (1.25, 1.25, 2) | |
pivot = (0, 0, 1) | |
objs.append(make_cube(objs[0], loc, scale, pivot, 'UpperLeg.L')) | |
loc = (0, 0, -3) | |
scale = (1.25, 1.25, 2) | |
pivot = (0, 0, 1) | |
objs.append(make_cube(objs[6], loc, scale, pivot, 'LowerLeg.L')) | |
loc = (-0.8, 0, -1) | |
scale = (1.25, 1.25, 2) | |
pivot = (0, 0, 1) | |
objs.append(make_cube(objs[0], loc, scale, pivot, 'UpperLeg.R')) | |
loc = (0, 0, -3) | |
scale = (1.25, 1.25, 2) | |
pivot = (0, 0, 1) | |
objs.append(make_cube(objs[8], loc, scale, pivot, 'LowerLeg.R')) | |
for o in range(len(objs)): # 人体の各部分について。 | |
obj = objs[o] | |
obj.animation_data_clear() | |
obj.rotation_mode = "XYZ" | |
set_animation(obj, 0, (0, 0, 0)) # 開始フレームでは直立姿勢です。 | |
for frame in range(25, 250, 25): | |
rot = rot_range[o] # 身体の各部分に許容する回転角です。 | |
# 一様分布でランダムな回転角を与えます。 | |
x = math.radians(random.uniform(-rot, rot)) | |
y = math.radians(random.uniform(-rot, rot)) | |
z = math.radians(random.uniform(-rot, rot)) | |
set_animation(obj, frame, (x, y, z)) | |
set_animation(obj, 250, (0, 0, 0)) # 終了フレームでは直立姿勢です。 | |
bpy.context.scene.frame_start = 0 | |
bpy.context.scene.frame_end = 250 | |
bpy.context.scene.frame_set(0) | |
def set_material(): | |
"""人体各部に同じマテリアルを割り当てます。""" | |
for material in bpy.data.materials: | |
bpy.data.materials.remove(material) | |
material = bpy.data.materials.new('MyMaterial') | |
material.use_nodes = True | |
node_tree = material.node_tree | |
assert isinstance(node_tree, bpy.types.ShaderNodeTree) | |
principled_bsdf = node_tree.nodes['Principled BSDF'] | |
assert isinstance(principled_bsdf, bpy.types.ShaderNodeBsdfPrincipled) | |
principled_bsdf.inputs['Base Color' ].default_value = (0.5, 0.5, 0.5, 1) | |
principled_bsdf.inputs['Roughness' ].default_value = 0.0 | |
principled_bsdf.inputs['Transmission'].default_value = 1.0 | |
for object in objs: | |
bpy.context.view_layer.objects.active = object | |
bpy.context.object.data.materials.append(material) | |
bpy.ops.object.select_all(action='DESELECT') | |
set_material() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment