Ah-Ha! That works! In trying this command, I also discovered the problem validate() was removing from my mesh too!
The sample code I was using tells you to write a triangle like this:
faces=[ (0,1,4,0), (1,2,4,1), (2,3,4,2), (3,0,4,3)]
…note that the first and last index are repeated to indicate that the poly is a triangle. Was this sample code written before BMesh? I ask because if I remove the repeated index, and only enter three vertex indices, my problems disappear.
Is my code only working by accident, or does this sample code needs to be updated?
Anyways, check it out. My code generates Penrose tiling! After running the algorithm, you need to remove double vertices and recalculate the face normals to get them all pointing the same way.
import bpy
import math
from mathutils import Vector
subDivIterations = 5
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 wheel of red triangles around the origin
def createWheel():
triangles = []
for i in range(10):
theta_i = i*2.0*math.pi/10.0
theta_ip1 = (i+1)*2.0*math.pi/10.0
x_i = math.cos(theta_i)
x_ip1 = math.cos(theta_ip1)
y_i = math.sin(theta_i)
y_ip1 = math.sin(theta_ip1)
A = Vector((0.0,0.0,0.0))
B = Vector((x_i,y_i,0.0))
C = Vector((x_ip1,y_ip1,0.0))
if i % 2 == 0:
B, C = C, B # Make sure to mirror every second triangle
triangles.append((0, A, B, C))
return triangles
# Generate map of tiling
listTriangles = createWheel()
for x in range(subDivIterations):
listTriangles = subdivide(listTriangles)
# 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)
# Build the mesh in Blender's API
mesh = bpy.data.meshes.new("penroseMesh") # create a new mesh
ob = bpy.data.objects.new("Pyramid", 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