Imagine a piece of paper and you fold it in half and then fold it again. that's what I am trying to do and cant. If I use bones the influence of the bones won't allow me to because I need 2 bones to control the same area. If I try shape keys it just deforms the mesh if I try to make it in multiple steps or does the wrong animation because it draws the shortest path instead of rotating from a point like a piece of paper would.
1 Answer
Hinge bone armature.
In the second part of this answer I wrote a script to make an armature, can be used here
import bpy
from mathutils import Matrix, Vector
from mathutils.geometry import intersect_point_line
import bmesh
context = bpy.context
def hinge(armob, ob, pb, face):
arm = armob.data
# add a bone from edge center to face center
face.select_set(True)
edges = [(l, f) for l in face.loops for f in l.edge.link_faces if not f.select]
for l, f in edges:
e = l.edge
b = arm.edit_bones.new(f"Hinge_{f.index}")
b.parent = pb
pt, dist = intersect_point_line(
f.calc_center_median(),
e.verts[1].co,
e.verts[0].co,
)
b.head = pt
b.tail = f.calc_center_median()
vg = (
ob.vertex_groups.get(b.name) or
ob.vertex_groups.new(name=b.name)
)
vg.add([v.index for v in f.verts], 1, 'ADD')
hinge(armob, ob, b, f)
def make_armature(ob, face_index):
me = ob.data
bm = bmesh.from_edit_mesh(me).copy()
face = bm.faces.active
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.armature_add()
arm = context.object
mw = (
ob.parent.matrix_world.copy() if ob.parent
else ob.matrix_world.copy()
)
ob.matrix_parent_inverse.identity()
#ob.matrix_world.identity()
ob.parent = arm
ob.matrix_parent_inverse = ob.matrix_world.inverted()
ob.vertex_groups.clear()
arm.matrix_world = ob.matrix_world
bpy.ops.object.mode_set(mode='EDIT')
b = arm.data.edit_bones[0]
b.tail += face.calc_center_median()
b.head += face.calc_center_median()
hinge(arm, ob, b, face)
bpy.ops.object.mode_set(mode='OBJECT')
for pb in arm.pose.bones[1:]:
pb.rotation_mode = 'AXIS_ANGLE'
pb.rotation_axis_angle = (0, 1, 0, 0)
ob.modifiers.clear()
mod = ob.modifiers.new(
"Hinger",
type='ARMATURE',
)
mod.object = arm
bpy.ops.object.mode_set(mode='POSE')
make_armature(context.object, 0)
With the mesh in edit mode, select one face, Run the script, creates an armature, with root bone at that face.
Now with the armature in pose mode Shift select the two bones going same way to fold. Can Alt change the property of one to change same property all selected. Type in 180 to fold in half.
Now the slightly tricky bit because the script wasn't designed to do this... Shift select the two bones going the other way. Change the axis of one by negating the X axis (1 -> -1) this will ensure both spin the same way for this fold. (Alternately one to 180 and one to -180 degrees, will do same.)
Now same as before press Alt and change the angle, and rotate to 180.
-
2$\begingroup$ Holly shit this is amazing. It works so well I am about to cry. thanks, man. I had to do another fold and it worked by changing to -1 also this great!! $\endgroup$ Commented Mar 1, 2021 at 17:04