0
$\begingroup$

I tried to write my own code that changes vertex colors based on the vertex Z-location(global). Which I derived from these links:

How can I get vertex positions from a mesh?

https://blenderartists.org/t/setting-vertex-color-via-python/481060/5

https://blenderartists.org/t/meshvertex-co-vertex-position-issue/670866

The base code looks like this:

from bpy import *
from random import *

bpy.context.scene.update()

#obj = context.active_object.
obj = data.objects["Cube"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]

When I ran a longer version of my code to change the vertex coloring of 5 'cubes' of different heights, I found that any "between" heights have the same color, when there should be a linear correlation to the height and green/red values.

snippet

Why is this? My formulae are both linear plots:

vertZloc = ((obj.matrix_world  * v.co)[2])
redMod = (28.3333333 * (vertZloc) - 28.3333333)
grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)

Stretch Help:

Also as a side note, I do want the all the top-vertex colors to change, not just the two vertices of the top plane, but I have not tried to solve that yet, I have just been focusing on the coloring function.

EDIT:

My full code, in case it is wanted, although it shouldn't explain anything else:

from bpy import *
from random import *

bpy.context.scene.update()

#obj = context.active_object.
obj = data.objects["Cube"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]

################### CUBE 1

#obj = context.active_object.
obj = data.objects["Cube.001"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]

################### CUBE 2

#obj = context.active_object.
obj = data.objects["Cube.002"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]

################### CUBE 3

#obj = context.active_object.
obj = data.objects["Cube.003"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]

################### CUBE 4

#obj = context.active_object.
obj = data.objects["Cube.004"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data

for v in verts:
    vertZloc = ((obj.matrix_world  * v.co)[2])
    #print(vertZloc) # for sanity check
    redMod = (28.3333333 * (vertZloc) - 28.3333333)
    grnMod = (-(28.3333333 * (vertZloc)) + 283.3333333)
    vColour = [(redMod,grnMod,0) for i in mesh.vertices]
    # asign colours to verts
    for i in range(len(faces)):
        v = vertexColour[i]
        f = faces[i].vertices
        #print('\n'.join(map(str, faces[i].vertices))) # sanity check
        v.color = vColour[f[0]]
        v.color = vColour[f[1]]
        v.color = vColour[f[2]]
        v.color = vColour[f[3]]
$\endgroup$

1 Answer 1

1
$\begingroup$

By adding 2 subdivisions to each cube, I was able to get full spectrum coloring with the code below:

success

import bpy
from collections import defaultdict

obj = bpy.data.objects["Cube"]
mesh = obj.data
verts = mesh.vertices
faces = mesh.polygons
vertexColour = mesh.vertex_colors[0].data
mHeight = 10
redMod = 0
bluMod = 0
grnMod = 0
step = (255 / mHeight)
index = 0


vcol_layer = mesh.vertex_colors.active

# create map of vertices to loop indices
vertex_map = defaultdict(list)
for poly in faces:
    for v_ix, l_ix in zip(poly.vertices, poly.loop_indices):
        vertex_map[v_ix].append(l_ix)

# reverses the dictionary access
def get_key(val, my_dict): 
    for key, value in my_dict.items():
        for subvalue in value:
             if val == subvalue:
                 return key

for poly in faces:
    for loop_index in poly.loop_indices:
        v = verts[get_key(loop_index, vertex_map)]
        vertZloc = ((obj.matrix_world  * v.co)[2])
        p = (vertZloc / mHeight)
        if p > .75:
            redMod = 1.0
            grnMod = (1 - ((p-.75)*4))
            bluMod = 0
        elif .75 >= p >= .50:
            redMod = ((p-.5)*4)
            grnMod = 1.0
            bluMod = 0
        elif .5 > p > .25:
            redMod = 0
            grnMod = 1.0
            bluMod = (1 - ((p - .25) * 4))
        else:
            redMod = 0
            grnMod = ((p)*4)
            bluMod = 1.0
        color = ( redMod, grnMod, bluMod)
            #loop_vert_index = mesh.loops[loop_index].vertex_index
        vcol_layer.data[loop_index].color = color
    index = index+1
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .