Files
omath/tests/lua/collision_tests.lua
2026-05-16 10:33:06 +03:00

170 lines
7.0 KiB
Lua

local function approx(a, b, eps) return math.abs(a - b) < (eps or 1e-4) end
local function cube_points()
return {
omath.Vec3.new(-1, -1, -1),
omath.Vec3.new(1, -1, -1),
omath.Vec3.new(-1, 1, -1),
omath.Vec3.new(1, 1, -1),
omath.Vec3.new(-1, -1, 1),
omath.Vec3.new(1, -1, 1),
omath.Vec3.new(-1, 1, 1),
omath.Vec3.new(1, 1, 1),
}
end
function Collision_Aabb_constructor_and_fields()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -2, -3), omath.Vec3.new(1, 2, 3))
assert(aabb.min.x == -1 and aabb.max.z == 3)
aabb.max = omath.Vec3.new(2, 3, 4)
assert(aabb.max.x == 2 and aabb.max.y == 3 and aabb.max.z == 4)
end
function Collision_Aabb_center_extents()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -2, -3), omath.Vec3.new(3, 6, 9))
local center = aabb:center()
local extents = aabb:extents()
assert(center.x == 1 and center.y == 2 and center.z == 3)
assert(extents.x == 2 and extents.y == 4 and extents.z == 6)
end
function Collision_Aabb_top_bottom_default_axis()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -2, -3), omath.Vec3.new(3, 6, 9))
assert(aabb:top().y == 6)
assert(aabb:bottom().y == -2)
end
function Collision_Aabb_top_bottom_explicit_axis()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -2, -3), omath.Vec3.new(3, 6, 9))
assert(aabb:top(omath.primitives.UpAxis.X).x == 3)
assert(aabb:bottom(omath.primitives.UpAxis.Z).z == -3)
end
function Collision_Aabb_is_collide()
local a = omath.primitives.Aabb.new(omath.Vec3.new(-1, -1, -1), omath.Vec3.new(1, 1, 1))
local b = omath.primitives.Aabb.new(omath.Vec3.new(0, 0, 0), omath.Vec3.new(2, 2, 2))
local c = omath.primitives.Aabb.new(omath.Vec3.new(3, 3, 3), omath.Vec3.new(4, 4, 4))
assert(a:is_collide(b))
assert(not a:is_collide(c))
end
function Collision_Aabb_as_table()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -2, -3), omath.Vec3.new(1, 2, 3))
local t = aabb:as_table()
assert(t.min.x == -1 and t.max.z == 3)
end
function Collision_Obb_constructor_and_vertices()
local obb = omath.primitives.Obb.new(
omath.Vec3.new(0, 0, 0),
omath.Vec3.new(1, 0, 0),
omath.Vec3.new(0, 1, 0),
omath.Vec3.new(0, 0, 1),
omath.Vec3.new(1, 2, 3)
)
local vertices = obb:vertices()
assert(#vertices == 8)
assert(vertices[1].x == -1 and vertices[1].y == -2 and vertices[1].z == -3)
assert(vertices[8].x == 1 and vertices[8].y == 2 and vertices[8].z == 3)
end
function Collision_Ray_constructor_and_direction()
local ray = omath.collision.Ray.new(omath.Vec3.new(1, 2, 3), omath.Vec3.new(4, 6, 3), true)
local dir = ray:direction_vector()
local normal = ray:direction_vector_normalized()
assert(ray.infinite_length)
assert(dir.x == 3 and dir.y == 4 and dir.z == 0)
assert(approx(normal:length(), 1))
end
function Collision_LineTracer_triangle_hit()
local tri = omath.Triangle.new(omath.Vec3.new(0, 0, 0), omath.Vec3.new(2, 0, 0), omath.Vec3.new(0, 2, 0))
local ray = omath.collision.Ray.new(omath.Vec3.new(0.5, 0.5, -1), omath.Vec3.new(0.5, 0.5, 1))
local hit = omath.collision.LineTracer.get_ray_hit_point(ray, tri)
assert(omath.collision.LineTracer.ray_hits_triangle(ray, tri))
assert(not omath.collision.LineTracer.can_trace_line(ray, tri))
assert(approx(hit.x, 0.5) and approx(hit.y, 0.5) and approx(hit.z, 0))
end
function Collision_LineTracer_triangle_miss()
local tri = omath.Triangle.new(omath.Vec3.new(0, 0, 0), omath.Vec3.new(1, 0, 0), omath.Vec3.new(0, 1, 0))
local ray = omath.collision.Ray.new(omath.Vec3.new(2, 2, -1), omath.Vec3.new(2, 2, 1))
local hit = omath.collision.LineTracer.get_ray_hit_point(ray, tri)
assert(not omath.collision.LineTracer.ray_hits_triangle(ray, tri))
assert(omath.collision.LineTracer.can_trace_line(ray, tri))
assert(hit == ray["end"])
end
function Collision_LineTracer_aabb_hit()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -1, -1), omath.Vec3.new(1, 1, 1))
local ray = omath.collision.Ray.new(omath.Vec3.new(0, 0, -3), omath.Vec3.new(0, 0, 3))
local hit = omath.collision.LineTracer.get_ray_hit_point(ray, aabb)
assert(omath.collision.LineTracer.ray_hits_aabb(ray, aabb))
assert(approx(hit.x, 0) and approx(hit.y, 0) and approx(hit.z, -1))
end
function Collision_LineTracer_aabb_miss()
local aabb = omath.primitives.Aabb.new(omath.Vec3.new(-1, -1, -1), omath.Vec3.new(1, 1, 1))
local ray = omath.collision.Ray.new(omath.Vec3.new(0, 3, -3), omath.Vec3.new(0, 3, 3))
local hit = omath.collision.LineTracer.get_ray_hit_point(ray, aabb)
assert(not omath.collision.LineTracer.ray_hits_aabb(ray, aabb))
assert(hit == ray["end"])
end
function Collision_LineTracer_obb_hit()
local obb = omath.primitives.Obb.new(
omath.Vec3.new(0, 0, 0),
omath.Vec3.new(1, 0, 0),
omath.Vec3.new(0, 1, 0),
omath.Vec3.new(0, 0, 1),
omath.Vec3.new(1, 1, 1)
)
local ray = omath.collision.Ray.new(omath.Vec3.new(0, 0, -3), omath.Vec3.new(0, 0, 3))
local hit = omath.collision.LineTracer.get_ray_hit_point(ray, obb)
assert(omath.collision.LineTracer.ray_hits_obb(ray, obb))
assert(approx(hit.z, -1))
end
function Collision_ConvexCollider_vertices_and_support()
local collider = omath.collision.ConvexCollider.new(cube_points(), omath.Vec3.new(2, 0, 0))
assert(collider:vertex_count() == 8)
assert(#collider:vertices() == 8)
local support = collider:find_abs_furthest_vertex_position(omath.Vec3.new(1, 0, 0))
assert(support.x == 3)
end
function Collision_Gjk_support_vertex()
local a = omath.collision.ConvexCollider.new(cube_points())
local b = omath.collision.ConvexCollider.new(cube_points())
local support = omath.collision.gjk_support_vertex(a, b, omath.Vec3.new(1, 0, 0))
assert(support.x == 2 and support.y == 0 and support.z == 0)
end
function Collision_Gjk_collide_true()
local a = omath.collision.ConvexCollider.new(cube_points())
local b = omath.collision.ConvexCollider.new(cube_points(), omath.Vec3.new(1, 0, 0))
assert(omath.collision.gjk_collide(a, b))
end
function Collision_Gjk_collide_false()
local a = omath.collision.ConvexCollider.new(cube_points())
local b = omath.collision.ConvexCollider.new(cube_points(), omath.Vec3.new(5, 0, 0))
assert(not omath.collision.gjk_collide(a, b))
end
function Collision_Epa_solve_hit()
local a = omath.collision.ConvexCollider.new(cube_points())
local b = omath.collision.ConvexCollider.new(cube_points(), omath.Vec3.new(1.5, 0, 0))
local result = omath.collision.epa_solve(a, b)
assert(result ~= nil)
assert(result.depth > 0)
assert(approx(result.normal:length(), 1))
assert(approx(result.penetration_vector:length(), result.depth))
end
function Collision_Epa_solve_miss()
local a = omath.collision.ConvexCollider.new(cube_points())
local b = omath.collision.ConvexCollider.new(cube_points(), omath.Vec3.new(5, 0, 0))
assert(omath.collision.epa_solve(a, b) == nil)
end