Properly calculate relative hit position for rotated objects
This commit is contained in:
parent
3dec491bb5
commit
932029b064
|
|
@ -39,14 +39,15 @@ pub fn main() {
|
|||
let objs: Vec<_> = [-1.25, -1.00, -0.85, -0.50, 0.00, 0.40, 0.70, 0.95, 1.05]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(k, y)| Object {
|
||||
.map(|(k, &y)| Object {
|
||||
id: k as i32,
|
||||
loc: {
|
||||
let pos = vec2(0.0, y * tube.external_halflength);
|
||||
let adj = tube.sqrt_at(pos).inverse().into();
|
||||
let adj: Mat2 = tube.sqrt_at(pos).inverse().into();
|
||||
let rot = Mat2::from_angle(y);
|
||||
Location {
|
||||
pos,
|
||||
rot: adj,
|
||||
rot: adj * rot,
|
||||
}
|
||||
},
|
||||
r: 20.0,
|
||||
|
|
@ -135,6 +136,11 @@ struct Hit {
|
|||
rel: Vec2, // положение в локальной ортонормированной СК объекта
|
||||
}
|
||||
|
||||
struct HitInternal<'a> {
|
||||
object: &'a Object,
|
||||
distance: f32,
|
||||
}
|
||||
|
||||
struct FlatTraceResult {
|
||||
end: Option<Ray>,
|
||||
objects: Vec<Hit>,
|
||||
|
|
@ -186,13 +192,17 @@ impl Space {
|
|||
assert_eq!(self.which_subspace(ray.pos), Inner);
|
||||
let cell = RectInside { rect: self.rect };
|
||||
let ray = cell.ray_to_local(ray);
|
||||
let objs = Self::trace_to_objects(self.list_objects_inner().as_slice(), ray);
|
||||
let objs = self.list_objects_inner();
|
||||
let hits = Self::trace_to_objects(objs.as_slice(), ray);
|
||||
let dist = cell.to_boundary(ray).expect("Can't get outta here!");
|
||||
let ray = ray.forward(dist);
|
||||
FlatTraceResult {
|
||||
end: Some(cell.ray_to_global(ray)),
|
||||
objects: objs.into_iter().filter_map(|Hit { id, distance, pos, rel }|
|
||||
if distance < dist { Some(Hit { id, distance, pos: cell.pos_to_global(pos), rel }) } else { None }
|
||||
end: Some(cell.ray_to_global(ray.forward(dist))),
|
||||
objects: hits.into_iter().filter_map(|HitInternal { object, distance }|
|
||||
if distance < dist {
|
||||
let pos = ray.forward(distance).pos;
|
||||
let rel = object.loc.rot.inverse() * cell.ray_to_global(Ray { pos: object.loc.pos, dir: pos - object.loc.pos }).dir;
|
||||
Some(Hit { id: object.id, distance, pos: cell.pos_to_global(pos), rel })
|
||||
} else { None }
|
||||
).collect(),
|
||||
}
|
||||
}
|
||||
|
|
@ -200,16 +210,27 @@ impl Space {
|
|||
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
||||
assert_eq!(self.which_subspace(ray.pos), Outer);
|
||||
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
|
||||
let objs = Self::trace_to_objects(self.list_objects_outer().as_slice(), ray);
|
||||
let objs = self.list_objects_outer();
|
||||
let hits = Self::trace_to_objects(objs.as_slice(), ray);
|
||||
if let Some(dist) = cell.trace_into(ray) {
|
||||
FlatTraceResult {
|
||||
end: Some(ray.forward(dist)),
|
||||
objects: objs.into_iter().filter(|hit| hit.distance < dist).collect(),
|
||||
objects: hits.into_iter().filter_map(|HitInternal { object, distance }|
|
||||
if distance < dist {
|
||||
let pos = ray.forward(distance).pos;
|
||||
let rel = object.loc.rot.inverse() * (pos - object.loc.pos);
|
||||
Some(Hit { id: object.id, distance, pos, rel })
|
||||
} else { None }
|
||||
).collect(),
|
||||
}
|
||||
} else {
|
||||
FlatTraceResult {
|
||||
end: None,
|
||||
objects: objs,
|
||||
objects: hits.into_iter().map(|HitInternal { object, distance }| {
|
||||
let pos = ray.forward(distance).pos;
|
||||
let rel = object.loc.rot.inverse() * (pos - object.loc.pos);
|
||||
Hit { id: object.id, distance, pos, rel }
|
||||
}).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,11 +249,13 @@ impl Space {
|
|||
Inner => {
|
||||
let Vec2 { x, y } = obj.loc.pos; // в основной СК
|
||||
let y = self.rect.u(y) + y.signum() * (self.rect.external_halflength - self.rect.internal_halflength);
|
||||
let dy = self.rect.du(y, 1.0);
|
||||
let m = Mat2::from_cols_array(&[1.0, 0.0, 0.0, dy]);
|
||||
Object {
|
||||
id: obj.id,
|
||||
loc: Location {
|
||||
pos: vec2(x, y), // в плоском продолжении СК Outer на область Inner
|
||||
rot: obj.loc.rot,
|
||||
rot: m * obj.loc.rot,
|
||||
},
|
||||
r: obj.r,
|
||||
}
|
||||
|
|
@ -262,7 +285,7 @@ impl Space {
|
|||
}).collect()
|
||||
}
|
||||
|
||||
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<Hit> {
|
||||
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<HitInternal> {
|
||||
objs.iter()
|
||||
.filter_map(|obj| {
|
||||
let rel = ray.pos - obj.loc.pos;
|
||||
|
|
@ -271,7 +294,7 @@ impl Space {
|
|||
let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared();
|
||||
if t >= 0.0 {
|
||||
let pos = ray.forward(t).pos;
|
||||
return Some(Hit { id: obj.id, distance: t, pos, rel: pos - obj.loc.pos });
|
||||
return Some(HitInternal { object: &obj, distance: t });
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user