Simple AABB-ray collision implementation (Slab method)
This is a bounding-box/AABB ray collision detection function implemented in JS. I wrote it during my brief exploration of using JavaScript as a basis for a simple game framework, which I never finished (I scrapped it while writing the HTML5 canvas abstractions and thank God for that). But I digress. Anyways, it makes the following assumptions:
- All input coordinates are represented in world space. Intermediate values are relative.
- The input ray is represented as two 2-dimensional points in global space: start and end.
- It is a member function of a bounding-box class with the following coordinates: x1, x2, y1, y2, hence the this voodoo keyword.
Here is the code.
raycast(start, end) {
let diff = end.subtract(start);
let
tx1 = (this.x1 - start.x) / diff.x;
let
tx2 = (this.x2 - start.x) / diff.x;
let
tminX = Math.min(tx1, tx2);
let
tmaxX = Math.max(tx1, tx2);
let
ty1 = (this.y1 - start.y) / diff.y;
let
ty2 = (this.y2 - start.y) / diff.y;
let
tminY = Math.min(ty1, ty2);
let tmaxY = Math.max(ty1, ty2);
let
tEnter = Math.max(tminX, tminY);
let
tExit = Math.min(tmaxX, tmaxY);
if
(tEnter > tExit || tExit < 0 || tEnter > 1) {
return
null;
}
let
tHit = Math.max(tEnter, 0.0);
return
start.add(diff.multiply(tHit));
}
I also return the intersection position if it exists. For consistency with the inputs, it's also in global space. In addition, I use three vector-specific functions:
-
vec2.add- adds two vectors and returns the result -
vec2.subtract- ditto, but with subtraction -
vec2.multiply- performs scalar multiplication of a vector
I keep this implementation as reference to implement ray casting in my future 2D game engines. I will probably also update this article, adding something written in a more familiar and fun language like C or C++. I hope you find my implementation useful in the meanwhile.