Refactored generic geometric utilities out of GunkBody

This commit is contained in:
Rob Kelly 2025-03-07 18:18:50 -07:00
parent c676393e6d
commit faaf48d6a7
3 changed files with 28 additions and 25 deletions

View File

@ -0,0 +1,25 @@
class_name GeometryTools
## Utilities for specialized geometric operations.
## Transform cartesian coordinates to barycentric wrt the given triangle.
static func barycentric(p: Vector3, a: Vector3, b: Vector3, c: Vector3) -> Vector3:
var v0 := b - a
var v1 := c - a
var v2 := p - a
var d00 := v0.dot(v0)
var d01 := v0.dot(v1)
var d11 := v1.dot(v1)
var d20 := v2.dot(v0)
var d21 := v2.dot(v1)
var denom := d00 * d11 - d01 * d01
var v := (d11 * d20 - d01 * d21) / denom
var w := (d00 * d21 - d01 * d20) / denom
var u := 1.0 - v - w
return Vector3(u, v, w)
## Is the given point on the planar triangle defined by v1, v2, and v3?
static func is_in_triangle(point: Vector3, v1: Vector3, v2: Vector3, v3: Vector3) -> bool:
var bc := barycentric(point, v1, v2, v3)
return (bc.x > 0 and bc.x < 1) and (bc.y > 0 and bc.y < 1) and (bc.z > 0 and bc.z < 1)

View File

@ -0,0 +1 @@
uid://cgh4qc5whocql

View File

@ -118,29 +118,6 @@ func get_clear_total() -> float:
return total return total
## Transform cartesian coordinates to barycentric wrt the given triangle.
func _barycentric(p: Vector3, a: Vector3, b: Vector3, c: Vector3) -> Vector3:
var v0 := b - a
var v1 := c - a
var v2 := p - a
var d00 := v0.dot(v0)
var d01 := v0.dot(v1)
var d11 := v1.dot(v1)
var d20 := v2.dot(v0)
var d21 := v2.dot(v1)
var denom := d00 * d11 - d01 * d01
var v := (d11 * d20 - d01 * d21) / denom
var w := (d00 * d21 - d01 * d20) / denom
var u := 1.0 - v - w
return Vector3(u, v, w)
## Is the given point on the planar triangle defined by v1, v2, and v3?
func _is_in_triangle(point: Vector3, v1: Vector3, v2: Vector3, v3: Vector3) -> bool:
var bc := _barycentric(point, v1, v2, v3)
return (bc.x > 0 and bc.x < 1) and (bc.y > 0 and bc.y < 1) and (bc.z > 0 and bc.z < 1)
## Get the index of the mesh face on which the given point+normal lies. ## Get the index of the mesh face on which the given point+normal lies.
## ##
## Returns -1 if the given point+normal does not lie on a mesh face within tolerance. ## Returns -1 if the given point+normal does not lie on a mesh face within tolerance.
@ -156,7 +133,7 @@ func _get_face(point: Vector3, normal: Vector3) -> int:
var v1 := meshtool.get_vertex(meshtool.get_face_vertex(i, 0)) var v1 := meshtool.get_vertex(meshtool.get_face_vertex(i, 0))
var v2 := meshtool.get_vertex(meshtool.get_face_vertex(i, 1)) var v2 := meshtool.get_vertex(meshtool.get_face_vertex(i, 1))
var v3 := meshtool.get_vertex(meshtool.get_face_vertex(i, 2)) var v3 := meshtool.get_vertex(meshtool.get_face_vertex(i, 2))
if _is_in_triangle(point, v1, v2, v3): if GeometryTools.is_in_triangle(point, v1, v2, v3):
min_i = i min_i = i
min_sdist = sdist min_sdist = sdist
return min_i return min_i
@ -175,7 +152,7 @@ func _get_uv(point: Vector3, normal: Vector3) -> Vector2:
var v1 := meshtool.get_vertex(fv0) var v1 := meshtool.get_vertex(fv0)
var v2 := meshtool.get_vertex(fv1) var v2 := meshtool.get_vertex(fv1)
var v3 := meshtool.get_vertex(fv2) var v3 := meshtool.get_vertex(fv2)
var bc := _barycentric(point, v1, v2, v3) # TODO memoize var bc := GeometryTools.barycentric(point, v1, v2, v3) # TODO memoize
var uv1 := meshtool.get_vertex_uv(fv0) var uv1 := meshtool.get_vertex_uv(fv0)
var uv2 := meshtool.get_vertex_uv(fv1) var uv2 := meshtool.get_vertex_uv(fv1)
var uv3 := meshtool.get_vertex_uv(fv2) var uv3 := meshtool.get_vertex_uv(fv2)