Skip to content

Instantly share code, notes, and snippets.

@McNull
Created March 20, 2022 10:19
Show Gist options
  • Save McNull/215152743ad532f88830dd977209e36f to your computer and use it in GitHub Desktop.
Save McNull/215152743ad532f88830dd977209e36f to your computer and use it in GitHub Desktop.
Blender: assign a unique vertex color for each material to the mesh (id map)
import bpy
import random
import colorsys
import math
RANDOM_COLORMAP = False
VERTEX_COLOR_LAYERNAME = "_IDMAP_"
NO_MATERIAL_COLOR = (0,0,0,1)
def material_to_random_color(mat):
seed = hash(mat.name)
random.seed(seed)
r, g, b = [random.random() for i in range(3)]
color = (r, g, b, 1.0)
return color
def get_material_random_colormap():
map = {}
for mat in bpy.data.materials:
color = material_to_random_color(mat)
map[mat.name] = color
return map
def sin01(r):
return (math.sin(r) + 1.0) * 0.5
def get_material_colormap():
if RANDOM_COLORMAP:
return get_material_random_colormap()
else:
map = {}
material_count = len(bpy.data.materials)
reciprocal = 1.0 / material_count
i = 0
for mat in bpy.data.materials:
h = i * reciprocal
s = 0.4 + sin01(math.pi * 2 * h * 191) * 0.6
v = 0.4 + sin01(math.pi * 2 * h * 7 * 191) * 0.6
color = colorsys.hsv_to_rgb(h, s, v)
color = (*color, 1.0)
print(i, mat.name, h,s,v)
map[mat.name] = color
i += 1
return map
def get_vertex_colors(obj):
vertex_colors = obj.data.vertex_colors.get(VERTEX_COLOR_LAYERNAME)
if vertex_colors == None:
vertex_colors = obj.data.vertex_colors.new(name = VERTEX_COLOR_LAYERNAME)
return vertex_colors
def main():
# make random color for each material
colormap = get_material_colormap()
# for each selected object
for obj in bpy.context.selected_objects:
if obj.type != 'MESH':
continue
if len(obj.material_slots) == 0:
print(obj.name + ": No materials assigned")
# ensure vertex color layer
vertex_colors = get_vertex_colors(obj)
# https://blender.stackexchange.com/questions/51782/get-material-and-color-of-material-on-a-face-of-an-object-in-python
# https://blender.stackexchange.com/questions/909/how-can-i-set-and-get-the-vertex-color-property
# for each object.data.polygon
i = 0
for polygon in obj.data.polygons:
# get object.material_slots[polygon.material_index]
vertex_color = NO_MATERIAL_COLOR
if len(obj.material_slots) > 0:
slot_index = polygon.material_index
mat = obj.material_slots[slot_index]
# get color by slot.material.name
vertex_color = colormap[mat.name]
# assign color to polygon
for loop_index in polygon.loop_indices:
vertex_colors.data[i].color = vertex_color
i += 1
pass
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment