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
$\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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.