Skip to content

Instantly share code, notes, and snippets.

@pgtwitter
Last active May 29, 2023 09:52
Show Gist options
  • Save pgtwitter/74665852177db828e91025c3cd0d98f1 to your computer and use it in GitHub Desktop.
Save pgtwitter/74665852177db828e91025c3cd0d98f1 to your computer and use it in GitHub Desktop.
3フレーム前から現在までの対象頂点位置を繋いだメッシュ(vとeのみ)を作成し,以降フレーム毎に位置を変えてシェープキーとして登録し,これを切り替えて動かしてみる.
import bpy
import mathutils
import bmesh
def d2r(deg):
return deg / 180.0 * 3.1415926
def deleteMesh(name):
if name not in bpy.data.objects:
return
obj = bpy.data.objects[name]
if hasattr(obj, "animation_data"):
if hasattr(obj.animation_data, "action"):
action = obj.animation_data.action
if action is not None:
bpy.data.actions.remove(action)
mesh = bpy.data.meshes[name]
if hasattr(mesh, "animation_data"):
if hasattr(mesh.animation_data, "action"):
action = mesh.animation_data.action
if action is not None:
bpy.data.actions.remove(action)
if mesh.shape_keys is not None:
if hasattr(mesh, "animation_data"):
if hasattr(mesh.animation_data, "action"):
action = mesh.shape_keys.animation_data.action
if action is not None:
bpy.data.actions.remove(action)
bpy.data.meshes.remove(mesh)
def setPlane(name="Plane"):
if name in bpy.data.meshes:
deleteMesh(name)
bpy.ops.mesh.primitive_plane_add(size=20)
plane = bpy.context.object
plane.data.name = name
plane.name = name
plane.location.z = -1.1
return plane
def setLight(name="Light"):
if name in bpy.data.lights:
bpy.data.lights.remove(bpy.data.lights[name])
bpy.ops.object.light_add(
type="AREA",
location=(0.0, 0.0, 8.0),)
light = bpy.context.object
light.data.name = name
light.name = name
light.data.energy = 500
light.data.shape = "SQUARE"
light.data.size = 3
def setCamera(name="Camera"):
if name in bpy.data.cameras:
bpy.data.cameras.remove(bpy.data.cameras[name])
bpy.ops.object.camera_add(
location=(0.0, -22.0, 10.0),
rotation=(d2r(63.0), 0.0, 0.0))
camera = bpy.context.object
camera.data.name = name
camera.name = name
return camera
def setCubeAnime(cube):
lrs = [
[(-5, -5, 0), (0, 0, 0)],
[(5, -5, 0), (0, 0, 0)],
[(5, -5, 0), (0, 0, d2r(135))],
[(-5, 5, 0), (d2r(180), 0, d2r(135))],
[(-5, 5, 0), (d2r(180), 0, 0)],
[(5, 5, 0), (d2r(180), 0, 0)],
[(5, 5, 0), (d2r(180), 0, -d2r(135+360))],
[(-5, -5, 0), (0, 0, -d2r(135+360))],
[(-5, -5, 0), (0, 0, -d2r(360))]
]
w = 15
cube.location = lrs[0][0]
cube.rotation_euler = lrs[0][1]
cube.keyframe_insert(data_path="location", frame=1)
cube.keyframe_insert(data_path="rotation_euler", frame=1)
for t in range(1, len(lrs)):
cube.location = lrs[t][0]
cube.rotation_euler = lrs[t][1]
cube.keyframe_insert(data_path="location", frame=w*t)
cube.keyframe_insert(data_path="rotation_euler", frame=w*t)
return w * (len(lrs)-1)
def setCube(name="Cube"):
bpy.ops.object.select_all(action="DESELECT")
if name in bpy.data.meshes:
deleteMesh(name)
bpy.ops.mesh.primitive_cube_add()
cube = bpy.context.object
cube.name = name
cube.data.name = name
bpy.ops.object.modifier_add(type="BEVEL")
bevel = cube.modifiers.active
bevel.segments = 5
bpy.ops.object.shade_smooth(use_auto_smooth=True)
return cube, setCubeAnime(cube)
def getMatrixs(cube):
bpy.ops.object.select_all(action="DESELECT")
matrixs = []
scene = bpy.context.scene
for t in range(scene.frame_start, scene.frame_end+1):
bpy.context.scene.frame_set(t)
matrixs.append(mathutils.Matrix(cube.matrix_world))
return matrixs
def getJet(name="jet", n=4):
bpy.ops.object.select_all(action="DESELECT")
if name in bpy.data.meshes:
deleteMesh(name)
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh)
bpy.context.scene.collection.objects.link(obj)
vs = [(0, 0, i+1) for i in range(n)]
es = [(i, i+1) for i in range(n-1)]
mesh.from_pydata(vs, es, [])
mesh.update()
return obj
def getShapeKeysIndexes(obj, idx):
idxes = []
bpy.ops.object.select_all(action="DESELECT")
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.shape_key_add(from_mix=False)
idxes.append(obj.active_shape_key_index) # Basis
for t in range(bpy.data.scenes["Scene"].frame_end):
bpy.ops.object.shape_key_add(from_mix=False)
idxes.append(obj.active_shape_key_index)
return idxes
def visibillity(obj, flag, t):
obj.hide_viewport = flag
obj.keyframe_insert(data_path="hide_viewport", frame=t)
obj.hide_render = flag
obj.keyframe_insert(data_path="hide_render", frame=t)
def setVertexPosition(obj, matrixs, v, j, sk_idx, cube):
obj.active_shape_key_index = sk_idx
shape_key = obj.data.shape_keys.key_blocks[sk_idx]
if j != 0:
shape_key.name = f"frame {j}"
bpy.ops.object.mode_set(mode="EDIT")
visibillity(obj, True, j)
if j < 3:
return
flag = False
for i in range(len(shape_key.data)):
loc = j - i - 1
if not (0 <= loc and loc < len(matrixs)):
flag = True
break
shape_key.data[i].co = (matrixs[loc] @ v).xyz
visibillity(obj, flag, j)
if not flag:
for value, frame in zip([0, 1, 0], [j-1, j, j+1]):
shape_key.value = value
shape_key.keyframe_insert(data_path="value", frame=frame)
def setPositionsOfVertex(cube):
ret = []
matrixs = getMatrixs(cube)
vs = [mathutils.Vector(v.co) for v in cube.data.vertices]
for i, v in enumerate(vs):
obj = getJet(name=f"{cube.name}_jet_{i}")
ret.append(obj)
idxes = getShapeKeysIndexes(obj, i)
bpy.ops.object.select_all(action="DESELECT")
cube.select_set(True)
bpy.context.view_layer.objects.active = cube
bpy.ops.object.mode_set(mode="OBJECT")
for j, sk_idx in enumerate(idxes):
setVertexPosition(obj, matrixs, v, j, sk_idx, cube)
bpy.ops.object.mode_set(mode="OBJECT")
return ret
def setMaterial(jets, name="jet_Material"):
if name in bpy.data.materials:
bpy.data.materials.remove(bpy.data.materials[name])
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = jets[0]
bpy.ops.material.new()
mat = bpy.data.materials[-1]
mat.name = name
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Emission"].default_value = mathutils.Vector((1, 1, 1, 1))
bsdf.inputs["Emission Strength"].default_value = 1.5
return mat
def setNodes(jets, material, name="jet_NodeTree"):
if name in bpy.data.node_groups:
bpy.data.node_groups.remove(bpy.data.node_groups[name])
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = jets[0]
bpy.ops.object.modifier_add(type="NODES")
mod = jets[0].modifiers.active
mod.name = name
bpy.ops.node.new_geometry_node_group_assign()
nodes = mod.node_group.nodes
links = mod.node_group.links
gi = nodes["Group Input"]
go = nodes["Group Output"]
sm = nodes.new(type="GeometryNodeSetMaterial")
sm.inputs['Material'].default_value = material
links.new(sm.outputs["Geometry"], go.inputs["Geometry"])
c2m = nodes.new(type="GeometryNodeCurveToMesh")
c2m.inputs["Fill Caps"].default_value = True
links.new(c2m.outputs["Mesh"], sm.inputs["Geometry"])
scr = nodes.new(type="GeometryNodeSetCurveRadius")
links.new(scr.outputs["Curve"], c2m.inputs["Curve"])
cc = nodes.new(type="GeometryNodeCurvePrimitiveCircle")
cc.inputs['Resolution'].default_value = 6
cc.inputs['Radius'].default_value = 0.05
links.new(cc.outputs["Curve"], c2m.inputs["Profile Curve"])
rsc = nodes.new(type="GeometryNodeResampleCurve")
links.new(rsc.outputs["Curve"], scr.inputs["Curve"])
m2c = nodes.new(type="GeometryNodeMeshToCurve")
links.new(m2c.outputs["Curve"], rsc.inputs["Curve"])
links.new(gi.outputs["Geometry"], m2c.inputs["Mesh"])
mul = nodes.new(type="ShaderNodeMath")
mul.operation = "MULTIPLY"
mul.inputs[1].default_value = 2.0
links.new(mul.outputs["Value"], scr.inputs["Radius"])
fc = nodes.new(type="ShaderNodeFloatCurve")
ps = fc.mapping.curves[-1].points
ps[0].location = mathutils.Vector((0.0, 0.25))
ps[1].location = mathutils.Vector((1.0, 0.0))
cmp = ps.new(0.1, 1.0)
cmp.handle_type = "VECTOR"
ps.new(0.5, 0.25)
links.new(fc.outputs["Value"], mul.inputs[0])
spp = nodes.new(type="GeometryNodeSplineParameter")
links.new(spp.outputs["Factor"], fc.inputs["Value"])
for jet in jets:
jet.select_set(True)
bpy.ops.object.make_links_data(type="MODIFIERS")
setCamera()
setLight()
setPlane()
cube, n = setCube()
bpy.data.scenes["Scene"].frame_end = n
jets = setPositionsOfVertex(cube)
setNodes(jets, setMaterial(jets))
@pgtwitter
Copy link
Author

dist145_cont.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment