com.teamwizardry.librarianlib.math.Ray2d.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
Core classes used by the other LibrarianLib modules
package com.teamwizardry.librarianlib.math
import com.teamwizardry.librarianlib.core.util.vec
import kotlin.math.max
import kotlin.math.min
public class Ray2d(originX: Double, originY: Double, directionX: Double, directionY: Double) {
public constructor(origin: Vec2d, direction: Vec2d): this(origin.x, origin.y, direction.x, direction.y)
/** The distance, measured in the multiple of the direction vector used for this trace (hit point = origin + distance * direction) */
public var hitDistance: Double = Double.NaN
private set
public var hitX: Double = Double.NaN
private set
public var hitY: Double = Double.NaN
private set
public val hit: Vec2d?
get() = if (hitX.isNaN() || hitY.isNaN()) null else vec(hitX, hitY)
public var hitNormalX: Double = Double.NaN
private set
public var hitNormalY: Double = Double.NaN
private set
public val hitNormal: Vec2d?
get() = if (hitNormalX.isNaN() || hitNormalY.isNaN()) null else vec(hitNormalX, hitNormalY)
public var originX: Double = originX
private set
public var originY: Double = originY
private set
public val origin: Vec2d
get() = vec(originX, originY)
public var directionX: Double = directionX
private set
public var directionY: Double = directionY
private set
public val direction: Vec2d
get() = vec(directionX, directionY)
private var invX: Double = 1 / directionX
private var invY: Double = 1 / directionY
public fun reset(origin: Vec2d, direction: Vec2d) {
reset(origin.x, origin.y, direction.x, direction.y)
}
public fun reset(originX: Double, originY: Double, directionX: Double, directionY: Double) {
this.hitDistance = Double.NaN
this.hitX = Double.NaN
this.hitY = Double.NaN
this.hitNormalX = Double.NaN
this.hitNormalY = Double.NaN
this.originX = originX
this.originY = originY
this.directionX = directionX
this.directionY = directionY
this.invX = 1 / directionX
this.invY = 1 / directionY
}
// https://tavianator.com/fast-branchless-raybounding-box-intersections-part-2-nans/
public fun raytrace(minX: Double, minY: Double, maxX: Double, maxY: Double): Boolean {
val tx1 = (minX - originX) * invX
val tx2 = (maxX - originX) * invX
var tmin = min(tx1, tx2)
var tmax = max(tx1, tx2)
val ty1 = (minY - originY) * invY
val ty2 = (maxY - originY) * invY
tmin = max(tmin, min(ty1, ty2))
tmax = min(tmax, max(ty1, ty2))
if (tmax >= tmin && tmax >= 0 && tmin >= 0 && (hitDistance.isNaN() || tmin < hitDistance)) {
hitDistance = tmin
hitX = originX + hitDistance * originX
hitY = originY + hitDistance * originY
hitNormalX = if (tmin == tx1) -1.0 else if (tmin == tx2) 1.0 else 0.0
hitNormalY = if (tmin == ty1) -1.0 else if (tmin == ty2) 1.0 else 0.0
return true
}
return false
}
}