Custom classes for mesh objects

I’ve been working a bit with UVs the past couple of days and I’ve been experiencing some pain in dealing with how vertices are linked to their UV coordinates in the API. So I started making my own UVVertex class, and it raised a question or two to me.

  1. Is there a performance reason why some classes in Blender don’t seem to link certain kinds of data? For example, to my knowledge there is no direct relationship between a vertex object and its UV coordinates/UV loop object(s).

  2. Should I avoid doing this kind of thing very heavily? If you define a class too far, it would hurt a dynamic addon(like a shrinkwrap modifier or viewport shader)'s performance just by its inclusion, wouldn’t it?

  3. Is it not really in line with standard Blender coding practice? I would like to share the things I make at some point so I’d prefer to be consistent with the standard as much as possible.

As an example, here’s the UVVertex class I’m making for my own convenience, with variables declared earlier in the code since I’m in the middle of writing it.


scn = bpy.context.scene
obj = scn.objects.active
mesh = obj.data
verts = mesh.vertices
edges = mesh.edges
loops = mesh.loops
#the mesh's collection of UV loops
uvd = mesh.uv_layers.active.data

#uvvindex = stands for "uv-vertex index". a dictionary containing keys=UV loops, values = mesh vertex indices
#links UV loops to their mesh vertex indices

#vuvvd = stands for "vertex-uvvertex dictionary". keys=mesh vertices, values =uv loops
#links mesh vertices to a list of its UV loops/vertices



#a class containing a lot of variables and information about UV "loops" which I find would be useful if I could easily access them
#loopi = the index of a loop object, i'll probably change this to vertex index if possible
class UVVertex(object):
    def __init__(self,loopi):
        self.uvloop = uvd[loopi]
        self.loop = loops[loopi]
        self.index_uv = self.loop.index
        self.index_mesh = self.loop.vertex_index
        self.mesh_vert = verts[self.index_mesh]
        self.uvcopies = vuvvd[self.mesh_vert]           #a list of UV vertices which also represent the mesh vertex
        self.co = self.uvloop.uv
        self.meshco = self.mesh_vert.co
        self.edges = []
        self.notedges = []
        self.linkedverts = []
        for v in self.uvcopies:           #build a list of mesh edges which are connected to this UVVertex; bugged at the moment
            if v.uv == self.co:
                self.edges.append(loops[uvvindex[v]].edge_index)
            else:
                self.notedges.append(loops[uvvindex[v]].edge_index)
        for e in self.edges:           
            
            for v in edges[e].vertices:
                if verts[v] != self.mesh_vert:
                    self.linkedverts.append(v)



It still needs work, and if I finished the class definition I’d get rid of the dictionary references; sorry if they’re confusing. I wanted to ask about this before I get too far into making my own classes.

Performance, memory usage and also the management of strong integrity are probably the reasons.

If you need to look up a lot of UVs by vertex, create a lookup dictionary:

import bpy
from collections import defaultdict

uvs_by_vertex = defaultdict(list)

me = bpy.context.object.data
uv_layer = me.uv_layers.active.data
for l in me.loops:
    uvs_by_vertex[l.vertex_index].append(uv_layer[l.index].uv)


for k, v in uvs_by_vertex.items():
    print("
Vertex {}".format(k))
    for uv in v:
        print("  {}".format(uv))