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]
|
let objs: Vec<_> = [-1.25, -1.00, -0.85, -0.50, 0.00, 0.40, 0.70, 0.95, 1.05]
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(k, y)| Object {
|
.map(|(k, &y)| Object {
|
||||||
id: k as i32,
|
id: k as i32,
|
||||||
loc: {
|
loc: {
|
||||||
let pos = vec2(0.0, y * tube.external_halflength);
|
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 {
|
Location {
|
||||||
pos,
|
pos,
|
||||||
rot: adj,
|
rot: adj * rot,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
r: 20.0,
|
r: 20.0,
|
||||||
|
|
@ -135,6 +136,11 @@ struct Hit {
|
||||||
rel: Vec2, // положение в локальной ортонормированной СК объекта
|
rel: Vec2, // положение в локальной ортонормированной СК объекта
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct HitInternal<'a> {
|
||||||
|
object: &'a Object,
|
||||||
|
distance: f32,
|
||||||
|
}
|
||||||
|
|
||||||
struct FlatTraceResult {
|
struct FlatTraceResult {
|
||||||
end: Option<Ray>,
|
end: Option<Ray>,
|
||||||
objects: Vec<Hit>,
|
objects: Vec<Hit>,
|
||||||
|
|
@ -186,13 +192,17 @@ impl Space {
|
||||||
assert_eq!(self.which_subspace(ray.pos), Inner);
|
assert_eq!(self.which_subspace(ray.pos), Inner);
|
||||||
let cell = RectInside { rect: self.rect };
|
let cell = RectInside { rect: self.rect };
|
||||||
let ray = cell.ray_to_local(ray);
|
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 dist = cell.to_boundary(ray).expect("Can't get outta here!");
|
||||||
let ray = ray.forward(dist);
|
|
||||||
FlatTraceResult {
|
FlatTraceResult {
|
||||||
end: Some(cell.ray_to_global(ray)),
|
end: Some(cell.ray_to_global(ray.forward(dist))),
|
||||||
objects: objs.into_iter().filter_map(|Hit { id, distance, pos, rel }|
|
objects: hits.into_iter().filter_map(|HitInternal { object, distance }|
|
||||||
if distance < dist { Some(Hit { id, distance, pos: cell.pos_to_global(pos), rel }) } else { None }
|
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(),
|
).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -200,16 +210,27 @@ impl Space {
|
||||||
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
||||||
assert_eq!(self.which_subspace(ray.pos), Outer);
|
assert_eq!(self.which_subspace(ray.pos), Outer);
|
||||||
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
|
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) {
|
if let Some(dist) = cell.trace_into(ray) {
|
||||||
FlatTraceResult {
|
FlatTraceResult {
|
||||||
end: Some(ray.forward(dist)),
|
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 {
|
} else {
|
||||||
FlatTraceResult {
|
FlatTraceResult {
|
||||||
end: None,
|
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 => {
|
Inner => {
|
||||||
let Vec2 { x, y } = obj.loc.pos; // в основной СК
|
let Vec2 { x, y } = obj.loc.pos; // в основной СК
|
||||||
let y = self.rect.u(y) + y.signum() * (self.rect.external_halflength - self.rect.internal_halflength);
|
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 {
|
Object {
|
||||||
id: obj.id,
|
id: obj.id,
|
||||||
loc: Location {
|
loc: Location {
|
||||||
pos: vec2(x, y), // в плоском продолжении СК Outer на область Inner
|
pos: vec2(x, y), // в плоском продолжении СК Outer на область Inner
|
||||||
rot: obj.loc.rot,
|
rot: m * obj.loc.rot,
|
||||||
},
|
},
|
||||||
r: obj.r,
|
r: obj.r,
|
||||||
}
|
}
|
||||||
|
|
@ -262,7 +285,7 @@ impl Space {
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<Hit> {
|
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<HitInternal> {
|
||||||
objs.iter()
|
objs.iter()
|
||||||
.filter_map(|obj| {
|
.filter_map(|obj| {
|
||||||
let rel = ray.pos - obj.loc.pos;
|
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();
|
let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared();
|
||||||
if t >= 0.0 {
|
if t >= 0.0 {
|
||||||
let pos = ray.forward(t).pos;
|
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
|
None
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user