You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blender中Bianchi-Pinkall曲面生成脚本故障修复请求

修复后的Bianchi-Pinkall曲面生成脚本

我从网上找了这个生成Bianchi-Pinkall曲面的脚本,据说以前能正常运行,但现在在Blender里跑不起来。我不懂Python,试过用VSCode查看也解决不了问题,想把这个脚本修好来做3D模型当礼物。

修复后的完整代码

import bpy
import math
from mathutils import Vector
import numpy

subDivIterations = 5

valminu=0
valmaxu=math.pi*2
valminv=0
valmaxv=math.pi*2
resolutionu=150
resolutionv=150
pasu = (valmaxu - valminu) / resolutionu
pasv = (valmaxv - valminv) / resolutionv

a=0.93 # 珊瑚半径,可调整
n=3 # 花瓣/子旋转数量
b=0.36 # 花形半径,可调整
c=0
d=0
k=15
varu= valminu
varv= valminv

goldenRatio = (1 + math.sqrt(5)) / 2

def subdivide(triangles):
    result = []
    for color, A, B, C in triangles:
        if color == 0:
            # 细分红色三角形
            P = A + (B - A) / goldenRatio
            result += [(0, C, P, B), (1, P, C, A)]
        else:
            # 细分蓝色三角形
            Q = B + (A - B) / goldenRatio
            R = B + (C - B) / goldenRatio
            result += [(1, R, C, A), (1, Q, R, B), (0, R, Q, A)]
    return result

# 创建曲面三角形
def createSurfaceBianchiPinkall():
    triangles = []
    epsilon = 1e-8  # 避免除以零的小数值

    for varu in numpy.arange(valminu, valmaxu, pasu):
        for varv in numpy.arange(valminv, valmaxv, pasv):

            gamma = a+b*math.sin(2*n*varv)
            x = math.cos(varu+varv)*math.cos(gamma)
            y = math.sin(varu+varv)*math.cos(gamma)
            z = math.cos(varu-varv)*math.sin(gamma)
            w = math.sin(varu-varv)*math.sin(gamma)
            # 处理w接近1时的除以零问题
            denominator = math.sqrt(max(1-w*w, epsilon))
            r = math.acos(w)/(math.pi*denominator)
            A = Vector((x*r,y*r,z*r))

            varva = varv + pasv
            gamma = a+b*math.sin(2*n*varva)
            x = math.cos(varu+varva)*math.cos(gamma)
            y = math.sin(varu+varva)*math.cos(gamma)
            z = math.cos(varu-varva)*math.sin(gamma)
            w = math.sin(varu-varva)*math.sin(gamma)
            denominator = math.sqrt(max(1-w*w, epsilon))
            r = math.acos(w)/(math.pi*denominator)
            B = Vector((x*r,y*r,z*r))

            varua = varu + pasu
            gamma = a+b*math.sin(2*n*varva)
            x = math.cos(varua+varva)*math.cos(gamma)
            y = math.sin(varua+varva)*math.cos(gamma)
            z = math.cos(varua-varva)*math.sin(gamma)
            w = math.sin(varua-varva)*math.sin(gamma)
            denominator = math.sqrt(max(1-w*w, epsilon))
            r = math.acos(w)/(math.pi*denominator)
            C = Vector((x*r,y*r,z*r))
            triangles.append((0, A, B, C))

            gamma = a+b*math.sin(2*n*varv)
            x = math.cos(varua+varv)*math.cos(gamma)
            y = math.sin(varua+varv)*math.cos(gamma)
            z = math.cos(varua-varv)*math.sin(gamma)
            w = math.sin(varua-varv)*math.sin(gamma)
            denominator = math.sqrt(max(1-w*w, epsilon))
            r = math.acos(w)/(math.pi*denominator)
            D = Vector((x*r,y*r,z*r))
            triangles.append((0, A, C, D))
    return triangles

# 生成曲面网格数据
listTriangles = createSurfaceBianchiPinkall()
# 如需细分可取消注释下面两行
# for x in range(subDivIterations):
#     listTriangles = subdivide(listTriangles)

# 构建顶点和面数据(优化重复顶点问题)
listVertices = []
vertex_map = {}
listFaces = []

for triangle in listTriangles:
    verts = []
    for vec in triangle[1:]:
        # 把向量转成可哈希的元组,用于判断是否已存在
        vert_tuple = (round(vec.x, 6), round(vec.y, 6), round(vec.z, 6))
        if vert_tuple not in vertex_map:
            vertex_map[vert_tuple] = len(listVertices)
            listVertices.append(vert_tuple)
        verts.append(vertex_map[vert_tuple])
    listFaces.append(tuple(verts))

# 创建Blender网格和对象
mesh = bpy.data.meshes.new("SurfaceBianchiPinkallMesh")
ob = bpy.data.objects.new("SurfaceBianchiPinkall", mesh)
ob.location = Vector((0,0,0))
# 适配Blender 2.8+的集合链接方式
bpy.context.collection.objects.link(ob)

# 填充网格数据
mesh.from_pydata(listVertices, [], listFaces)
mesh.validate(clean_customdata=True)
mesh.update()

修复说明

  • 适配Blender新版本API:把旧版的bpy.context.scene.objects.link(ob)换成了Blender 2.8+支持的bpy.context.collection.objects.link(ob),解决对象无法链接到场景的问题。
  • 解决数值计算错误:添加了epsilon小值,避免计算sqrt(1-w²)时出现除以零的情况,防止脚本崩溃。
  • 优化顶点存储:用字典记录已存在的顶点,避免重复添加相同顶点,大幅减少模型的顶点数量,提升性能。
  • 保留细分功能:原脚本的细分迭代功能被注释,如需更高精度的曲面,可取消注释对应的两行代码(注意:高迭代次数会大幅增加计算量)。

内容的提问来源于stack exchange,提问作者Jack4789

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:10:54