无法在Blender中运行这个bianchi-Pinkall脚本

0 投票
1 回答
24 浏览
提问于 2025-04-13 17:17

这不是我的作品,但我正在尝试让它正常工作。这是我在网上找到的一个脚本,用来生成一个叫做“bianchi Pinkall”的表面,听说之前是可以运行的,但现在不行了。如果有人能帮我让它工作,那就太棒了,因为我想在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 #rayon de la corale à tester sous : analyticphysics.com/Higher Dimensions/Interactive Bianchi-Pinkall Flat Tori.htm
n=3 #Nbre de sous rotation ou de pétaile
b=0.36 #rayon internet de la fleur
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:
# Subdivide red triangle
P = A + (B - A) / goldenRatio
result += [(0, C, P, B), (1, P, C, A)]
else:
# Subdivide blue triangle
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

# Create des tirangles du coquillage
# Create wheel of red triangles around the origin
#x = f(u,v) = u + uv2 – (1/3)u3, y = g(u,v) = v + u2v – (1/3)v3, z = h(u,v) = u2 – v2.
def createSurfaceBianchiPinkall():
triangles = []

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)
r = math.acos(w)/math.pi/math.sqrt(1-w*w);
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)
r = math.acos(w)/math.pi/math.sqrt(1-w*w);
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)
r = math.acos(w)/math.pi/math.sqrt(1-w*w);
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)
r = math.acos(w)/math.pi/math.sqrt(1-w*w);
D = Vector((x*r,y*r,z*r))
triangles.append((0, A, C, D))
return triangles

# Generate map of tiling
listTriangles = createSurfaceBianchiPinkall()
#for x in range(subDivIterations):
# listTriangles = subdivide(listTriangles)

# Construction du coquilage
# Construct the lists necessary for generation of geometry
listVertices = []
listFaces = []
for triangle in listTriangles:
# write the vertex coords to the list, and remember the vertex indices
# In Blender, the mesh data stores each vertex as a tuple of 3 floats.
newVertex1 = (triangle[1][0],triangle[1][1],triangle[1][2])
newVertex2 = (triangle[2][0],triangle[2][1],triangle[2][2])
newVertex3 = (triangle[3][0],triangle[3][1],triangle[3][2])

listVertices.append(newVertex1)
newVertex1_i = len(listVertices) - 1
listVertices.append(newVertex2)
newVertex2_i = len(listVertices) - 1
listVertices.append(newVertex3)
newVertex3_i = len(listVertices) - 1
# write to the list of edges
# Define the faces by index numbers. Each faces is defined by 4 consecutive integers.
# For triangles you need to repeat the first vertex also in the fourth position.
newFace = (newVertex1_i,newVertex2_i,newVertex3_i)
listFaces.append(newFace)


mesh = bpy.data.meshes.new("SurfaceBianchiPinkallMesh") # create a new mesh

ob = bpy.data.objects.new("SurfaceBianchiPinkall", mesh) # create an object with that mesh
ob.location = Vector((0,0,0)) #by.context.scene.cursor_location # position object at 3d-cursor
bpy.context.scene.objects.link(ob) # Link object to scene

# Fill the mesh with verts, edges, faces
mesh.from_pydata(listVertices,[],listFaces) # edges or faces should be [], or you ask for problems
mesh.validate(True)
#mesh.update(calc_edges=True) # Update mesh with new data

我试着用VScode查看这个Python脚本,但我不懂Python,所以……这一切都是为了给一个特别的人准备的礼物。

1 个回答

0

可能有很多原因导致问题出现,首先你附上的代码没有按照正确的Python缩进格式来写。如果我们修正这个问题,就可以进行真正的修改,这些修改只是因为Blender 2.8及以上版本的重构。

Blender 2.8的集合变更日志中我们了解到:

图层和组被集合取代了。

