Compare commits

...

6 Commits

Author SHA1 Message Date
8801a82ee9 negative everything 2025-11-26 13:20:56 -08:00
9c4e49ce15 make hint_point consistent with vert 2025-11-26 12:30:06 -08:00
fee511e0db load source once at runtime 2025-11-26 11:47:53 -08:00
c57423553a fix it 2025-11-26 11:29:46 -08:00
9f5af7060f implement lua 2025-11-26 11:09:59 -08:00
6ef2e41421 add mlua 2025-11-26 11:09:59 -08:00
6 changed files with 189 additions and 26 deletions

14
Cargo.lock generated
View File

@@ -1974,9 +1974,9 @@ dependencies = [
[[package]]
name = "luau0-src"
version = "0.15.11+luau697"
version = "0.17.0+luau701"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdbf698d77af7b846fab212ca666c5d597b9ff445ef1a647e181d3392e13dfdf"
checksum = "ed8f8edd8aba9654a9eeb62b2fe7461589f2faf2d0a1bc04bd64c0123319b3fc"
dependencies = [
"cc",
]
@@ -2149,12 +2149,13 @@ dependencies = [
[[package]]
name = "mlua"
version = "0.11.4"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be1c2bfc684b8a228fbaebf954af7a47a98ec27721986654a4cc2c40a20cc7e"
checksum = "935ac67539907efcd7198137eb7358e052555f77fe1b2916600a2249351f2b33"
dependencies = [
"bstr",
"either",
"libc",
"mlua-sys",
"num-traits",
"parking_lot",
@@ -2164,9 +2165,9 @@ dependencies = [
[[package]]
name = "mlua-sys"
version = "0.8.3"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d4dc9cfc5a7698899802e97480617d9726f7da78c910db989d4d0fd4991d900"
checksum = "8c968af21bf6b19fc9ca8e7b85ee16f86e4c9e3d0591de101a5608086bda0ad8"
dependencies = [
"cc",
"cfg-if",
@@ -3814,6 +3815,7 @@ dependencies = [
"arrayvec",
"glam",
"id",
"mlua",
"strafesnet_common",
]

View File

@@ -7,6 +7,7 @@ edition = "2024"
arrayvec = "0.7.6"
glam = "0.30.0"
id = { version = "0.1.0", registry = "strafesnet" }
mlua = { version = "0.11.5", features = ["luau"] }
strafesnet_common = { path = "../../lib/common", registry = "strafesnet" }
[lints]

View File

@@ -3,6 +3,7 @@ mod face_crawler;
mod model;
mod push_solve;
mod minimum_difference;
mod minimum_difference_lua;
pub mod physics;

View File

@@ -103,7 +103,7 @@ fn reduce1(
)->Reduced{
// --debug.profilebegin("reduceSimplex0")
// local a = a1 - a0
let p0=mesh.vert(v0);
let p0=-mesh.vert(v0);
// local p = -a
let p=-(p0+point);
@@ -133,8 +133,8 @@ fn reduce2(
// --debug.profilebegin("reduceSimplex1")
// local a = a1 - a0
// local b = b1 - b0
let p0=mesh.vert(v0);
let p1=mesh.vert(v1);
let p0=-mesh.vert(v0);
let p1=-mesh.vert(v1);
// local p = -a
// local u = b - a
@@ -191,9 +191,9 @@ fn reduce3(
// local a = a1 - a0
// local b = b1 - b0
// local c = c1 - c0
let p0=mesh.vert(v0);
let p1=mesh.vert(v1);
let p2=mesh.vert(v2);
let p0=-mesh.vert(v0);
let p1=-mesh.vert(v1);
let p2=-mesh.vert(v2);
// local p = -a
// local u = b - a
@@ -301,10 +301,10 @@ fn reduce4(
// local b = b1 - b0
// local c = c1 - c0
// local d = d1 - d0
let p0=mesh.vert(v0);
let p1=mesh.vert(v1);
let p2=mesh.vert(v2);
let p3=mesh.vert(v3);
let p0=-mesh.vert(v0);
let p1=-mesh.vert(v1);
let p2=-mesh.vert(v2);
let p3=-mesh.vert(v3);
// local p = -a
// local u = b - a
@@ -593,14 +593,14 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T>(
// local new_point_p = queryP(initialAxis)
// local new_point_q = queryQ(-initialAxis)
// local direction, a0, a1, b0, b1, c0, c1, d0, d1
let mut direction=mesh.hint_point()+point;
let mut initial_axis=-mesh.hint_point()+point;
// degenerate case
if direction==vec3::zero(){
direction=choose_any_direction();
if initial_axis==vec3::zero(){
initial_axis=choose_any_direction();
}
let last_point=mesh.farthest_vert(direction);
// this represents the 'a' value in the commented code
let mut last_pos=mesh.vert(last_point);
let mut last_pos=-mesh.vert(last_point);
let Reduced{dir:mut direction,simplex:mut simplex_small}=reduce1([last_point],mesh,point);
// exitRadius = testIntersection and 0 or exitRadius or 1/0
@@ -610,7 +610,7 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T>(
// new_point_q = queryQ(direction)
// local next_point = new_point_q - new_point_p
let next_point=mesh.farthest_vert(-direction);
let next_pos=mesh.vert(next_point);
let next_pos=-mesh.vert(next_point);
// if -direction:Dot(next_point) > (exitRadius + radiusP + radiusQ)*direction.magnitude then
if ENABLE_FAST_FAIL&&direction.dot(next_pos+point).is_negative(){

View File

@@ -0,0 +1,159 @@
use mlua::{Lua,FromLuaMulti,IntoLuaMulti,Function,Result as LuaResult,Vector};
use strafesnet_common::integer::{Planar64,Planar64Vec3,FixedFromFloatError};
use crate::model::{MeshQuery,MinkowskiMesh};
pub fn contains_point(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
)->LuaResult<bool>{
Ok(minimum_difference(mesh,point,true)?.hits)
}
pub fn minimum_difference_details(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
)->LuaResult<(bool,Details)>{
let md=minimum_difference(mesh,point,false)?;
Ok((md.hits,md.details.unwrap()))
}
fn p64v3(v:Vector)->Result<Planar64Vec3,FixedFromFloatError>{
Ok(Planar64Vec3::new([
v.x().try_into()?,
v.y().try_into()?,
v.z().try_into()?,
]))
}
fn vec(v:Planar64Vec3)->Vector{
Vector::new(v.x.into(),v.y.into(),v.z.into())
}
struct MinimumDifference{
hits:bool,
details:Option<Details>
}
pub struct Details{
pub distance:Planar64,
pub p_pos:Planar64Vec3,
pub p_norm:Planar64Vec3,
pub q_pos:Planar64Vec3,
pub q_norm:Planar64Vec3,
}
impl FromLuaMulti for MinimumDifference{
fn from_lua_multi(mut values:mlua::MultiValue,_lua:&Lua)->LuaResult<Self>{
match values.make_contiguous(){
&mut [
mlua::Value::Boolean(hits),
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
]=>Ok(Self{hits,details:None}),
&mut [
mlua::Value::Boolean(hits),
mlua::Value::Number(distance),
mlua::Value::Vector(p_pos),
mlua::Value::Vector(p_norm),
mlua::Value::Vector(q_pos),
mlua::Value::Vector(q_norm),
]=>Ok(Self{
hits,
details:Some(Details{
distance:distance.try_into().unwrap(),
p_pos:p64v3(p_pos).unwrap(),
p_norm:p64v3(p_norm).unwrap(),
q_pos:p64v3(q_pos).unwrap(),
q_norm:p64v3(q_norm).unwrap(),
}),
}),
values=>Err(mlua::Error::runtime(format!("Invalid return values: {values:?}"))),
}
}
}
struct Args{
query_p:Function,
radius_p:f64,
query_q:Function,
radius_q:f64,
exit_radius:f64,
test_intersection:bool,
}
impl Args{
fn new(
lua:&Lua,
mesh:&'static MinkowskiMesh<'static>,
point:Planar64Vec3,
test_intersection:bool,
)->LuaResult<Self>{
let radius_p=0.0;
let radius_q=0.0;
let exit_radius=0.0;
// Query the farthest point on the mesh in the given direction.
let query_p=lua.create_function(move|_,dir:Option<Vector>|{
let Some(dir)=dir else{
return Ok(vec(mesh.mesh0.hint_point()));
};
let dir=p64v3(dir).unwrap();
let vert_id=mesh.mesh0.farthest_vert(dir);
let dir=mesh.mesh0.vert(vert_id);
Ok(vec(dir))
})?;
// query_q is different since it includes the test point offset.
let query_q=lua.create_function(move|_,dir:Option<Vector>|{
let Some(dir)=dir else{
return Ok(vec(mesh.mesh1.hint_point()+point));
};
let dir=p64v3(dir).unwrap();
let vert_id=mesh.mesh1.farthest_vert(dir);
let dir=mesh.mesh1.vert(vert_id)+point;
Ok(vec(dir))
})?;
Ok(Args{
query_p,
radius_p,
query_q,
radius_q,
exit_radius,
test_intersection,
})
}
}
impl IntoLuaMulti for Args{
fn into_lua_multi(self,lua:&Lua)->LuaResult<mlua::MultiValue>{
use mlua::IntoLua;
Ok(mlua::MultiValue::from_vec(vec![
self.query_p.into_lua(lua)?,
self.radius_p.into_lua(lua)?,
self.query_q.into_lua(lua)?,
self.radius_q.into_lua(lua)?,
self.exit_radius.into_lua(lua)?,
self.test_intersection.into_lua(lua)?,
]))
}
}
fn minimum_difference(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
test_intersection:bool,
)->LuaResult<MinimumDifference>{
let ctx=init_lua()?;
// SAFETY: mesh lifetime must outlive args usages
let mesh=unsafe{core::mem::transmute(mesh)};
let args=Args::new(&ctx.lua,mesh,point,test_intersection)?;
ctx.f.call(args)
}
struct Ctx{
lua:Lua,
f:Function,
}
fn init_lua()->LuaResult<Ctx>{
static SOURCE:std::sync::LazyLock<String>=std::sync::LazyLock::new(||std::fs::read_to_string("/home/quat/strafesnet/game/src/ReplicatedStorage/Shared/Trey-MinimumDifference.lua").unwrap());
let lua=Lua::new();
lua.sandbox(true)?;
let lib_f=lua.load(SOURCE.as_str()).set_name("Trey-MinimumDifference").into_function()?;
let lib:mlua::Table=lib_f.call(())?;
let f=lib.raw_get("difference")?;
Ok(Ctx{lua,f})
}

View File

@@ -619,8 +619,8 @@ pub enum MinkowskiFace{
#[derive(Debug)]
pub struct MinkowskiMesh<'a>{
mesh0:TransformedMesh<'a>,
mesh1:TransformedMesh<'a>,
pub mesh0:TransformedMesh<'a>,
pub mesh1:TransformedMesh<'a>,
}
//infinity fev algorithm state transition
@@ -811,8 +811,9 @@ impl MinkowskiMesh<'_>{
best_edge
}
pub fn contains_point(&self,point:Planar64Vec3)->bool{
let contains_point_lua=crate::minimum_difference_lua::contains_point(self,point).unwrap();
let contains_point=crate::minimum_difference::contains_point(self,point);
println!("contains_point={contains_point}");
println!("contains_point={contains_point} contains_point_lua={contains_point_lua}");
contains_point
}
}
@@ -853,8 +854,7 @@ impl MeshQuery for MinkowskiMesh<'_>{
}
}
fn hint_point(&self)->Planar64Vec3{
self.mesh1.transform.vertex.translation-
self.mesh0.transform.vertex.translation
self.mesh0.transform.vertex.translation-self.mesh1.transform.vertex.translation
}
fn face_edges(&self,face_id:MinkowskiFace)->impl AsRef<[MinkowskiDirectedEdge]>{
match face_id{