Optimise BoundingBox rayCast methods
ikudrickiy opened this issue · comments
ikudrickiy commented
Context
public rayCast(ray: Ray, farClipDistance = Infinity): boolean
and
public rayCastTime(ray: Ray, farClipDistance = Infinity): number
blindly follow attached article:
tmin
andtmax
variables are initiated for no reason- inverted variables are pre-computed for single instance optimisation which is very limited in this context but causing extra rounding error accumulation and decreased readability
tmax >= Math.max(0, tmin)
contains the original logictmax >= 0 && tmax >= tmin
, but hides it and so reduces readabilitytmin
is actually maxtmin
from a pair ortMaxMin
and so it should be named. Similar stands for 'tmax'- https://youtu.be/GqwUHXvQ7oA should be added in comments as a great visualisation
Proposal
Optimize the code to get rid of the above shortcomings:
/**
* Determines whether a ray intersects with a bounding box
*/
public rayCast(ray: Ray, farClipDistance = Infinity): boolean {
// algorithm from https://tavianator.com/fast-branchless-raybounding-box-intersections/
// principle visualisation: https://youtu.be/GqwUHXvQ7oA
let tMinMax, tMaxMin;
const tx1 = (this.left - ray.pos.x) / ray.dir.x;
const tx2 = (this.right - ray.pos.x) / ray.dir.x;
tMaxMin = Math.min(tx1, tx2);
tMinMax = Math.max(tx1, tx2);
const ty1 = (this.top - ray.pos.y) / ray.dir.y;
const ty2 = (this.bottom - ray.pos.y) / ray.dir.y;
tMaxMin = Math.max(tMaxMin, Math.min(ty1, ty2));
tMinMax = Math.min(tMinMax, Math.max(ty1, ty2));
return tMinMax >= 0 && tMinMax >= tMaxMin && tMaxMin < farClipDistance;
}
public rayCastTime(ray: Ray, farClipDistance = Infinity): number {
// algorithm from https://tavianator.com/fast-branchless-raybounding-box-intersections/
// principle visualisation: https://youtu.be/GqwUHXvQ7oA
let tMinMax, tMaxMin;
const tx1 = (this.left - ray.pos.x) / ray.dir.x;
const tx2 = (this.right - ray.pos.x) / ray.dir.x;
tMaxMin = Math.min(tx1, tx2);
tMinMax = Math.max(tx1, tx2);
const ty1 = (this.top - ray.pos.y) / ray.dir.y;
const ty2 = (this.bottom - ray.pos.y) / ray.dir.y;
tMaxMin = Math.max(tMaxMin, Math.min(ty1, ty2));
tMinMax = Math.min(tMinMax, Math.max(ty1, ty2));
if (tMinMax >= 0 && tMinMax >= tMaxMin && tMaxMin < farClipDistance) {
return tMaxMin;
}
return -1;
}
ikudrickiy commented
I had to call it "refactoring" but initially it seemed to me single instance optimisation was totally useless here (it is not, we have atleast 2 divisions per instance) and I just forgot to rename the issue.