3
$\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$
  • $\begingroup$ So are you trying to make a normal map? $\endgroup$ – Soapy Jun 17 '15 at 7:58
  • $\begingroup$ yes, but stored in the vertex colors $\endgroup$ – StreakyCat Jun 17 '15 at 8:00
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()
|improve this answer|||||
$\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.