mirror of
https://github.com/Relintai/broken_seals.git
synced 2025-01-15 02:01:09 +01:00
Mesh data resource editor now uses MeshUtils to uv unwrap meshes. Removed my half-finished unwrapping code.
This commit is contained in:
parent
04bc717331
commit
96fff0331e
@ -124,448 +124,16 @@ func uv_unwrap() -> void:
|
||||
|
||||
var mesh : Array = mdr.get_array()
|
||||
|
||||
# partition the meshes along the already existing seams (no new vertices)
|
||||
var partitioned_meshes : Array = partition_mesh(mesh)
|
||||
var uvs : PoolVector2Array = MeshUtils.uv_unwrap(mesh)
|
||||
|
||||
for m in partitioned_meshes:
|
||||
#m.print()
|
||||
m.unwrap()
|
||||
|
||||
mesh[ArrayMesh.ARRAY_TEX_UV] = m.processed_calc_uvs
|
||||
|
||||
mesh[ArrayMesh.ARRAY_TEX_UV] = uvs
|
||||
|
||||
mdr.set_array(mesh)
|
||||
|
||||
if mdr:
|
||||
mdi_ed_gui.set_mesh_data_resource(mdr)
|
||||
|
||||
|
||||
class STriangle:
|
||||
var i1 : int = 0
|
||||
var i2 : int = 0
|
||||
var i3 : int = 0
|
||||
|
||||
var index : int = 0
|
||||
|
||||
var v1 : Vector3
|
||||
var v2 : Vector3
|
||||
var v3 : Vector3
|
||||
|
||||
var vn1 : Vector3
|
||||
var vn2 : Vector3
|
||||
var vn3 : Vector3
|
||||
|
||||
var vns1 : Vector2
|
||||
var vns2 : Vector2
|
||||
var vns3 : Vector2
|
||||
|
||||
var uv1 : Vector2
|
||||
var uv2 : Vector2
|
||||
var uv3 : Vector2
|
||||
|
||||
var n1 : Vector3
|
||||
var n2 : Vector3
|
||||
var n3 : Vector3
|
||||
|
||||
var neighbour_v1_v2 : int = -1
|
||||
var neighbour_v2_v3 : int = -1
|
||||
var neighbour_v1_v3 : int = -1
|
||||
|
||||
var face_normal : Vector3
|
||||
var basis : Basis
|
||||
|
||||
func set_indices(pi1 : int, pi2 : int, pi3 : int, pindex : int):
|
||||
i1 = pi1
|
||||
i2 = pi2
|
||||
i3 = pi3
|
||||
index = pindex
|
||||
|
||||
func set_vertices(pv1 : Vector3, pv2 : Vector3, pv3 : Vector3):
|
||||
v1 = pv1
|
||||
v2 = pv2
|
||||
v3 = pv3
|
||||
|
||||
#for debugging
|
||||
func set_normals(pn1 : Vector3, pn2 : Vector3, pn3 : Vector3):
|
||||
n1 = pn1
|
||||
n2 = pn2
|
||||
n3 = pn3
|
||||
|
||||
func is_neighbour(pi1 : int, pi2 : int, pi3 : int) -> bool:
|
||||
var c : int = 0
|
||||
|
||||
if i1 == pi1 || i1 == pi2 || i1 == pi3:
|
||||
c += 1
|
||||
|
||||
if i2 == pi1 || i2 == pi2 || i2 == pi3:
|
||||
c += 1
|
||||
|
||||
if i3 == pi1 || i3 == pi2 || i3 == pi3:
|
||||
c += 1
|
||||
|
||||
if c >= 1:
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
func project_vertices() -> void:
|
||||
vn3 = v3 - v2
|
||||
vn1 = v1 - v2
|
||||
vn2 = Vector3() #v2 - v2
|
||||
|
||||
face_normal = vn1.cross(vn3).normalized()
|
||||
|
||||
# face normal has to end up the y coordinate in the world coordinate system a.k.a 0 1 0
|
||||
# then triangle is in x, z plane
|
||||
|
||||
basis = Basis(vn1.normalized(), face_normal, vn3.normalized())
|
||||
basis = basis.orthonormalized()
|
||||
|
||||
vn1 = basis.xform_inv(vn1)
|
||||
vn2 = basis.xform_inv(vn2)
|
||||
vn3 = basis.xform_inv(vn3)
|
||||
|
||||
#these are not real uvs yet, just projections of the vertices to a 2d plane (v2 is at the origin)
|
||||
#where the plane is parallel to our triangle
|
||||
uv1 = Vector2(vn1.x, vn1.z)
|
||||
uv2 = Vector2(vn2.x, vn2.z)
|
||||
uv3 = Vector2(vn3.x, vn3.z)
|
||||
|
||||
vns1 = uv1
|
||||
vns2 = uv2
|
||||
vns3 = uv3
|
||||
|
||||
func has_edge(pi1 : int, pi2 : int):
|
||||
if i1 == pi1 || i2 == pi1 || i3 == pi1:
|
||||
if i1 == pi2 || i2 == pi2 || i3 == pi2:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func print():
|
||||
print("[ Tri: " + str(i1) + ", " + str(i2) + ", " + str(i3) + ", " + str(index) + " ]")
|
||||
|
||||
func print_verts():
|
||||
print("[ Tri vets: " + str(v1) + ", " + str(v2) + ", " + str(v3) + " ]")
|
||||
|
||||
func print_nverts():
|
||||
print("[ Tri nvets: " + str(vn1) + ", " + str(vn2) + ", " + str(vn3) + " ]")
|
||||
|
||||
func print_uvs():
|
||||
print("[ Tri uvs: " + str(uv1) + ", " + str(uv2) + ", " + str(uv3) + " ]")
|
||||
|
||||
func print_normals():
|
||||
print("[ Tri normals: " + str(n1) + ", " + str(n2) + ", " + str(n3) + " ]")
|
||||
|
||||
func print_neighbours():
|
||||
print("[ Tri neighbours: " + str(neighbour_v1_v2) + ", " + str(neighbour_v2_v3) + ", " + str(neighbour_v1_v3) + " ]")
|
||||
|
||||
|
||||
class SMesh:
|
||||
var indices : PoolIntArray
|
||||
var vertices : PoolVector3Array
|
||||
var uvs : PoolVector2Array
|
||||
var triangles : Array
|
||||
|
||||
var processed_vertices : Dictionary = Dictionary()
|
||||
var processed_triangles : Dictionary = Dictionary()
|
||||
var processed_calc_uvs : PoolVector2Array = PoolVector2Array()
|
||||
|
||||
func is_triangle_neighbour(tri : STriangle) -> bool:
|
||||
for t in triangles:
|
||||
if t.is_neighbour(tri.i1, tri.i2, tri.i3):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func try_to_merge(o : SMesh) -> bool:
|
||||
for t in o.triangles:
|
||||
if is_triangle_neighbour(t):
|
||||
triangles.append_array(o.triangles)
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func unwrap():
|
||||
project_vertices()
|
||||
find_neighbours()
|
||||
layout_uvs()
|
||||
normalize_uvs()
|
||||
|
||||
# print(processed_calc_uvs)
|
||||
|
||||
func project_vertices():
|
||||
for t in triangles:
|
||||
t.project_vertices()
|
||||
|
||||
func find_neighbours():
|
||||
for i in range(triangles.size()):
|
||||
var t = triangles[i]
|
||||
|
||||
t.neighbour_v1_v2 = find_neighbour(i, t.i1, t.i2)
|
||||
t.neighbour_v2_v3 = find_neighbour(i, t.i2, t.i3)
|
||||
t.neighbour_v1_v3 = find_neighbour(i, t.i1, t.i3)
|
||||
|
||||
func layout_uvs():
|
||||
processed_vertices = Dictionary()
|
||||
processed_triangles = Dictionary()
|
||||
processed_calc_uvs = PoolVector2Array()
|
||||
|
||||
processed_calc_uvs.resize(vertices.size())
|
||||
|
||||
for i in range(processed_calc_uvs.size()):
|
||||
processed_calc_uvs.set(i, Vector2())
|
||||
|
||||
var t = triangles[0]
|
||||
|
||||
#don't
|
||||
#processed_triangles[t.index] = true
|
||||
|
||||
processed_vertices[t.i1] = true
|
||||
processed_vertices[t.i2] = true
|
||||
processed_vertices[t.i3] = true
|
||||
|
||||
processed_calc_uvs[t.i1] = t.uv1
|
||||
processed_calc_uvs[t.i2] = t.uv2
|
||||
processed_calc_uvs[t.i3] = t.uv3
|
||||
|
||||
#print(str(t.uv1) + str(t.uv2) + str(t.uv3))
|
||||
|
||||
join_triangles(0)
|
||||
|
||||
var count : int = 0
|
||||
|
||||
func join_triangles(tindex):
|
||||
if tindex == -1:
|
||||
return
|
||||
|
||||
if processed_triangles.has(tindex):
|
||||
return
|
||||
|
||||
processed_triangles[tindex] = true
|
||||
|
||||
var t = triangles[tindex]
|
||||
|
||||
#note that only one of these can be false
|
||||
#except for the first triangle (where all sould be true see layout_uvs()
|
||||
var v1d : bool = processed_vertices.has(t.i1)
|
||||
var v2d : bool = processed_vertices.has(t.i2)
|
||||
var v3d : bool = processed_vertices.has(t.i3)
|
||||
|
||||
if !v1d:
|
||||
processed_vertices[t.i1] = true
|
||||
|
||||
processed_calc_uvs[t.i1] = transform_uv(t.vns2, t.vns3, t.vns1, processed_calc_uvs[t.i3], processed_calc_uvs[t.i2])
|
||||
#print(processed_calc_uvs[t.i1])
|
||||
|
||||
if !v2d:
|
||||
processed_vertices[t.i2] = true
|
||||
|
||||
processed_calc_uvs[t.i2] = transform_uv(t.vns1, t.vns3, t.vns2, processed_calc_uvs[t.i3], processed_calc_uvs[t.i1])
|
||||
|
||||
if !v3d:
|
||||
processed_vertices[t.i3] = true
|
||||
|
||||
processed_calc_uvs[t.i3] = transform_uv(t.vns1, t.vns2, t.vns3, processed_calc_uvs[t.i2], processed_calc_uvs[t.i1])
|
||||
|
||||
join_triangles(t.neighbour_v1_v2)
|
||||
join_triangles(t.neighbour_v2_v3)
|
||||
join_triangles(t.neighbour_v1_v3)
|
||||
|
||||
func transform_uv(v1 : Vector2, v2 : Vector2, v3 : Vector2, vt1 : Vector2, vt2 : Vector2) -> Vector2:
|
||||
if count >= 5:
|
||||
return Vector2()
|
||||
|
||||
count += 1
|
||||
|
||||
var a : float = (v2 - v1).angle_to(v3 - v1)
|
||||
var l : float = (v3 - v1).length()
|
||||
|
||||
var ret : Vector2 = (vt2 - vt1).normalized() * l
|
||||
|
||||
var retr : Vector2 = ret.rotated(-a)
|
||||
|
||||
return retr
|
||||
|
||||
func overlaps(v1 : Vector2, v2 : Vector2, v3 : Vector2, vs1 : Vector2, vs2 : Vector2, vs3 : Vector2) -> bool:
|
||||
var tri1 : PoolVector2Array = PoolVector2Array()
|
||||
var tri2 : PoolVector2Array = PoolVector2Array()
|
||||
|
||||
tri1.resize(3)
|
||||
tri2.resize(3)
|
||||
|
||||
tri1[0] = v1
|
||||
tri1[1] = v2
|
||||
tri1[2] = v3
|
||||
|
||||
tri2[0] = vs1
|
||||
tri2[1] = vs2
|
||||
tri2[2] = vs3
|
||||
|
||||
return tri_tri_overlap_test(tri1, tri2)
|
||||
|
||||
#from https://rosettacode.org/wiki/Determine_if_two_triangles_overlap
|
||||
#there is probably a simpler way in this case, as one edge is shared
|
||||
func tri_tri_overlap_test(tri1 : PoolVector2Array, tri2 : PoolVector2Array) -> bool:
|
||||
for i in range(3):
|
||||
var j : int = (i + 1) % 3
|
||||
|
||||
if bound_doesnt_collide_check(tri1[i], tri1[j], tri2[0]) && bound_doesnt_collide_check(tri1[i], tri1[j], tri2[1]) && bound_doesnt_collide_check(tri1[i], tri1[j], tri2[2]):
|
||||
return false
|
||||
|
||||
for i in range(3):
|
||||
var j : int = (i + 1) % 3
|
||||
|
||||
if bound_doesnt_collide_check(tri2[i], tri2[j], tri1[0]) && bound_doesnt_collide_check(tri2[i], tri2[j], tri1[1]) && bound_doesnt_collide_check(tri2[i], tri2[j], tri1[2]):
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func det2d(p1 : Vector2, p2 : Vector2, p3 : Vector2) -> float:
|
||||
return p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)
|
||||
|
||||
func bound_doesnt_collide_check(p1 : Vector2, p2 : Vector2, p3 : Vector2, eps : float = 0.00001):
|
||||
return det2d(p1, p2, p3) <= eps
|
||||
|
||||
func normalize_uvs():
|
||||
var uv_xmin : float = processed_calc_uvs[0].x
|
||||
var uv_xmax : float = processed_calc_uvs[0].x
|
||||
var uv_ymin : float = processed_calc_uvs[0].y
|
||||
var uv_ymax : float = processed_calc_uvs[0].y
|
||||
|
||||
var incvec : Vector2 = Vector2()
|
||||
|
||||
for i in range(1, processed_calc_uvs.size()):
|
||||
var uv : Vector2 = processed_calc_uvs[i]
|
||||
|
||||
if uv.x < uv_xmin:
|
||||
uv_xmin = uv.x
|
||||
|
||||
if uv.x > uv_xmax:
|
||||
uv_xmax = uv.x
|
||||
|
||||
if uv.y < uv_ymin:
|
||||
uv_ymin = uv.y
|
||||
|
||||
if uv.y > uv_ymax:
|
||||
uv_ymax = uv.y
|
||||
|
||||
if uv_ymin < 0 || uv_xmin < 0:
|
||||
|
||||
|
||||
if uv_xmin < 0:
|
||||
incvec.x = -uv_xmin
|
||||
uv_xmin = 0
|
||||
uv_xmax += incvec.x
|
||||
|
||||
if uv_ymin < 0:
|
||||
incvec.y = -uv_ymin
|
||||
uv_ymin = 0
|
||||
uv_ymax += incvec.y
|
||||
|
||||
for i in range(processed_calc_uvs.size()):
|
||||
processed_calc_uvs[i] += incvec
|
||||
|
||||
var rx : float = uv_xmax - uv_xmin
|
||||
var ry : float = uv_ymax - uv_ymin
|
||||
|
||||
for i in range(processed_calc_uvs.size()):
|
||||
var v : Vector2 = processed_calc_uvs[i]
|
||||
|
||||
v.x -= uv_xmin
|
||||
v.y -= uv_ymin
|
||||
v.x /= rx
|
||||
v.y /= ry
|
||||
|
||||
processed_calc_uvs[i] = v
|
||||
|
||||
#debug
|
||||
var z : Vector2 = Vector2(incvec.x, incvec.y)
|
||||
|
||||
z.x -= uv_xmin
|
||||
z.y -= uv_ymin
|
||||
z.x /= rx
|
||||
z.y /= ry
|
||||
|
||||
for i in range(processed_calc_uvs.size()):
|
||||
if processed_calc_uvs[i].is_equal_approx(z):
|
||||
processed_calc_uvs[i] = Vector2()
|
||||
|
||||
func find_neighbour(current_index : int, i1 : int, i2 : int):
|
||||
for i in range(triangles.size()):
|
||||
if current_index == i:
|
||||
continue
|
||||
|
||||
if triangles[i].has_edge(i1, i2):
|
||||
return i
|
||||
|
||||
return -1
|
||||
|
||||
func print():
|
||||
print("[ SMesh:")
|
||||
|
||||
for t in triangles:
|
||||
t.print()
|
||||
|
||||
print("]")
|
||||
|
||||
|
||||
func partition_mesh(mesh : Array) -> Array:
|
||||
var meshes : Array = Array()
|
||||
|
||||
if mesh.size() != ArrayMesh.ARRAY_MAX:
|
||||
return meshes
|
||||
|
||||
var vertices : PoolVector3Array = mesh[ArrayMesh.ARRAY_VERTEX]
|
||||
#for debugging
|
||||
var normals : PoolVector3Array = mesh[ArrayMesh.ARRAY_NORMAL]
|
||||
var indices : PoolIntArray = mesh[ArrayMesh.ARRAY_INDEX]
|
||||
|
||||
if vertices.size() == 0:
|
||||
return meshes
|
||||
|
||||
if indices.size() == 0:
|
||||
return meshes
|
||||
|
||||
var tricount : int = indices.size() / 3
|
||||
|
||||
for it in range(tricount):
|
||||
var iit : int = it * 3
|
||||
|
||||
var tri : STriangle = STriangle.new()
|
||||
tri.set_indices(indices[iit], indices[iit + 1], indices[iit + 2], it)
|
||||
tri.set_vertices(vertices[indices[iit]], vertices[indices[iit + 1]], vertices[indices[iit + 2]])
|
||||
tri.set_normals(normals[indices[iit]], normals[indices[iit + 1]], normals[indices[iit + 2]])
|
||||
|
||||
var found : bool = false
|
||||
for m in meshes:
|
||||
if m.is_triangle_neighbour(tri):
|
||||
m.triangles.append(tri)
|
||||
found = true
|
||||
break
|
||||
|
||||
if !found:
|
||||
var sm : SMesh = SMesh.new()
|
||||
sm.triangles.append(tri)
|
||||
|
||||
meshes.append(sm)
|
||||
|
||||
var changed : bool = true
|
||||
while changed:
|
||||
changed = false
|
||||
|
||||
for i in range(meshes.size() - 1):
|
||||
if meshes[i].try_to_merge(meshes[i + 1]):
|
||||
changed = true
|
||||
meshes.remove(i + 1)
|
||||
break
|
||||
|
||||
for m in meshes:
|
||||
m.vertices = vertices
|
||||
m.indices = indices
|
||||
m.uvs.resize(vertices.size())
|
||||
|
||||
return meshes
|
||||
|
||||
#func forward_spatial_gui_input(camera, event):
|
||||
# for g in active_gizmos:
|
||||
# if g.forward_spatial_gui_input(0, camera, event):
|
||||
|
Loading…
Reference in New Issue
Block a user