620 lines
23 KiB
GDScript
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
|