Skip to content
This repository was archived by the owner on Nov 10, 2024. It is now read-only.

Commit 09e794f

Browse files
committed
충돌 감지 일부 구현
1 parent 344af6c commit 09e794f

File tree

6 files changed

+82
-45
lines changed

6 files changed

+82
-45
lines changed

src/app/graphics/plot.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ impl SimPlot {
7777
continue;
7878
}
7979

80+
let obj_state = &mut obj.current_state();
81+
8082
plot_ui.polygon(
8183
Polygon::new(
82-
obj.shape().get_plot_points(obj.current_state().position)
84+
obj_state.shape.get_plot_points(obj_state.position)
8385
)
8486
.color(PlotColor::Object.get_color()),
8587
);

src/app/simulations/classic_simulation.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::app::NVec2;
66

77
use egui::{Response, Ui};
88
use nalgebra::{vector, SMatrix};
9+
use tracing::info;
910

1011
use crate::app::graphics::plot::{InputMessage, PlotData};
1112
use crate::app::manager::SIMULATION_TICK;
@@ -128,8 +129,8 @@ impl Simulation for ClassicSimulation {
128129
if let Some(pointer_pos) = msg.pointer_pos {
129130
if response.clicked() {
130131
for (index, obj) in simulation_objects.iter().enumerate() {
131-
if let Some(_obj_state) = obj.state_at_timestep(state.current_step) {
132-
if is_inside(pointer_pos, obj.shape().get_points()) {
132+
if let Some(obj_state) = obj.state_at_timestep(state.current_step) {
133+
if is_inside(pointer_pos, obj_state.shape.get_points()) {
133134
plot.selected_index = index;
134135
break;
135136
}
@@ -142,8 +143,8 @@ impl Simulation for ClassicSimulation {
142143
if let Some(pointer_pos) = msg.pointer_pos {
143144
if response.drag_started() {
144145
for (index, obj) in simulation_objects.iter().enumerate() {
145-
if let Some(_obj_state) = obj.state_at_timestep(state.current_step) {
146-
if is_inside(pointer_pos, obj.shape().get_points()) {
146+
if let Some(obj_state) = obj.state_at_timestep(state.current_step) {
147+
if is_inside(pointer_pos, obj_state.shape.get_points()) {
147148
plot.selected_index = index;
148149
plot.dragging_object = true;
149150
break;
@@ -204,19 +205,34 @@ impl Simulation for ClassicSimulation {
204205
}
205206
}
206207

207-
for child in &mut self.objects {
208-
child.update(state);
208+
let length = self.objects.len();
209209

210-
if let Some(attached_fn) = &child.attached() {
211-
attached_fn(child.current_state_mut());
210+
for i in 1..length+1 {
211+
212+
let (front, end) = self.objects.split_at_mut(i-1);
213+
214+
let Some((obj, rest)) = end.split_first_mut() else {panic!("Cannot Reach")};
215+
216+
let obj_state = &mut obj.current_state();
217+
218+
obj.update(state);
219+
220+
if let Some(attached_fn) = &obj.attached() {
221+
attached_fn(obj.current_state_mut());
212222
}
213223

214-
physics_system(child, self.global_acc_list.iter().sum());
224+
physics_system(obj, self.global_acc_list.iter().sum());
215225

216-
// contact
217-
{}
226+
for obj2 in rest {
227+
228+
let obj2_state = &mut obj2.current_state();
229+
230+
if let Some(contact) = obj_state.shape.contact(obj_state.position, &obj2_state.shape, obj2_state.position){
231+
info!("{:?}", contact);
232+
}
233+
}
218234

219-
child.save_state();
235+
obj.save_state();
220236
}
221237
}
222238

src/app/simulations/classic_simulation/object.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ pub struct CSimObject {
1919
init_timestep: usize,
2020
timestep: usize,
2121

22-
#[getset(get = "pub")]
23-
shape: ObjectShape,
2422
#[getset(get = "pub")]
2523
hide: bool,
2624
#[getset(get = "pub")]

src/app/simulations/classic_simulation/object/builder.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ impl CSimObjectBuilder {
4242
state_timeline: vec![self.init_state.unwrap_or_default()],
4343
init_timestep,
4444
timestep: init_timestep,
45-
shape: self.shape.unwrap_or(ObjectShape::default()),
4645
hide: false,
4746
attached: self.attached,
4847
}

src/app/simulations/classic_simulation/object/shape.rs

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use crate::app::NVec2;
22
use egui::plot::PlotPoints;
33
use std::f64::consts::TAU;
4+
use std::ops::{Div, DivAssign};
45

56
pub trait Shape {
67
fn get_points(&self) -> Vec<[f64; 2]>;
7-
fn get_plot_points(&self) -> PlotPoints;
8+
fn get_plot_points(&self, pos: NVec2) -> PlotPoints;
9+
}
10+
11+
pub trait Collision {
12+
fn contact(&self, this_pos: NVec2, ops: &ObjectShape, ops_pos: NVec2) -> Option<ContactInfo>;
813
}
914

1015
#[allow(dead_code)]
@@ -22,16 +27,14 @@ impl Default for ObjectShape {
2227

2328
#[allow(dead_code)]
2429
impl ObjectShape {
25-
pub fn circle(pos: NVec2, radius: f64) -> Self {
30+
pub fn circle(radius: f64) -> Self {
2631
Self::Circle(Circle {
2732
radius,
28-
position: pos,
2933
})
3034
}
3135

32-
pub fn rect(pos: NVec2, width: f64, height: f64) -> Self {
36+
pub fn rect(width: f64, height: f64) -> Self {
3337
Self::Rect(Rect {
34-
position: pos,
3538
width,
3639
height,
3740
})
@@ -44,22 +47,23 @@ impl ObjectShape {
4447
}
4548
}
4649

47-
pub fn get_plot_points(&self) -> PlotPoints {
50+
pub fn get_plot_points(&self, pos: NVec2) -> PlotPoints {
4851
match self {
49-
Self::Circle(circle) => circle.get_plot_points(),
50-
Self::Rect(rect) => rect.get_plot_points(),
52+
Self::Circle(circle) => circle.get_plot_points(pos),
53+
Self::Rect(rect) => rect.get_plot_points(pos),
5154
}
5255
}
5356

54-
pub fn contact(&self, ops: ObjectShape) -> Option<ContactInfo> {
57+
pub fn contact(&self,this_pos: NVec2, ops: &ObjectShape, ops_pos: NVec2) -> Option<ContactInfo> {
5558
match self {
56-
Self::Circle(circle) => circle.contact(ops),
57-
Self::Rect(rect) => rect.contact(ops),
59+
Self::Circle(circle) => circle.contact(this_pos, ops, ops_pos),
60+
Self::Rect(rect) => rect.contact(this_pos, ops, ops_pos),
5861
}
5962
}
6063
}
6164

62-
struct ContactInfo {
65+
#[derive(Debug, Clone, Copy)]
66+
pub struct ContactInfo {
6367
pub contact_point: NVec2,
6468
pub contact_normal: NVec2,
6569
pub penetration: f64,
@@ -68,14 +72,12 @@ struct ContactInfo {
6872
#[derive(Debug, Clone, Copy)]
6973
pub struct Circle {
7074
pub radius: f64,
71-
pub position: NVec2,
7275
}
7376

7477
impl Default for Circle {
7578
fn default() -> Self {
7679
Self {
7780
radius: Self::DEFAULT_RADIUS,
78-
position: Default::default(),
7981
}
8082
}
8183
}
@@ -85,12 +87,12 @@ impl Shape for Circle {
8587
self._get_points(Self::DEFAULT_RESOLUTION)
8688
}
8789

88-
fn get_plot_points(&self) -> PlotPoints {
90+
fn get_plot_points(&self, pos: NVec2) -> PlotPoints {
8991
PlotPoints::from_parametric_callback(
9092
move |t| {
9193
(
92-
t.sin() * self.radius + self.position.x,
93-
t.cos() * self.radius + self.position.y,
94+
t.sin() * self.radius + pos.x,
95+
t.cos() * self.radius + pos.y,
9496
)
9597
},
9698
0.0..TAU,
@@ -123,17 +125,35 @@ impl Circle {
123125
self._get_points(resolution)
124126
}
125127

126-
pub fn contact(&self, ops: ObjectShape) -> Option<ContactInfo> {
128+
}
129+
130+
impl Collision for Circle{
131+
fn contact(&self, this_pos: NVec2, ops: &ObjectShape, ops_pos: NVec2) -> Option<ContactInfo> {
127132
match ops {
128133
ObjectShape::Circle(circle) => {
129134
//TODO: copilot maked code, may be wrong
130-
let distance = (self.position - circle.position).norm();
131-
let penetration = self.radius + circle.radius - distance;
132-
let contact_normal = (circle.position - self.position).normalize();
133-
let contact_point = self.position + contact_normal * self.radius;
135+
let delta_pos = ops_pos - this_pos;
136+
137+
let penetration = self.radius + circle.radius - delta_pos.norm();
138+
139+
if penetration < 0.0 {
140+
return None;
141+
}
142+
143+
let normalized = delta_pos.normalize();
144+
145+
146+
let contact_normal = delta_pos.normalize();
147+
148+
let this_contact_normal = normalized * penetration;
149+
150+
let ops_contact_normal = -normalized * penetration;
151+
let contact_point = (this_pos + ops_pos).div(2.0);
152+
153+
134154
Some(ContactInfo {
135155
contact_point,
136-
contact_normal,
156+
contact_normal: this_contact_normal,
137157
penetration,
138158
})
139159
}
@@ -148,8 +168,6 @@ impl Circle {
148168
pub struct Rect {
149169
pub width: f64,
150170
pub height: f64,
151-
152-
pub position: NVec2,
153171
}
154172

155173
impl Shape for Rect {
@@ -164,7 +182,7 @@ impl Shape for Rect {
164182
]
165183
}
166184

167-
fn get_plot_points(&self) -> PlotPoints {
185+
fn get_plot_points(&self, pos: NVec2) -> PlotPoints {
168186
let width = self.width;
169187
let height = self.height;
170188
vec![
@@ -174,14 +192,14 @@ impl Shape for Rect {
174192
(-width / 2.0, height / 2.0),
175193
]
176194
.into_iter()
177-
.map(|e| [e.0 + self.position.x, e.1 + self.position.y])
195+
.map(|e| [e.0 + pos.x, e.1 + pos.y])
178196
.collect::<Vec<_>>()
179197
.into()
180198
}
181199
}
182200

183-
impl Rect {
184-
pub fn contact(&self, ops: ObjectShape) -> Option<ContactInfo> {
201+
impl Collision for Rect {
202+
fn contact(&self, this_pos: NVec2, ops: &ObjectShape, ops_pos: NVec2) -> Option<ContactInfo> {
185203
todo!()
186204
}
187205
}

src/app/simulations/classic_simulation/object/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::app::NVec2;
2+
use crate::app::simulations::classic_simulation::object::shape::ObjectShape;
23

34
#[repr(usize)]
45
pub enum ForceIndex {
@@ -14,9 +15,11 @@ pub struct CSObjectState {
1415
pub last_velocity: NVec2,
1516
pub mass: f64,
1617
pub acc_list: Vec<NVec2>,
18+
pub shape: ObjectShape,
1719
}
1820

1921
impl CSObjectState {
22+
2023
pub(crate) fn momentum(&self) -> NVec2 {
2124
// P = mv , v = P/m
2225
self.velocity * self.mass
@@ -45,6 +48,7 @@ impl Default for CSObjectState {
4548
last_velocity: Default::default(),
4649
mass: 10.0,
4750
acc_list: vec![NVec2::zeros(); ForceIndex::MAX as usize],
51+
shape: ObjectShape::default(),
4852
}
4953
}
5054
}

0 commit comments

Comments
 (0)