这意味着你在第121行的代码bpy.context.scene.objects.link(ob)现在会报错AttributeError: bpy_prop_collection: attribute "link" not found,因为“link”这个属性已经被移到了bpy.context.scene.objects下面,具体可以参考文档。所以你需要把第121行替换成:

bpy.context.collection.objects.link(ob)

接下来的错误是TypeError: Mesh.validate(): required parameter "verbose" to be a keyword argument!,这个错误出现在第124行mesh.validate(True),问题很简单,为了避免和clean_customdata参数混淆,我们需要明确告诉程序我们提供的是“verbosity”,所以我们把第124行替换成:

mesh.validate(verbose=True)

我在Blender 3.4和4.0上验证了这个修改是有效的。

我在下面附上了完整的修改代码(包括我重新调整的缩进),以及成功输出的截图。 Bianchi Pinkall Surface in Blender 4.0

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 #rayon de la corale à tester sous : analyticphysics.com/Higher Dimensions/Interactive Bianchi-Pinkall Flat Tori.htm
n=3 #Nbre de sous rotation ou de pétaile
b=0.36 #rayon internet de la fleur
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:
            # Subdivide red triangle
            P = A + (B - A) / goldenRatio
            result += [(0, C, P, B), (1, P, C, A)]
        else:
            # Subdivide blue triangle
            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

# Create des tirangles du coquillage
# Create wheel of red triangles around the origin
#x = f(u,v) = u + uv2 – (1/3)u3, y = g(u,v) = v + u2v – (1/3)v3, z = h(u,v) = u2 – v2.
def createSurfaceBianchiPinkall():
    triangles = []

    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)
            r = math.acos(w)/math.pi/math.sqrt(1-w*w);
            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)
            r = math.acos(w)/math.pi/math.sqrt(1-w*w);
            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)
            r = math.acos(w)/math.pi/math.sqrt(1-w*w);
            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)
            r = math.acos(w)/math.pi/math.sqrt(1-w*w);
            D = Vector((x*r,y*r,z*r))
            triangles.append((0, A, C, D))
    return triangles

# Generate map of tiling
listTriangles = createSurfaceBianchiPinkall()
#for x in range(subDivIterations):
# listTriangles = subdivide(listTriangles)

# Construction du coquilage
# Construct the lists necessary for generation of geometry
listVertices = []
listFaces = []
for triangle in listTriangles:
    # write the vertex coords to the list, and remember the vertex indices
    # In Blender, the mesh data stores each vertex as a tuple of 3 floats.
    newVertex1 = (triangle[1][0],triangle[1][1],triangle[1][2])
    newVertex2 = (triangle[2][0],triangle[2][1],triangle[2][2])
    newVertex3 = (triangle[3][0],triangle[3][1],triangle[3][2])

    listVertices.append(newVertex1)
    newVertex1_i = len(listVertices) - 1
    listVertices.append(newVertex2)
    newVertex2_i = len(listVertices) - 1
    listVertices.append(newVertex3)
    newVertex3_i = len(listVertices) - 1
    # write to the list of edges
    # Define the faces by index numbers. Each faces is defined by 4 consecutive integers.
    # For triangles you need to repeat the first vertex also in the fourth position.
    newFace = (newVertex1_i,newVertex2_i,newVertex3_i)
    listFaces.append(newFace)


mesh = bpy.data.meshes.new("SurfaceBianchiPinkallMesh") # create a new mesh

ob = bpy.data.objects.new("SurfaceBianchiPinkall", mesh) # create an object with that mesh
ob.location = Vector((0,0,0)) #by.context.scene.cursor_location # position object at 3d-cursor
bpy.context.collection.objects.link(ob) # Link object to scene
# Fill the mesh with verts, edges, faces
mesh.from_pydata(listVertices,[],listFaces) # edges or faces should be [], or you ask for problems
mesh.validate(verbose=True)
#mesh.update(calc_edges=True) # Update mesh with new data

撰写回答