Add camera rigs: Add camera offset bone to the 3D rig

This commit is contained in:
Wayne Dixon 2020-06-13 13:21:29 +10:00 committed by Damien Picard
parent ba2521b7ed
commit 0068e69d3a
3 changed files with 88 additions and 77 deletions

View File

@ -19,7 +19,7 @@
bl_info = {
"name": "Add Camera Rigs",
"author": "Wayne Dixon, Brian Raschko, Kris Wittig, Damien Picard, Flavio Perez",
"version": (1, 4, 3),
"version": (1, 4, 4),
"blender": (2, 80, 0),
"location": "View3D > Add > Camera > Dolly or Crane Rig",
"description": "Adds a Camera Rig with UI",

View File

@ -24,8 +24,9 @@ from rna_prop_ui import rna_idprop_ui_prop_get
from math import pi
from .create_widgets import (create_root_widget,
create_camera_widget, create_aim_widget,
create_circle_widget, create_corner_widget)
create_camera_widget, create_camera_offset_widget,
create_aim_widget, create_circle_widget,
create_corner_widget)
def create_prop_driver(rig, cam, prop_from, prop_to):
@ -66,11 +67,23 @@ def create_dolly_bones(rig):
ctrl.tail = (0.0, 1.0, 1.7)
ctrl.show_wire = True
ctrl_offset = bones.new("Camera_offset")
ctrl_offset.head = (0.0, 0.0, 1.7)
ctrl_offset.tail = (0.0, 1.0, 1.7)
ctrl_offset.show_wire = True
# Setup hierarchy
ctrl.parent = root
ctrl_offset.parent = ctrl
ctrl_aim.parent = root
ctrl_aim_child.parent = ctrl_aim
# Jump into object mode
bpy.ops.object.mode_set(mode='OBJECT')
pose_bones = rig.pose.bones
# Lock the relevant scale channels of the Camera_offset bone
pose_bones["Camera_offset"].lock_scale = (True,) * 3
def create_crane_bones(rig):
"""Create bones for the crane camera rig"""
@ -95,6 +108,10 @@ def create_crane_bones(rig):
ctrl.head = (0.0, 1.0, 1.7)
ctrl.tail = (0.0, 2.0, 1.7)
ctrl_offset = bones.new("Camera_offset")
ctrl_offset.head = (0.0, 1.0, 1.7)
ctrl_offset.tail = (0.0, 2.0, 1.7)
arm = bones.new("Crane_arm")
arm.head = (0.0, 0.0, 1.7)
arm.tail = (0.0, 1.0, 1.7)
@ -105,6 +122,7 @@ def create_crane_bones(rig):
# Setup hierarchy
ctrl.parent = arm
ctrl_offset.parent = ctrl
ctrl.use_inherit_rotation = False
ctrl.use_inherit_scale = False
ctrl.show_wire = True
@ -123,9 +141,10 @@ def create_crane_bones(rig):
# Lock the relevant loc, rot and scale
pose_bones["Crane_arm"].lock_rotation = (False, True, False)
pose_bones["Crane_arm"].lock_scale = (True, False, True)
pose_bones["Crane_height"].lock_location = (True, True, True)
pose_bones["Crane_height"].lock_rotation = (True, True, True)
pose_bones["Crane_height"].lock_location = (True,) * 3
pose_bones["Crane_height"].lock_rotation = (True,) * 3
pose_bones["Crane_height"].lock_scale = (True, False, True)
pose_bones["Camera_offset"].lock_scale = (True,) * 3
def setup_3d_rig(rig, cam):
@ -148,14 +167,16 @@ def setup_3d_rig(rig, cam):
# Build the widgets
root_widget = create_root_widget("Camera_Root")
camera_widget = create_camera_widget("Camera")
camera_offset_widget = create_camera_offset_widget("Camera_offset")
aim_widget = create_aim_widget("Aim")
# Add the custom bone shapes
pose_bones["Root"].custom_shape = root_widget
pose_bones["Aim"].custom_shape = aim_widget
pose_bones["Camera"].custom_shape = camera_widget
pose_bones["Camera_offset"].custom_shape = camera_offset_widget
# Set the "At" field to the shape mecanism
# Set the "Override Transform" field to the mechanism position
pose_bones["Aim"].custom_shape_transform = pose_bones["Aim_shape_rotation-MCH"]
# Add constraints to bones
@ -243,7 +264,8 @@ def create_2d_bones(context, rig, cam):
driver = center_drivers[1].driver
driver.type = 'SCRIPTED'
driver.expression = '({distance_x} - (left_x-right_x))*(res_y/res_x)/2 + (left_y + right_y)/2'.format(distance_x=corner_distance_x)
driver.expression = '({distance_x} - (left_x-right_x))*(res_y/res_x)/2 + (left_y + right_y)/2'.format(
distance_x=corner_distance_x)
for direction in ('x', 'y'):
for corner in ('left', 'right'):
@ -324,7 +346,8 @@ def create_2d_bones(context, rig, cam):
# Focal length driver
driver = cam.data.driver_add('lens').driver
driver.expression = 'abs({distance_z} - (left_z + right_z)/2 + cam_z) * 36 / frame_width'.format(distance_z=corner_distance_z)
driver.expression = 'abs({distance_z} - (left_z + right_z)/2 + cam_z) * 36 / frame_width'.format(
distance_z=corner_distance_z)
var = driver.variables.new()
var.name = 'frame_width'
@ -369,7 +392,8 @@ def create_2d_bones(context, rig, cam):
# Shift driver X
driver = cam.data.driver_add('shift_x').driver
driver.expression = 'rotation_shift * (((left_x + right_x)/2 - cam_x) * lens / abs({distance_z} - (left_z + right_z)/2 + cam_z) / 36)'.format(distance_z=corner_distance_z)
driver.expression = 'rotation_shift * (((left_x + right_x)/2 - cam_x) * lens / abs({distance_z} - (left_z + right_z)/2 + cam_z) / 36)'.format(
distance_z=corner_distance_z)
var = driver.variables.new()
var.name = 'rotation_shift'
@ -405,7 +429,8 @@ def create_2d_bones(context, rig, cam):
# Shift driver Y
driver = cam.data.driver_add('shift_y').driver
driver.expression = 'rotation_shift * -(({distance_y} - (left_y + right_y)/2 + cam_y) * lens / abs({distance_z} - (left_z + right_z)/2 + cam_z) / 36 - (res_y/res_x)/2)'.format(distance_y=corner_distance_y, distance_z=corner_distance_z)
driver.expression = 'rotation_shift * -(({distance_y} - (left_y + right_y)/2 + cam_y) * lens / abs({distance_z} - (left_z + right_z)/2 + cam_z) / 36 - (res_y/res_x)/2)'.format(
distance_y=corner_distance_y, distance_z=corner_distance_z)
var = driver.variables.new()
var.name = 'rotation_shift'
@ -478,7 +503,10 @@ def build_camera_rig(context, mode):
cam.location = (0.0, -1.0, 0.0) # Move the camera to the correct position
cam.parent = rig
cam.parent_type = "BONE"
cam.parent_bone = "Camera"
if mode == "2D":
cam.parent_bone = "Camera"
else:
cam.parent_bone = "Camera_offset"
# Change display to BBone: it just looks nicer
rig.data.display_type = 'BBONE'

View File

@ -54,8 +54,8 @@ def create_corner_widget(name, reverse=False):
obj = create_widget(name)
if not obj.data.vertices:
reverse = -1 if reverse else 1
verts = (Vector((reverse * 0.0, 0.0, 0.0)),
Vector((reverse * 0.0, 1.0, 0.0)),
verts = (Vector((reverse * 0.0, 0.0, 0.0)),
Vector((reverse * 0.0, 1.0, 0.0)),
Vector((reverse * -0.1, 1.0, 0.0)),
Vector((reverse * -0.1, 0.1, 0.0)),
Vector((reverse * -1.0, 0.1, 0.0)),
@ -154,76 +154,59 @@ def create_camera_widget(name):
"""Create a camera control widget"""
obj = create_widget(name)
if not obj.data.vertices:
verts = [(0.27513638138771057, 0.0, -0.27513638138771057),
(0.359483003616333, 0.0, -0.14890272915363312),
(0.38910162448883057, 0.0, 0.0),
(0.359483003616333, 0.0, 0.1489027738571167),
(0.27513638138771057, 0.0, 0.27513638138771057),
(0.1489027589559555, 0.0, 0.359483003616333),
(-1.9481809943044937e-07, 0.0, 0.38910162448883057),
(-1.175054293867106e-07, 0.0, -0.38910162448883057),
(0.148903027176857, 0.0, -0.35948291420936584),
(0.6635494828224182, 0.0, -0.09360162913799286),
(0.6635494828224182, 0.0, 0.09360162913799286),
(0.49765610694885254, 0.0, 0.09360162913799286),
(0.49765610694885254, 0.0, -0.09360168874263763),
(0.6635494828224182, 0.0, 0.17350149154663086),
(0.6635494828224182, 0.0, -0.17350149154663086),
(0.8751950263977051, 0.0, 0.0),
(-0.14890296757221222, 0.0, 0.35948291420936584),
(-0.14890283346176147, 0.0, -0.359483003616333),
(-0.27513641119003296, 0.0, -0.2751363217830658),
(-0.359483003616333, 0.0, -0.14890272915363312),
(-0.38910162448883057, 0.0, 0.0),
(-0.359483003616333, 0.0, 0.1489028036594391),
(-0.2751363217830658, 0.0, 0.27513641119003296),
(1.0342557033027333e-07, 0.0, 0.8751950263977051),
(0.17350155115127563, 0.0, 0.6635494828224182),
(-0.17350146174430847, 0.0, 0.6635494828224182),
(0.09360174089670181, 0.0, 0.49765610694885254),
(-0.09360159188508987, 0.0, 0.49765610694885254),
(-0.09360159188508987, 0.0, 0.6635494828224182),
(0.09360168874263763, 0.0, 0.6635494828224182),
(-0.0936015248298645, 0.0, -0.6635494828224182),
(0.09360174834728241, 0.0, -0.6635494828224182),
(0.09360172599554062, 0.0, -0.49765610694885254),
(-0.09360159933567047, 0.0, -0.49765610694885254),
(0.1735016107559204, 0.0, -0.6635494828224182),
(-0.1735014021396637, 0.0, -0.6635494828224182),
(9.422691960025986e-08, 0.0, -0.8751950263977051),
(-0.8751950263977051, 0.0, 0.0),
(-0.6635494828224182, 0.0, 0.17350131273269653),
(-0.6635494828224182, 0.0, -0.17350167036056519),
(-0.49765610694885254, 0.0, 0.0936015397310257),
(-0.49765610694885254, 0.0, -0.0936017706990242),
(-0.6635494828224182, 0.0, -0.09360179305076599),
(-0.6635494828224182, 0.0, 0.09360147267580032),
(-0.16527177393436432, 0.0, 0.1652718484401703),
(-0.21593798696994781, 0.0, 0.08944448828697205),
(-0.23372963070869446, 0.0, 0.0),
(-0.21593798696994781, 0.0, -0.08944445103406906),
(-0.1652718484401703, 0.0, -0.16527177393436432),
(-0.08944450318813324, 0.0, -0.21593798696994781),
(-0.0894445851445198, 0.0, 0.21593795716762543),
(0.0894446149468422, 0.0, -0.21593795716762543),
(-7.058439166485186e-08, 0.0, -0.23372963070869446),
(-1.1702535118729429e-07, 0.0, 0.23372963070869446),
(0.08944445848464966, 0.0, 0.21593798696994781),
(0.1652718037366867, 0.0, 0.1652718037366867),
(0.21593798696994781, 0.0, 0.08944446593523026),
(0.23372963070869446, 0.0, 0.0),
(0.21593798696994781, 0.0, -0.08944445848464966),
(0.1652718037366867, 0.0, -0.1652718037366867)]
verts = [(0.275136, 0, -0.275136), (0.359483, 0, -0.148903),
(0.389102, 0, 0), (0.359483, 0, 0.148903),
(0.275136, 0, 0.275136), (0.148903, 0, 0.359483),
(-1.94818e-07, 0, 0.389102), (-1.17505e-07, 0, -0.389102),
(0.148903, 0, -0.359483), (0.663549, 0, -0.0936016),
(0.663549, 0, 0.0936016), (0.497656, 0, 0.0936016),
(0.497656, 0, -0.0936017), (0.663549, 0, 0.173501),
(0.663549, 0, -0.173501), (0.875195, 0, 0),
(-0.148903, 0, 0.359483), (-0.148903, 0, -0.359483),
(-0.275136, 0, -0.275136), (-0.359483, 0, -0.148903),
(-0.389102, 0, 0), (-0.359483, 0, 0.148903),
(-0.275136, 0, 0.275136), (1.03426e-07, 0, 0.875195),
(0.173502, 0, 0.663549), (-0.173501, 0, 0.663549),
(0.0936017, 0, 0.497656), (-0.0936016, 0, 0.497656),
(-0.0936016, 0, 0.663549), (0.0936017, 0, 0.663549),
(-0.0936015, 0, -0.663549), (0.0936017, 0, -0.663549),
(0.0936017, 0, -0.497656), (-0.0936016, 0, -0.497656),
(0.173502, 0, -0.663549), (-0.173501, 0, -0.663549),
(9.42269e-08, 0, -0.875195), (-0.875195, 0, 0),
(-0.663549, 0, 0.173501), (-0.663549, 0, -0.173502),
(-0.497656, 0, 0.0936015), (-0.497656, 0, -0.0936018),
(-0.663549, 0, -0.0936018), (-0.663549, 0, 0.0936015),
]
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8),
(10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15),
(16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17),
(6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 29), (27, 28),
(31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), (35, 36),
(37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), (41, 42),
(50, 53), (49, 52), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49),
(44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), (56, 57),
(57, 58), (58, 59), (27, 26)]
(27, 26)]
mesh = obj.data
mesh.from_pydata(verts, edges, [])
mesh.update()
return obj
def create_camera_offset_widget(name):
"""Create a camera offset control widget"""
obj = create_widget(name)
if not obj.data.vertices:
verts = [(0.23286, 0, 0), (0.215135, 0, 0.0891117),
(0.164657, 0, 0.164657), (0.0891117, 0, 0.215135),
(0, 0, 0.23286), (-0.0891117, 0, 0.215135),
(-0.164657, 0, 0.164657), (-0.215135, 0, 0.0891117),
(-0.23286, 0, 0), (-0.215135, 0, -0.0891117),
(-0.164657, 0, -0.164657), (-0.0891117, 0, -0.215135),
(0, 0, -0.23286), (0.0891117, 0, -0.215135),
(0.164657, 0, -0.164657), (0.215135, 0, -0.0891117),
]
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8),
(8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15),
(15, 0)]
mesh = obj.data
mesh.from_pydata(verts, edges, [])