initial parent code
This commit is contained in:
@@ -159,6 +159,72 @@ def plane_on_bone(bone, arm=None, cam=None, set_rotation=True, mesh=True):
|
||||
plane = plane_coords()
|
||||
return matrix_transform(plane, mat @ mat_scale)
|
||||
|
||||
def place_object_to_ref_facing_cam(obj, ref_ob, bone=None, cam=None, set_rotation=True):
|
||||
'''
|
||||
obj (Object): the object to place
|
||||
ref_ob (Object): the reference object or armature
|
||||
bone (posebone): reference pose bone
|
||||
arm (optional: Armature): Armature of the pose bone (if not passed found using bone.id_data)
|
||||
cam (optional: Camera) : Camera to align plane to (if not passed use scene camera)
|
||||
set_rotation (bool): rotate the plane on cam view axis according to bone direction in 2d cam space
|
||||
'''
|
||||
|
||||
if cam is None:
|
||||
cam = bpy.context.scene.camera
|
||||
|
||||
# if ref_ob is None:
|
||||
# ref_ob = bone.id_data
|
||||
|
||||
mat = cam.matrix_world.copy()
|
||||
|
||||
if set_rotation:
|
||||
if bone:
|
||||
head_world_coord = ref_ob.matrix_world @ bone.head
|
||||
mat.translation = head_world_coord
|
||||
|
||||
## Apply 2d bone rotation facing camera
|
||||
# Get 2d camera space coords (NDC: normalized device coordinate, 0,0 is bottom-left)
|
||||
head_2d, tail_2d = get_bone_head_tail_2d(bone, cam=cam)
|
||||
else:
|
||||
mat.translation = ref_ob.matrix_world
|
||||
# Get 2d camera space coords (NDC: normalized device coordinate, 0,0 is bottom-left)
|
||||
scene = bpy.context.scene
|
||||
up_vec = Vector((0,0,1))
|
||||
up_vec.rotate(ref_ob.matrix_world)
|
||||
tail_3d = ref_ob.matrix_world.to_translation() + up_vec
|
||||
head_2d = world_to_camera_view(scene, cam, ref_ob.matrix_world.to_translation())
|
||||
tail_2d = world_to_camera_view(scene, cam, tail_3d)
|
||||
ratio = scene.render.resolution_y / scene.render.resolution_x
|
||||
head_2d.y *= ratio
|
||||
tail_2d.y *= ratio
|
||||
|
||||
vec_from_corner_2d = (tail_2d - head_2d).normalized()
|
||||
up_vec_2d = Vector((0,1))
|
||||
# angle = acos(up_vec_2d.dot(vec_from_corner_2d)) ## equivalent but not signed!
|
||||
angle = up_vec_2d.angle_signed(vec_from_corner_2d)
|
||||
|
||||
## Axis camera aim (seem slightly off)
|
||||
# rot_axis = Vector((0, 0, -1))
|
||||
# rot_axis.rotate(cam.matrix_world)
|
||||
|
||||
## Axis camera origin -> pivot
|
||||
rot_axis = head_world_coord - cam.matrix_world.translation
|
||||
mat = rotate_matrix_around_pivot(mat, angle, head_world_coord, rot_axis)
|
||||
|
||||
else:
|
||||
if bone:
|
||||
## Use mid bone to better follow movement
|
||||
mat.translation = ref_ob.matrix_world @ ((bone.tail + bone.head) / 2) # Mid bone
|
||||
else:
|
||||
mat.translation = ref_ob.matrix_world
|
||||
|
||||
## change/adapt scale
|
||||
# mat_scale = Matrix.Scale(10, 4) # maybe move above mesh condition
|
||||
# mat = mat @ mat_scale
|
||||
obj.matrix_world = mat
|
||||
|
||||
|
||||
|
||||
def create_plane(name='Plane', collection=None):
|
||||
'''Create a plane using pydata
|
||||
collection: link in passed collection, else do not link in scene
|
||||
@@ -335,3 +401,9 @@ def following_keys(forward=True, all_keys=False) -> list:# -> list[int] | list |
|
||||
if new is None:
|
||||
return []
|
||||
return [int(new)]
|
||||
|
||||
|
||||
## -- animation
|
||||
|
||||
def is_animated(obj):
|
||||
return True
|
||||
Reference in New Issue
Block a user