You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求助:用Blender Python脚本实现分层坐标点正确连接以生成空心3D模型

求助:用Blender Python脚本实现分层坐标点正确连接以生成空心3D模型

嘿,我完全懂你现在的困扰——手里有一堆分层的坐标点,想做出CGRP染色的空心3D模型,结果要么只能显示零散的点,要么被凸包算法乱连所有点,甚至运行脚本直接崩Blender,确实挺闹心的。让我先帮你分析下现有代码的问题,再给你一套能精准分层连接的解决方案。

先说说你现有代码的核心问题

  1. 第一个代码:只是用空物体把坐标点可视化了,根本没做任何连接,只能用来确认点的位置,没法生成模型;
  2. 第二个凸包代码convex_hull的本质是生成包裹所有点的最小凸面,它完全不会管你的分层逻辑,只会把所有点往“最外层”连,完全不符合你要的分层邻近点连接需求;
  3. 第三个连线代码:它把所有坐标点连成了一个单一环形,但你的点是分层的啊!跨层连线直接打乱了结构,再加上200页的海量坐标,这种粗暴的连线方式会让Blender的几何计算过载,不崩溃才怪。

解决方案:按层分组处理坐标,生成分层空心模型

你的需求核心是分层轮廓连接——每层是一个闭合的轮廓环,然后连接上下层的对应(或邻近)点生成侧面,最终形成空心的壳状/管状模型。前提是你要先把坐标按层整理好(比如把200页的坐标按切片层分成子列表),这是实现的关键!

完整实现代码

import bpy
import bmesh
from mathutils import Vector

# ----------------------
# 第一步:按层整理坐标(替换成你的实际分层数据)
# 示例:3层,每层4个点,每层是闭合的环形(点按顺时针/逆时针排序)
layers = [
    # 第一层(z=0)
    [(1, 1, 0), (-1, 1, 0), (-1, -1, 0), (1, -1, 0)],
    # 第二层(z=1)
    [(0.8, 0.8, 1), (-0.8, 0.8, 1), (-0.8, -0.8, 1), (0.8, -0.8, 1)],
    # 第三层(z=2)
    [(0.5, 0.5, 2), (-0.5, 0.5, 2), (-0.5, -0.5, 2), (0.5, -0.5, 2)]
]

# ----------------------
# 第二步:创建网格与Bmesh对象
mesh = bpy.data.meshes.new("CGRP_Hollow_Mesh")
obj = bpy.data.objects.new("CGRP_Hollow_Object", mesh)
bpy.context.collection.objects.link(obj)

bm = bmesh.new()

# ----------------------
# 第三步:添加所有顶点,并记录每层的顶点索引
layer_verts = []
for layer_coords in layers:
    verts = []
    for coord in layer_coords:
        vert = bm.verts.new(Vector(coord))
        verts.append(vert)
    layer_verts.append(verts)

bm.verts.ensure_lookup_table()

# ----------------------
# 第四步:生成每层的顶面/底面(可选,若需要空心闭合的话)
for verts in layer_verts:
    # 检查是否是闭合环,尝试生成面
    try:
        # 用BMesh的多边形工具生成闭合面
        bm.faces.new(verts)
    except ValueError:
        print(f"无法生成当前层的面:点可能未按闭合环排序,或点共线")

# ----------------------
# 第五步:生成上下层之间的侧面(核心:连接对应点)
for i in range(len(layer_verts) - 1):
    current_layer = layer_verts[i]
    next_layer = layer_verts[i+1]
    layer_len = len(current_layer)
    
    # 确保上下层点数量一致(如果不一致,需要改成找邻近点的逻辑)
    if len(next_layer) != layer_len:
        print(f"警告:第{i}层和第{i+1}层点数量不一致,跳过侧面生成")
        continue
    
    # 连接对应位置的点,生成侧面的四边形
    for j in range(layer_len):
        # 当前点和下一个点(闭合环)
        v1 = current_layer[j]
        v2 = current_layer[(j+1) % layer_len]
        v3 = next_layer[(j+1) % layer_len]
        v4 = next_layer[j]
        # 生成四边形面
        try:
            bm.faces.new([v1, v2, v3, v4])
        except ValueError:
            print(f"无法生成侧面四边形:点顺序错误或共面")

# ----------------------
# 第六步:将BMesh数据写入网格,清理资源
bm.to_mesh(mesh)
bm.free()
mesh.update()

print("分层空心模型生成完成!")

关键注意事项(必看!)

  • 坐标分层整理:你必须把200页的坐标按切片层分组,每层的点要按顺时针或逆时针的闭合顺序排列——这是生成正确面的前提,不然会出现面翻转、错误连接的问题;
  • 大量坐标优化:如果坐标数量极多,建议先拿1-2层小批量测试,没问题再导入全量数据;同时可以在生成前删除Blender场景中无关的物体,减少内存占用;
  • 点数量不一致的处理:如果某些层的点数量不同,你需要把代码中“连接对应点”的逻辑改成寻找邻近点(比如用KNN算法找每个点的最近点),但这会增加复杂度,优先保证每层点数量一致是最高效的;
  • 空心模型的调整:如果不需要每层的顶面/底面,只需要侧面,就把第四步的代码删掉,这样就是完全空心的管状结构。

为什么这个代码不会崩溃?

  • 我们用BMesh来处理几何,它比直接用from_pydata更高效,适合处理大量顶点;
  • 按层分批处理,避免一次性生成所有错误的边/面,减少Blender的计算压力;
  • 每一步都有错误捕获,不会因为个别层的问题导致整个脚本崩溃。

你可以先把少量坐标按层整理好测试代码,确认效果后再导入全量数据,应该就能得到你想要的CGRP染色3D空心模型了!

备注:内容来源于stack exchange,提问作者Iniya Anandan

火山引擎 最新活动