godot.core.math.Vector4.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of godot-library-release Show documentation
Show all versions of godot-library-release Show documentation
Contains godot api as kotlin classes and jvm cpp interaction code.
@file:Suppress("PackageDirectoryMismatch", "unused")
package godot.core
import godot.util.RealT
import godot.util.cubicInterpolateInTime
import godot.util.fposmod
import godot.util.isEqualApprox
import godot.util.snapped
import godot.util.toRealT
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.round
import kotlin.math.sign
import kotlin.math.sqrt
class Vector4(
var x: RealT,
var y: RealT,
var z: RealT,
var w: RealT
) : Comparable, CoreType {
//CONSTANTS
enum class Axis(val id: Long) {
X(0L),
Y(1L),
Z(2L),
W(3L);
companion object {
fun from(value: Long) = when (value) {
0L -> X
1L -> Y
2L -> Z
3L -> W
else -> throw AssertionError("Unknown axis for Vector4: $value")
}
}
}
companion object {
val ZERO: Vector4
get() = Vector4(0, 0, 0, 0)
val ONE: Vector4
get() = Vector4(1, 1, 1, 1)
val INF: Vector4
get() = Vector4(RealT.POSITIVE_INFINITY, RealT.POSITIVE_INFINITY, RealT.POSITIVE_INFINITY, RealT.POSITIVE_INFINITY)
}
//CONSTRUCTOR
constructor() :
this(0.0, 0.0, 0.0, 0.0)
constructor(vec: Vector4) :
this(vec.x, vec.y, vec.z, vec.w)
constructor(other: Vector4i) : this(other.x, other.y, other.z, other.w)
constructor(x: Number, y: Number, z: Number, w: Number) :
this(x.toRealT(), y.toRealT(), z.toRealT(), w.toRealT())
//API
/**
* Returns a new vector with all components in absolute values (i.e. positive).
*/
fun abs(): Vector4 {
return Vector4(abs(x), abs(y), abs(z), abs(w))
}
/**
* Returns a new vector with all components rounded up.
*/
fun ceil(): Vector4 {
return Vector4(ceil(x), ceil(y), ceil(z), ceil(w))
}
/**
* Returns a new vector with all components clamped between the components of min and max, by running
* @GlobalScope.clamp on each component.
*/
fun clamp(min: Vector4, max: Vector4) = Vector4(
x.coerceIn(min.x, max.x),
y.coerceIn(min.y, max.y),
z.coerceIn(min.z, max.z),
w.coerceIn(min.w, max.w)
)
/**
* Performs a cubic interpolation between vectors pre_a, a, b, post_b (a is current), by the given amount t.
* t is in the range of 0.0 - 1.0, representing the amount of interpolation.
*/
fun cubicInterpolate(b: Vector4, pre: Vector4, post: Vector4, t: RealT): Vector4 {
val t2 = t * t
val t3 = t2 * t
return ((this * 2.0) +
(-pre + b) * t +
(pre * 2.0 - this * 5.0 + b * 4.0 - post) * t2 +
(-pre + this * 3.0 - b * 3.0 + post) * t3) * 0.5
}
/**
* Cubically interpolates between this vector and b using pre_a and post_b as handles, and returns the result at
* position weight. weight is on the range of 0.0 to 1.0, representing the amount of interpolation.
*/
fun cubicInterpolateInTime(
b: Vector4,
preA: Vector4,
postB: Vector4,
weight: RealT,
bT: RealT,
preAT: RealT,
postBT: RealT
) = Vector4(this).also {
it.x = cubicInterpolateInTime(
it.x,
b.x,
preA.x,
postB.x,
weight,
bT,
preAT,
postBT
)
it.y = cubicInterpolateInTime(
it.y,
b.y,
preA.y,
postB.y,
weight,
bT,
preAT,
postBT
)
it.z = cubicInterpolateInTime(
it.z,
b.z,
preA.z,
postB.z,
weight,
bT,
preAT,
postBT
)
it.w = cubicInterpolateInTime(
it.w,
b.w,
preA.w,
postB.w,
weight,
bT,
preAT,
postBT
)
}
/**
* Returns the normalized vector pointing from this vector to b.
*/
fun directionTo(other: Vector4): Vector4 {
val ret = Vector4(other.x - x, other.y - y, other.z - z, other.w - w)
ret.normalize()
return ret
}
/**
* Returns the squared distance to b.
* Prefer this function over distance_to if you need to sort vectors or need the squared distance for some formula.
*/
fun distanceSquaredTo(other: Vector4): RealT {
return (other - this).lengthSquared()
}
/**
* Returns the distance to b.
*/
fun distanceTo(other: Vector4): RealT {
return (other - this).length()
}
/**
* Returns the dot product with b.
*/
fun dot(b: Vector4): RealT {
return x * b.x + y * b.y + z * b.z + w * b.w
}
/**
* Returns a new vector with all components rounded down.
*/
fun floor(): Vector4 {
return Vector4(floor(x), floor(y), floor(z), floor(w))
}
/**
* Returns the inverse of the vector. This is the same as Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z ).
*/
fun inverse() = Vector4(1.0 / x, 1.0 / y, 1.0 / z, 1.0 / w)
/**
* Returns true if this vector and v are approximately equal, by running isEqualApprox on each component.
*/
fun isEqualApprox(other: Vector4): Boolean {
return other.x.isEqualApprox(x) && other.y.isEqualApprox(y) && other.z.isEqualApprox(z) && other.w.isEqualApprox(w)
}
/**
* Returns true if this vector is finite, by calling [Float.isFinite] on each component.
*/
fun isFinite() = x.isFinite() && y.isFinite() && z.isFinite() && w.isFinite()
/**
* Returns true if the vector is normalized.
*/
fun isNormalized(): Boolean {
return this.length().isEqualApprox(1.0)
}
/**
* Returns true if this vector's values are approximately zero
*/
fun isZeroApprox() = isEqualApprox(ZERO)
/**
* Returns the vector’s length.
*/
fun length(): RealT {
return sqrt(lengthSquared())
}
/**
* Returns the vector’s length squared.
* Prefer this function over length if you need to sort vectors or need the squared length for some formula.
*/
fun lengthSquared() = this.dot(this)
/**
* Returns the result of the linear interpolation between this vector and to by amount weight. weight is on the
* range of 0.0 to 1.0, representing the amount of interpolation.
*/
fun lerp(to: Vector4, weight: RealT) = Vector4(
x + (weight * (to.x - x)),
y + (weight * (to.y - y)),
z + (weight * (to.z - z)),
w + (weight * (to.w - w))
)
/**
* Returns the axis of the vector's highest value. See AXIS_* constants.
* If all components are equal, this method returns AXIS_X.
*/
fun maxAxis(): Axis {
var maxIndex = 0
var maxValue = x
for (i in 1 until 4) {
val axisValue = this[i]
if (axisValue <= maxValue) {
continue
}
maxIndex = i
maxValue = axisValue
}
return Axis.from(maxIndex.toLong())
}
/**
* Returns the axis of the vector’s smallest value. See AXIS_* constants.
*/
fun minAxis(): Axis {
var minIndex = 0
var minValue = x
for (i in 1 until 4) {
val axisValue = this[i]
if (axisValue > minValue) {
continue
}
minIndex = i
minValue = axisValue
}
return Axis.from(minIndex.toLong())
}
/**
* Returns the vector scaled to unit length. Equivalent to v / v.length().
*/
fun normalized(): Vector4 {
val v = Vector4(this)
v.normalize()
return v
}
internal fun normalize() {
val l = this.length()
if (l.isEqualApprox(0.0)) {
x = 0.0
y = 0.0
z = 0.0
w = 0.0
} else {
x /= l
y /= l
z /= l
w /= l
}
}
/**
* Returns a vector composed of the fposmod of this vector’s components and mod.
*/
fun posmod(mod: RealT) = Vector4(x.fposmod(mod), y.fposmod(mod), z.fposmod(mod), w.fposmod(mod))
/**
* Returns a vector composed of the fposmod of this vector’s components and modv’s components.
*/
fun posmodv(modv: Vector4) = Vector4(x.fposmod(modv.x), y.fposmod(modv.y), z.fposmod(modv.z), w.fposmod(modv.w))
/**
* Returns the vector with all components rounded to the nearest integer, with halfway cases rounded away from zero.
*/
fun round(): Vector4 {
return Vector4(round(x), round(y), round(z), round(w))
}
/**
* Returns the vector with each component set to one or negative one, depending on the signs of the components.
*/
fun sign(): Vector4 {
return Vector4(sign(x), sign(y), sign(z), sign(w))
}
/**
* Returns a new vector with each component snapped to the closest multiple of the corresponding component in [step].
*/
fun snapped(by: Vector4): Vector4 {
val v = Vector4(this)
v.snap(by)
return v
}
internal fun snap(by: Vector4) {
x = snapped(x, by.x)
y = snapped(y, by.y)
z = snapped(z, by.z)
w = snapped(w, by.w)
}
internal fun snap(vecal: RealT) {
if (vecal.isEqualApprox(0.0)) {
x = (floor(x / vecal + 0.5) * vecal)
y = (floor(y / vecal + 0.5) * vecal)
z = (floor(z / vecal + 0.5) * vecal)
w = (floor(w / vecal + 0.5) * vecal)
}
}
fun toVector4i() = Vector4i(this)
operator fun get(n: Int): RealT = when (n) {
0 -> x
1 -> y
2 -> z
3 -> w
else -> throw IndexOutOfBoundsException()
}
operator fun set(n: Int, f: RealT): Unit = when (n) {
0 -> x = f
1 -> y = f
2 -> z = f
3 -> w = f
else -> throw IndexOutOfBoundsException()
}
operator fun get(axis: Axis): RealT = when (axis) {
Axis.X -> x
Axis.Y -> y
Axis.Z -> z
Axis.W -> w
}
operator fun set(axis: Axis, f: RealT) = when (axis) {
Axis.X -> x = f
Axis.Y -> y = f
Axis.Z -> z = f
Axis.W -> w = f
}
operator fun plus(vec: Vector4) = Vector4(x + vec.x, y + vec.y, z + vec.z, w + vec.w)
operator fun plus(scalar: Int) = Vector4(x + scalar, y + scalar, z + scalar, w + scalar)
operator fun plus(scalar: Long) = Vector4(x + scalar, y + scalar, z + scalar, w + scalar)
operator fun plus(scalar: Float) = Vector4(x + scalar, y + scalar, z + scalar, w + scalar)
operator fun plus(scalar: Double) = Vector4(x + scalar, y + scalar, z + scalar, w + scalar)
operator fun minus(vec: Vector4) = Vector4(x - vec.x, y - vec.y, z - vec.z, w - vec.w)
operator fun minus(scalar: Int) = Vector4(x - scalar, y - scalar, z - scalar, w - scalar)
operator fun minus(scalar: Long) = Vector4(x - scalar, y - scalar, z - scalar, w - scalar)
operator fun minus(scalar: Float) = Vector4(x - scalar, y - scalar, z - scalar, w - scalar)
operator fun minus(scalar: Double) = Vector4(x - scalar, y - scalar, z - scalar, w - scalar)
operator fun times(vec: Vector4) = Vector4(x * vec.x, y * vec.y, z * vec.z, w * vec.w)
operator fun times(scalar: Int) = Vector4(x * scalar, y * scalar, z * scalar, w * scalar)
operator fun times(scalar: Long) = Vector4(x * scalar, y * scalar, z * scalar, w * scalar)
operator fun times(scalar: Float) = Vector4(x * scalar, y * scalar, z * scalar, w * scalar)
operator fun times(scalar: Double) = Vector4(x * scalar, y * scalar, z * scalar, w * scalar)
operator fun div(vec: Vector4) = Vector4(x / vec.x, y / vec.y, z / vec.z, w / vec.w)
operator fun div(scalar: Int) = Vector4(x / scalar, y / scalar, z / scalar, w / scalar)
operator fun div(scalar: Long) = Vector4(x / scalar, y / scalar, z / scalar, w / scalar)
operator fun div(scalar: Float) = Vector4(x / scalar, y / scalar, z / scalar, w / scalar)
operator fun div(scalar: Double) = Vector4(x / scalar, y / scalar, z / scalar, w / scalar)
operator fun unaryMinus() = Vector4(-x, -y, -z, -w)
override fun equals(other: Any?): Boolean = when (other) {
is Vector4 -> (x == other.x && y == other.y && z == other.z && w == other.w)
else -> false
}
override fun compareTo(other: Vector4): Int {
if (x == other.x) {
if (y == other.y) {
return if (z == other.z) {
when {
w < other.w -> -1
w == other.w -> 0
else -> 1
}
} else {
when {
z < other.z -> -1
else -> 1
}
}
} else {
return when {
y < other.y -> -1
else -> 1
}
}
} else {
return when {
x < other.x -> -1
else -> 1
}
}
}
override fun toString(): String {
return "($x, $y, $z, $w)"
}
override fun hashCode(): Int {
return this.toString().hashCode()
}
}
operator fun Int.plus(vec: Vector4) = vec + this
operator fun Long.plus(vec: Vector4) = vec + this
operator fun Float.plus(vec: Vector4) = vec + this
operator fun Double.plus(vec: Vector4) = vec + this
operator fun Int.minus(vec: Vector4) = Vector4(this - vec.x, this - vec.y, this - vec.z, this - vec.w)
operator fun Long.minus(vec: Vector4) = Vector4(this - vec.x, this - vec.y, this - vec.z, this - vec.w)
operator fun Float.minus(vec: Vector4) = Vector4(this - vec.x, this - vec.y, this - vec.z, this - vec.w)
operator fun Double.minus(vec: Vector4) = Vector4(this - vec.x, this - vec.y, this - vec.z, this - vec.w)
operator fun Int.times(vec: Vector4) = vec * this
operator fun Long.times(vec: Vector4) = vec * this
operator fun Float.times(vec: Vector4) = vec * this
operator fun Double.times(vec: Vector4) = vec * this