Page 1 of 1

Mesh building with Tessfaces and tessface_uv_textures

Posted: Mon May 20, 2013 8:37 pm
by ssontech
I'm trying to build a mesh with UV texture coordinates from python, continuation of I'm trying to get the tessfaces to work.

I don't get any error messages now --- or mesh for that matter. What's the right incantation to make this work? I've wasted enough time trying to reverse engineer this.

coords = [
[ -18.75, -14.02027027, 0 ],
[ -15.625, -14.02027027, 0 ],
[ -12.5, -14.02027027, 0 ],
[ -9.375, -14.02027027, 0 ],
[ -6.25, -14.02027027, 0 ],
[ -3.125, -14.02027027, 0 ],
faces = [
[ 0, 1, 13 ],
[ 1, 14, 13 ],
[ 1, 2, 14 ],
[ 2, 15, 14 ],
[ 2, 3, 15 ],
texFaces = [
[[0, 0], [0.08333333333, 0], [0, 0.08333333333]],
[[0.08333333333, 0], [0.08333333333, 0.08333333333], [0, 0.08333333333]],
[[0.08333333333, 0], [0.1666666667, 0], [0.08333333333, 0.08333333333]],
[[0.1666666667, 0], [0.1666666667, 0.08333333333], [0.08333333333, 0.08333333333]],
mshobj ='obj01')
mshobj.loops.add(sum((len(f) for f in faces)))
vertices_flat = [f for v in coords for f in v]
mshobj.vertices.foreach_set("co", vertices_flat)
del vertices_flat
uvtex = = "officialUV"
for n,tf in enumerate(texFaces):
datum =[n]
datum.uv1 = tf[0]
datum.uv2 = tf[1]
datum.uv3 = tf[2]
ob =, mshobj)

I need to know what flourish is required to make this work, not a completely different method please. It's based on from_pydata code, roughly.

There's some code that I'm not including, doesn't seem to make much difference...I'm not sure how it might be supposed to factor in here.

loop_index = 0
for i, p in enumerate(mshobj.polygons):
f = faces
loop_len = len(f)
p.loop_start = loop_index
p.loop_total = loop_len
p.vertices = f
loop_index += loop_len

I very much wish that developers would stop making changes in the python API that are not backwards compatible. The time spent providing compatibility will save many times that for users. If there is a break in compatibility, then how to work around it has to be explained super-thoroughly... ie it should be quicker to provide backwards compatibility than to have to explain why it is not. Having blender updates that break existing scripts and force them to be redeveloped doesn't help move blender forward.

Posted: Mon May 20, 2013 10:42 pm
by CoDEmanX
the api change was absolutely necessary due the complete overhauling of the mesh modelling system. Since 2.63, Blender can handle Ngons, this made it impossible to stay compatible in mesh data and API.

Using loops along with tessfaces seems just wrong (should be either tessfaces + tessface_uv_textures or polygons + loops + uv_layers), read the docs: ... tion-faces

Posted: Tue May 21, 2013 12:37 am
by ssontech
Adding new stuff was necessary, but breaking the old stuff is less obvious. What I'm doing is quite the common case. I've seen those docs, they aren't particularly helpful. They just say... use this not that, but not what the details of using this are, and there's substantial hidden undisclosed fine print. I've looked at the OBJ importer a bit too, the import and creation are tangled together.

The three arrays are quite simple, surely creating a mesh with them can't be more than 10-20 lines, right? Surely this should be trivial! I believe that a relatively straightforward fix of the code I show should work. Or the new API. Either way it is a simple task.

A new API shouldn't replace an old API until it can easily do what the old API does easily. Interoperability support for blender users depends on the API being stable or at least well documented.

Posted: Tue May 21, 2013 12:52 am
by CoDEmanX
see or maybe use bmesh module instead, it's easier to use as you don't need to worry about loops.

Posted: Tue May 21, 2013 1:09 am
by ssontech
"maybe use bmesh module instead" --- LOL! I would do that, if there was something that told me how. I don't have a couple days to waste figuring something out that worked fine before.

I need a piece of code that does what I said above. It was, and should be, simple. Other people are looking for it to, from what I've seen. If blender wants to be taken seriously, you can't just scorch existing work like this. "We broke it and you should be able figure out how to fix it" --- that just doesn't cut it.

Posted: Tue May 21, 2013 10:26 am
by CoDEmanX ... bmesh.html - especially CustomData access

and look at the bmesh.types

Posted: Tue May 21, 2013 12:50 pm
by CoDEmanX
This generates a .py script that contains the mesh data and the code to create an object from that data:

Code: Select all

import bpy

ob = bpy.context.object
if ob is None or ob.type != 'MESH':
    raise TypeError("Mesh object required")

me =

if not me.tessfaces and me.polygons:

# Adjust this path!
file = open("D:\\", "w")

file.write("import bpy\n")
file.write("from bpy_extras.io_utils import unpack_list, unpack_face_list\n")
file.write("coords = (\n")

for v in me.vertices:
    file.write("\t(%f, %f, %f),\n" %[:])

file.write("faces = (\n")

for f in me.tessfaces:
    fv = f.vertices
    if len(fv) == 3:
        tris = (fv[0], fv[1], fv[2]),
        tris = (fv[0], fv[1], fv[2]), (fv[2], fv[3], fv[0])
    for tri in tris:
        file.write("\t%s,\n" % str(tri))


file.write("texFaces = (\n")

uv_tex =
for f in me.tessfaces:
    if len(f.vertices) == 3:
        tris = (0, 1, 2),
        tris = (0, 1, 2),(2, 3, 0)
    uv_face = uv_tex[f.index]
    for tri in tris:
        file.write(", ".join("(%f, %f)" % (uv_face.uv[i][:]) for i in tri))


script = """
me ='obj01')
vertices_flat = [vv for v in coords for vv in v] 
me.vertices.foreach_set("co", vertices_flat) 

#mshobj.loops.add(sum((len(f) for f in faces))) 

me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces))

uv_tex ="officialUV")

for i, face in enumerate(faces):
    tface =[i]
    tface.uv1 = texFaces[i][0]
    tface.uv2 = texFaces[i][1]
    tface.uv3 = texFaces[i][2]


ob =, me)


Posted: Wed May 22, 2013 5:15 pm
by ssontech
mshobj ='myObject')
vertices_flat = [f for v in coords for f in v]
mshobj.vertices.foreach_set("co", vertices_flat)
del vertices_flat
nbr_faces = len(faces)
mshobj.loops.add(nbr_faces * 3)
eekadoodle_faces = []
for face in faces:
v1, v2, v3 = face
eekadoodle_faces.extend((v3, v1, v2) if v3 == 0 else (v1, v2, v3))
mshobj.polygons.foreach_set("loop_start", range(0, nbr_faces * 3, 3))
mshobj.polygons.foreach_set("loop_total", (3,) * nbr_faces)
mshobj.loops.foreach_set("vertex_index", eekadoodle_faces)
uvtex =
uvl =[:]
for fidx, pl in enumerate(mshobj.polygons):
face = faces[fidx]
v1, v2, v3 = face
# eekadoodle
if v3 == 0:
uvl[pl.loop_start].uv = texFaces[fidx][2]
uvl[pl.loop_start + 1].uv = texFaces[fidx][0]
uvl[pl.loop_start + 2].uv = texFaces[fidx][1]
uvl[pl.loop_start].uv = texFaces[fidx][0]
uvl[pl.loop_start + 1].uv = texFaces[fidx][1]
uvl[pl.loop_start + 2].uv = texFaces[fidx][2]
# always a tri

(sorry about the spacing, code option dnw)

Posted: Wed May 22, 2013 5:24 pm
by stiv
(sorry about the spacing, code option dnw)
You are welcome to try again. Your friendly moderators will be happy to delete the broken post. Call us lazy, but that is just too much work to figure out.

Posted: Wed May 22, 2013 9:05 pm
by CoDEmanX

Code: Select all

-tags dang it and say what you mean...