use super::types::{
Mesh, CONCAVE_EDGE1, CONCAVE_EDGE2, CONCAVE_EDGE3, INVERSE_CONCAVE_EDGE1,
INVERSE_CONCAVE_EDGE2, INVERSE_CONCAVE_EDGE3, MESH_STACK_SIZE,
};
use crate::constants::linear_slop;
use crate::distance::{
compute_proxy_aabb, make_local_proxy, make_proxy, shape_distance, DistanceInput, ShapeProxy,
SimplexCache,
};
use crate::geometry::{Capsule, PlaneResult};
use crate::math_functions::{
add, max, min, mul, mul_sv, sub, test_bounds_overlap, test_bounds_triangle_overlap, Aabb,
Plane, Transform, Triangle, Vec3, TRANSFORM_IDENTITY,
};
pub fn overlap_mesh(shape: &Mesh<'_>, shape_transform: Transform, proxy: &ShapeProxy) -> bool {
debug_assert!(proxy.count > 0);
let mut cache = SimplexCache::default();
let local_proxy = make_local_proxy(proxy, shape_transform);
let aabb = compute_proxy_aabb(&local_proxy);
let mesh_scale = shape.scale;
let inv_scale = Vec3 {
x: 1.0 / mesh_scale.x,
y: 1.0 / mesh_scale.y,
z: 1.0 / mesh_scale.z,
};
let temp1 = mul(inv_scale, aabb.lower_bound);
let temp2 = mul(inv_scale, aabb.upper_bound);
let inv_scaled_bounds_min = min(temp1, temp2);
let inv_scaled_bounds_max = max(temp1, temp2);
let inv_scaled_bounds_center = mul_sv(0.5, add(inv_scaled_bounds_min, inv_scaled_bounds_max));
let inv_scaled_bounds_extent = sub(inv_scaled_bounds_max, inv_scaled_bounds_center);
let mut input = DistanceInput {
proxy_a: Default::default(),
proxy_b: local_proxy,
transform: TRANSFORM_IDENTITY,
use_radii: true,
};
let mut stack = [0i32; MESH_STACK_SIZE];
let mut count = 0usize;
let mut node_index = 0usize;
let data = shape.data;
let triangles = &data.triangles;
let vertices = &data.vertices;
loop {
let node = &data.nodes[node_index];
if test_bounds_overlap(
node.lower_bound,
node.upper_bound,
inv_scaled_bounds_min,
inv_scaled_bounds_max,
) {
if node.is_leaf() {
let triangle_count = node.triangle_count() as i32;
let triangle_offset = node.triangle_offset as i32;
for index in 0..triangle_count {
let triangle_index = triangle_offset + index;
let triangle = triangles[triangle_index as usize];
let vertex1 = vertices[triangle.index1 as usize];
let vertex2 = vertices[triangle.index2 as usize];
let vertex3 = vertices[triangle.index3 as usize];
if test_bounds_triangle_overlap(
inv_scaled_bounds_center,
inv_scaled_bounds_extent,
vertex1,
vertex2,
vertex3,
) {
let triangle_vertices = [
mul(mesh_scale, vertex1),
mul(mesh_scale, vertex2),
mul(mesh_scale, vertex3),
];
input.proxy_a = make_proxy(&triangle_vertices, 0.0);
cache.count = 0;
let output = shape_distance(&input, &mut cache, None);
let tolerance = 0.1 * linear_slop();
if output.distance < tolerance {
return true;
}
}
}
} else {
debug_assert!(count <= MESH_STACK_SIZE - 1);
stack[count] = node_index as i32 + node.child_offset() as i32;
count += 1;
node_index += 1;
continue;
}
}
if count == 0 {
break;
}
count -= 1;
node_index = stack[count] as usize;
}
false
}
pub fn get_mesh_triangle(mesh: &Mesh<'_>, triangle_index: i32) -> Triangle {
debug_assert!(0 <= triangle_index && triangle_index < mesh.data.triangle_count);
let triangles = &mesh.data.triangles;
let flags = &mesh.data.flags;
let vertices = &mesh.data.vertices;
let triangle = triangles[triangle_index as usize];
let triangle_flags = flags[triangle_index as usize];
let scale = mesh.scale;
let mut result = Triangle {
vertices: [Default::default(); 3],
i1: triangle.index1,
i2: 0,
i3: 0,
flags: 0,
};
result.vertices[0] = mul(scale, vertices[triangle.index1 as usize]);
if scale.x * scale.y * scale.z < 0.0 {
result.vertices[1] = mul(scale, vertices[triangle.index3 as usize]);
result.vertices[2] = mul(scale, vertices[triangle.index2 as usize]);
result.i2 = triangle.index3;
result.i3 = triangle.index2;
result.flags = 0;
if (triangle_flags as i32) & INVERSE_CONCAVE_EDGE1 != 0 {
result.flags |= CONCAVE_EDGE1;
}
if (triangle_flags as i32) & INVERSE_CONCAVE_EDGE2 != 0 {
result.flags |= CONCAVE_EDGE2;
}
if (triangle_flags as i32) & INVERSE_CONCAVE_EDGE3 != 0 {
result.flags |= CONCAVE_EDGE3;
}
} else {
result.vertices[1] = mul(scale, vertices[triangle.index2 as usize]);
result.vertices[2] = mul(scale, vertices[triangle.index3 as usize]);
result.i2 = triangle.index2;
result.i3 = triangle.index3;
result.flags = triangle_flags as i32;
}
result
}
pub fn collide_mover_and_mesh(
planes: &mut [PlaneResult],
shape: &Mesh<'_>,
mover: &Capsule,
) -> i32 {
let capacity = planes.len() as i32;
if capacity == 0 {
return 0;
}
let mut distance_input = DistanceInput {
proxy_a: Default::default(),
proxy_b: make_proxy(&[mover.center1, mover.center2], 0.0),
transform: TRANSFORM_IDENTITY,
use_radii: false,
};
let mut cache = SimplexCache::default();
let radius = mover.radius;
let r = Vec3 {
x: radius,
y: radius,
z: radius,
};
let bounds_min = sub(min(mover.center1, mover.center2), r);
let bounds_max = add(max(mover.center1, mover.center2), r);
let mesh_scale = shape.scale;
let inv_scale = Vec3 {
x: 1.0 / mesh_scale.x,
y: 1.0 / mesh_scale.y,
z: 1.0 / mesh_scale.z,
};
let temp1 = mul(inv_scale, bounds_min);
let temp2 = mul(inv_scale, bounds_max);
let inv_scaled_bounds_min = min(temp1, temp2);
let inv_scaled_bounds_max = max(temp1, temp2);
let inv_scaled_bounds_center = mul_sv(0.5, add(inv_scaled_bounds_min, inv_scaled_bounds_max));
let inv_scaled_bounds_extent = sub(inv_scaled_bounds_max, inv_scaled_bounds_center);
let mut stack = [0i32; MESH_STACK_SIZE];
let mut count = 0usize;
let mut node_index = 0usize;
let data = shape.data;
let triangles = &data.triangles;
let vertices = &data.vertices;
let mut plane_count = 0i32;
while plane_count < capacity {
let node = &data.nodes[node_index];
if test_bounds_overlap(
node.lower_bound,
node.upper_bound,
inv_scaled_bounds_min,
inv_scaled_bounds_max,
) {
if node.is_leaf() {
let triangle_count = node.triangle_count() as i32;
let triangle_offset = node.triangle_offset as i32;
for index in 0..triangle_count {
let triangle_index = triangle_offset + index;
let triangle = triangles[triangle_index as usize];
let vertex1 = vertices[triangle.index1 as usize];
let vertex2 = vertices[triangle.index2 as usize];
let vertex3 = vertices[triangle.index3 as usize];
if test_bounds_triangle_overlap(
inv_scaled_bounds_center,
inv_scaled_bounds_extent,
vertex1,
vertex2,
vertex3,
) {
let triangle_vertices = [
mul(mesh_scale, vertex1),
mul(mesh_scale, vertex2),
mul(mesh_scale, vertex3),
];
distance_input.proxy_a = make_proxy(&triangle_vertices, 0.0);
cache.count = 0;
let distance_output = shape_distance(&distance_input, &mut cache, None);
if distance_output.distance == 0.0 {
} else if distance_output.distance <= mover.radius {
let plane = Plane {
normal: distance_output.normal,
offset: mover.radius - distance_output.distance,
};
planes[plane_count as usize] = PlaneResult {
plane,
point: distance_output.point_a,
};
plane_count += 1;
if plane_count == capacity {
return plane_count;
}
}
}
}
} else {
debug_assert!(count <= MESH_STACK_SIZE - 1);
stack[count] = node_index as i32 + node.child_offset() as i32;
count += 1;
node_index += 1;
continue;
}
}
if count == 0 {
break;
}
count -= 1;
node_index = stack[count] as usize;
}
plane_count
}
pub fn query_mesh<F>(mesh: &Mesh<'_>, bounds: Aabb, mut fcn: F)
where
F: FnMut(Vec3, Vec3, Vec3, i32) -> bool,
{
let mesh_scale = mesh.scale;
let clockwise = mesh_scale.x * mesh_scale.y * mesh_scale.z > 0.0;
let inv_scale = Vec3 {
x: 1.0 / mesh_scale.x,
y: 1.0 / mesh_scale.y,
z: 1.0 / mesh_scale.z,
};
let temp1 = mul(inv_scale, bounds.lower_bound);
let temp2 = mul(inv_scale, bounds.upper_bound);
let inv_scaled_bounds_min = min(temp1, temp2);
let inv_scaled_bounds_max = max(temp1, temp2);
let inv_scaled_bounds_center = mul_sv(0.5, add(inv_scaled_bounds_min, inv_scaled_bounds_max));
let inv_scaled_bounds_extent = sub(inv_scaled_bounds_max, inv_scaled_bounds_center);
let data = mesh.data;
let mut stack = [0i32; MESH_STACK_SIZE];
let mut count = 0usize;
let mut node_index = 0usize;
let triangles = &data.triangles;
let vertices = &data.vertices;
loop {
let node = &data.nodes[node_index];
if test_bounds_overlap(
node.lower_bound,
node.upper_bound,
inv_scaled_bounds_min,
inv_scaled_bounds_max,
) {
if node.is_leaf() {
let triangle_count = node.triangle_count() as i32;
let triangle_offset = node.triangle_offset as i32;
for index in 0..triangle_count {
let triangle_index = triangle_offset + index;
let triangle = triangles[triangle_index as usize];
let vertex1 = vertices[triangle.index1 as usize];
let vertex2 = vertices[triangle.index2 as usize];
let vertex3 = vertices[triangle.index3 as usize];
if test_bounds_triangle_overlap(
inv_scaled_bounds_center,
inv_scaled_bounds_extent,
vertex1,
vertex2,
vertex3,
) {
let a = mul(mesh_scale, vertex1);
let (b, c) = if clockwise {
(mul(mesh_scale, vertex2), mul(mesh_scale, vertex3))
} else {
(mul(mesh_scale, vertex3), mul(mesh_scale, vertex2))
};
if !fcn(a, b, c, triangle_index) {
return;
}
}
}
} else {
debug_assert!(count <= MESH_STACK_SIZE - 1);
stack[count] = node_index as i32 + node.child_offset() as i32;
count += 1;
node_index += 1;
continue;
}
}
if count == 0 {
break;
}
count -= 1;
node_index = stack[count] as usize;
}
}