use crate::helper::array_flatslice;
use crate::{obj, ObjectId, VertexId};
pub fn mj_multiRay<const N_RAY: usize>(
m: &crate::mjModel,
d: &mut crate::mjData,
pnt: [f64; 3],
vec: [[f64; 3]; N_RAY],
geomgroup: Option<&[u8]>,
flg_static: bool,
bodyexclude: i32,
cutoff: f64,
) -> Vec<Option<(ObjectId::<obj::Geom>, f64)>> {
let mut geomid = vec![-1; N_RAY];
let mut dist = vec![-1.0; N_RAY];
unsafe {
crate::bindgen::mj_multiRay(
m.as_ptr(),
d.as_mut_ptr(),
&pnt,
vec.as_ptr(),
geomgroup.map_or(std::ptr::null(), |g| g.as_ptr()),
flg_static as u8,
bodyexclude,
geomid.as_mut_ptr(),
dist.as_mut_ptr(),
N_RAY as i32,
cutoff,
)
}
Iterator::zip(geomid.into_iter(), dist.into_iter()).map(|(geomid, dist)| {
if geomid < 0 || dist < 0.0 {
None
} else {
Some((unsafe { ObjectId::new_unchecked(geomid as usize) }, dist))
}
}).collect()
}
pub fn mj_ray(
m: &crate::mjModel,
d: &crate::mjData,
pnt: [f64; 3],
vec: [f64; 3],
geomgroup: Option<[bool; crate::bindgen::mjNGROUP as usize]>,
flg_static: bool,
bodyexclude: ObjectId<obj::Body>,
) -> Option<(ObjectId<obj::Geom>, f64)> {
let geomgroup = geomgroup.map(|geomgroup| geomgroup.map(|bool| bool as u8));
let mut geomid = [-1];
let distance = unsafe {
crate::bindgen::mj_ray(
m.as_ptr(),
d.as_ptr(),
&pnt,
&vec,
geomgroup.map_or(std::ptr::null(), |gg| gg.as_ptr()),
flg_static as u8,
bodyexclude.index() as i32,
&mut geomid,
)
};
if geomid[0] < 0 || distance < 0.0 {
None
} else {
Some((unsafe { ObjectId::new_unchecked(geomid[0] as usize) }, distance))
}
}
pub fn mj_rayHfield(
m: &crate::mjModel,
d: &crate::mjData,
geomid: ObjectId<obj::Geom>,
pnt: [f64; 3],
vec: [f64; 3],
) -> Option<f64> {
let distance = unsafe {
crate::bindgen::mj_rayHfield(
m.as_ptr(),
d.as_ptr(),
geomid.index() as i32,
&pnt,
&vec,
)
};
if distance < 0.0 {
None
} else {
Some(distance)
}
}
pub fn mj_rayMesh(
m: &crate::mjModel,
d: &crate::mjData,
geomid: ObjectId<obj::Geom>,
pnt: [f64; 3],
vec: [f64; 3],
) -> Option<f64> {
let distance = unsafe {
crate::bindgen::mj_rayMesh(
m.as_ptr(),
d.as_ptr(),
geomid.index() as i32,
&pnt,
&vec,
)
};
if distance < 0.0 {
None
} else {
Some(distance)
}
}
pub fn mju_rayGeom(
pos: [f64; 3],
mat: [f64; 9],
size: [f64; 3],
pnt: [f64; 3],
vec: [f64; 3],
geomtype: crate::bindgen::mjtGeom,
) -> Option<f64> {
let distance = unsafe {
crate::bindgen::mju_rayGeom(
&pos,
&mat,
&size,
&pnt,
&vec,
geomtype.0 as i32,
)
};
if distance < 0.0 {
None
} else {
Some(distance)
}
}
pub fn mju_rayFlex(
m: &crate::mjModel,
d: &crate::mjData,
flex_layer: Option<usize>,
flg_vert: bool,
flg_edge: bool,
flg_face: bool,
flg_skin: bool,
flexid: ObjectId<obj::Flex>,
pnt: [f64; 3],
vec: [f64; 3],
) -> Option<(VertexId<obj::Flex>, f64)> {
let mut vertid = [-1];
let distance = unsafe {
crate::bindgen::mju_rayFlex(
m.as_ptr(),
d.as_ptr(),
flex_layer.map_or(-1, |l| l as i32),
flg_vert as u8,
flg_edge as u8,
flg_face as u8,
flg_skin as u8,
flexid.index() as i32,
&pnt,
&vec,
&mut vertid,
)
};
if vertid[0] < 0 || distance < 0.0 {
None
} else {
Some((unsafe { VertexId::<obj::Flex>::new_unchecked(vertid[0] as usize) }, distance))
}
}
pub fn mju_raySkin<const N_FACE: usize, const N_VERT: usize>(
face_indices: [[usize; 3]; N_FACE],
vert_coordinates: [[f32; 3]; N_VERT],
pnt: [f64; 3],
vec: [f64; 3],
) -> Option<(VertexId<obj::Mesh>, f64)> {
let vert_coordinates: &[f32] = array_flatslice(&vert_coordinates);
let face_indices: &[usize] = array_flatslice(&face_indices);
let face_indices: Vec<i32> = face_indices.iter().map(|&i| i as i32).collect();
let mut vertid = [-1];
let distance = unsafe {
crate::bindgen::mju_raySkin(
N_FACE as i32,
N_VERT as i32,
face_indices.as_ptr(),
vert_coordinates.as_ptr(),
&pnt,
&vec,
&mut vertid,
)
};
if vertid[0] < 0 || distance < 0.0 {
None
} else {
Some((unsafe { VertexId::<obj::Mesh>::new_unchecked(vertid[0] as usize) }, distance))
}
}