201 lines
8.0 KiB
GDScript
201 lines
8.0 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
|
|
|
|
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 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
|
|
assert max_point != min_point
|
|
var cd = max_point - min_point
|
|
var ncd = max_normal - min_normal
|
|
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()
|
|
|
|
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
|