Speep up vertex color assignment

Hi all, this is what I am using right now to assign vertex colors to an arbitrary mesh. Currently, this method is quite slow (takes ~15 seconds on a 20k face mesh). Any idea how to speed this up?

	a = time.time()
	vColour = [(0, 0, 0) for j in ob.data.verts]
	# vColour = getVCol(blah)
	for fa,co in zip(ob.data.faces, ob.data.vertex_colors[0].data):
		f = fa.verts_raw
		co.color1 = vColour[f[0]]
		co.color2 = vColour[f[1]]
		co.color3 = vColour[f[2]]


	print (time.time()-start)

in python 2.x i would’ve use the map() function with a simple function holding what u have in the for-loop, but the speedup whould be minimal. and python 3.x 's map() function works differently so that doesnt work anymore.

though if i may ask: what kind of computer do you run, cuz on a plane of 59k verts your script runs in under a second on my laptop. (235k verts in 4.3 secs)

hope that helps.

dreampainter, the API call is what’s slowing it down, the pure Python part (loops, iterators or whatnot) does not take up any time at all.

But after you mentioned the performance you are getting, i started doing some further investigation and realized that the bottleneck comes from the large number of object I have in the scene (1000+), even though they do nothing, if I delete those object, the vcolor operation takes less than a second.

so… somehow, doing a bpy.data.object really slows blender down.

As i mentioned in the previous post, the problem is that I have a LOT of object in the scene, and somehow, the speed of using an iterator to access (bpy.data.objects…) is proportional to the number of object, which is why the script is slow.

For anyone who is interested, here my new way of mapping vertex colors, it is MUCH faster (15 seconds down to 0.1 seconds), and is not dependent on the object count in the scene.


    start = time.time()
    vColor = []
    for f in ob.data.faces:
        vColor.extend(getVCol(f.verts_raw[0]))
    ob.data.vertex_colors[0].data.foreach_set('color1', vColor)

    vColor = []
    for f in ob.data.faces:
        vColor.extend(getVCol(f.verts_raw[1]))
    ob.data.vertex_colors[0].data.foreach_set('color2', vColor)

    vColor = []
    for f in ob.data.faces:
        vColor.extend(getVCol(f.verts_raw[2]))
    ob.data.vertex_colors[0].data.foreach_set('color3', vColor)

    # skip these 4 lines if you are only dealing with triangles
    vColor = []
    for f in ob.data.faces:
        vColor.extend(getVCol(f.verts_raw[3]))
    ob.data.vertex_colors[0].data.foreach_set('color4', vColor)


    print (time.time()-start)

i forgot about the foreach_set, thanks for the reminder :stuck_out_tongue:

but this can even be sped up more.
at the beginning of your script add:


bpy.context.user_preferences.edit.global_undo = False

and at the end:


bpy.context.user_preferences.edit.global_undo = True

according to matt ebb, this results in a 3-5x speed increase. it is especially efficient with a lot of bpy calls, which will happen alot with 1000+ objects.

also reading from an array is alot faster than running a function every time


vColor = [getVcol(i) for i in range(len(ob.data.verts))]
vColor1 = []
    for f in ob.data.faces:
        vColor1.extend(vColor[f.verts_raw[0]])
ob.data.vertex_colors[0].data.foreach_set('color1', vColor1)

though again, that is a pure python thing, and you said that that is not the issue

hope that helps