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

相关推荐
壕壕7 天前
Re: 0x03. 从零开始的光线追踪实现-多球体着色
macos·计算机图形学
web像素之境13 天前
实时光线追踪加速硬件结构(详细版)
游戏·gpu·计算机图形学
唯道行23 天前
计算机图形学·9 几何学
人工智能·线性代数·计算机视觉·矩阵·几何学·计算机图形学
唯道行1 个月前
计算机图形学·6 OpenGL编程3 谢尔宾斯基垫与三维编程
人工智能·算法·计算机视觉·计算机图形学·三维·谢尔宾斯基垫
charlie1145141911 个月前
2D 计算机图形学基础速建——2
笔记·学习·线性代数·教程·计算机图形学
charlie1145141911 个月前
2D 计算机图形学基础速建——1
笔记·学习·教程·计算机图形学·基础
ObjectX前端实验室2 个月前
【图形编辑器架构】节点树与渲染树的双向绑定原理
前端·计算机图形学·图形学
ObjectX前端实验室2 个月前
【图形编辑器架构】渲染层篇 — 从 React 到 Canvas 的声明式渲染实现
前端·计算机图形学·图形学
ObjectX前端实验室2 个月前
【图形编辑器架构】节点树篇 — 从零构建你的编辑器数据中枢
前端·计算机图形学·图形学
壕壕2 个月前
Re: 0x02. 从零开始的光线追踪实现-射线跟球的相交
macos·计算机图形学