Created
December 15, 2021 14:32
-
-
Save elect86/4960063397eeeed0c609573e08145fe7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:OptIn(kotlin.contracts.ExperimentalContracts::class) | |
package glm.vec2 | |
import glm.* | |
import glm.extensions.* | |
import kotlin.jvm.* | |
import kotlin.math.abs | |
import kotlin.math.sqrt | |
import glm.vec1.* | |
import glm.vec2.* | |
import glm.vec3.* | |
import glm.vec4.* | |
import glm.mat2.* | |
import glm.mat2x3.* | |
import glm.mat2x4.* | |
import glm.mat3x2.* | |
import glm.mat3.* | |
import glm.mat3x4.* | |
import glm.mat4x2.* | |
import glm.mat4x3.* | |
import glm.mat4.* | |
open class Vec2(var array: FloatArray, var ofs: Int = 0) : Vec2T<Float>() { | |
override var x: Float | |
get() = array[ofs] | |
set(value) { | |
array[ofs] = value | |
} | |
override var y: Float | |
get() = array[ofs + 1] | |
set(value) { | |
array[ofs + 1] = value | |
} | |
// Implicit basic constructors | |
constructor() : this(FloatArray(2)) | |
constructor(v: Vec2) : this(v.x, v.y) | |
// Explicit basic constructors | |
constructor(x: Float) : this(x, x) | |
constructor(x: Number) : this(x.f) | |
constructor(x: Float, y: Float) : this(floatArrayOf(x, y)) | |
// Conversion scalar constructors | |
constructor(v: Vec1T<out Number>) : this(v.x.f) | |
// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) | |
constructor(x: Number, y: Number) : this(x.f, y.f) | |
constructor(x: Number, y: Vec1T<out Number>) : this(x, y.x) | |
constructor(x: Vec1T<out Number>, y: Number) : this(x.x, y) | |
constructor(x: Vec1T<out Number>, y: Vec1T<out Number>) : this(x.x, y.x) | |
// Conversion vector constructors | |
// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) | |
constructor(v: Vec2T<out Number>) : this(v.x, v.y) | |
constructor(v: Vec3T<out Number>) : this(v.x, v.y) | |
constructor(v: Vec4T<out Number>) : this(v.x, v.y) | |
// Unary arithmetic operators | |
operator fun plusAssign(scalar: Number) = plusAssign(scalar.f) | |
operator fun plusAssign(scalar: Float) { | |
x += scalar | |
y += scalar | |
} | |
operator fun plusAssign(v: Vec1T<out Number>) { | |
x += v.x.f | |
y += v.x.f | |
} | |
operator fun plusAssign(v: Vec1) { | |
x += v.x | |
y += v.x | |
} | |
operator fun plusAssign(v: Vec2T<out Number>) { | |
x += v.x.f | |
y += v.y.f | |
} | |
operator fun plusAssign(v: Vec2) { | |
x += v.x | |
y += v.y | |
} | |
operator fun minusAssign(scalar: Number) = minusAssign(scalar.f) | |
operator fun minusAssign(scalar: Float) { | |
x -= scalar | |
y -= scalar | |
} | |
operator fun minusAssign(v: Vec1T<out Number>) { | |
x -= v.x.f | |
y -= v.x.f | |
} | |
operator fun minusAssign(v: Vec1) { | |
x -= v.x | |
y -= v.x | |
} | |
operator fun minusAssign(v: Vec2T<out Number>) { | |
x -= v.x.f | |
y -= v.y.f | |
} | |
operator fun minusAssign(v: Vec2) { | |
x -= v.x | |
y -= v.y | |
} | |
operator fun timesAssign(scalar: Number) = timesAssign(scalar.f) | |
operator fun timesAssign(scalar: Float) { | |
x *= scalar | |
y *= scalar | |
} | |
operator fun timesAssign(v: Vec1T<out Number>) { | |
x *= v.x.f | |
y *= v.x.f | |
} | |
operator fun timesAssign(v: Vec1) { | |
x *= v.x | |
y *= v.x | |
} | |
operator fun timesAssign(v: Vec2T<out Number>) { | |
x *= v.x.f | |
y *= v.y.f | |
} | |
operator fun timesAssign(v: Vec2) { | |
x *= v.x | |
y *= v.y | |
} | |
operator fun divAssign(scalar: Number) = divAssign(scalar.f) | |
operator fun divAssign(scalar: Float) { | |
x /= scalar | |
y /= scalar | |
} | |
operator fun divAssign(v: Vec1T<out Number>) { | |
x /= v.x.f | |
y /= v.x.f | |
} | |
operator fun divAssign(v: Vec1) { | |
x /= v.x | |
y /= v.x | |
} | |
operator fun divAssign(v: Vec2T<out Number>) { | |
x /= v.x.f | |
y /= v.y.f | |
} | |
operator fun divAssign(v: Vec2) { | |
x /= v.x | |
y /= v.y | |
} | |
// Increment and decrement operators | |
operator fun inc(): Vec2 { | |
x++ | |
y++ | |
return this | |
} | |
operator fun dec(): Vec2 { | |
x-- | |
y-- | |
return this | |
} | |
operator fun invoke(x: Float, y: Float): Vec2 { | |
this.x = x | |
this.y = y | |
return this | |
} | |
// Unary bit operators TODO | |
// Unary operators | |
operator fun unaryPlus(): Vec2 = this | |
operator fun unaryMinus(): Vec2 = Vec2(-x, -y) | |
// Binary operators | |
operator fun plus(scalar: Float): Vec2 = plus(scalar, scalar, Vec2()) | |
fun plus(scalar: Float, res: Vec2): Vec2 = plus(scalar, scalar, res) | |
inline fun plus(scalar: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
plus(x, y, scalar, scalar, res) | |
} | |
operator fun plus(v: Vec1): Vec2 = plus(v.x, v.x, Vec2()) | |
fun plus(v: Vec1, res: Vec2): Vec2 = plus(v.x, v.x, res) | |
inline fun plus(v: Vec1, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
plus(x, y, v.x, v.x, res) | |
} | |
operator fun plus(v: Vec2): Vec2 = plus(v.x, v.y, Vec2()) | |
fun plus(v: Vec2, res: Vec2): Vec2 = plus(v.x, v.y, res) | |
inline fun plus(v: Vec2, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
plus(x, y, v.x, v.y, res) | |
} | |
fun plus(x: Float, y: Float, res: Vec2): Vec2 = res(this.x + x, this.y + y) | |
inline fun plus(x: Float, y: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
plus(x, y, x, y, res) | |
} | |
operator fun minus(scalar: Float): Vec2 = minus(scalar, scalar, Vec2()) | |
fun minus(scalar: Float, res: Vec2): Vec2 = minus(scalar, scalar, res) | |
inline fun minus(scalar: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
minus(x, y, scalar, scalar, res) | |
} | |
operator fun minus(v: Vec1): Vec2 = minus(v.x, v.x, Vec2()) | |
fun minus(v: Vec1, res: Vec2): Vec2 = minus(v.x, v.x, res) | |
inline fun minus(v: Vec1, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
minus(x, y, v.x, v.x, res) | |
} | |
operator fun minus(v: Vec2): Vec2 = minus(v.x, v.y, Vec2()) | |
fun minus(v: Vec2, res: Vec2): Vec2 = minus(v.x, v.y, res) | |
inline fun minus(v: Vec2, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
minus(x, y, v.x, v.y, res) | |
} | |
fun minus(x: Float, y: Float, res: Vec2): Vec2 = res(this.x - x, this.y - y) | |
inline fun minus(x: Float, y: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
minus(x, y, x, y, res) | |
} | |
operator fun times(scalar: Float): Vec2 = times(scalar, scalar, Vec2()) | |
fun times(scalar: Float, res: Vec2): Vec2 = times(scalar, scalar, res) | |
inline fun times(scalar: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(x, y, scalar, scalar, res) | |
} | |
operator fun times(v: Vec1): Vec2 = times(v.x, v.x, Vec2()) | |
fun times(v: Vec1, res: Vec2): Vec2 = times(v.x, v.x, res) | |
inline fun times(v: Vec1, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(x, y, v.x, v.x, res) | |
} | |
operator fun times(v: Vec2): Vec2 = times(v.x, v.y, Vec2()) | |
fun times(v: Vec2, res: Vec2): Vec2 = times(v.x, v.y, res) | |
inline fun times(v: Vec2, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(x, y, v.x, v.y, res) | |
} | |
fun times(x: Float, y: Float, res: Vec2): Vec2 = res(this.x * x, this.y * y) | |
inline fun times(x: Float, y: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(x, y, x, y, res) | |
} | |
operator fun times(m: Mat2): Vec2 = times(m, Vec2()) | |
fun times(m: Mat2, res: Vec2): Vec2 = res(x * m.a0 + y * m.a1, | |
x * m.b0 + y * m.b1) | |
inline fun times(m: Mat2, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(m.a0, m.a1, | |
m.b0, m.b1, res) | |
} | |
inline fun times(a0: Float, a1: Float, | |
b0: Float, b1: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(x * a0 + y * a1, | |
x * b0 + y * b1) | |
} | |
operator fun times(m: Mat3x2): Vec3 = times(m, Vec3()) | |
fun times(m: Mat3x2, res: Vec3): Vec3 = res(x * m.a0 + y * m.a1, | |
x * m.b0 + y * m.b1, | |
x * m.c0 + y * m.c1) | |
inline fun times(m: Mat3x2, res: (resX: Float, resY: Float, resZ: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(m.a0, m.a1, | |
m.b0, m.b1, | |
m.c0, m.c1, res) | |
} | |
inline fun times(a0: Float, a1: Float, | |
b0: Float, b1: Float, | |
c0: Float, c1: Float, res: (resX: Float, resY: Float, resZ: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(x * a0 + y * a1, | |
x * b0 + y * b1, | |
x * c0 + y * c1) | |
} | |
operator fun times(m: Mat4x2): Vec4 = times(m, Vec4()) | |
fun times(m: Mat4x2, res: Vec4): Vec4 = res(x * m.a0 + y * m.a1, | |
x * m.b0 + y * m.b1, | |
x * m.c0 + y * m.c1, | |
x * m.d0 + y * m.d1) | |
inline fun times(m: Mat4x2, res: (resX: Float, resY: Float, resZ: Float, resW: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
times(m.a0, m.a1, | |
m.b0, m.b1, | |
m.c0, m.c1, | |
m.d0, m.d1, res) | |
} | |
inline fun times(a0: Float, a1: Float, | |
b0: Float, b1: Float, | |
c0: Float, c1: Float, | |
d0: Float, d1: Float, res: (resX: Float, resY: Float, resZ: Float, resW: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(x * a0 + y * a1, | |
x * b0 + y * b1, | |
x * c0 + y * c1, | |
x * d0 + y * d1) | |
} | |
operator fun div(scalar: Float): Vec2 = div(scalar, scalar, Vec2()) | |
fun div(scalar: Float, res: Vec2): Vec2 = div(scalar, scalar, res) | |
inline fun div(scalar: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
div(x, y, scalar, scalar, res) | |
} | |
operator fun div(v: Vec1): Vec2 = div(v.x, v.x, Vec2()) | |
fun div(v: Vec1, res: Vec2): Vec2 = div(v.x, v.x, res) | |
inline fun div(v: Vec1, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
div(x, y, v.x, v.x, res) | |
} | |
operator fun div(v: Vec2): Vec2 = div(v.x, v.y, Vec2()) | |
fun div(v: Vec2, res: Vec2): Vec2 = div(v.x, v.y, res) | |
inline fun div(v: Vec2, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
div(x, y, v.x, v.y, res) | |
} | |
fun div(x: Float, y: Float, res: Vec2): Vec2 = res(this.x / x, this.y / y) | |
inline fun div(x: Float, y: Float, res: (resX: Float, resY: Float) -> Unit) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
div(x, y, x, y, res) | |
} | |
operator fun div(m: Mat2): Vec2 = div(m, Vec2()) | |
fun div(m: Mat2, res: Vec2): Vec2 { | |
val oneOverDeterminant = 1f / ( | |
+ m.a0 * m.b1 | |
- m.b0 * m.a1) | |
val i00 = + m.b1 * oneOverDeterminant | |
val i01 = - m.a1 * oneOverDeterminant | |
val i10 = - m.b0 * oneOverDeterminant | |
val i11 = + m.a0 * oneOverDeterminant | |
return res(x * i00 + y * i01, | |
x * i10 + y * i11) | |
} | |
// geometric | |
/** | |
* Returns the dot product of this [Vec2] and [b], i.e., `result = this * b`. | |
* @see [GLSL dot man page](http://www.opengl.org/sdk/docs/manglsl/xhtml/dot.xml) | |
* @see [GLSL 4.20.8 specification, section 8.5 Geometric Functions](http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf) | |
*/ | |
infix fun dot(b: Vec2): Float { | |
val x: Float; val y: Float | |
times(b) { resX, resY -> x = resX; y = resY } | |
return x + y | |
} | |
/** | |
* Returns the length of this [Vec2], i.e., `sqrt(this * this)`. | |
* @see [GLSL length man page](http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml) | |
* @see [GLSL 4.20.8 specification, section 8.5 Geometric Functions](http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf) | |
*/ | |
fun length(): Float = sqrt(this dot this) | |
// Dot products | |
@JvmName("dotUByte") | |
infix fun dot(v: Vec2T<UByte>) = (x * v.x.f + y * v.y.f).f | |
@JvmName("dotUShort") | |
infix fun dot(v: Vec2T<UShort>) = (x * v.x.f + y * v.y.f).f | |
@JvmName("dotUInt") | |
infix fun dot(v: Vec2T<UInt>) = (x * v.x.f + y * v.y.f).f | |
@JvmName("dotULong") | |
infix fun dot(v: Vec2T<ULong>) = (x * v.x.f + y * v.y.f).f | |
infix fun dot(v: Vec2T<out Number>) = (x * v.x.f + y * v.y.f).f | |
override fun equals(other: Any?) = other is Vec2 && x == other.x && y == other.y | |
override fun hashCode() = 1 * x.hashCode() + 31 * y.hashCode() | |
fun equal(v: Vec2, epsilon: Float = Float.MIN_VALUE) = BooleanArray(length) { abs(array[it] - v.array[it]) <= epsilon } | |
fun notEqual(v: Vec2, epsilon: Float = Float.MIN_VALUE) = BooleanArray(length) { abs(array[it] - v.array[it]) > epsilon } | |
fun allEqual(v: Vec2, epsilon: Float = Float.MIN_VALUE): Boolean { | |
for (i in 0 until length) | |
if(abs(array[i] - v.array[i]) > epsilon) | |
return false | |
return true | |
} | |
fun anyNotEqual(v: Vec2, epsilon: Float = Float.MIN_VALUE): Boolean { | |
for (i in 0 until length) | |
if(abs(array[i] - v.array[i]) > epsilon) | |
return true | |
return false | |
} | |
companion object { | |
const val length = Vec2T.length | |
const val size = length * Float.SIZE_BYTES | |
inline fun plus(aX: Float, aY: Float, | |
bX: Float, bY: Float, res:(resX: Float, resY: Float) -> Unit ) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(aX + bX, aY + bY) | |
} | |
inline fun minus(aX: Float, aY: Float, | |
bX: Float, bY: Float, res:(resX: Float, resY: Float) -> Unit ) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(aX - bX, aY - bY) | |
} | |
inline fun times(aX: Float, aY: Float, | |
bX: Float, bY: Float, res:(resX: Float, resY: Float) -> Unit ) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(aX * bX, aY * bY) | |
} | |
inline fun div(aX: Float, aY: Float, | |
bX: Float, bY: Float, res:(resX: Float, resY: Float) -> Unit ) { | |
kotlin.contracts.contract { callsInPlace(res, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } | |
res(aX / bX, aY / bY) | |
} | |
} | |
} | |
// Binary operators | |
operator fun Float.plus(v: Vec2) = Vec2(this + v.x, this + v.y) | |
operator fun Vec1.plus(v: Vec2) = Vec2(x + v.x, x + v.y) | |
operator fun Float.minus(v: Vec2) = Vec2(this - v.x, this - v.y) | |
operator fun Vec1.minus(v: Vec2) = Vec2(x - v.x, x - v.y) | |
operator fun Float.times(v: Vec2) = Vec2(this * v.x, this * v.y) | |
operator fun Vec1.times(v: Vec2) = Vec2(x * v.x, x * v.y) | |
operator fun Float.div(v: Vec2) = Vec2(this / v.x, this / v.y) | |
operator fun Vec1.div(v: Vec2) = Vec2(x / v.x, x / v.y) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment