forked from pfalkingham/XROMM_BlenderTools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoRel.py
More file actions
86 lines (66 loc) · 3.54 KB
/
Copy pathoRel.py
File metadata and controls
86 lines (66 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
########################################
#Calculate relative motion between two objects, and apply data to a new object
#Parents existing axes to prox object, and creates new axes parented to distal object, then calculates motion between them.
#Written by Peter Falkingham, July 2023
#Credit for original Maya Mel scripts on which this is based goes to: Dave Baier.
########################################
import bpy
from mathutils import Matrix
#####
# Ariel Camp would like to be able to calculate relative motion between two objects,
# and have the data stored in a new object. i.e. without using axes
# Shouldn't be too hard to implemt (if axis_object=null), but not a priority right now.
####
def calcRelMotion(axis_object, proximal_object, distal_object):
bpy.ops.object.select_all(action='DESELECT')
axis_object.select_set(True)
#apply any constraints on axis_object
bpy.ops.object.visual_transform_apply()
#Clear all constraints on axis_object
bpy.context.view_layer.objects.active = axis_object
bpy.ops.object.constraints_clear()
#delete the two locators that share the same name as axis_object plus either _posz or _negz
for obj in bpy.data.objects:
if obj.name == axis_object.name + "_posZ" or obj.name == axis_object.name + "_negZ":
bpy.data.objects.remove(obj, do_unlink=True)
#duplicate axis_object and rename it to axis_object.name + "Prox"
bpy.ops.object.select_all(action='DESELECT')
axis_object.select_set(True)
bpy.ops.object.duplicate_move()
bpy.context.object.name = axis_object.name + "Prox"
axis_object_prox = bpy.data.objects[axis_object.name + "Prox"]
#parent axis_object_prox to proximal object
bpy.ops.object.select_all(action='DESELECT')
axis_object_prox.select_set(True)
proximal_object.select_set(True)
bpy.context.view_layer.objects.active = proximal_object
bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
#parent axis_object to distal_object
bpy.ops.object.select_all(action='DESELECT')
axis_object.select_set(True)
distal_object.select_set(True)
bpy.context.view_layer.objects.active = distal_object
bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
#Now create an empty we can store relative position and rotation values in
# Create a new empty object
arrows_object = bpy.data.objects.new("Arrows", None)
arrows_object.name = axis_object.name + "_Data"
# Add the empty object to the scene
bpy.context.collection.objects.link(arrows_object)
#calculate relative translation and rotation over the timeline, and store it in the empty
# Iterate over the frames in the timeline
for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1):
# Set the current frame
bpy.context.scene.frame_set(frame)
# Get the relative transform between the two axes
rel_transform = axis_object_prox.matrix_world.inverted() @ axis_object.matrix_world
# Extract the relative rotation and translation from the relative transform
rel_rotation = rel_transform.to_euler()
rel_translation = rel_transform.to_translation()
# Set the rotation and translation of the arrows object
arrows_object.rotation_mode = 'XYZ'
arrows_object.rotation_euler = rel_rotation
arrows_object.location = rel_translation
# Insert a keyframe for the arrows object
arrows_object.keyframe_insert(data_path='location', frame=frame)
arrows_object.keyframe_insert(data_path='rotation_euler', frame=frame)