Created
March 20, 2022 10:19
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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