import bpy from mathutils import Vector from . import nodeutils, utils, vars from .properties import CC3CharacterCache, CC3MaterialCache def normal_to_height(normal_image: bpy.types.Image, height_image: bpy.types.Image, iterations = 10): pixels = pixels = list(normal_image.pixels) w = int(normal_image.size[0]) h = int(normal_image.size[1]) l = w*h N: Vector D: Vector T: Vector # convert to normal vectors normals = [None]*l for i in range(0, l): p = i*4 x = 2*pixels[p]-1 y = 2*pixels[p+1]-1 z = 2*pixels[p+2]-1 N = Vector((x,y,z)) #N.normalize() normals[i] = N directional_displacements = [] print("Building directional displacements") for j in range(-1, 2): for k in range(-1, 2): D = Vector((j, -k, 0)) if k == 0 and j == 0: directional_displacements.append(None) else: displacement_map = [0]*l for i in range(0, l): N = normals[i] a = N.dot(D) T = D - N*a T.normalize() d = T.z * 0.5 * D.length displacement_map[i] = d directional_displacements.append(displacement_map) heights = [0]*l for itx in range(0, iterations): print(f"iteration: {itx}") for v in range(0, h): for u in range(0, w): i = u+v*w height = 0 for j in range(-1, 2, 1): uu = min(max(u+j, 0), w-1) for k in range(-1, 2, 1): if j == 0 and k == 0: continue vv = min(max(v+k, 0), h-1) ii = uu + vv*w jk = j + 3*k + 4 d = directional_displacements[jk][ii] + directional_displacements[jk][i] height += heights[ii] - d height /= 8 heights[i] = height min_height = 999999 max_height = -999999 abs_height = 0 for i in range(0, l): min_height = min(min_height, heights[i]) max_height = max(max_height, heights[i]) abs_height = max(abs_height, abs(heights[i])) print(f"min: {min_height} max: {max_height} abs: {abs_height}") pixels = list(height_image.pixels) for i in range(0, l): p = i * 4 h = min(5*0.5*heights[i]/abs_height + 0.5,1) pixels[p] = h pixels[p+1] = h pixels[p+2] = h height_image.pixels[:] = pixels def build_displacement_system(chr_cache: CC3CharacterCache, mat_cache: CC3MaterialCache): mat: bpy.types.Material = mat_cache.material nodes = mat.node_tree.nodes links = mat.node_tree.links normal_node = nodeutils.find_node_by_type_and_keywords(nodes, "TEX_IMAGE", "(NORMAL)") normal1_node = nodeutils.find_node_by_type_and_keywords(nodes, "TEX_IMAGE", "(WRINKLENORMAL1)") normal2_node = nodeutils.find_node_by_type_and_keywords(nodes, "TEX_IMAGE", "(WRINKLENORMAL2)") normal3_node = nodeutils.find_node_by_type_and_keywords(nodes, "TEX_IMAGE", "(WRINKLENORMAL3)") blend_normal_node = nodeutils.find_node_by_type_and_keywords(nodes, "TEX_IMAGE", "(NORMALBLEND)") image = bpy.data.images["3K1L562.png"] if "TEST_HEIGHT" in bpy.data.images: height_image = bpy.data.images["TEST_HEIGHT"] height_image.scale(image.size[0], image.size[1]) else: height_image = bpy.data.images.new("TEST_HEIGHT", image.size[0], image.size[1], is_data=True) height_image.pixels[0] = 0 normal_to_height(image, height_image, 5) return