Blender driver functions for animation bake
This commit is contained in:
80
blender_driver_func.py
Normal file
80
blender_driver_func.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
from mathutils import *
|
||||||
|
from math import *
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
|
def angle_to_length(angle: float, target: float = 1.0) -> float:
|
||||||
|
"""
|
||||||
|
Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 180deg(!).
|
||||||
|
The distance is clamped to the target value.
|
||||||
|
|
||||||
|
:param angle: Input angle (in radians)
|
||||||
|
:type angle: float
|
||||||
|
:param target: Desired distance between end points, defaults to 1.0
|
||||||
|
:type target: float, optional
|
||||||
|
:return: The distance between two points
|
||||||
|
:rtype: float
|
||||||
|
"""
|
||||||
|
if angle > 0:
|
||||||
|
return (target * 0.5 * sin(pi - angle)) / sin(angle * 0.5) # School trigonometry
|
||||||
|
else:
|
||||||
|
return target
|
||||||
|
|
||||||
|
|
||||||
|
def half_angle_to_length(angle: float, target: float = 1.0) -> float:
|
||||||
|
"""
|
||||||
|
Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 90deg.
|
||||||
|
The distance is clamped to the target value.
|
||||||
|
|
||||||
|
:param angle: Input angle (in radians)
|
||||||
|
:type angle: float
|
||||||
|
:param target: Desired distance between end points, defaults to 1.0
|
||||||
|
:type target: float, optional
|
||||||
|
:return: The distance between two points
|
||||||
|
:rtype: float
|
||||||
|
"""
|
||||||
|
side = sqrt(pow(target, 2) * 0.5) # Length of imaginary triangle's side
|
||||||
|
angle = abs(pi * 0.5 - angle) # Default angle is 90deg
|
||||||
|
return (side * sin(angle)) / sin((pi - angle) * 0.5)
|
||||||
|
|
||||||
|
|
||||||
|
def angle_compensation(angle: float) -> float:
|
||||||
|
side_len = sqrt(pow(pi * 0.5, 2) * 0.5) # Length of imaginary triangle's side
|
||||||
|
distance = 0.5 # Distance to which move bone to
|
||||||
|
|
||||||
|
angle = abs(pi - angle)
|
||||||
|
|
||||||
|
# Compensate non-linear input angle
|
||||||
|
if angle > 0:
|
||||||
|
comp_angle = (side_len * 0.5 * sin(angle)) / sin(angle * 0.5)
|
||||||
|
else:
|
||||||
|
comp_angle = side_len
|
||||||
|
|
||||||
|
return (sqrt(pow(tan(comp_angle), 2) + 1) - 1) * distance
|
||||||
|
|
||||||
|
|
||||||
|
def half_angle_compensation(angle: float) -> float:
|
||||||
|
side = sqrt(pow(pi * 0.25, 2) * 0.5) # Length of imaginary triangle's side
|
||||||
|
angle = abs(angle)
|
||||||
|
final_angle = (side * sin(angle)) / sin((pi - angle) * 0.5) # Width of imaginary triangle's base
|
||||||
|
return sqrt(pow(tan(final_angle), 2) + 1) - 1 # What the fuck??
|
||||||
|
|
||||||
|
|
||||||
|
def test_compensation(angle: float) -> float:
|
||||||
|
side = sqrt(pow(pi * 0.5, 2) * 0.5) # Triangle's side is now a desired output angle in radians
|
||||||
|
angle = abs(pi - angle) # Rotate default angle to 180deg
|
||||||
|
return angle_to_length(angle, side)
|
||||||
|
|
||||||
|
|
||||||
|
def test_half_compensation(angle: float) -> float:
|
||||||
|
side = pi * 0.25
|
||||||
|
angle = abs(pi * 0.5 + angle) # Rotate default angle to 90deg
|
||||||
|
return half_angle_to_length(angle, side)
|
||||||
|
|
||||||
|
|
||||||
|
bpy.app.driver_namespace["angle_to_length"] = angle_to_length
|
||||||
|
bpy.app.driver_namespace["half_angle_to_length"] = half_angle_to_length
|
||||||
|
bpy.app.driver_namespace["angle_compensation"] = angle_compensation
|
||||||
|
bpy.app.driver_namespace["half_angle_compensation"] = half_angle_compensation
|
||||||
|
bpy.app.driver_namespace["test_compensation"] = test_compensation
|
||||||
|
bpy.app.driver_namespace["test_half_compensation"] = test_half_compensation
|
||||||
Reference in New Issue
Block a user