Bender 中的细分修改器默认也使用 catmull 。 这个太高级,先研究低纬度的问题 ------ 二维线段插值。
和上一篇一样,使用了人工智能,基本思路:场景中设计控制点。python检测到变化后,重新生成曲线。
问:
bpy I have several points in collection PTS : point.001 point.002 ... now , connect each of them as curve
put geneted objs to collection RET
两两相连,而不是一整条
用的doubao。感觉这玩意有点敷衍了,每次都要修改。
场景setup以及效果:

算法有问题,需要调整。但是,
这场景。。太昏暗了!
怎么换背景啊。
参考资料:
可用的 python 脚本 (算法有问题):
python
from configparser import SectionProxy
import re
import bpy
import math
from mathutils import Euler
print("\n\nrun!!! ")
def worldSet(name, create=1) :
ret = bpy.data.collections.get(name)
print('worldSet', ret)
if not ret : # and create
ret = bpy.data.collections.new(name)
print('create', ret)
bpy.context.scene.collection.children.link(ret)
# bpy.data.scenes["Scene"].collection.children.link(ret)
return ret
ret_collection = worldSet("RET")
objects_to_remove = [obj for obj in ret_collection.objects]
for obj in objects_to_remove:
bpy.data.objects.remove(obj)
# 获取名为"PTS"的集合
pts_collection = bpy.data.collections.get("SDF")
if not pts_collection:
raise Exception("找不到名为'PTS'的集合")
# 收集集合中的所有点对象
point_objects = [obj for obj in pts_collection.objects if obj.name.find("point")>=0]
for obj in point_objects:
print("point_objects", obj.name)
# 按名称中的数字对点进行排序(point.001, point.002...)
def get_point_number(obj):
match = re.search(r'\d+$', obj.name)
return int(match.group()) if match else 0
point_objects.sort(key=get_point_number)
# # 创建新曲线
# curve_data = bpy.data.curves.new(name="Points_Polyline", type='CURVE')
# curve_data.dimensions = '3D'
#
# polyline = curve_data.splines.new('POLY')
# polyline.points.add(len(point_objects) - 1) # 已包含一个点,需要添加其余点
# # 设置每个点的坐标
# for i, obj in enumerate(point_objects):
# polyline.points[i].co = (obj.location.x, obj.location.y, obj.location.z, 1)
# curve_obj = bpy.data.objects.new("Points_Polyline", curve_data)
# ret_collection.objects.link(curve_obj)
points_count = len(point_objects)
# 插值精度(值越小曲线越平滑)
segments = 10 # 每段曲线的细分数量
def catmull_rom_point(p0, p1, p2, p3, t):
p0 = [p0.x, p0.z]
p1 = [p1.x, p1.z]
p2 = [p2.x, p2.z]
p3 = [p3.x, p3.z]
t2 = t * t
t3 = t2 * t
x = 0.5 * ((2 * p1[0]) + (-p0[0] + p2[0]) * t + \
(2 * p0[0] - 5 * p1[0] + 4 * p2[0] - p3[0]) * t2 + \
(-p0[0] + 3 * p1[0] - 3 * p2[0] + p3[0]) * t3)
y = 0.5 * ((2 * p1[1]) + (-p0[1] + p2[1]) * t + \
(2 * p0[1] - 5 * p1[1] + 4 * p2[1] - p3[1]) * t2 + \
(-p0[1] + 3 * p1[1] - 3 * p2[1] + p3[1]) * t3)
return [x, 0, y]
# 两两连接点(point.001与point.002连接,point.003与point.004连接,依此类推)
# 最后一个与第一个相连
for i in range(0, len(point_objects), 1):
# 检查是否有下一个点可以配对
if i >= len(point_objects):
print(f"点 {point_objects[i].name} 没有配对的点,已跳过", i+1, len(point_objects))
break
point1 = point_objects[i]
if i + 1 >= len(point_objects):
point2 = point_objects[0]
else:
point2 = point_objects[i + 1]
# 准备四个控制点(处理边界情况)
p0 = point_objects[i-2].location if i >= 2 else point1.location
p1 = point1.location
p2 = point2.location
p3 = point_objects[(i+3) % points_count].location if (i+3) % points_count < points_count else point2.location
# 创建新曲线
curve_data = bpy.data.curves.new(name=f"Curve_{point1.name}_{point2.name}", type='CURVE')
curve_data.dimensions = '3D'
# 创建曲线段
polyline = curve_data.splines.new('POLY')
polyline.points.add(segments) # 添加插值点
# 计算并设置插值点
for s in range(segments + 1):
t = s / segments # t从0到1
xyz = catmull_rom_point(p0, p1, p2, p3, t)
# polyline.points[s].co = (point.x, point.y, point.z, 1)
polyline.points[s].co = (xyz[0], xyz[1], xyz[2], 1) # +s*1
# xyz = catmull_rom_point(p0, p1, p2, p3, t0, t1, t2, t3, s, segments)
# polyline.points[s].co = (xyz[0], xyz[1], xyz[2], 1) # +s*1
# 创建曲线对象并链接到RET集合
curve_obj = bpy.data.objects.new(f"Curve_{point1.name}_{point2.name}", curve_data)
ret_collection.objects.link(curve_obj)
print(f"已成功将 {len(point_objects)} 个点连接成多段线", segments)
碎碎念:
blender 细分修改器默认用 catmull,模型复杂很慢,会卡顿。可以切换成简单模式。
怎么让细分默认就是简单模式呢?
无法设置,我呸,bl真难用。只好先弄个模板,然后复制粘修改器。快捷键是啥来着?
碎碎念 1:
怎么让python脚本自动运行呢?(修改场景后,自动执行python脚本)
我是用插件,注册了 depsgraph_update_post。场景变化后, exec 脚本。
碎碎念 2:
怎么让python脚本自动运行呢?(修改代码后,自动执行python脚本)
我还是用插件,理论上,检测最后的脚本修改时间,然后切换bl至前台时,如果脚本变化,立即自动执行即可。
但小破blender的api有限,竟然没有检测窗口前后台的api,只有一个app.background与此无关,好像是无头模式?
只好配合 AHK,当blender切换到前台时,在内存盘创建一个标志文件,然后python里面开启定时器,循环检测,检测到标志文件就删除并执行逻辑。