physics: implement precise width conversion
This commit is contained in:
engine/physics/src
@ -42,12 +42,12 @@ impl<T> Body<T>
|
|||||||
pub fn extrapolated_position(&self,time:Time<T>)->Planar64Vec3{
|
pub fn extrapolated_position(&self,time:Time<T>)->Planar64Vec3{
|
||||||
let dt=time-self.time;
|
let dt=time-self.time;
|
||||||
self.position
|
self.position
|
||||||
+(self.velocity*dt).map(|elem|elem.divide().fix_1())
|
+(self.velocity*dt).map(|elem|elem.divide().clamp_1())
|
||||||
+self.acceleration.map(|elem|(dt*dt*elem/2).divide().fix_1())
|
+self.acceleration.map(|elem|(dt*dt*elem/2).divide().clamp_1())
|
||||||
}
|
}
|
||||||
pub fn extrapolated_velocity(&self,time:Time<T>)->Planar64Vec3{
|
pub fn extrapolated_velocity(&self,time:Time<T>)->Planar64Vec3{
|
||||||
let dt=time-self.time;
|
let dt=time-self.time;
|
||||||
self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1())
|
self.velocity+(self.acceleration*dt).map(|elem|elem.divide().clamp_1())
|
||||||
}
|
}
|
||||||
pub fn advance_time(&mut self,time:Time<T>){
|
pub fn advance_time(&mut self,time:Time<T>){
|
||||||
self.position=self.extrapolated_position(time);
|
self.position=self.extrapolated_position(time);
|
||||||
@ -71,12 +71,12 @@ impl<T> Body<T>
|
|||||||
D2:Copy,
|
D2:Copy,
|
||||||
Planar64:core::ops::Mul<D2,Output=N4>,
|
Planar64:core::ops::Mul<D2,Output=N4>,
|
||||||
N4:integer::Divide<D2,Output=T1>,
|
N4:integer::Divide<D2,Output=T1>,
|
||||||
T1:integer::Fix<Planar64>,
|
T1:integer::Clamp<Planar64>,
|
||||||
{
|
{
|
||||||
// a*dt^2/2 + v*dt + p
|
// a*dt^2/2 + v*dt + p
|
||||||
// (a*dt/2+v)*dt+p
|
// (a*dt/2+v)*dt+p
|
||||||
(self.acceleration.map(|elem|dt*elem/2)+self.velocity).map(|elem|dt.mul_ratio(elem))
|
(self.acceleration.map(|elem|dt*elem/2)+self.velocity).map(|elem|dt.mul_ratio(elem))
|
||||||
.map(|elem|elem.divide().fix())+self.position
|
.map(|elem|elem.divide().clamp())+self.position
|
||||||
}
|
}
|
||||||
pub fn extrapolated_velocity_ratio_dt<Num,Den,N1,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3
|
pub fn extrapolated_velocity_ratio_dt<Num,Den,N1,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3
|
||||||
where
|
where
|
||||||
@ -85,10 +85,10 @@ impl<T> Body<T>
|
|||||||
Num:core::ops::Mul<Planar64,Output=N1>,
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
Planar64:core::ops::Mul<Den,Output=N1>,
|
Planar64:core::ops::Mul<Den,Output=N1>,
|
||||||
N1:integer::Divide<Den,Output=T1>,
|
N1:integer::Divide<Den,Output=T1>,
|
||||||
T1:integer::Fix<Planar64>,
|
T1:integer::Clamp<Planar64>,
|
||||||
{
|
{
|
||||||
// a*dt + v
|
// a*dt + v
|
||||||
self.acceleration.map(|elem|(dt*elem).divide().fix())+self.velocity
|
self.acceleration.map(|elem|(dt*elem).divide().clamp())+self.velocity
|
||||||
}
|
}
|
||||||
pub fn advance_time_ratio_dt(&mut self,dt:crate::model::GigaTime){
|
pub fn advance_time_ratio_dt(&mut self,dt:crate::model::GigaTime){
|
||||||
self.position=self.extrapolated_position_ratio_dt(dt);
|
self.position=self.extrapolated_position_ratio_dt(dt);
|
||||||
|
@ -63,7 +63,8 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref();
|
let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref();
|
||||||
//WARNING: d is moved out of the *2 block because of adding two vertices!
|
//WARNING: d is moved out of the *2 block because of adding two vertices!
|
||||||
//WARNING: precision is swept under the rug!
|
//WARNING: precision is swept under the rug!
|
||||||
for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){
|
//wrap for speed
|
||||||
|
for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
||||||
@ -84,7 +85,8 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
//edge_n gets parity from the order of edge_faces
|
//edge_n gets parity from the order of edge_faces
|
||||||
let n=face_n.cross(edge_n)*((i as i64)*2-1);
|
let n=face_n.cross(edge_n)*((i as i64)*2-1);
|
||||||
//WARNING yada yada d *2
|
//WARNING yada yada d *2
|
||||||
for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){
|
//wrap for speed
|
||||||
|
for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Face(edge_face_id),dt);
|
best_transition=Transition::Next(FEV::Face(edge_face_id),dt);
|
||||||
@ -98,7 +100,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
let n=edge_n*(1-2*(i as i64));
|
let n=edge_n*(1-2*(i as i64));
|
||||||
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4());
|
let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4());
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Vert(vert_id),dt);
|
best_transition=Transition::Next(FEV::Vert(vert_id),dt);
|
||||||
break;
|
break;
|
||||||
@ -114,7 +116,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
let n=-mesh.directed_edge_n(directed_edge_id);
|
let n=-mesh.directed_edge_n(directed_edge_id);
|
||||||
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4());
|
let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4());
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
||||||
break;
|
break;
|
||||||
@ -129,11 +131,11 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
|||||||
pub fn crawl(mut self,mesh:&M,relative_body:&Body,start_time:Time,time_limit:Time)->CrawlResult<M>{
|
pub fn crawl(mut self,mesh:&M,relative_body:&Body,start_time:Time,time_limit:Time)->CrawlResult<M>{
|
||||||
let mut body_time={
|
let mut body_time={
|
||||||
let r=(start_time-relative_body.time).to_ratio();
|
let r=(start_time-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
Ratio::new(r.num.widen_4(),r.den.widen_4())
|
||||||
};
|
};
|
||||||
let time_limit={
|
let time_limit={
|
||||||
let r=(time_limit-relative_body.time).to_ratio();
|
let r=(time_limit-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
Ratio::new(r.num.widen_4(),r.den.widen_4())
|
||||||
};
|
};
|
||||||
for _ in 0..20{
|
for _ in 0..20{
|
||||||
match self.next_transition(body_time,mesh,relative_body,time_limit){
|
match self.next_transition(body_time,mesh,relative_body,time_limit){
|
||||||
|
@ -378,8 +378,8 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{
|
|||||||
}
|
}
|
||||||
//assume face hash is stable, and there are no flush faces...
|
//assume face hash is stable, and there are no flush faces...
|
||||||
let face=Face{
|
let face=Face{
|
||||||
normal:(normal/len as i64).divide().fix_1(),
|
normal:(normal/len as i64).divide().narrow_1().unwrap(),
|
||||||
dot:(dot/(len*len) as i64).fix_1(),
|
dot:(dot/(len*len) as i64).narrow_1().unwrap(),
|
||||||
};
|
};
|
||||||
let face_id=match face_id_from_face.get(&face){
|
let face_id=match face_id_from_face.get(&face){
|
||||||
Some(&face_id)=>face_id,
|
Some(&face_id)=>face_id,
|
||||||
@ -519,7 +519,8 @@ impl MeshQuery for TransformedMesh<'_>{
|
|||||||
(transformed_n,transformed_d)
|
(transformed_n,transformed_d)
|
||||||
}
|
}
|
||||||
fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{
|
fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{
|
||||||
self.transform.vertex.transform_point3(self.view.vert(vert_id)).fix_1()
|
// wrap for speed
|
||||||
|
self.transform.vertex.transform_point3(self.view.vert(vert_id)).wrap_1()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn face_edges(&self,face_id:SubmeshFaceId)->impl AsRef<[SubmeshDirectedEdgeId]>{
|
fn face_edges(&self,face_id:SubmeshFaceId)->impl AsRef<[SubmeshDirectedEdgeId]>{
|
||||||
@ -659,7 +660,8 @@ impl MinkowskiMesh<'_>{
|
|||||||
if !d.is_negative()&&d<=edge_nn{
|
if !d.is_negative()&&d<=edge_nn{
|
||||||
let distance_squared={
|
let distance_squared={
|
||||||
let c=diff.cross(edge_n);
|
let c=diff.cross(edge_n);
|
||||||
(c.dot(c)/edge_nn).divide().fix_2()
|
//wrap for speed
|
||||||
|
(c.dot(c)/edge_nn).divide().wrap_2()
|
||||||
};
|
};
|
||||||
if distance_squared<=*best_distance_squared{
|
if distance_squared<=*best_distance_squared{
|
||||||
best_transition=EV::Edge(directed_edge_id.as_undirected());
|
best_transition=EV::Edge(directed_edge_id.as_undirected());
|
||||||
@ -764,7 +766,7 @@ impl MinkowskiMesh<'_>{
|
|||||||
};
|
};
|
||||||
let mut best_time={
|
let mut best_time={
|
||||||
let r=(time_limit-relative_body.time).to_ratio();
|
let r=(time_limit-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
Ratio::new(r.num.widen_4(),r.den.widen_4())
|
||||||
};
|
};
|
||||||
let mut best_edge=None;
|
let mut best_edge=None;
|
||||||
let face_n=self.face_nd(contact_face_id).0;
|
let face_n=self.face_nd(contact_face_id).0;
|
||||||
@ -776,7 +778,8 @@ impl MinkowskiMesh<'_>{
|
|||||||
let d=n.dot(self.vert(v0)+self.vert(v1));
|
let d=n.dot(self.vert(v0)+self.vert(v1));
|
||||||
//WARNING! d outside of *2
|
//WARNING! d outside of *2
|
||||||
//WARNING: truncated precision
|
//WARNING: truncated precision
|
||||||
for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).fix_4(),n.dot(relative_body.velocity).fix_4()*2,n.dot(relative_body.acceleration).fix_4()){
|
//wrap for speed
|
||||||
|
for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).wrap_4(),n.dot(relative_body.velocity).wrap_4()*2,n.dot(relative_body.acceleration).wrap_4()){
|
||||||
if start_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
if start_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||||
best_time=dt;
|
best_time=dt;
|
||||||
best_edge=Some(directed_edge_id);
|
best_edge=Some(directed_edge_id);
|
||||||
@ -822,7 +825,7 @@ impl MeshQuery for MinkowskiMesh<'_>{
|
|||||||
let n=edge0_n.cross(edge1_n);
|
let n=edge0_n.cross(edge1_n);
|
||||||
let e0d=n.dot(self.mesh0.vert(e0v0)+self.mesh0.vert(e0v1));
|
let e0d=n.dot(self.mesh0.vert(e0v0)+self.mesh0.vert(e0v1));
|
||||||
let e1d=n.dot(self.mesh1.vert(e1v0)+self.mesh1.vert(e1v1));
|
let e1d=n.dot(self.mesh1.vert(e1v0)+self.mesh1.vert(e1v1));
|
||||||
((n*(parity as i64*4-2)).fix_3(),((e0d-e1d)*(parity as i64*2-1)).fix_4())
|
((n*(parity as i64*4-2)).widen_3(),((e0d-e1d)*(parity as i64*2-1)).widen_4())
|
||||||
},
|
},
|
||||||
MinkowskiFace::FaceVert(f0,v1)=>{
|
MinkowskiFace::FaceVert(f0,v1)=>{
|
||||||
let (n,d)=self.mesh0.face_nd(f0);
|
let (n,d)=self.mesh0.face_nd(f0);
|
||||||
@ -954,7 +957,8 @@ impl MeshQuery for MinkowskiMesh<'_>{
|
|||||||
face_normals.clone_from(&v0f_n);
|
face_normals.clone_from(&v0f_n);
|
||||||
for face_n in &v1f_n{
|
for face_n in &v1f_n{
|
||||||
//add reflected mesh1 faces
|
//add reflected mesh1 faces
|
||||||
face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().fix_3());
|
//wrap for speed
|
||||||
|
face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().wrap_3());
|
||||||
}
|
}
|
||||||
if is_empty_volume(face_normals){
|
if is_empty_volume(face_normals){
|
||||||
edges.push(MinkowskiDirectedEdge::EdgeVert(directed_edge_id,v1));
|
edges.push(MinkowskiDirectedEdge::EdgeVert(directed_edge_id,v1));
|
||||||
@ -966,7 +970,8 @@ impl MeshQuery for MinkowskiMesh<'_>{
|
|||||||
let mut face_normals=Vec::with_capacity(the_len);
|
let mut face_normals=Vec::with_capacity(the_len);
|
||||||
face_normals.clone_from(&v1f_n);
|
face_normals.clone_from(&v1f_n);
|
||||||
for face_n in &v0f_n{
|
for face_n in &v0f_n{
|
||||||
face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().fix_3());
|
//wrap for speed
|
||||||
|
face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().wrap_3());
|
||||||
}
|
}
|
||||||
if is_empty_volume(face_normals){
|
if is_empty_volume(face_normals){
|
||||||
edges.push(MinkowskiDirectedEdge::VertEdge(v0,directed_edge_id));
|
edges.push(MinkowskiDirectedEdge::VertEdge(v0,directed_edge_id));
|
||||||
@ -1008,6 +1013,6 @@ fn is_empty_volume(normals:Vec<Vector3<Fixed<3,96>>>)->bool{
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_empty_volume(){
|
fn test_is_empty_volume(){
|
||||||
assert!(!is_empty_volume([vec3::X.fix_3(),vec3::Y.fix_3(),vec3::Z.fix_3()].to_vec()));
|
assert!(!is_empty_volume([vec3::X.widen_3(),vec3::Y.widen_3(),vec3::Z.widen_3()].to_vec()));
|
||||||
assert!(is_empty_volume([vec3::X.fix_3(),vec3::Y.fix_3(),vec3::Z.fix_3(),vec3::NEG_X.fix_3()].to_vec()));
|
assert!(is_empty_volume([vec3::X.widen_3(),vec3::Y.widen_3(),vec3::Z.widen_3(),vec3::NEG_X.widen_3()].to_vec()));
|
||||||
}
|
}
|
||||||
|
@ -117,8 +117,8 @@ impl TransientAcceleration{
|
|||||||
}else{
|
}else{
|
||||||
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
||||||
TransientAcceleration::Reachable{
|
TransientAcceleration::Reachable{
|
||||||
acceleration:target_diff.with_length(accel).divide().fix_1(),
|
acceleration:target_diff.with_length(accel).divide().wrap_1(),
|
||||||
time:time+Time::from((target_diff.length()/accel).divide().fix_1())
|
time:time+Time::from((target_diff.length()/accel).divide().clamp_1())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,7 +407,7 @@ impl HitboxMesh{
|
|||||||
let transform=PhysicsMeshTransform::new(transform);
|
let transform=PhysicsMeshTransform::new(transform);
|
||||||
let transformed_mesh=TransformedMesh::new(mesh.complete_mesh_view(),&transform);
|
let transformed_mesh=TransformedMesh::new(mesh.complete_mesh_view(),&transform);
|
||||||
for vert in transformed_mesh.verts(){
|
for vert in transformed_mesh.verts(){
|
||||||
aabb.grow(vert.fix_1());
|
aabb.grow(vert.narrow_1().unwrap());
|
||||||
}
|
}
|
||||||
Self{
|
Self{
|
||||||
halfsize:aabb.size()>>1,
|
halfsize:aabb.size()>>1,
|
||||||
@ -460,12 +460,12 @@ impl StyleHelper for StyleModifiers{
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
||||||
(camera.rotation_y()*self.get_control_dir(controls)).fix_1()
|
(camera.rotation_y()*self.get_control_dir(controls)).wrap_1()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_propulsion_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
fn get_propulsion_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{
|
||||||
//don't interpolate this! discrete mouse movement, constant acceleration
|
//don't interpolate this! discrete mouse movement, constant acceleration
|
||||||
(camera.rotation()*self.get_control_dir(controls)).fix_1()
|
(camera.rotation()*self.get_control_dir(controls)).wrap_1()
|
||||||
}
|
}
|
||||||
fn calculate_mesh(&self)->HitboxMesh{
|
fn calculate_mesh(&self)->HitboxMesh{
|
||||||
let mesh=match self.hitbox.mesh{
|
let mesh=match self.hitbox.mesh{
|
||||||
@ -1084,7 +1084,7 @@ impl PhysicsData{
|
|||||||
let mut aabb=aabb::Aabb::default();
|
let mut aabb=aabb::Aabb::default();
|
||||||
let transformed_mesh=TransformedMesh::new(view,transform);
|
let transformed_mesh=TransformedMesh::new(view,transform);
|
||||||
for v in transformed_mesh.verts(){
|
for v in transformed_mesh.verts(){
|
||||||
aabb.grow(v.fix_1());
|
aabb.grow(v.narrow_1().unwrap());
|
||||||
}
|
}
|
||||||
(ConvexMeshId{
|
(ConvexMeshId{
|
||||||
model_id,
|
model_id,
|
||||||
@ -1162,7 +1162,8 @@ fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&Contact
|
|||||||
let model_mesh=models.contact_mesh(contact);
|
let model_mesh=models.contact_mesh(contact);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||||
// TODO: normalize to i64::MAX>>1
|
// TODO: normalize to i64::MAX>>1
|
||||||
minkowski.face_nd(contact.face_id).0.fix_1()
|
// wrap for speed
|
||||||
|
minkowski.face_nd(contact.face_id).0.wrap_1()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recalculate_touching(
|
fn recalculate_touching(
|
||||||
@ -1321,7 +1322,7 @@ fn teleport_to_spawn(
|
|||||||
const EPSILON:Planar64=Planar64::raw((1<<32)/16);
|
const EPSILON:Planar64=Planar64::raw((1<<32)/16);
|
||||||
let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?;
|
let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?;
|
||||||
//TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation
|
//TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation
|
||||||
let point=transform.vertex.transform_point3(vec3::Y).fix_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]);
|
let point=transform.vertex.transform_point3(vec3::Y).clamp_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]);
|
||||||
teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time);
|
teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1485,7 +1486,7 @@ fn collision_start_contact(
|
|||||||
Some(gameplay_attributes::ContactingBehaviour::Surf)=>(),
|
Some(gameplay_attributes::ContactingBehaviour::Surf)=>(),
|
||||||
Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
||||||
&Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{
|
&Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{
|
||||||
let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).fix_1();
|
let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).wrap_1();
|
||||||
set_velocity(body,touching,models,hitbox_mesh,reflected_velocity);
|
set_velocity(body,touching,models,hitbox_mesh,reflected_velocity);
|
||||||
},
|
},
|
||||||
Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=>
|
Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=>
|
||||||
@ -1708,7 +1709,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
|
|||||||
let control_dir=state.style.get_control_dir(masked_controls);
|
let control_dir=state.style.get_control_dir(masked_controls);
|
||||||
if control_dir!=vec3::ZERO{
|
if control_dir!=vec3::ZERO{
|
||||||
let camera_mat=state.camera.simulate_move_rotation_y(state.input_state.lerp_delta(state.time).x);
|
let camera_mat=state.camera.simulate_move_rotation_y(state.input_state.lerp_delta(state.time).x);
|
||||||
if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().fix_1()){
|
if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().wrap_1()){
|
||||||
//this is wrong but will work ig
|
//this is wrong but will work ig
|
||||||
//need to note which push planes activate in push solve and keep those
|
//need to note which push planes activate in push solve and keep those
|
||||||
state.cull_velocity(data,ticked_velocity);
|
state.cull_velocity(data,ticked_velocity);
|
||||||
|
@ -152,18 +152,19 @@ const fn get_push_ray_0(point:Planar64Vec3)->Ray{
|
|||||||
Ray{origin:point,direction:vec3::ZERO}
|
Ray{origin:point,direction:vec3::ZERO}
|
||||||
}
|
}
|
||||||
fn get_push_ray_1(point:Planar64Vec3,c0:&Contact)->Option<Ray>{
|
fn get_push_ray_1(point:Planar64Vec3,c0:&Contact)->Option<Ray>{
|
||||||
let direction=solve1(c0)?.divide().fix_1();
|
//wrap for speed
|
||||||
|
let direction=solve1(c0)?.divide().wrap_1();
|
||||||
let [s0]=decompose1(direction,c0.velocity)?;
|
let [s0]=decompose1(direction,c0.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let origin=point+solve1(
|
let origin=point+solve1(
|
||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
)?.divide().fix_1();
|
)?.divide().wrap_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
||||||
let direction=solve2(c0,c1)?.divide().fix_1();
|
let direction=solve2(c0,c1)?.divide().wrap_1();
|
||||||
let [s0,s1]=decompose2(direction,c0.velocity,c1.velocity)?;
|
let [s0,s1]=decompose2(direction,c0.velocity,c1.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
@ -171,11 +172,11 @@ fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{
|
|||||||
let origin=point+solve2(
|
let origin=point+solve2(
|
||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
&c1.relative_to(point),
|
&c1.relative_to(point),
|
||||||
)?.divide().fix_1();
|
)?.divide().wrap_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Option<Ray>{
|
fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Option<Ray>{
|
||||||
let direction=solve3(c0,c1,c2)?.divide().fix_1();
|
let direction=solve3(c0,c1,c2)?.divide().wrap_1();
|
||||||
let [s0,s1,s2]=decompose3(direction,c0.velocity,c1.velocity,c2.velocity)?;
|
let [s0,s1,s2]=decompose3(direction,c0.velocity,c1.velocity,c2.velocity)?;
|
||||||
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO)||s2.lt_ratio(RATIO_ZERO){
|
if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO)||s2.lt_ratio(RATIO_ZERO){
|
||||||
return None;
|
return None;
|
||||||
@ -184,7 +185,7 @@ fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Optio
|
|||||||
&c0.relative_to(point),
|
&c0.relative_to(point),
|
||||||
&c1.relative_to(point),
|
&c1.relative_to(point),
|
||||||
&c2.relative_to(point),
|
&c2.relative_to(point),
|
||||||
)?.divide().fix_1();
|
)?.divide().wrap_1();
|
||||||
Some(Ray{origin,direction})
|
Some(Ray{origin,direction})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user