4
$\begingroup$

How do i set the vertex color to vertex normal for all vertices of an selected object?

My approach here somehow prints only a few vertices and spares out the rest :( How can i fix that and include ALL other planes, too? (see images below)

import bpy

current_obj = bpy.context.active_object 
mesh = current_obj.data

if mesh.vertex_colors:
    vcol_layer = mesh.vertex_colors.active
else:
    vcol_layer = mesh.vertex_colors.new()

print("*"*40)

for poly in mesh.polygons:
        for loop_index in poly.loop_indices:
            loop_vert_index = mesh.loops[loop_index].vertex_index

            #color = [1 , 0, 0]

            #vcol_layer.data[loop_index].color = color

            #vcol_layer.data[loop_index].color = mesh.vertices[loop_vert_index].normal
            color = mesh.vertices[loop_vert_index].normal
            vcol_layer.data[loop_vert_index].color = color

            print("painting vert",loop_index, "to color ", color[0], color[1], color[2])


mesh.vertex_colors.active = vcol_layer


mesh.update()

Outcome for a sphere (paints only 1/4 of vertices??):

Sphere

Outcome for a foliage-mesh (all planes are joined into one mesh) Still paints not all vertices???? enter image description here

Please help me out, how to include all vertices :)

$\endgroup$
2
  • $\begingroup$ So are you trying to make a normal map? $\endgroup$
    – Soapy
    Commented Jun 17, 2015 at 7:58
  • $\begingroup$ yes, but stored in the vertex colors $\endgroup$
    – StreakyCat
    Commented Jun 17, 2015 at 8:00

1 Answer 1

2
$\begingroup$

You must set vcol with loop index, not vertex index, because those are loop data (i.e. one color per face corner):

import bpy

current_obj = bpy.context.active_object 
mesh = current_obj.data

if mesh.vertex_colors:
    vcol_layer = mesh.vertex_colors.active
else:
    vcol_layer = mesh.vertex_colors.new()

print("*"*40)

for poly in mesh.polygons:
        for loop_index in poly.loop_indices:
            loop_vert_index = mesh.loops[loop_index].vertex_index

            #color = [1 , 0, 0]

            #vcol_layer.data[loop_index].color = color

            #vcol_layer.data[loop_index].color = mesh.vertices[loop_vert_index].normal
            color = mesh.vertices[loop_vert_index].normal
            vcol_layer.data[loop_vert_index].color = color

            print("painting vert",loop_index, "to color ", color[0], color[1], color[2])


mesh.vertex_colors.active = vcol_layer


mesh.update()

However, since you are merely using vertex normal, it’s much simpler (and efficient) to loop directly on loops - and vcol are clamped to positive numbers, so you'll likely want to encode negative values with something like col = nor * 0.5 + 0.5:

import bpy
from mathutils import Vector

current_obj = bpy.context.active_object 
mesh = current_obj.data

if mesh.vertex_colors:
    vcol_layer = mesh.vertex_colors.active
else:
    vcol_layer = mesh.vertex_colors.new()

print("*"*40)

for loop_index, loop in enumerate(mesh.loops):
        loop_vert_index = loop.vertex_index

        #color = [1 , 0, 0]

        #vcol_layer.data[loop_index].color = color

        #vcol_layer.data[loop_index].color = mesh.vertices[loop_vert_index].normal
        color = (mesh.vertices[loop_vert_index].normal * 0.5) + Vector((0.5,) * 3)
        vcol_layer.data[loop_index].color = color

        print("painting vert",loop_index, "to color ", color[0], color[1], color[2])


mesh.vertex_colors.active = vcol_layer


mesh.update()
$\endgroup$
0

You must log in to answer this question.

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