time for a snapshot
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { type AABB, type Span, sweepInterval, type Vec } from "./given.ts";
|
||||
|
||||
/** A collision: the fraction of the frame at impact, and the surface normal. */
|
||||
export type Hit = { time: number; normal: Vec };
|
||||
|
||||
/**
|
||||
* A point at `p` moving by `v` over this frame, against a static box.
|
||||
* Returns the entry Hit, or null if there is no collision this frame.
|
||||
*
|
||||
* Reuse sweepInterval twice (x and y), then combine:
|
||||
* entry = max of the two entries, exit = min of the two exits.
|
||||
*/
|
||||
export function rayVsAABB(p: Vec, v: Vec, box: AABB): Hit | null {
|
||||
const spanX = sweepInterval(p.x, v.x, box.x, box.x + box.w);
|
||||
if (spanX === null) {
|
||||
return null;
|
||||
}
|
||||
const spanY = sweepInterval(p.y, v.y, box.y, box.y + box.h);
|
||||
if (spanY === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const span: Span = {
|
||||
entry: Math.max(spanX.entry, spanY.entry),
|
||||
exit: Math.min(spanX.exit, spanY.exit),
|
||||
};
|
||||
|
||||
if (span.entry > span.exit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (span.entry >= 1 || span.exit <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const time = span.entry;
|
||||
const normal = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
if (spanX.entry > spanY.entry) {
|
||||
normal.x = v.x > 0 ? -1 : 1;
|
||||
} else {
|
||||
normal.y = v.y > 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
return {
|
||||
time,
|
||||
normal,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user