[feature] spline animation
This commit is contained in:
parent
f02f8fc2f0
commit
cd99362bb1
1 changed files with 59 additions and 46 deletions
105
butils.py
105
butils.py
|
@ -221,26 +221,26 @@ def get_hook_modifiers(blender_object: bpy.types.Object):
|
||||||
return [m for m in blender_object.modifiers if m.type == "HOOK"]
|
return [m for m in blender_object.modifiers if m.type == "HOOK"]
|
||||||
|
|
||||||
|
|
||||||
class BezierSplinePoint:
|
class HookBezierSplinePoint:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
co: mathutils.Vector,
|
|
||||||
handle_left: mathutils.Vector,
|
handle_left: mathutils.Vector,
|
||||||
|
co: mathutils.Vector,
|
||||||
handle_right: mathutils.Vector,
|
handle_right: mathutils.Vector,
|
||||||
):
|
):
|
||||||
self.co: mathutils.Vector = co
|
self.handle_left: mathutils.Vector = mathutils.Vector(handle_left)
|
||||||
self.handle_left: mathutils.Vector = handle_left
|
self.co: mathutils.Vector = mathutils.Vector(co)
|
||||||
self.handle_right: mathutils.Vector = handle_right
|
self.handle_right: mathutils.Vector = mathutils.Vector(handle_right)
|
||||||
|
|
||||||
|
|
||||||
class BezierSpline:
|
class HookBezierSpline:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
n: int,
|
n: int,
|
||||||
use_cyclic_u: bool,
|
use_cyclic_u: bool,
|
||||||
resolution_u: int,
|
resolution_u: int,
|
||||||
):
|
):
|
||||||
self.bezier_points = [BezierSplinePoint] * n
|
self.bezier_points = [HookBezierSplinePoint] * n
|
||||||
self.use_cyclic_u: int = use_cyclic_u
|
self.use_cyclic_u: int = use_cyclic_u
|
||||||
self.resolution_u: int = resolution_u
|
self.resolution_u: int = resolution_u
|
||||||
self.beziers: []
|
self.beziers: []
|
||||||
|
@ -249,34 +249,31 @@ class BezierSpline:
|
||||||
|
|
||||||
def calc_length(self, resolution) -> float:
|
def calc_length(self, resolution) -> float:
|
||||||
# ignore resolution when accessing length to imitate blender function
|
# ignore resolution when accessing length to imitate blender function
|
||||||
print(f"{self.total_length=}")
|
|
||||||
return self.total_length
|
return self.total_length
|
||||||
|
|
||||||
|
|
||||||
class BezierData:
|
class HookBezierData:
|
||||||
def __init__(self, n):
|
def __init__(self, n):
|
||||||
self.splines = [BezierSpline] * n
|
self.splines = [HookBezierSpline] * n
|
||||||
|
|
||||||
|
|
||||||
class BezierCurve:
|
class HookBezierCurve:
|
||||||
def __init__(self, blender_curve: bpy.types.Object, resolution_factor=1.0):
|
def __init__(self, blender_curve: bpy.types.Object, resolution_factor=1.0):
|
||||||
self.data = BezierData(len(blender_curve.data.splines))
|
self.data = HookBezierData(len(blender_curve.data.splines))
|
||||||
i = 0
|
i = 0
|
||||||
hooks = get_hook_modifiers(blender_curve)
|
hooks = get_hook_modifiers(blender_curve)
|
||||||
print(f"{blender_curve.name=} =============================================")
|
|
||||||
for si, blender_spline in enumerate(blender_curve.data.splines):
|
for si, blender_spline in enumerate(blender_curve.data.splines):
|
||||||
self.data.splines[si] = BezierSpline(
|
self.data.splines[si] = HookBezierSpline(
|
||||||
len(blender_spline.bezier_points),
|
len(blender_spline.bezier_points),
|
||||||
blender_spline.use_cyclic_u,
|
blender_spline.use_cyclic_u,
|
||||||
blender_spline.resolution_u,
|
blender_spline.resolution_u,
|
||||||
)
|
)
|
||||||
for pi, blender_bezier_point in enumerate(blender_spline.bezier_points):
|
for pi, blender_bezier_point in enumerate(blender_spline.bezier_points):
|
||||||
self.data.splines[si].bezier_points[pi] = BezierSplinePoint(
|
self.data.splines[si].bezier_points[pi] = HookBezierSplinePoint(
|
||||||
blender_bezier_point.co,
|
|
||||||
blender_bezier_point.handle_left,
|
blender_bezier_point.handle_left,
|
||||||
|
blender_bezier_point.co,
|
||||||
blender_bezier_point.handle_right,
|
blender_bezier_point.handle_right,
|
||||||
)
|
)
|
||||||
print(pi)
|
|
||||||
for hook in hooks:
|
for hook in hooks:
|
||||||
hook_co = False
|
hook_co = False
|
||||||
hook_handle_left = False
|
hook_handle_left = False
|
||||||
|
@ -293,40 +290,57 @@ class BezierCurve:
|
||||||
blender_curve.matrix_world.inverted()
|
blender_curve.matrix_world.inverted()
|
||||||
@ hook.object.matrix_world.translation
|
@ hook.object.matrix_world.translation
|
||||||
)
|
)
|
||||||
print(f"co {location=}")
|
|
||||||
self.data.splines[si].bezier_points[pi].co = (
|
self.data.splines[si].bezier_points[pi].co = (
|
||||||
self.data.splines[si]
|
self.data.splines[si]
|
||||||
.bezier_points[pi]
|
.bezier_points[pi]
|
||||||
.co.lerp(location, hook.strength)
|
.co.lerp(location, hook.strength)
|
||||||
)
|
)
|
||||||
# if hook_handle_left:
|
if hook_handle_left:
|
||||||
# location = (
|
location_left = location + (
|
||||||
# hook.object.matrix_world.translation
|
self.data.splines[si].bezier_points[pi].co
|
||||||
# - blender_curve.matrix_world.translation
|
- self.data.splines[si].bezier_points[pi].handle_left
|
||||||
# ) + mathutils.Vector((-1, 0, 0))
|
)
|
||||||
# print(f"handle_left {location=}")
|
self.data.splines[si].bezier_points[pi].handle_left = (
|
||||||
# self.data.splines[si].bezier_points[pi].handle_left = (
|
self.data.splines[si]
|
||||||
# self.data.splines[si]
|
.bezier_points[pi]
|
||||||
# .bezier_points[pi]
|
.co.lerp(location_left, hook.strength)
|
||||||
# .handle_left.lerp(location, hook.strength)
|
)
|
||||||
# )
|
if hook_handle_right:
|
||||||
# if hook_handle_right:
|
location_right = location + (
|
||||||
# location = (
|
self.data.splines[si].bezier_points[pi].co
|
||||||
# hook.object.matrix_world.translation
|
- self.data.splines[si].bezier_points[pi].handle_right
|
||||||
# - blender_curve.matrix_world.translation
|
)
|
||||||
# )
|
self.data.splines[si].bezier_points[pi].handle_right = (
|
||||||
# self.data.splines[si].bezier_points[pi].handle_right = (
|
self.data.splines[si]
|
||||||
# self.data.splines[si]
|
.bezier_points[pi]
|
||||||
# .bezier_points[pi]
|
.co.lerp(location, hook.strength)
|
||||||
# .handle_right.lerp(location, hook.strength)
|
)
|
||||||
# )
|
elif hook_handle_left:
|
||||||
|
location = (
|
||||||
|
blender_curve.matrix_world.inverted()
|
||||||
|
@ hook.object.matrix_world.translation
|
||||||
|
)
|
||||||
|
self.data.splines[si].bezier_points[pi].handle_left = (
|
||||||
|
self.data.splines[si]
|
||||||
|
.bezier_points[pi]
|
||||||
|
.handle_left.lerp(location, hook.strength)
|
||||||
|
)
|
||||||
|
elif hook_handle_right:
|
||||||
|
location = (
|
||||||
|
blender_curve.matrix_world.inverted()
|
||||||
|
@ hook.object.matrix_world.translation
|
||||||
|
)
|
||||||
|
self.data.splines[si].bezier_points[pi].handle_right = (
|
||||||
|
self.data.splines[si]
|
||||||
|
.bezier_points[pi]
|
||||||
|
.handle_right.lerp(location, hook.strength)
|
||||||
|
)
|
||||||
i += 1
|
i += 1
|
||||||
(
|
(
|
||||||
self.data.splines[si].beziers,
|
self.data.splines[si].beziers,
|
||||||
self.data.splines[si].lengths,
|
self.data.splines[si].lengths,
|
||||||
self.data.splines[si].total_length,
|
self.data.splines[si].total_length,
|
||||||
) = get_real_beziers_and_lengths(self.data.splines[si], resolution_factor)
|
) = get_real_beziers_and_lengths(self.data.splines[si], resolution_factor)
|
||||||
print(f"total length {self.data.splines[si].total_length}")
|
|
||||||
|
|
||||||
|
|
||||||
def get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor):
|
def get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor):
|
||||||
|
@ -391,7 +405,7 @@ def calc_point_on_bezier_spline(
|
||||||
if p.handle_left == p.co and len(bezier_spline_obj.bezier_points) > 1:
|
if p.handle_left == p.co and len(bezier_spline_obj.bezier_points) > 1:
|
||||||
beziers, lengths, total_length = (
|
beziers, lengths, total_length = (
|
||||||
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
|
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
|
||||||
if not isinstance(bezier_spline_obj, BezierSpline)
|
if not isinstance(bezier_spline_obj, HookBezierSpline)
|
||||||
else (
|
else (
|
||||||
bezier_spline_obj.beziers,
|
bezier_spline_obj.beziers,
|
||||||
bezier_spline_obj.lengths,
|
bezier_spline_obj.lengths,
|
||||||
|
@ -411,7 +425,7 @@ def calc_point_on_bezier_spline(
|
||||||
|
|
||||||
beziers, lengths, total_length = (
|
beziers, lengths, total_length = (
|
||||||
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
|
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
|
||||||
if not isinstance(bezier_spline_obj, BezierSpline)
|
if not isinstance(bezier_spline_obj, HookBezierSpline)
|
||||||
else (
|
else (
|
||||||
bezier_spline_obj.beziers,
|
bezier_spline_obj.beziers,
|
||||||
bezier_spline_obj.lengths,
|
bezier_spline_obj.lengths,
|
||||||
|
@ -460,16 +474,15 @@ def calc_point_on_bezier_curve(
|
||||||
output_spline_index=False,
|
output_spline_index=False,
|
||||||
resolution_factor=1.0,
|
resolution_factor=1.0,
|
||||||
):
|
):
|
||||||
# bezier_curve = BezierCurve(bezier_curve_obj)
|
bezier_curve = HookBezierCurve(bezier_curve_obj)
|
||||||
# curve = bezier_curve.data
|
curve = bezier_curve.data
|
||||||
curve = bezier_curve_obj.data
|
# curve = bezier_curve_obj.data
|
||||||
|
|
||||||
# Loop through all splines in the curve
|
# Loop through all splines in the curve
|
||||||
total_length = 0
|
total_length = 0
|
||||||
for i, spline in enumerate(curve.splines):
|
for i, spline in enumerate(curve.splines):
|
||||||
resolution = int(spline.resolution_u * resolution_factor)
|
resolution = int(spline.resolution_u * resolution_factor)
|
||||||
length = spline.calc_length(resolution=resolution)
|
length = spline.calc_length(resolution=resolution)
|
||||||
print(f"{utils.LINE()} {length=}")
|
|
||||||
if total_length + length > distance or i == len(curve.splines) - 1:
|
if total_length + length > distance or i == len(curve.splines) - 1:
|
||||||
if output_spline_index and output_tangent:
|
if output_spline_index and output_tangent:
|
||||||
# return value from c_p_o_b_s is a tuple
|
# return value from c_p_o_b_s is a tuple
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue