extends Reference class_name DNA #var min_point: Vector3 = Vector3() #var max_point: Vector3 = Vector3() #var min_normal: Vector3 = Vector3() #var max_normal: Vector3 = Vector3() var maps : = {} #var vert_indices : = {} var orig_body_mesh: ArrayMesh var meshes : = {} var clothes : = {} func get_modifier_list() -> Array: var mod_list = [] for e in maps.keys(): if e.find(":") < 0: mod_list.push_back(e) return mod_list func add_mesh(part_name: String, mesh: ArrayMesh, surface: int = 0, v_indices: Dictionary = {}): var arrays: Array = mesh.surface_get_arrays(surface) var mat: Material = mesh.surface_get_material(surface) meshes[part_name] = { "orig_mesh": mesh, "orig_arrays": arrays, "material": mat, "same_indices": v_indices } func triangulate_uv(v0: Vector3, vs: PoolVector3Array, uvs: PoolVector2Array) -> Vector2: assert(vs.size() == 3) var d1: float = v0.distance_to(vs[0]) var d2: float = v0.distance_to(vs[1]) var d3: float = v0.distance_to(vs[2]) var ln = max(d1, max(d2, d3)) var v = Vector3(d1/ln, d2/ln, d3/ln) var midp : Vector2 = (uvs[0] + uvs[1] + uvs[2]) * 1.0 / 3.0 var uv: Vector2 = midp.linear_interpolate(uvs[0], v.x) + midp.linear_interpolate(uvs[1], v.y) + midp.linear_interpolate(uvs[2], v.z) uv /= 3.0 return uv func _prepare_cloth(arrays_body: Array, arrays_cloth: Array) -> Array: if arrays_cloth[ArrayMesh.ARRAY_TEX_UV2] != null: return arrays_cloth else: var d: PoolVector2Array = PoolVector2Array() d.resize(arrays_cloth[ArrayMesh.ARRAY_VERTEX].size()) assert(d.size() > 0) arrays_cloth[ArrayMesh.ARRAY_TEX_UV2] = d var tmp: Dictionary = {} for vcloth in range(arrays_cloth[ArrayMesh.ARRAY_VERTEX].size()): for vbody in range(arrays_body[ArrayMesh.ARRAY_VERTEX].size()): var vc: Vector3 = arrays_cloth[ArrayMesh.ARRAY_VERTEX][vcloth] var vb: Vector3 = arrays_body[ArrayMesh.ARRAY_VERTEX][vbody] if vc.distance_to(vb) < 0.8: if tmp.has(vcloth): tmp[vcloth].push_back(vbody) else: tmp[vcloth] = [vbody] for k in tmp.keys(): var vc: Vector3 = arrays_cloth[ArrayMesh.ARRAY_VERTEX][k] var res: Array = [] for v in tmp[k]: var vb: Vector3 = arrays_body[ArrayMesh.ARRAY_VERTEX][v] var d1 = vc.distance_squared_to(vb) if res.size() >= 3: for mv in range(res.size()): var vb1: Vector3 = arrays_body[ArrayMesh.ARRAY_VERTEX][res[mv]] var d2 = vc.distance_squared_to(vb1) if d1 < d2 && !v in res: res[mv] = v else: if ! v in res: res.push_back(v) tmp[k] = res if res.size() == 3: var vtx: Vector3 = arrays_cloth[ArrayMesh.ARRAY_VERTEX][k] var bverts = PoolVector3Array() var buvs = PoolVector2Array() for e in res: var vb: Vector3 = arrays_body[ArrayMesh.ARRAY_VERTEX][e] var ub: Vector2 = arrays_body[ArrayMesh.ARRAY_TEX_UV][e] bverts.push_back(vb) buvs.push_back(ub) arrays_cloth[ArrayMesh.ARRAY_TEX_UV2][k] = triangulate_uv(vtx, bverts, buvs) return arrays_cloth func add_cloth_mesh(cloth_name: String, cloth_helper: String, mesh: ArrayMesh) -> Array: add_mesh(cloth_name, mesh, 0, {}) var cloth_array = _prepare_cloth(meshes.body.orig_arrays, meshes[cloth_name].orig_arrays) meshes[cloth_name].orig_arrays = cloth_array clothes[cloth_name] = {} meshes[cloth_name].helper = cloth_helper var modifiers = {} for k in get_modifier_list(): var helper = meshes[cloth_name].helper if helper == "body": helper = "" var mod = k if helper.length() > 0: mod = helper + ":" + k if !maps.has(mod): mod = k print("adding modifier for ", cloth_name, " name: ", mod) modifiers[k] = get_mesh_modifier(mod, cloth_array) print(cloth_name, ": ", k, ": size: ", modifiers[k][0].size()) meshes[cloth_name].modifiers = modifiers return cloth_array func add_body_mesh(mesh: ArrayMesh, same_indices: Dictionary) -> Array: add_mesh("body", mesh, 0, same_indices) var modifiers = {} for k in get_modifier_list(): modifiers[k] = get_mesh_modifier(k, meshes["body"].orig_arrays) meshes["body"].modifiers = modifiers meshes["body"].helper = "" return meshes["body"].orig_arrays #func __modify_mesh(orig_mesh: ArrayMesh, v_indices: Dictionary) -> ArrayMesh: # for k in maps.keys(): # maps[k].image.lock() # maps[k].image_normal.lock() # var surf : = 0 # var mod_mesh = ArrayMesh.new() # var mrect: Rect2 # for k in maps.keys(): # if maps[k].value > 0.0001: # if mrect: # mrect = mrect.merge(maps[k].rect) # else: # mrect = maps[k].rect # for surface in range(orig_mesh.get_surface_count()): # var arrays: Array = orig_mesh.surface_get_arrays(surface) # var uv_index: int = ArrayMesh.ARRAY_TEX_UV # if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0: # uv_index = ArrayMesh.ARRAY_TEX_UV2 # for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()): # var v: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][index] # var n: Vector3 = arrays[ArrayMesh.ARRAY_NORMAL][index] # var uv: Vector2 = arrays[uv_index][index] # if !mrect.has_point(uv): # continue # var diff : = Vector3() # var diffn : = Vector3() # for k in maps.keys(): # if !maps[k].rect.has_point(uv) || abs(maps[k].value) < 0.0001: # continue # var pos: Vector2 = Vector2(uv.x * maps[k].width, uv.y * maps[k].height) # var offset: Color = maps[k].image.get_pixelv(pos) # var offsetn: Color = maps[k].image_normal.get_pixelv(pos) # var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b) # var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b) # for u in range(3): # diff[u] = range_lerp(pdiff[u], 0.0, 1.0, min_point[u], max_point[u]) * maps[k].value # diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, min_normal[u], max_normal[u]) * maps[k].value # if abs(diff[u]) < 0.0001: # diff[u] = 0 # v -= diff # n -= diffn # arrays[ArrayMesh.ARRAY_VERTEX][index] = v # arrays[ArrayMesh.ARRAY_NORMAL][index] = n.normalized() # for v in v_indices.keys(): # if v_indices[v].size() <= 1: # continue # var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][0]] # for idx in range(1, v_indices[v].size()): # vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][idx]], 0.5) # for idx in v_indices[v]: # arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx # # mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays) # if orig_mesh.surface_get_material(surface): # mod_mesh.surface_set_material(surface, orig_mesh.surface_get_material(surface).duplicate(true)) # surf += 1 # for k in maps.keys(): # maps[k].image.unlock() # maps[k].image_normal.unlock() # return mod_mesh #func modify_part(part_name) -> ArrayMesh: ## var mesh = meshes[part_name].orig_mesh ## var indices = meshes[part_name].same_indices ## return modify_mesh(mesh, indices) # return _mod_part(part_name) #func set_modifier_value(modifier: String, value: float): # maps[modifier].value = value #func get_mesh_modifier(m_name: String, arrays: Array) -> Array: # maps[m_name].image.lock() # maps[m_name].image_normal.lock() # var indices = PoolIntArray() # var mod_vertex = PoolVector3Array() # var mod_normal = PoolVector3Array() # var uv_index: int = ArrayMesh.ARRAY_TEX_UV # if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0: # uv_index = ArrayMesh.ARRAY_TEX_UV2 # var mrect: Rect2 = maps[m_name].rect # var count = 0 # var max_count = arrays[ArrayMesh.ARRAY_VERTEX].size() # var width: int = maps[m_name].width # var height: int = maps[m_name].height # indices.resize(max_count) # mod_vertex.resize(max_count) # mod_normal.resize(max_count) # if uv_index != ArrayMesh.ARRAY_TEX_UV2: # print("not on uv2") # for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()): # var uv: Vector2 = arrays[uv_index][index] # if !mrect.has_point(uv): # continue # var diff: = Vector3() # var diffn: = Vector3() # var pos: Vector2 = Vector2(uv.x * width, uv.y * height) # var offset: Color = maps[m_name].image.get_pixelv(pos) # var offsetn: Color = maps[m_name].image_normal.get_pixelv(pos) # var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b) # var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b) # for u in range(3): # diff[u] = range_lerp(pdiff[u], 0.0, 1.0, maps[m_name].min_point[u], maps[m_name].min_point[u] + maps[m_name].point_scaler[u]) # diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, maps[m_name].min_normal[u], maps[m_name].min_normal[u] + maps[m_name].normal_scaler[u]) # if abs(diff[u]) < 0.0001: # diff[u] = 0 # if diff.length() > 0.001: # indices[count] = index # mod_vertex[count] = diff # mod_normal[count] = diffn # count += 1 # indices.resize(count) # mod_vertex.resize(count) # mod_normal.resize(count) # maps[m_name].image.unlock() # maps[m_name].image_normal.unlock() # return [indices, mod_vertex, mod_normal] #func apply_modifier(mod: Array, arrays: Array, value: float, offset = 0.0): # var value_: float = clamp(value, 0.0, 1.0) # var indices: PoolIntArray = mod[0] # var mod_vertex: PoolVector3Array = mod[1] # var mod_normal: PoolVector3Array = mod[2] # for count in range(indices.size()): # var index: int = indices[count] # var diff: Vector3 = mod_vertex[count] # var diffn: Vector3 = mod_normal[count] # var n = (arrays[ArrayMesh.ARRAY_NORMAL][index] - diffn).normalized() * offset # arrays[ArrayMesh.ARRAY_VERTEX][index] -= diff * value_ - n # # do not normalize now # arrays[ArrayMesh.ARRAY_NORMAL][index] -= diffn * value_ #func _mod_part(part_name: String) -> ArrayMesh: # print("modifying ", part_name) # print("helper:", meshes[part_name].helper) # var start_time = OS.get_unix_time() ## var mesh: ArrayMesh = meshes[part_name].orig_mesh # var mod_mesh: = ArrayMesh.new() # var indices: Dictionary = meshes[part_name].same_indices # var surface: int = 0 # if meshes[part_name].has("surface"): # surface = meshes[part_name].surface ## var arrays: Array = mesh.surface_get_arrays(surface) # var arrays: Array = meshes[part_name].orig_arrays.duplicate() # if part_name == "body": # for mod in meshes[part_name].modifiers.keys(): # var mod_data = meshes[part_name].modifiers[mod] # apply_modifier(mod_data, arrays, maps[mod].value) # else: # for mod in meshes[part_name].modifiers.keys(): # var mod_data = meshes[part_name].modifiers[mod] # apply_modifier(mod_data, arrays, maps[mod].value, 0.0002) # for v in indices.keys(): # if indices[v].size() <= 1: # continue # var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][indices[v][0]] # for idx in range(1, indices[v].size()): # vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][indices[v][idx]], 0.5) # for idx in indices[v]: # arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx # mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays) # if meshes[part_name].material: # mod_mesh.surface_set_material(surface, meshes[part_name].material.duplicate(true)) ## if mesh.surface_get_material(surface): ## mod_mesh.surface_set_material(surface, mesh.surface_get_material(surface).duplicate(true)) # var elapsed = OS.get_unix_time() - start_time # print("modified ", part_name, " ", elapsed) # return mod_mesh #func load_maps(path: String): # maps = {} # var fd: File = File.new() # fd.open(path, File.READ) # if !fd.is_open(): # print("Could not open " + path) # print(fd.get_len()) # var count = fd.get_var() # print(count) # for c in range(count): # var map_name = fd.get_var() # map_name = map_name.replace("base:", "") # var rect = fd.get_var() # var map_min_point = fd.get_var() # var point_scaler = fd.get_var() # var map_min_normal = fd.get_var() # var normal_scaler = fd.get_var() # var map_width = fd.get_var() # var map_height = fd.get_var() # var data_size = fd.get_var() # var data = fd.get_var() # var map_normal_width = fd.get_var() # var map_normal_height = fd.get_var() # var normal_data_size = fd.get_var() # var normal_data = fd.get_var() # maps[map_name] = {} # maps[map_name].rect = rect # maps[map_name].min_point = map_min_point # maps[map_name].point_scaler = point_scaler # maps[map_name].min_normal = map_min_normal # maps[map_name].normal_scaler = normal_scaler # maps[map_name].width = map_width # maps[map_name].height = map_height # maps[map_name].normal_width = map_normal_width # maps[map_name].normal_height = map_normal_height # data = data.decompress(data_size, File.COMPRESSION_DEFLATE) # maps[map_name].image = Image.new() # maps[map_name].image.create_from_data(maps[map_name].width, maps[map_name].height, false, Image.FORMAT_RGB8, data) # normal_data = normal_data.decompress(normal_data_size, File.COMPRESSION_DEFLATE) # maps[map_name].image_normal = Image.new() # maps[map_name].image_normal.create_from_data(maps[map_name].normal_width, maps[map_name].normal_height, false, Image.FORMAT_RGB8, normal_data) # print(map_name, " ", map_width, " ", map_height, " ", data_size, " ", data.size(), " ", map_normal_width, " ", map_normal_height, " ", normal_data_size, " ", normal_data.size()) # maps[map_name].value = 0.0 # fd.close() #func _init(path: String): # load_maps("res://characters/blendmaps.bin") # var fd = File.new() # fd.open(path, File.READ) # min_point = fd.get_var() # max_point = fd.get_var() # min_normal = fd.get_var() # max_normal = fd.get_var() # maps = fd.get_var() ## print(maps.keys()) ## vert_indices = fd.get_var() # fd.close() # print("min: ", min_point, " max: ", max_point) ## for k in maps.keys(): ## print(k, ": ", maps[k].rect) # for k in maps.keys(): # maps[k].image_normal = Image.new() # var normal_data = maps[k].image_normal_data.decompress(maps[k].image_normal_size, File.COMPRESSION_FASTLZ) # var data = maps[k].image_data.decompress(maps[k].image_size, File.COMPRESSION_FASTLZ) # maps[k].image_normal.create_from_data(maps[k].width, maps[k].height, false, maps[k].format, normal_data) # maps[k].image = Image.new() # maps[k].image.create_from_data(maps[k].width, maps[k].height, false, maps[k].format, data) # maps[k].value = 0.0