无法在Blender中运行这个bianchi-Pinkall脚本
这不是我的作品,但我正在尝试让它正常工作。这是我在网上找到的一个脚本,用来生成一个叫做“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 个回答
可能有很多原因导致问题出现,首先你附上的代码没有按照正确的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上验证了这个修改是有效的。
我在下面附上了完整的修改代码(包括我重新调整的缩进),以及成功输出的截图。
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