This commit is contained in:
Orion Kindel
2025-01-25 16:51:12 -06:00
parent 1c9f5ff544
commit bc29eddb0e
9 changed files with 106 additions and 127 deletions

View File

@@ -22,7 +22,7 @@ use nalgebra::Vector3;
use rapier3d::prelude::*;
use crate::body::{self, Body};
use crate::debug_render::{DebugRenderPipelineResource, RapierDebugRenderPlugin};
use crate::debug_render::DebugRenderPipelineResource;
use crate::either::Either;
use crate::mesh::Mesh;
use crate::physics::PhysicsState;
@@ -93,7 +93,7 @@ impl State {
pub fn setup_bodies(&self) -> &[(String, BevyEntity)] {
match self {
| Self::Setup { bodies, .. } => &bodies,
| Self::Setup { bodies, .. } => bodies,
| _ => unreachable!(),
}
}
@@ -134,7 +134,10 @@ impl State {
pub fn setup_done(self, ctx: &mut Ctx) -> Self {
match self {
| Self::Setup { debug_render, bodies, freq, .. } => {
| Self::Setup { debug_render,
bodies,
freq,
.. } => {
for (_, id) in bodies.iter() {
ctx.commands.entity(*id).insert(body::building::Commit);
}
@@ -170,41 +173,41 @@ impl SetupView {
| SetupView::Spawn(a) => a.render(ui, ctx),
| SetupView::Init => {
ui.vertical(|ui| {
ui.label("Entities");
let bodies = ctx.state.setup_bodies();
let mut selected: Option<BevyEntity> = None;
ComboBox::from_id_salt("choose_entity").show_ui(ui, |ui| {
bodies.iter().for_each(|(name, ent)| {
ui.label("Entities");
let bodies = ctx.state.setup_bodies();
let mut selected: Option<BevyEntity> = None;
ComboBox::from_id_salt("choose_entity").show_ui(ui, |ui| {
bodies.iter().for_each(|(name, ent)| {
ui.selectable_value(&mut selected,
Some(*ent),
name);
});
});
});
if let Some(ent) = selected {
ctx.state.setup_nav(SetupView::Transform { ent,
scale_uniform: true });
}
if let Some(ent) = selected {
ctx.state.setup_nav(SetupView::Transform { ent,
scale_uniform: true });
}
if button!(ui, "+ Spawn", heading).clicked() {
ctx.state.setup_nav(SetupView::Spawn(Default::default()));
}
if button!(ui, "+ Spawn", heading).clicked() {
ctx.state.setup_nav(SetupView::Spawn(Default::default()));
}
ui.separator();
ui.horizontal(|ui| {
ui.label("Physics Step Frequency (hz)");
ui.add(DragValue::new(ctx.state.setup_freq()));
});
ui.separator();
ui.horizontal(|ui| {
ui.label("Physics Step Frequency (hz)");
ui.add(DragValue::new(ctx.state.setup_freq()));
});
ui.horizontal(|ui| {
ui.checkbox(&mut ctx.state.setup_debug_render(), "Debug Render");
});
ui.horizontal(|ui| {
ui.checkbox(ctx.state.setup_debug_render(), "Debug Render");
});
ui.separator();
ui.separator();
if button!(ui, "Done", heading).clicked() {
*ctx.state = core::mem::take(ctx.state.deref_mut()).setup_done(ctx);
}
if button!(ui, "Done", heading).clicked() {
*ctx.state = core::mem::take(ctx.state.deref_mut()).setup_done(ctx);
}
});
},
| SetupView::Error(err) => {
@@ -561,10 +564,9 @@ pub fn render(mut ctx: Ctx, mut egui: Query<&mut EguiContext>) {
button!(ui, "Load File", heading).clicked();
if button!(ui, "+ New", heading).clicked() {
*ctx.state = State::Setup {
freq: 60.0,
debug_render: false,
bodies: Default::default(),
*ctx.state = State::Setup { freq: 60.0,
debug_render: false,
bodies: Default::default(),
view: SetupView::Init };
}
});

View File

@@ -129,7 +129,6 @@ pub mod building {
pub mod physics {
use bevy::prelude as bevy;
use nalgebra::Vector3;
use rapier3d::prelude as rapier;
use crate::mesh::TriMesh;

View File

@@ -4,8 +4,7 @@ use bevy::color::Color;
use bevy::prelude::{Gizmos, Query, ResMut, Resource, Transform};
use nalgebra::{SimdValue, Vector3};
use rapier3d::math::Point;
use rapier3d::prelude::{Aabb,
DebugRenderBackend,
use rapier3d::prelude::{DebugRenderBackend,
DebugRenderMode,
DebugRenderObject,
DebugRenderPipeline,

View File

@@ -1,6 +1,5 @@
use fixed::types::{I24F8, I32F32};
use nalgebra::{Scale3, UnitQuaternion, Vector3};
use parry3d::query::sat::cuboid_segment_find_local_separating_edge_twoway;
use rapier3d::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{Deserialize, Serialize};
@@ -413,13 +412,13 @@ impl Bones {
.filter_map(|(ix_, (_, bh, bt, _, _))| {
if ix_ == ix {
None
} else if !ahl.contains(&ix_) && ah.relative_eq(&bh, 1e-2, f32::EPSILON) {
} else if !ahl.contains(&ix_) && ah.relative_eq(bh, 1e-2, f32::EPSILON) {
Some((Link::HH, ix_))
} else if !atl.contains(&ix_) && at.relative_eq(&bh, 1e-2, f32::EPSILON) {
} else if !atl.contains(&ix_) && at.relative_eq(bh, 1e-2, f32::EPSILON) {
Some((Link::TH, ix_))
} else if !ahl.contains(&ix_) && ah.relative_eq(&bt, 1e-2, f32::EPSILON) {
} else if !ahl.contains(&ix_) && ah.relative_eq(bt, 1e-2, f32::EPSILON) {
Some((Link::HT, ix_))
} else if !atl.contains(&ix_) && at.relative_eq(&bt, 1e-2, f32::EPSILON) {
} else if !atl.contains(&ix_) && at.relative_eq(bt, 1e-2, f32::EPSILON) {
Some((Link::TT, ix_))
} else {
None
@@ -430,11 +429,7 @@ impl Bones {
#[allow(clippy::type_complexity)]
fn build_graph(ix: usize,
bones: &mut [(&str,
Vector3<f32>,
Vector3<f32>,
Vec<usize>,
Vec<usize>)]) {
bones: &mut [(&str, Vector3<f32>, Vector3<f32>, Vec<usize>, Vec<usize>)]) {
for (link, other) in new_links(ix, bones) {
match link {
| Link::HT => {

View File

@@ -1,8 +1,7 @@
use std::collections::VecDeque;
use std::sync::LazyLock;
use ::bevy::prelude::{Cuboid, Meshable};
use ::bevy::render::mesh::{Indices, MeshVertexAttribute, VertexAttributeValues};
use ::bevy::prelude::Meshable;
use ::bevy::render::mesh::{Indices, VertexAttributeValues};
use bevy::prelude as bevy;
use itertools::Itertools;
use nalgebra::{vector, Point, Vector3};
@@ -149,64 +148,57 @@ impl Prefab {
let tri = self.trimesh();
let msh = Mesh::from_trimesh(&tri.vertices, &tri.faces, Some(0.01));
let mut bones = FxHashMap::default();
let center = BoneVertex {
x: 0.0,
y: 0.0,
z: 0.0,
};
let center = BoneVertex { x: 0.0,
y: 0.0,
z: 0.0 };
let bone_points = vec![
vector![0.4, 0.4, 0.4],
vector![0.4, 0.4, -0.4],
vector![-0.4, 0.4, 0.4],
vector![-0.4, 0.4, -0.4],
vector![0.4, -0.4, 0.4],
vector![0.4, -0.4, -0.4],
vector![-0.4, -0.4, 0.4],
vector![-0.4, -0.4, -0.4],
];
let bone_points = [vector![0.4, 0.4, 0.4],
vector![0.4, 0.4, -0.4],
vector![-0.4, 0.4, 0.4],
vector![-0.4, 0.4, -0.4],
vector![0.4, -0.4, 0.4],
vector![0.4, -0.4, -0.4],
vector![-0.4, -0.4, 0.4],
vector![-0.4, -0.4, -0.4]];
bone_points.iter().enumerate().for_each(|(ix, a)| {
bones.insert(
format!("diag_{}", ix),
Bone {
head: BoneVertex {
x: a.x,
y: a.y,
z: a.z,
},
tail: center,
},
);
});
bones.insert(format!("diag_{}", ix),
Bone { head: BoneVertex { x: a.x,
y: a.y,
z: a.z },
tail: center });
});
bone_points.iter().copied().enumerate().flat_map(|(ax, a)| bone_points.iter().copied().enumerate().map(move |(bx, b)| (a, ax, b, bx))).for_each(|(a, ax, b, bx)| {
if ax == bx || dbg!((a - b).magnitude()) > 0.8 {return}
bone_points.iter()
.copied()
.enumerate()
.flat_map(|(ax, a)| {
bone_points.iter()
.copied()
.enumerate()
.map(move |(bx, b)| (a, ax, b, bx))
})
.for_each(|(a, ax, b, bx)| {
if ax == bx || dbg!((a - b).magnitude()) > 0.8 {
return;
}
let (ax, a, bx, b) = {
if ax < bx {
(ax, a, bx, b)
} else {
(bx, b, ax, a)
}
};
let (ax, a, bx, b) = {
if ax < bx {
(ax, a, bx, b)
} else {
(bx, b, ax, a)
}
};
bones.insert(
format!("edge_{}_{}", ax, bx),
Bone {
head: BoneVertex {
x: a.x,
y: a.y,
z: a.z,
},
tail: BoneVertex {
x: b.x,
y: b.y,
z: b.z,
},
},
);
});
bones.insert(format!("edge_{}_{}", ax, bx),
Bone { head: BoneVertex { x: a.x,
y: a.y,
z: a.z },
tail: BoneVertex { x: b.x,
y: b.y,
z: b.z } });
});
(msh, Bones::new(bones))
},

View File

@@ -19,7 +19,6 @@ use rustc_hash::{FxHashMap, FxHashSet};
use super::constraint::{graph, Constraint, Stiffness};
use super::{constraint, step, Body, Handle, Set};
use crate::either::Either;
use crate::mesh::{Mesh, TriMesh};
use crate::xpbd::step::Step;
@@ -85,7 +84,7 @@ impl Inserted {
linear_damping,
&mut extra_dst);
me.faces = faces.into_iter()
me.faces = faces.iter()
.map(|a| {
a.map(|x| {
let v = vertices[x as usize].map(I32F32::from_num);

View File

@@ -177,9 +177,7 @@ pub mod contact {
vec![]
}
fn init(&mut self, _: &rustc_hash::FxHashMap<rapier3d::prelude::RigidBodyHandle, usize>) {
()
}
fn init(&mut self, _: &rustc_hash::FxHashMap<rapier3d::prelude::RigidBodyHandle, usize>) {}
}
}

View File

@@ -1,14 +1,10 @@
use core::f32;
use core::fmt::Debug;
use std::collections::BTreeMap;
pub use builder::Builder;
use constraint::Constraint;
pub use handle::Handle;
use nalgebra::Vector3;
use rapier3d::parry::bounding_volume::Aabb;
use rapier3d::parry::partitioning::Qbvh;
use rapier3d::parry::query::details::RayCompositeShapeToiAndNormalBestFirstVisitor;
use rapier3d::prelude::{RigidBodyHandle, *};
use rustc_hash::FxHashSet;
pub use set::Set;
@@ -46,7 +42,6 @@ impl Body {
}
step.predict_next();
}
/// Apply simulation results to rapier environment
@@ -110,7 +105,7 @@ impl Body {
ix_of_other: usize,
other: &parry3d::shape::TriMesh) {
if !other.aabb(&Isometry::identity()).intersects(&self.aabb()) {
return
return;
}
let points = self.step
@@ -146,20 +141,20 @@ impl Body {
pub fn update_contacts(&mut self, bodies: &[Self]) {
// self.constraints
// .iter_mut()
// .filter_map(|c| match c {
// | constraint::impl_::Constraint::Contact(c) => Some(c),
// | _ => None,
// })
// .for_each(|contact| {
// let face = bodies[contact.other].trimesh[contact.face];
// let [a, b, c] = face.map(|x| Point::from(bodies[contact.other].step.bodies[x].next.p));
// let tri = parry3d::shape::Triangle::new(a, b, c);
// let proj =
// tri.project_local_point(&Point::from(self.step.bodies[contact.idx].next.p), false);
// contact.normal = tri.normal().unwrap();
// contact.contact_point = proj.point.coords;
// });
// .iter_mut()
// .filter_map(|c| match c {
// | constraint::impl_::Constraint::Contact(c) => Some(c),
// | _ => None,
// })
// .for_each(|contact| {
// let face = bodies[contact.other].trimesh[contact.face];
// let [a, b, c] = face.map(|x| Point::from(bodies[contact.other].step.bodies[x].next.p));
// let tri = parry3d::shape::Triangle::new(a, b, c);
// let proj =
// tri.project_local_point(&Point::from(self.step.bodies[contact.idx].next.p), false);
// contact.normal = tri.normal().unwrap();
// contact.contact_point = proj.point.coords;
// });
}
pub fn aabb(&self) -> Aabb {

View File

@@ -59,7 +59,7 @@ impl Set {
/// Do a single simulation step
pub fn step(&self, bodies: &mut RigidBodySet) {
let mut bs = self.bodies.lock().unwrap();
if bs.len() == 0 {
if bs.is_empty() {
return;
}
@@ -115,7 +115,7 @@ impl Set {
for (ax, ab) in bsa.iter_mut().enumerate() {
// update contact constraints with update face
// positions
ab.update_contacts(&bsb);
ab.update_contacts(bsb);
if n == 0 || n % substep_interval[ax] == 0 {
ab.substep();