Files
kicking-high/proto2/characters/dna_tool.gd

620 lines
23 KiB
GDScript

extends Reference
class_name DNATool
const TEX_SIZE: int = 512
var min_point = Vector3()
var max_point = Vector3()
var min_normal = Vector3()
var max_normal = Vector3()
var dna: DNA
var vert_indices = {}
func get_mesh(base: Node, mesh_name: String) -> ArrayMesh:
var queue = [base]
var mesh: ArrayMesh
while queue.size() > 0:
var item = queue[0]
queue.pop_front()
if item is MeshInstance && item.name == mesh_name && item.mesh:
mesh = item.mesh
break
for c in item.get_children():
queue.push_back(c)
return mesh
func get_mi(base: Node, mesh_name: String) -> MeshInstance:
var queue = [base]
var ret: MeshInstance
while queue.size() > 0:
var item = queue.pop_front()
if item is MeshInstance && item.name == mesh_name && item.mesh:
ret = item
break
for c in item.get_children():
queue.push_back(c)
return ret
func find_same_verts(characters: Array):
for chdata in range(characters.size()):
var ch_scene = characters[chdata].instance()
var bmesh = get_mesh(ch_scene, "body")
if !vert_indices.has(chdata):
vert_indices[chdata] = {}
for surface in range(bmesh.get_surface_count()):
var arrays: Array = bmesh.surface_get_arrays(surface).duplicate(true)
for index1 in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
var v1: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][index1]
var ok = false
for rk in vert_indices[chdata].keys():
if (v1 - rk).length() < 0.001:
ok = true
vert_indices[chdata][rk].push_back(index1)
if !ok:
vert_indices[chdata][v1] = [index1]
func find_min_max(mesh: ArrayMesh):
var shape_arrays = mesh.surface_get_blend_shape_arrays(0)
var surf_arrays = mesh.surface_get_arrays(0)
if min_point.length() == 0.0:
min_point = shape_arrays[0][ArrayMesh.ARRAY_VERTEX][0] - surf_arrays[ArrayMesh.ARRAY_VERTEX][0]
if min_normal.length() == 0.0:
min_normal = shape_arrays[0][ArrayMesh.ARRAY_NORMAL][0] - surf_arrays[ArrayMesh.ARRAY_NORMAL][0]
if max_point.length() == 0.0:
max_point = shape_arrays[0][ArrayMesh.ARRAY_VERTEX][0] - surf_arrays[ArrayMesh.ARRAY_VERTEX][0]
if max_normal.length() == 0.0:
max_point = shape_arrays[0][ArrayMesh.ARRAY_NORMAL][0] - surf_arrays[ArrayMesh.ARRAY_NORMAL][0]
for sc in range(mesh.get_surface_count()):
var bshapes: Array = mesh.surface_get_blend_shape_arrays(sc).duplicate(true)
var arrays: Array = mesh.surface_get_arrays(sc).duplicate(true)
for src in bshapes:
for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
var v: Vector3 = src[ArrayMesh.ARRAY_VERTEX][index] - arrays[ArrayMesh.ARRAY_VERTEX][index]
var n: Vector3 = src[ArrayMesh.ARRAY_NORMAL][index] - arrays[ArrayMesh.ARRAY_NORMAL][index]
for ipos in range(3):
if min_point[ipos] > v[ipos]:
min_point[ipos] = v[ipos]
if max_point[ipos] < v[ipos]:
max_point[ipos] = v[ipos]
if min_normal[ipos] > n[ipos]:
min_normal[ipos] = n[ipos]
if max_normal[ipos] < n[ipos]:
max_normal[ipos] = n[ipos]
print("mesh: ", mesh.resource_name, "/", mesh, "min: ", min_point, "max: ", max_point)
func find_min_max_dict(d: Dictionary):
if d.triangles_v.size() == 0:
return
if d.triangles_n.size() == 0:
return
if min_point.length() == 0.0:
min_point = d.triangles_v[0]
if max_point.length() == 0.0:
max_point = d.triangles_v[0]
if min_normal.length() == 0.0:
min_normal = d.triangles_n[0]
if max_normal.length() == 0.0:
max_normal = d.triangles_n[0]
for v in d.triangles_v:
for ipos in range(3):
if min_point[ipos] > v[ipos]:
min_point[ipos] = v[ipos]
if max_point[ipos] < v[ipos]:
max_point[ipos] = v[ipos]
for n in d.triangles_n:
for ipos in range(3):
if min_normal[ipos] > n[ipos]:
min_normal[ipos] = n[ipos]
if max_normal[ipos] < n[ipos]:
max_normal[ipos] = n[ipos]
func get_cd():
return max_point - min_point
func get_ncd():
return max_normal - min_normal
func save_viewport(v: Viewport, maps: Dictionary, shape_name: String, rect: Rect2, draw_normals: bool):
var viewport: Viewport = v
# viewport.set_clear_mode(Viewport.CLEAR_MODE_ONLY_NEXT_FRAME)
# yield(viewport.get_tree(), "idle_frame")
# yield(viewport.get_tree(), "idle_frame")
var vtex : = viewport.get_texture()
var tex_img : = vtex.get_data()
# tex_img.flip_y()
var fn = ""
if !maps.has(shape_name):
maps[shape_name] = {}
maps[shape_name].width = tex_img.get_width()
maps[shape_name].height = tex_img.get_height()
maps[shape_name].format = tex_img.get_format()
var byte_data = tex_img.duplicate(true).get_data()
var image_size = byte_data.size()
if draw_normals:
maps[shape_name].image_normal_data = byte_data.compress(File.COMPRESSION_FASTLZ)
maps[shape_name].image_normal_size = image_size
else:
maps[shape_name].image_data = byte_data.compress(File.COMPRESSION_FASTLZ)
maps[shape_name].rect = rect.grow(0.003)
maps[shape_name].image_size = image_size
static func check_triangle(verts: Array, vs: Array, ns: Array) -> bool:
var uv1 = verts[0]
var uv2 = verts[1]
var uv3 = verts[2]
var v1 = uv1 - uv3
var v2 = uv1 - uv3
if v1.length() * TEX_SIZE < 1.2:
return false
if v2.length() * TEX_SIZE < 1.2:
return false
var sumdata = Vector3()
for k in vs + ns:
sumdata += k
if sumdata.length() < 0.001:
return false
return true
func build_triangles(mesh: ArrayMesh, diffmap: Dictionary):
assert(mesh)
for sc in range(mesh.get_surface_count()):
var shape_arrays = mesh.surface_get_blend_shape_arrays(sc)
var surf_arrays = mesh.surface_get_arrays(sc)
for bshape in range(shape_arrays.size()):
var bs_name = mesh.get_blend_shape_name(bshape)
if !diffmap.has(bs_name):
diffmap[bs_name] = {}
diffmap[bs_name].base_v = []
diffmap[bs_name].shape_v = []
diffmap[bs_name].triangles = []
diffmap[bs_name].triangles_uv = []
diffmap[bs_name].triangles_v = []
diffmap[bs_name].triangles_n = []
for vid in range(0, surf_arrays[ArrayMesh.ARRAY_INDEX].size(), 3):
var p1_index = surf_arrays[ArrayMesh.ARRAY_INDEX][vid + 0]
var p2_index = surf_arrays[ArrayMesh.ARRAY_INDEX][vid + 1]
var p3_index = surf_arrays[ArrayMesh.ARRAY_INDEX][vid + 2]
var p1 = surf_arrays[ArrayMesh.ARRAY_TEX_UV2][p1_index]
var p2 = surf_arrays[ArrayMesh.ARRAY_TEX_UV2][p2_index]
var p3 = surf_arrays[ArrayMesh.ARRAY_TEX_UV2][p3_index]
var base_v1 = surf_arrays[ArrayMesh.ARRAY_VERTEX][p1_index]
var base_v2 = surf_arrays[ArrayMesh.ARRAY_VERTEX][p2_index]
var base_v3 = surf_arrays[ArrayMesh.ARRAY_VERTEX][p3_index]
var shape_v1 = shape_arrays[bshape][ArrayMesh.ARRAY_VERTEX][p1_index]
var shape_v2 = shape_arrays[bshape][ArrayMesh.ARRAY_VERTEX][p2_index]
var shape_v3 = shape_arrays[bshape][ArrayMesh.ARRAY_VERTEX][p3_index]
var d1 = shape_v1 - base_v1
var d2 = shape_v2 - base_v2
var d3 = shape_v3 - base_v3
var base_n1 = surf_arrays[ArrayMesh.ARRAY_NORMAL][p1_index]
var base_n2 = surf_arrays[ArrayMesh.ARRAY_NORMAL][p2_index]
var base_n3 = surf_arrays[ArrayMesh.ARRAY_NORMAL][p3_index]
var shape_n1 = shape_arrays[bshape][ArrayMesh.ARRAY_NORMAL][p1_index]
var shape_n2 = shape_arrays[bshape][ArrayMesh.ARRAY_NORMAL][p2_index]
var shape_n3 = shape_arrays[bshape][ArrayMesh.ARRAY_NORMAL][p3_index]
var nd1 = shape_n1 - base_n1
var nd2 = shape_n2 - base_n2
var nd3 = shape_n3 - base_n3
var triangle = [p1_index, p2_index, p3_index]
var triangle_uv = [p1, p2, p3]
var triangle_v = [d1, d2, d3]
var triangle_n = [nd1, nd2, nd3]
if check_triangle(triangle_uv, triangle_v, triangle_n):
diffmap[bs_name].triangles += triangle
diffmap[bs_name].base_v += [base_v1, base_v2, base_v3]
diffmap[bs_name].shape_v += [shape_v1, shape_v2, shape_v3]
diffmap[bs_name].triangles_uv += triangle_uv
diffmap[bs_name].triangles_v += triangle_v
diffmap[bs_name].triangles_n += triangle_n
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 distance_to_tri(v: Vector3, v1: Vector3, v2: Vector3, v3: Vector3):
var d1 = v.distance_squared_to(v1)
var d2 = v.distance_squared_to(v2)
var d3 = v.distance_squared_to(v3)
return Vector3(d1, d2, d3).length_squared()
#class SparsePointGrid extends Reference:
# var items = {}
# var grid_size = 0.1
# var grid_max: int = 1000
# func add_point(point: Vector3, id: int):
func find_closest_triangle(v3: Vector3, arrays: Array):
var tri : = -1
var distance : = -1.0
for vid in range(0, arrays[ArrayMesh.ARRAY_INDEX].size(), 3):
var index = arrays[ArrayMesh.ARRAY_INDEX][vid]
var p1 = arrays[ArrayMesh.ARRAY_VERTEX][index + 0]
var p2 = arrays[ArrayMesh.ARRAY_VERTEX][index + 1]
var p3 = arrays[ArrayMesh.ARRAY_VERTEX][index + 2]
var d1 = v3.distance_squared_to(p1)
var d2 = v3.distance_squared_to(p2)
var d3 = v3.distance_squared_to(p3)
var mind = min(d1, min(d2, d3))
if distance < 0 || distance > mind:
distance = mind
tri = vid
return tri
func get_triangle_area(v1, v2, v3) -> float:
var a: Vector3 = v2 - v1
var b: Vector3 = v3 - v1
return a.cross(b).length() / 2.0
func get_baricentric(pt, v1, v2, v3) -> Vector3:
var n = (v2 - v1).cross(v3 - v1)
var d = n.dot(v1)
var denom = n.dot(n)
# print_debug("triangle: ", v1, " ", v2, " ", v3, " pt: ", pt, " normal: ", n, " d: ", d, " denom: ", denom)
var t = (-n.dot(pt) + d) / denom
var p = pt + t * n
# print_debug("t: ", t, " p: ", p)
var area = get_triangle_area(v1, v2, v3)
var c = get_triangle_area(v1, v2, p)
c = get_triangle_area(v2, v3, p)
var u = c / area
c = get_triangle_area(v3, v1, p)
var v = c / area
return Vector3(u, v, 1 - u - v)
class TriGrid extends Reference:
var grid_size = 0.1
var d = 100
var grid = {}
func point_id(p: Vector3) -> int:
var point_x: int = int(p.x / grid_size)
var point_y: int = int(p.y / grid_size)
var point_z: int = int(p.z / grid_size)
var ret: int = point_x + d * point_y + d * d * point_z
return ret
func get_tri_aabb(triangle: Array):
var ret: AABB = AABB(triangle[0], Vector3())
for h in triangle:
ret = ret.expand(h)
return ret
func get_center(id: int) -> Vector3:
assert(grid.has(id))
var aabb: AABB = grid[id].aabb
return aabb.position + aabb.size / 2.0
func get_radius(id: int) -> float:
assert(grid.has(id))
var aabb: AABB = grid[id].aabb
return aabb.get_longest_axis_size() * 1.4
func min_distance(p: Vector3, id: int) -> float:
var center : = get_center(id)
var radius : = get_radius(id)
var dist = p.distance_squared_to(center)
var ret: float = dist - radius * radius
if ret < 0.0:
ret = 0.0
return ret
func radius_search(p: Vector3, radius: float) -> Array:
var ret = []
var r_sq = radius * radius
for k in grid.keys():
var item = grid[k]
if min_distance(p, k) < r_sq:
for tid in range(item.triangles.size()):
var cur_tri = item.triangles[tid]
var ok: bool = false
for pt in cur_tri:
if p.distance_squared_to(pt) < r_sq:
ok = true
break
if ok:
var cur_tri_id = PoolIntArray(item.triangle_ids[tid])
if not cur_tri_id in ret:
ret.push_back(cur_tri_id)
return ret
func add_triangle(triangle: Array, triangle_id: Array):
for p in range(3):
var pt = triangle[p]
var id = triangle_id[p]
var grid_id = point_id(pt)
if grid.has(grid_id):
var item = grid[grid_id]
var item_aabb: AABB = item.aabb
var xaabb = get_tri_aabb(triangle)
item_aabb = item_aabb.merge(xaabb)
item.aabb = item_aabb
item.triangles.push_back(triangle)
item.triangle_ids.push_back(triangle_id)
grid[grid_id] = item
else:
var item = {}
item.aabb = get_tri_aabb(triangle)
item.triangles = [triangle]
item.triangle_ids = [triangle_id]
grid[grid_id] = item
func partition_mesh(mesh: ArrayMesh, surface: int = 0) -> TriGrid:
var array = mesh.surface_get_arrays(surface)
var items = []
var item = {}
var trigrid : = TriGrid.new()
for id in range(0, array[ArrayMesh.ARRAY_INDEX].size(), 3):
var index1 = array[ArrayMesh.ARRAY_INDEX][id]
var index2 = array[ArrayMesh.ARRAY_INDEX][id + 1]
var index3 = array[ArrayMesh.ARRAY_INDEX][id + 2]
var p1 : Vector3 = array[ArrayMesh.ARRAY_VERTEX][index1]
var p2 : Vector3 = array[ArrayMesh.ARRAY_VERTEX][index2]
var p3 : Vector3 = array[ArrayMesh.ARRAY_VERTEX][index3]
var triangle = [p1, p2, p3]
var triangle_id = [index1, index2, index3]
trigrid.add_triangle(triangle, triangle_id)
return trigrid
func check_normal(n: Vector3, normals: PoolVector3Array) -> bool:
for nt in normals:
if n.dot(nt) < 0:
return false
return true
func create_common2gender(base_mesh: ArrayMesh, gender_mesh: ArrayMesh):
var start_time = OS.get_unix_time()
var surface : = 0
var base_array = base_mesh.surface_get_arrays(surface)
var gender_array = gender_mesh.surface_get_arrays(surface)
var diffmap : = {}
# var base_trigrid = partition_mesh(base_mesh)
# var gender_trigrid = partition_mesh(gender_mesh)
diffmap.base_v = []
diffmap.shape_v = []
diffmap.triangles = []
diffmap.triangles_uv = []
diffmap.triangles_v = []
diffmap.triangles_n = []
var shape_vertices: = PoolVector3Array()
var shape_normals: = PoolVector3Array()
# var shape_uvs: = PoolVector2Array()
print("looking for exact points...")
var exact_points : = PoolIntArray()
exact_points.resize(base_array[ArrayMesh.ARRAY_TEX_UV2].size())
for k in range(exact_points.size()):
exact_points[k] = -1
var dst_check = 0.0001
var dst_sq_check = dst_check * dst_check
var pd1: PoolVector2Array = base_array[ArrayMesh.ARRAY_TEX_UV2]
var pd2: PoolVector2Array = gender_array[ArrayMesh.ARRAY_TEX_UV]
var pa1 = Array(pd1)
var pa2 = Array(pd2)
var pdata1 = PoolVector2Array(pa1)
var pdata2 = PoolVector2Array(pa2)
for vid in range(pdata1.size()):
for gid in range(pdata2.size()):
var vb: Vector2 = pdata1[vid]
var vg: Vector2 = pdata2[gid]
if vb.distance_squared_to(vg) < dst_sq_check:
exact_points[vid] = gid
if vid % 100 == 0:
print("vertex: ", vid)
# print("vertex: ", vid, " ", exact_points.keys().size())
print("looking for best vertices:")
var bad_verts : = 0
var triangles = {}
var buckets = [
{
"dir": [Vector3(-1, 0, 0), Vector3(0, 0, 1)],
"triangles": PoolIntArray()
},
{
"dir": [Vector3(-1, 0, 0), Vector3(0, 0, -1)],
"triangles": PoolIntArray()
},
{
"dir": [Vector3(1, 0, 0), Vector3(0, 0, 1)],
"triangles": PoolIntArray()
},
{
"dir": [Vector3(1, 0, 0), Vector3(0, 0, -1)],
"triangles": PoolIntArray()
}
]
print("partitioning...")
var p_start_time = OS.get_unix_time()
var tcount = 0
for idx in range(0, gender_array[ArrayMesh.ARRAY_INDEX].size(), 3):
if tcount % 400 == 0:
print("index: ", tcount)
var index1 = gender_array[ArrayMesh.ARRAY_INDEX][idx]
var index2 = gender_array[ArrayMesh.ARRAY_INDEX][idx + 1]
var index3 = gender_array[ArrayMesh.ARRAY_INDEX][idx + 2]
if index1 in exact_points && index2 in exact_points && index3 in exact_points:
continue
var ng1: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][index1]
var ng2: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][index2]
var ng3: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][index3]
var normals = [ng1, ng2, ng3]
var indices = PoolIntArray([index1, index2, index3])
var tn = (ng1 + ng2 + ng3).normalized()
for mb in range(buckets.size()):
if check_normal(tn, buckets[mb].dir):
var nt = Array(buckets[mb].triangles) + Array(indices)
buckets[mb].triangles = PoolIntArray(nt)
# print("k ", " ", indices.size(), " ", buckets[mb].triangles.size())
# break
# for r in range(indices.size()):
# buckets[mb].triangles.push_back(indices[r])
tcount += 1
var p_end_time = OS.get_unix_time()
print(p_end_time - p_start_time)
for mb in range(buckets.size()):
print(buckets[mb].dir, buckets[mb].triangles.size())
# var p_start_time = OS.get_unix_time()
# for vid in range(0, base_array[ArrayMesh.ARRAY_VERTEX].size()):
# var pt = base_array[ArrayMesh.ARRAY_VERTEX][vid]
# var nb: Vector3 = base_array[ArrayMesh.ARRAY_NORMAL][vid]
# for idx in range(0, gender_array[ArrayMesh.ARRAY_INDEX].size(), 3):
# var index1 = gender_array[ArrayMesh.ARRAY_INDEX][idx]
# var index2 = gender_array[ArrayMesh.ARRAY_INDEX][idx + 1]
# var index3 = gender_array[ArrayMesh.ARRAY_INDEX][idx + 2]
# var ng1: Vector3 = gender_array[ArrayMesh.ARRAY_VERTEX][index1]
# var ng2: Vector3 = gender_array[ArrayMesh.ARRAY_VERTEX][index2]
# var ng3: Vector3 = gender_array[ArrayMesh.ARRAY_VERTEX][index3]
# var normals = [ng1, ng2, ng3]
# var indices = PoolIntArray([index1, index2, index3])
# for mb in range(buckets.size()):
# for t in range(normals.size()):
# if buckets[mb].dir.dot(normals[t]) > 0:
# buckets[mb].triangles.append_array(indices)
# var p_end_time = OS.get_unix_time()
# print(p_end_time - p_start_time)
print("building...")
for vid in range(0, base_array[ArrayMesh.ARRAY_VERTEX].size()):
# if vid in exact_points.keys():
# continue
if exact_points[vid] != -1:
var new_vertex = gender_array[ArrayMesh.ARRAY_VERTEX][exact_points[vid]]
var new_normal = gender_array[ArrayMesh.ARRAY_NORMAL][exact_points[vid]]
shape_vertices.push_back(new_vertex)
shape_normals.push_back(new_normal)
continue
var best_triangle : = {}
var best_distance : = 1000000.0
var pt = base_array[ArrayMesh.ARRAY_VERTEX][vid]
var nb: Vector3 = base_array[ArrayMesh.ARRAY_NORMAL][vid]
# var triangles = gender_trigrid.radius_search(pt, 1.0)
# print(triangles.size())
var indices: PoolIntArray
for mb in range(buckets.size()):
if check_normal(nb, buckets[mb].dir):
indices = PoolIntArray(Array(indices) + Array(buckets[mb].triangles))
if vid % 100 == 0:
print("vertex: ", vid, " ", indices.size())
for idx in range(0, indices.size(), 3):
var index1 = indices[idx]
var ng: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][index1]
if nb.dot(ng) < 0:
continue
var index2 = indices[idx + 1]
var index3 = indices[idx + 2]
var p1 = gender_array[ArrayMesh.ARRAY_VERTEX][index1]
var p2 = gender_array[ArrayMesh.ARRAY_VERTEX][index2]
var p3 = gender_array[ArrayMesh.ARRAY_VERTEX][index3]
var bc : = get_baricentric(pt, p1, p2, p3)
if bc.length() < best_distance:
best_distance = bc.length()
best_triangle.triangle = [index1, index2, index3]
best_triangle.triangle_v = [p1, p2, p3]
best_triangle.baricentric = bc
if best_triangle.empty():
shape_vertices.push_back(pt)
bad_verts += 1
# shape_uvs.push_back(base_array[ArrayMesh.ARRAY_TEX_UV2][vid])
continue
var bc: Vector3 = best_triangle.baricentric
var v = best_triangle.triangle_v
var t = best_triangle.triangle
var new_vertex: Vector3 = v[0] * bc.x + v[1] * bc.y + v[2] * bc.z
var n1: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][t[0]]
var n2: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][t[1]]
var n3: Vector3 = gender_array[ArrayMesh.ARRAY_NORMAL][t[2]]
var new_normal: Vector3 = n1 * bc.x + n2 * bc.y + n3 * bc.z
# var uv1 = gender_array[ArrayMesh.ARRAY_TEX_UV2][t[0]]
# var uv2 = gender_array[ArrayMesh.ARRAY_TEX_UV2][t[1]]
# var uv3 = gender_array[ArrayMesh.ARRAY_TEX_UV2][t[2]]
# var new_uv: Vector2 = uv1 * bc.x + uv2 * bc.y + uv3 * bc.z
shape_vertices.push_back(new_vertex)
shape_normals.push_back(new_normal)
# shape_uvs.push_back(new_uv)
print("bad verts: ", bad_verts)
print("building diffmap data")
for xid in range(0, base_array[ArrayMesh.ARRAY_INDEX].size(), 3):
if xid % 100 == 0:
print("vertex: ", xid)
var p1_index = base_array[ArrayMesh.ARRAY_INDEX][xid + 0]
var p2_index = base_array[ArrayMesh.ARRAY_INDEX][xid + 1]
var p3_index = base_array[ArrayMesh.ARRAY_INDEX][xid + 2]
var p1 = base_array[ArrayMesh.ARRAY_TEX_UV2][p1_index]
var p2 = base_array[ArrayMesh.ARRAY_TEX_UV2][p2_index]
var p3 = base_array[ArrayMesh.ARRAY_TEX_UV2][p3_index]
var base_v1 = base_array[ArrayMesh.ARRAY_VERTEX][p1_index]
var base_v2 = base_array[ArrayMesh.ARRAY_VERTEX][p2_index]
var base_v3 = base_array[ArrayMesh.ARRAY_VERTEX][p3_index]
var bv = [base_v1, base_v2, base_v3]
var shape_v1 = shape_vertices[p1_index]
var shape_v2 = shape_vertices[p2_index]
var shape_v3 = shape_vertices[p3_index]
var sv = [shape_v1, shape_v2, shape_v3]
var base_n1 = base_array[ArrayMesh.ARRAY_NORMAL][p1_index]
var base_n2 = base_array[ArrayMesh.ARRAY_NORMAL][p2_index]
var base_n3 = base_array[ArrayMesh.ARRAY_NORMAL][p3_index]
var bn = [base_n1, base_n2, base_n3]
var shape_n1 = shape_normals[p1_index]
var shape_n2 = shape_normals[p2_index]
var shape_n3 = shape_normals[p3_index]
var sn = [shape_n1, shape_n2, shape_n3]
var d = [Vector3(), Vector3(), Vector3()]
var nd = [Vector3(), Vector3(), Vector3()]
for u in range(3):
for e in range(3):
d[u][e] = sv[u][e] - bv[u][e]
nd[u][e] = sn[u][e] - bn[u][e]
diffmap.base_v += bv
diffmap.shape_v += sv
diffmap.triangles += [p1_index, p2_index, p3_index]
diffmap.triangles_uv += [p1, p2, p3]
diffmap.triangles_v += d
diffmap.triangles_n += nd
print("done")
var end_time = OS.get_unix_time()
print_debug("create_common2gender: ", end_time - start_time)
return diffmap
func convert_triangles(base: ArrayMesh, helper: ArrayMesh) -> ArrayMesh:
var v2idxb = {}
var v2idxh = {}
var v2uv = {}
var sc = 0
var ret_mesh: = ArrayMesh.new()
var base_surf_array = base.surface_get_arrays(sc)
for idx in range(base_surf_array[ArrayMesh.ARRAY_VERTEX].size()):
var v = base_surf_array[ArrayMesh.ARRAY_VERTEX][idx]
v2idxb[v] = idx
var helper_surf_array = helper.surface_get_arrays(sc)
var bshapes = helper.surface_get_blend_shape_arrays(sc)
for idx in range(helper_surf_array[ArrayMesh.ARRAY_VERTEX].size()):
var v = helper_surf_array[ArrayMesh.ARRAY_VERTEX][idx]
v2idxh[v] = idx
# find 3 closest vertices on base mesh
var best_idx = -1
var best_dist = 1000.0
for k in v2idxh.keys():
for l in v2idxb.keys():
var dst = k.distance_to(l)
if dst < best_dist:
best_idx = v2idxb[l]
best_dist = dst
var uvh = base_surf_array[ArrayMesh.ARRAY_TEX_UV2][best_idx]
helper_surf_array[ArrayMesh.ARRAY_TEX_UV2][v2idxh[k]] = uvh
for h in bshapes.size():
bshapes[h][ArrayMesh.ARRAY_TEX_UV2][v2idxh[k]] = uvh
for k in range(helper.get_blend_shape_count()):
ret_mesh.add_blend_shape(helper.get_blend_shape_name(k))
ret_mesh.blend_shape_mode
ret_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, helper_surf_array, bshapes)
return ret_mesh
func build_uv_to_uv2(mesh:ArrayMesh, sc: int) -> Dictionary:
var uv2uv2 : = {}
var surf_array : = mesh.surface_get_arrays(sc)
for idx in range(surf_array[ArrayMesh.ARRAY_TEX_UV].size()):
var uv = surf_array[ArrayMesh.ARRAY_TEX_UV][idx]
var uv2 = surf_array[ArrayMesh.ARRAY_TEX_UV2][idx]
uv2uv2[uv] = uv2
return uv2uv2