diff --git a/src/bin/flat/main.rs b/src/bin/flat/main.rs index 3520924..89f36f6 100644 --- a/src/bin/flat/main.rs +++ b/src/bin/flat/main.rs @@ -133,7 +133,7 @@ struct Hit { distance: f32, id: i32, pos: Vec2, // положение в основной СК - rel: Vec2, // положение в локальной ортонормированной СК объекта + rel: Ray, // в локальной ортонормированной СК объекта } struct HitInternal<'a> { @@ -200,8 +200,10 @@ impl Space { objects: hits.into_iter().filter_map(|HitInternal { object, distance }| if distance < dist { let pos = ray.forward(distance).pos; + // NB: object.loc.rot задан относительно object.loc.pos, поэтому и ray_to_global надо делать относительно object.loc.pos, а не 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 }) + let dir = object.loc.rot.inverse() * cell.ray_to_global(Ray { pos: object.loc.pos, dir: ray.dir }).dir; + Some(Hit { id: object.id, distance, pos: cell.pos_to_global(pos), rel: Ray { pos: rel, dir } }) } else { None } ).collect(), } @@ -220,7 +222,8 @@ impl Space { 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 }) + let dir = object.loc.rot.inverse() * ray.dir; + Some(Hit { id: object.id, distance, pos, rel: Ray { pos: rel, dir } }) } else { None } ).collect(), } @@ -336,10 +339,20 @@ fn draw_ray_2(gc: &mut Vec, space: &Space, base: Vec2, dir: Vec2) { for hit in ret.objects { let obj = space.objs[hit.id as usize]; hits.move_to(obj.loc.pos.x, obj.loc.pos.y); - for pt in trace_iter(&space.rect, obj.loc.pos, obj.loc.rot * hit.rel, hit.rel.length() / 100.0).take(100) { + for pt in trace_iter(&space.rect, obj.loc.pos, obj.loc.rot * hit.rel.pos, hit.rel.pos.length() / 100.0).take(100) { hits.line_to(pt.x, pt.y); } hits.circle(hit.pos.x, hit.pos.y, 1.5); + let Ray { pos: rel, dir } = hit.rel; + let diff = rel.dot(dir).powi(2) - dir.length_squared() * (rel.length_squared() - obj.r.powi(2)); + assert!(diff >= 0.0); + let t = (-rel.dot(dir) + diff.sqrt()) / dir.length_squared(); + let rel2 = hit.rel.forward(t).pos; + let pos2 = trace_iter(&space.rect, obj.loc.pos, obj.loc.rot * rel2, rel2.length() / 100.0).nth(100).unwrap(); + hits.move_to(pos2.x - 1.0, pos2.y - 1.0); + hits.line_to(pos2.x + 1.0, pos2.y + 1.0); + hits.move_to(pos2.x - 1.0, pos2.y + 1.0); + hits.line_to(pos2.x + 1.0, pos2.y - 1.0); } let a = ray.pos; ray = match ret.end {