Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Created October 4, 2020 13:21
Show Gist options
  • Save steveruizok/10cf23cffa351e52402926988ff74a0e to your computer and use it in GitHub Desktop.
Save steveruizok/10cf23cffa351e52402926988ff74a0e to your computer and use it in GitHub Desktop.
Cast a ray.
export function castRay<T = any>(
from: number[],
direction: number[],
hitTest: (info: {
point: number[]
distance: number
position: number[]
positions: number[][]
}) => T,
maxDistance: number = 9999,
minDistance: number = 0
): {
hit?: T
point: number[]
normal: number[]
distance: number
position: number[]
positions: number[][]
} {
let stepLength = Math.hypot(direction[0], direction[1])
if (stepLength < minDistance) {
return {
hit: undefined,
point: [...from],
normal: [0, 0],
position: [...from],
positions: [[...from]],
distance: 0,
}
}
const position = [Math.floor(from[0]) | 0, Math.floor(from[1]) | 0]
const delta = [direction[0] / stepLength, direction[1] / stepLength]
const step = [delta[0] > 0 ? 1 : -1, delta[1] > 0 ? 1 : -1]
const positionDelta = [
step[0] > 0 ? position[0] + 1 - from[0] : from[0] - position[0],
step[1] > 0 ? position[1] + 1 - from[1] : from[1] - position[1],
]
const stepDelta = [2, 2]
const stepped = [
stepDelta[0] < Infinity ? stepDelta[0] * positionDelta[0] : Infinity,
stepDelta[1] < Infinity ? stepDelta[1] * positionDelta[1] : Infinity,
]
let hit: any
let point: number[] = [...from]
let normal: number[] = [0, 0]
let positions: number[][] = [[...position]]
let steppedDistance = 0.0
let steppedIndex = -1
let distance = 0
function moveAlongXAxis() {
position[0] += step[0]
stepped[0] += stepDelta[0]
steppedDistance = stepped[0]
steppedIndex = 0
}
function moveAlongYAxis() {
position[1] += step[1]
stepped[1] += stepDelta[1]
steppedDistance = stepped[1]
steppedIndex = 1
}
while (steppedDistance <= maxDistance) {
distance++
stepped[0] < stepped[1] ? moveAlongXAxis() : moveAlongYAxis()
positions.push([...position])
point[0] = from[0] + steppedDistance * delta[0]
point[1] = from[1] + steppedDistance * delta[1]
normal[0] = steppedIndex === 0 ? -step[0] : 0
normal[1] = steppedIndex === 1 ? -step[1] : 0
hit = hitTest({
point,
distance,
position,
positions,
})
if (hit !== undefined) {
return {
hit,
point,
normal,
position,
positions,
distance,
}
}
}
return {
hit,
point,
normal,
position,
positions,
distance,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment