再战catmull插值算法 —— 在Bender中使用

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以及效果:

算法有问题,需要调整。但是,

这场景。。太昏暗了!

怎么换背景啊。

参考资料:

math - python 中的 Catmull-Rom 样条 - Stack Overflow --- math - Catmull-Rom splines in python - Stack Overflow

可用的 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里面开启定时器,循环检测,检测到标志文件就删除并执行逻辑。

相关推荐
Mintopia1 天前
🎯 光与面的命运交锋:Möller-Trumbore 线段三角形相交算法全解析
前端·javascript·计算机图形学
Mintopia2 天前
🧠 三分视界:Three.js 离屏渲染与多重视角的艺术
前端·javascript·计算机图形学
Mintopia2 天前
🔮 点在四面体内?计算几何中的灵魂拷问与精度之战
前端·javascript·计算机图形学
Mintopia3 天前
✨你在我的四面体心房吗?——判断点是否在四面体内的图形学魔法
前端·javascript·计算机图形学
Mintopia5 天前
🌌 一发入魂:计算机图形学中的光线与球的相遇之约
前端·javascript·计算机图形学
Mintopia6 天前
🌌 计算机图形学奇谈
前端·javascript·计算机图形学
Mintopia6 天前
坐标的奇妙旅行:从世界到屏幕的深度之恋
前端·javascript·计算机图形学
Mintopia9 天前
🌪️ 点云世界的炼金术:法线估计与泊松重建教程
前端·javascript·计算机图形学
Mintopia9 天前
🌌 探索虚空中的结构:光线步进与 Marching Cubes 的奇幻冒险
前端·javascript·计算机图形学