There is room for microoptimization, such as getting rid of all the getattrs in the inner loops, and simplifying the math in the loop. You can also use a memoryview to directly manipulate the index array. Give this a try (untested, there might be mistakes):
def internal_build(self):
tss = self.TSS
faces = modelInstance.faces
setVertData = self.vertex.setData3f
setClrData = self.color.setData4f
setUvData = self.UV.setData2f
invTss = Vec2(1.0 / tss[0], 1.0 / tss[1])
topLeft = Vec2(0, invTss[1])
topRight = Vec2(invTss[0], invTss[1])
bottomRight = Vec2(invTss[0], 0)
locScale = invTss * (1.0 / 32.0)
verts = self.triangles.modifyVertices()
verts.uncleanSetNumRows(len(faces) * 6)
vertView = memoryview(verts)
vertexId = 0
indexId = 0
for x1, y1, z1, x2, y2, z2, texture, color in faces:
# It's faster if you store these in the correct order to begin with!
if x1 != x2:
setVertData(x1, y1, z1)
setVertData(x2, y1, z1)
setVertData(x2, y2, z2)
setVertData(x1, y2, z2)
else:
setVertData(x1, y1, z1)
setVertData(x2, y2, z1)
setVertData(x2, y2, z2)
setVertData(x1, y1, z2)
# It's probably faster if you store your color as a VBase4 to begin with!
setClrData(color, color, color, 1.0)
setClrData(color, color, color, 1.0)
setClrData(color, color, color, 1.0)
setClrData(color, color, color, 1.0)
location = Vec2(*materialIndex[texture])
location.componentwiseMult(locScale)
setUvData(location + topLeft)
setUvData(location)
setUvData(location + bottomRight)
setUvData(location + topRight)
vertView[indexId] = vertexId
vertView[indexId + 1] = vertexId + 1
vertView[indexId + 2] = vertexId + 3
vertView[indexId + 3] = vertexId + 1
vertView[indexId + 4] = vertexId + 2
vertView[indexId + 5] = vertexId + 3
vertexId += 4
indexId += 6
self.faceCounter += len(faces)
There may be further microoptimizations to be found, but it’s probably diminishing returns after this point.