[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"]
|
||||
|
||||
|
||||
class BezierSplinePoint:
|
||||
class HookBezierSplinePoint:
|
||||
def __init__(
|
||||
self,
|
||||
co: mathutils.Vector,
|
||||
handle_left: mathutils.Vector,
|
||||
co: mathutils.Vector,
|
||||
handle_right: mathutils.Vector,
|
||||
):
|
||||
self.co: mathutils.Vector = co
|
||||
self.handle_left: mathutils.Vector = handle_left
|
||||
self.handle_right: mathutils.Vector = handle_right
|
||||
self.handle_left: mathutils.Vector = mathutils.Vector(handle_left)
|
||||
self.co: mathutils.Vector = mathutils.Vector(co)
|
||||
self.handle_right: mathutils.Vector = mathutils.Vector(handle_right)
|
||||
|
||||
|
||||
class BezierSpline:
|
||||
class HookBezierSpline:
|
||||
def __init__(
|
||||
self,
|
||||
n: int,
|
||||
use_cyclic_u: bool,
|
||||
resolution_u: int,
|
||||
):
|
||||
self.bezier_points = [BezierSplinePoint] * n
|
||||
self.bezier_points = [HookBezierSplinePoint] * n
|
||||
self.use_cyclic_u: int = use_cyclic_u
|
||||
self.resolution_u: int = resolution_u
|
||||
self.beziers: []
|
||||
|
@ -249,34 +249,31 @@ class BezierSpline:
|
|||
|
||||
def calc_length(self, resolution) -> float:
|
||||
# ignore resolution when accessing length to imitate blender function
|
||||
print(f"{self.total_length=}")
|
||||
return self.total_length
|
||||
|
||||
|
||||
class BezierData:
|
||||
class HookBezierData:
|
||||
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):
|
||||
self.data = BezierData(len(blender_curve.data.splines))
|
||||
self.data = HookBezierData(len(blender_curve.data.splines))
|
||||
i = 0
|
||||
hooks = get_hook_modifiers(blender_curve)
|
||||
print(f"{blender_curve.name=} =============================================")
|
||||
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),
|
||||
blender_spline.use_cyclic_u,
|
||||
blender_spline.resolution_u,
|
||||
)
|
||||
for pi, blender_bezier_point in enumerate(blender_spline.bezier_points):
|
||||
self.data.splines[si].bezier_points[pi] = BezierSplinePoint(
|
||||
blender_bezier_point.co,
|
||||
self.data.splines[si].bezier_points[pi] = HookBezierSplinePoint(
|
||||
blender_bezier_point.handle_left,
|
||||
blender_bezier_point.co,
|
||||
blender_bezier_point.handle_right,
|
||||
)
|
||||
print(pi)
|
||||
for hook in hooks:
|
||||
hook_co = False
|
||||
hook_handle_left = False
|
||||
|
@ -293,40 +290,57 @@ class BezierCurve:
|
|||
blender_curve.matrix_world.inverted()
|
||||
@ 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.lerp(location, hook.strength)
|
||||
)
|
||||
# if hook_handle_left:
|
||||
# location = (
|
||||
# hook.object.matrix_world.translation
|
||||
# - blender_curve.matrix_world.translation
|
||||
# ) + 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.lerp(location, hook.strength)
|
||||
# )
|
||||
# if hook_handle_right:
|
||||
# location = (
|
||||
# hook.object.matrix_world.translation
|
||||
# - blender_curve.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)
|
||||
# )
|
||||
if hook_handle_left:
|
||||
location_left = location + (
|
||||
self.data.splines[si].bezier_points[pi].co
|
||||
- self.data.splines[si].bezier_points[pi].handle_left
|
||||
)
|
||||
self.data.splines[si].bezier_points[pi].handle_left = (
|
||||
self.data.splines[si]
|
||||
.bezier_points[pi]
|
||||
.co.lerp(location_left, hook.strength)
|
||||
)
|
||||
if hook_handle_right:
|
||||
location_right = location + (
|
||||
self.data.splines[si].bezier_points[pi].co
|
||||
- self.data.splines[si].bezier_points[pi].handle_right
|
||||
)
|
||||
self.data.splines[si].bezier_points[pi].handle_right = (
|
||||
self.data.splines[si]
|
||||
.bezier_points[pi]
|
||||
.co.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
|
||||
(
|
||||
self.data.splines[si].beziers,
|
||||
self.data.splines[si].lengths,
|
||||
self.data.splines[si].total_length,
|
||||
) = 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):
|
||||
|
@ -391,7 +405,7 @@ def calc_point_on_bezier_spline(
|
|||
if p.handle_left == p.co and len(bezier_spline_obj.bezier_points) > 1:
|
||||
beziers, lengths, total_length = (
|
||||
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 (
|
||||
bezier_spline_obj.beziers,
|
||||
bezier_spline_obj.lengths,
|
||||
|
@ -411,7 +425,7 @@ def calc_point_on_bezier_spline(
|
|||
|
||||
beziers, lengths, total_length = (
|
||||
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 (
|
||||
bezier_spline_obj.beziers,
|
||||
bezier_spline_obj.lengths,
|
||||
|
@ -460,16 +474,15 @@ def calc_point_on_bezier_curve(
|
|||
output_spline_index=False,
|
||||
resolution_factor=1.0,
|
||||
):
|
||||
# bezier_curve = BezierCurve(bezier_curve_obj)
|
||||
# curve = bezier_curve.data
|
||||
curve = bezier_curve_obj.data
|
||||
bezier_curve = HookBezierCurve(bezier_curve_obj)
|
||||
curve = bezier_curve.data
|
||||
# curve = bezier_curve_obj.data
|
||||
|
||||
# Loop through all splines in the curve
|
||||
total_length = 0
|
||||
for i, spline in enumerate(curve.splines):
|
||||
resolution = int(spline.resolution_u * resolution_factor)
|
||||
length = spline.calc_length(resolution=resolution)
|
||||
print(f"{utils.LINE()} {length=}")
|
||||
if total_length + length > distance or i == len(curve.splines) - 1:
|
||||
if output_spline_index and output_tangent:
|
||||
# return value from c_p_o_b_s is a tuple
|
||||
|
|
Loading…
Add table
Reference in a new issue