Remove linear algebra module since it really should be separate project if to be maintained outside of kstarbound

This commit is contained in:
DBotThePony 2024-04-19 14:21:45 +07:00
parent 6adef84355
commit 66b0f3ffd8
Signed by: DBot
GPG Key ID: DCC23B5715498507
41 changed files with 1 additions and 6954 deletions

View File

@ -4,7 +4,7 @@ kotlin.code.style=official
specifyKotlinAsDependency=false
projectGroup=ru.dbotthepony.kommons
projectVersion=2.14.1
projectVersion=2.15.0
guavaDepVersion=33.0.0
gsonDepVersion=2.8.9

View File

@ -1,43 +0,0 @@
plugins {
kotlin("jvm")
}
repositories {
mavenCentral()
}
val gsonDepVersion: String by project
val specifyKotlinAsDependency: String by project
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
implementation(project(":linear-algebra"))
implementation(project(":gson"))
implementation(project(":"))
implementation("com.google.code.gson:gson:$gsonDepVersion")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
artifact(tasks["sourceJar"])
artifactId = "kommons-gson-linear-algebra"
pom {
dependencies {
if (specifyKotlinAsDependency.toBoolean()) implementation(kotlin("stdlib"))
implementation(project(":linear-algebra"))
implementation(project(":gson"))
implementation(project(":"))
implementation("com.google.code.gson:gson:[2.8,)")
}
}
}
}
}

View File

@ -1,39 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.util.AABB
object AABBTypeAdapter : TypeAdapter<AABB>() {
override fun write(out: JsonWriter, value: AABB) {
`out`.beginArray()
`out`.value(value.mins.x)
`out`.value(value.mins.y)
`out`.value(value.maxs.x)
`out`.value(value.maxs.y)
`out`.endArray()
}
override fun read(`in`: JsonReader): AABB {
`in`.beginArray()
val minX = `in`.nextDouble()
val minY = `in`.nextDouble()
val maxX = `in`.nextDouble()
val maxY = `in`.nextDouble()
`in`.endArray()
val xMins = minX.coerceAtMost(maxX)
val xMaxs = maxX.coerceAtLeast(minX)
val yMins = minY.coerceAtMost(maxY)
val yMaxs = maxX.coerceAtLeast(minY)
return AABB(
Vector2d(xMins, yMins),
Vector2d(xMaxs, yMaxs),
)
}
}

View File

@ -1,38 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kommons.util.AABBi
object AABBiTypeAdapter : TypeAdapter<AABBi>() {
override fun write(out: JsonWriter, value: AABBi) {
`out`.beginArray()
`out`.value(value.mins.x)
`out`.value(value.mins.y)
`out`.value(value.maxs.x)
`out`.value(value.maxs.y)
`out`.endArray()
}
override fun read(`in`: JsonReader): AABBi {
`in`.beginArray()
val minX = `in`.nextInt()
val minY = `in`.nextInt()
val maxX = `in`.nextInt()
val maxY = `in`.nextInt()
`in`.endArray()
val xMins = minX.coerceAtMost(maxX)
val xMaxs = maxX.coerceAtLeast(minX)
val yMins = minY.coerceAtMost(maxY)
val yMaxs = maxX.coerceAtLeast(minY)
return AABBi(
Vector2i(xMins, yMins),
Vector2i(xMaxs, yMaxs),
)
}
}

View File

@ -1,26 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector2d
object Vector2dTypeAdapter : TypeAdapter<Vector2d>() {
override fun write(out: JsonWriter, value: Vector2d) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector2d {
`in`.beginArray()
val x = `in`.nextDouble()
val y = `in`.nextDouble()
`in`.endArray()
return Vector2d(x, y)
}
}

View File

@ -1,26 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector2f
object Vector2fTypeAdapter : TypeAdapter<Vector2f>() {
override fun write(out: JsonWriter, value: Vector2f) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector2f {
`in`.beginArray()
val x = `in`.nextDouble().toFloat()
val y = `in`.nextDouble().toFloat()
`in`.endArray()
return Vector2f(x, y)
}
}

View File

@ -1,26 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector2i
object Vector2iTypeAdapter : TypeAdapter<Vector2i>() {
override fun write(out: JsonWriter, value: Vector2i) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector2i {
`in`.beginArray()
val x = `in`.nextInt()
val y = `in`.nextInt()
`in`.endArray()
return Vector2i(x, y)
}
}

View File

@ -1,28 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector3d
object Vector3dTypeAdapter : TypeAdapter<Vector3d>() {
override fun write(out: JsonWriter, value: Vector3d) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector3d {
`in`.beginArray()
val x = `in`.nextDouble()
val y = `in`.nextDouble()
val z = `in`.nextDouble()
`in`.endArray()
return Vector3d(x, y, z)
}
}

View File

@ -1,28 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector3f
object Vector3fTypeAdapter : TypeAdapter<Vector3f>() {
override fun write(out: JsonWriter, value: Vector3f) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector3f {
`in`.beginArray()
val x = `in`.nextDouble().toFloat()
val y = `in`.nextDouble().toFloat()
val z = `in`.nextDouble().toFloat()
`in`.endArray()
return Vector3f(x, y, z)
}
}

View File

@ -1,28 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector3i
object Vector3iTypeAdapter : TypeAdapter<Vector3i>() {
override fun write(out: JsonWriter, value: Vector3i) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector3i {
`in`.beginArray()
val x = `in`.nextInt()
val y = `in`.nextInt()
val z = `in`.nextInt()
`in`.endArray()
return Vector3i(x, y, z)
}
}

View File

@ -1,30 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector4d
object Vector4dTypeAdapter : TypeAdapter<Vector4d>() {
override fun write(out: JsonWriter, value: Vector4d) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.value(value.w)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector4d {
`in`.beginArray()
val x = `in`.nextDouble()
val y = `in`.nextDouble()
val z = `in`.nextDouble()
val w = `in`.nextDouble()
`in`.endArray()
return Vector4d(x, y, z, w)
}
}

View File

@ -1,30 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector4f
object Vector4fTypeAdapter : TypeAdapter<Vector4f>() {
override fun write(out: JsonWriter, value: Vector4f) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.value(value.w)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector4f {
`in`.beginArray()
val x = `in`.nextDouble().toFloat()
val y = `in`.nextDouble().toFloat()
val z = `in`.nextDouble().toFloat()
val w = `in`.nextDouble().toFloat()
`in`.endArray()
return Vector4f(x, y, z, w)
}
}

View File

@ -1,30 +0,0 @@
package ru.dbotthepony.kommons.gson
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.vector.Vector4i
object Vector4iTypeAdapter : TypeAdapter<Vector4i>() {
override fun write(out: JsonWriter, value: Vector4i) {
`out`.beginArray()
`out`.value(value.x)
`out`.value(value.y)
`out`.value(value.z)
`out`.value(value.w)
`out`.endArray()
}
override fun read(`in`: JsonReader): Vector4i {
`in`.beginArray()
val x = `in`.nextInt()
val y = `in`.nextInt()
val z = `in`.nextInt()
val w = `in`.nextInt()
`in`.endArray()
return Vector4i(x, y, z, w)
}
}

View File

@ -1,34 +0,0 @@
plugins {
kotlin("jvm")
}
val specifyKotlinAsDependency: String by project
repositories {
mavenCentral()
}
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
implementation(project(":"))
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
artifact(tasks["sourceJar"])
artifactId = "kommons-linear-algebra"
pom {
dependencies {
if (specifyKotlinAsDependency.toBoolean()) implementation(kotlin("stdlib"))
implementation(project(":"))
}
}
}
}
}

View File

@ -1,65 +0,0 @@
package ru.dbotthepony.kommons.io
import ru.dbotthepony.kommons.util.DelegateGetter
import ru.dbotthepony.kommons.util.DelegateSetter
import ru.dbotthepony.kommons.util.ListenableDelegate
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2f
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kommons.vector.Vector3d
import ru.dbotthepony.kommons.vector.Vector3f
import ru.dbotthepony.kommons.vector.Vector3i
import ru.dbotthepony.kommons.vector.Vector4d
import ru.dbotthepony.kommons.vector.Vector4f
import ru.dbotthepony.kommons.vector.Vector4i
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.InputStream
private inline fun <T, I> InputStream.read2(factory: (I, I) -> T, reader: (InputStream) -> I): T {
return factory(reader(this), reader(this))
}
private inline fun <T, I> InputStream.read3(factory: (I, I, I) -> T, reader: (InputStream) -> I): T {
return factory(reader(this), reader(this), reader(this))
}
private inline fun <T, I> InputStream.read4(factory: (I, I, I, I) -> T, reader: (InputStream) -> I): T {
return factory(reader(this), reader(this), reader(this), reader(this))
}
fun InputStream.readVector2i() = read2(::Vector2i) { it.readInt() }
fun InputStream.readVector2d() = read2(::Vector2d) { it.readDouble() }
fun InputStream.readVector2f() = read2(::Vector2f) { it.readFloat() }
fun InputStream.readVector3i() = read3(::Vector3i) { it.readInt() }
fun InputStream.readVector3d() = read3(::Vector3d) { it.readDouble() }
fun InputStream.readVector3f() = read3(::Vector3f) { it.readFloat() }
fun InputStream.readVector4i() = read4(::Vector4i) { it.readInt() }
fun InputStream.readVector4d() = read4(::Vector4d) { it.readDouble() }
fun InputStream.readVector4f() = read4(::Vector4f) { it.readFloat() }
val Vector2iCodec = StreamCodec.Impl(DataInputStream::readVector2i, DataOutputStream::writeStruct2i)
val Vector2dCodec = StreamCodec.Impl(DataInputStream::readVector2d, DataOutputStream::writeStruct2d)
val Vector2fCodec = StreamCodec.Impl(DataInputStream::readVector2f, DataOutputStream::writeStruct2f)
val Vector3iCodec = StreamCodec.Impl(DataInputStream::readVector3i, DataOutputStream::writeStruct3i)
val Vector3dCodec = StreamCodec.Impl(DataInputStream::readVector3d, DataOutputStream::writeStruct3d)
val Vector3fCodec = StreamCodec.Impl(DataInputStream::readVector3f, DataOutputStream::writeStruct3f)
val Vector4iCodec = StreamCodec.Impl(DataInputStream::readVector4i, DataOutputStream::writeStruct4i)
val Vector4dCodec = StreamCodec.Impl(DataInputStream::readVector4d, DataOutputStream::writeStruct4d)
val Vector4fCodec = StreamCodec.Impl(DataInputStream::readVector4f, DataOutputStream::writeStruct4f)
fun DelegateSyncher.vec2i(value: Vector2i, setter: DelegateSetter<Vector2i> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector2i> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector2iCodec)
fun DelegateSyncher.vec2d(value: Vector2d, setter: DelegateSetter<Vector2d> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector2d> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector2dCodec)
fun DelegateSyncher.vec2f(value: Vector2f, setter: DelegateSetter<Vector2f> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector2f> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector2fCodec)
fun DelegateSyncher.vec3i(value: Vector3i, setter: DelegateSetter<Vector3i> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector3i> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector3iCodec)
fun DelegateSyncher.vec3d(value: Vector3d, setter: DelegateSetter<Vector3d> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector3d> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector3dCodec)
fun DelegateSyncher.vec3f(value: Vector3f, setter: DelegateSetter<Vector3f> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector3f> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector3fCodec)
fun DelegateSyncher.vec4i(value: Vector4i, setter: DelegateSetter<Vector4i> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector4i> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector4iCodec)
fun DelegateSyncher.vec4d(value: Vector4d, setter: DelegateSetter<Vector4d> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector4d> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector4dCodec)
fun DelegateSyncher.vec4f(value: Vector4f, setter: DelegateSetter<Vector4f> = DelegateSetter.passthrough(), getter: DelegateGetter<Vector4f> = DelegateGetter.passthrough()) = Slot(ListenableDelegate.maskSmart(value, getter, setter), Vector4fCodec)

View File

@ -1,81 +0,0 @@
package ru.dbotthepony.kommons.math
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2f
import ru.dbotthepony.kommons.vector.Vector3d
import ru.dbotthepony.kommons.vector.Vector3f
import ru.dbotthepony.kommons.vector.Vector4d
import ru.dbotthepony.kommons.vector.Vector4f
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Float, a: Vector2f, b: Vector2f): Vector2f {
if (t <= 0f)
return a
else if (t >= 1f)
return b
return a + (b - a) * t
}
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Float, a: Vector3f, b: Vector3f): Vector3f {
if (t <= 0f)
return a
else if (t >= 1f)
return b
return a + (b - a) * t
}
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Float, a: Vector4f, b: Vector4f): Vector4f {
if (t <= 0f)
return a
else if (t >= 1f)
return b
return a + (b - a) * t
}
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Double, a: Vector2d, b: Vector2d): Vector2d {
if (t <= 0.0)
return a
else if (t >= 1.0)
return b
return a + (b - a) * t
}
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Double, a: Vector3d, b: Vector3d): Vector3d {
if (t <= 0.0)
return a
else if (t >= 1.0)
return b
return a + (b - a) * t
}
/**
* Linear interpolation between [a] and [b] by [t]
*/
fun linearInterpolation(t: Double, a: Vector4d, b: Vector4d): Vector4d {
if (t <= 0.0)
return a
else if (t >= 1.0)
return b
return a + (b - a) * t
}

View File

@ -1,310 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Double2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.vector.Vector2d
import java.nio.ByteBuffer
import java.nio.DoubleBuffer
sealed class Matrix2d : Double2DArray() {
abstract var c00: Double
abstract var c01: Double
abstract var c10: Double
abstract var c11: Double
fun c00() = c00
fun c00(value: Double): Matrix2d { c00 = value; return this }
fun c01() = c01
fun c01(value: Double): Matrix2d { c01 = value; return this }
fun c10() = c10
fun c10(value: Double): Matrix2d { c10 = value; return this }
fun c11() = c11
fun c11(value: Double): Matrix2d { c11 = value; return this }
var r00: Double get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Double get() = c10; set(value) { c10 = value } // row 1 column 0
var r10: Double get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Double get() = c11; set(value) { c11 = value } // row 1 column 1
fun r00() = r00
fun r00(value: Double): Matrix2d { r00 = value; return this }
fun r01() = r01
fun r01(value: Double): Matrix2d { r01 = value; return this }
fun r10() = r10
fun r10(value: Double): Matrix2d { r10 = value; return this }
fun r11() = r11
fun r11(value: Double): Matrix2d { r11 = value; return this }
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c10 = r10,
c11 = r11,
)
final override val rows: Int
get() = 2
final override val columns: Int
get() = 2
final override fun get(column: Int, row: Int): Double {
return when (row or (column shl 1)) {
C00 -> c00
C01 -> c01
C10 -> c10
C11 -> c11
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Double) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C10 -> c10 = value
C11 -> c11 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
final override val determinant: Double
get() = super.determinant!!
final override val cofactorMatrix
get() = from(super.cofactorMatrix!!)
final override val adjugateMatrix
get() = from(super.adjugateMatrix!!)
final override val inversed
get() = super.inversed?.let { from(it) }
fun mul(other: Matrix2d): Matrix2d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
this.c00 = c00
this.c01 = c01
this.c10 = c10
this.c11 = c11
return this
}
fun mulIntoOther(other: Matrix2d): Matrix2d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
other.c00 = c00
other.c01 = c01
other.c10 = c10
other.c11 = c11
return other
}
fun mul(
c00: Double = 1.0,
c01: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
): Matrix2d {
val fc00 = this.c00 * c00 + this.c10 * c01
val fc01 = this.c01 * c00 + this.c11 * c01
val fc10 = this.c00 * c10 + this.c10 * c11
val fc11 = this.c01 * c10 + this.c11 * c11
this.c00 = fc00
this.c01 = fc01
this.c10 = fc10
this.c11 = fc11
return this
}
fun mulIntoThis(
c00: Double = 1.0,
c01: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
): Matrix2d {
val fc00 = c00 * this.c00 + c10 * this.c01
val fc01 = c01 * this.c00 + c11 * this.c01
val fc10 = c00 * this.c10 + c10 * this.c11
val fc11 = c01 * this.c10 + c11 * this.c11
this.c00 = fc00
this.c01 = fc01
this.c10 = fc10
this.c11 = fc11
return this
}
final override fun add(other: Double): Matrix2d {
return super.add(other) as Matrix2d
}
final override fun sub(other: Double): Matrix2d {
return super.sub(other) as Matrix2d
}
final override fun mul(other: Double): Matrix2d {
return super.mul(other) as Matrix2d
}
final override fun div(other: Double): Matrix2d {
return super.div(other) as Matrix2d
}
final override fun add(other: Double2DArray): Matrix2d {
return super.add(other) as Matrix2d
}
final override fun sub(other: Double2DArray): Matrix2d {
return super.sub(other) as Matrix2d
}
fun to3d(filler: Double) = Matrix3d.from(this, filler)
fun to3d() = Matrix3d.from(this)
fun to4d(filler: Double) = Matrix4d.from(this, filler)
fun to4d() = Matrix4d.from(this)
fun copy(): Matrix2d {
return Impl(c00, c01, c10, c11)
}
@JvmOverloads
fun scale(x: Double = 1.0, y: Double = 1.0): Matrix2d {
return mul(c00 = x, c11 = y)
}
fun scale(value: IStruct2d) = scale(value.component1(), value.component2())
fun scale(value: Vector2d) = scale(value.component1(), value.component2())
@JvmOverloads
fun preScale(x: Double = 1.0, y: Double = 1.0): Matrix2d {
return mulIntoThis(c00 = x, c11 = y)
}
fun preScale(value: IStruct2d) = preScale(value.component1(), value.component2())
fun preScale(value: Vector2d) = preScale(value.component1(), value.component2())
fun translate(x: Double) = mul(c10 = x)
fun preTranslate(x: Double) = mulIntoThis(c10 = x)
private data class Impl(
override var c00: Double = 1.0,
override var c01: Double = 0.0,
override var c10: Double = 0.0,
override var c11: Double = 1.0,
) : Matrix2d() {
override fun toString(): String {
return "Matrix2d" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix2d) return false
return this === other || c00 == other.c00 &&
c01 == other.c01 &&
c10 == other.c10 &&
c11 == other.c11
}
}
private class View(private val parent: Matrix2d) : Matrix2d() {
override var c00: Double get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Double get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Double get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Double get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Double) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Double) = construct2(value, ::columnMajor)
@JvmStatic
fun zero() = all(0.0)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix2d): Matrix2d {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Double = 1.0,
c01: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
): Matrix2d {
return Impl(c00, c01, c10, c11)
}
@JvmStatic
fun rowMajor(
r00: Double = 1.0, r01: Double = 0.0,
r10: Double = 0.0, r11: Double = 1.0,
): Matrix2d {
return Impl(
r00, r10,
r01, r11,
)
}
@JvmStatic
fun from(matrix: Double2DArray, filler: Double) = construct2(matrix, Double2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Double2DArray) = construct2(matrix, Double2DArray::get, ::columnMajor, 0.0)
@JvmStatic
fun from(matrix: Matrix2d) = construct2(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix3d) = construct2(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix4d) = construct2(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Double2DArray) = construct2(matrix, Double2DArray::get, Companion::rowMajor, 0.0)
@JvmStatic
fun fromTransposed(matrix: Double2DArray, filler: Double) = construct2(matrix, Double2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Matrix2d) = construct2(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix3d) = construct2(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix4d) = construct2(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: DoubleBuffer) = construct2(buffer, DoubleBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct2(buffer, ByteBuffer::getDouble, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: DoubleBuffer) = construct2(buffer, DoubleBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct2(buffer, ByteBuffer::getDouble, Companion::rowMajor)
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 1))
const val C01 = (0 or (1 shl 1))
const val C10 = (1 or (0 shl 1))
const val C11 = (1 or (1 shl 1))
}
}

View File

@ -1,310 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Float2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.vector.Vector2f
import java.nio.ByteBuffer
import java.nio.FloatBuffer
sealed class Matrix2f : Float2DArray() {
abstract var c00: Float
abstract var c01: Float
abstract var c10: Float
abstract var c11: Float
fun c00() = c00
fun c00(value: Float): Matrix2f { c00 = value; return this }
fun c01() = c01
fun c01(value: Float): Matrix2f { c01 = value; return this }
fun c10() = c10
fun c10(value: Float): Matrix2f { c10 = value; return this }
fun c11() = c11
fun c11(value: Float): Matrix2f { c11 = value; return this }
var r00: Float get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Float get() = c10; set(value) { c10 = value } // row 1 column 0
var r10: Float get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Float get() = c11; set(value) { c11 = value } // row 1 column 1
fun r00() = r00
fun r00(value: Float): Matrix2f { r00 = value; return this }
fun r01() = r01
fun r01(value: Float): Matrix2f { r01 = value; return this }
fun r10() = r10
fun r10(value: Float): Matrix2f { r10 = value; return this }
fun r11() = r11
fun r11(value: Float): Matrix2f { r11 = value; return this }
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c10 = r10,
c11 = r11,
)
final override val rows: Int
get() = 2
final override val columns: Int
get() = 2
final override fun get(column: Int, row: Int): Float {
return when (row or (column shl 1)) {
C00 -> c00
C01 -> c01
C10 -> c10
C11 -> c11
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Float) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C10 -> c10 = value
C11 -> c11 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
final override val determinant: Float
get() = super.determinant!!
final override val cofactorMatrix
get() = from(super.cofactorMatrix!!)
final override val adjugateMatrix
get() = from(super.adjugateMatrix!!)
final override val inversed
get() = super.inversed?.let { from(it) }
fun mul(other: Matrix2f): Matrix2f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
this.c00 = c00
this.c01 = c01
this.c10 = c10
this.c11 = c11
return this
}
fun mulIntoOther(other: Matrix2f): Matrix2f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
other.c00 = c00
other.c01 = c01
other.c10 = c10
other.c11 = c11
return other
}
fun mul(
c00: Float = 1f,
c01: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
): Matrix2f {
val fc00 = this.c00 * c00 + this.c10 * c01
val fc01 = this.c01 * c00 + this.c11 * c01
val fc10 = this.c00 * c10 + this.c10 * c11
val fc11 = this.c01 * c10 + this.c11 * c11
this.c00 = fc00
this.c01 = fc01
this.c10 = fc10
this.c11 = fc11
return this
}
fun mulIntoThis(
c00: Float = 1f,
c01: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
): Matrix2f {
val fc00 = c00 * this.c00 + c10 * this.c01
val fc01 = c01 * this.c00 + c11 * this.c01
val fc10 = c00 * this.c10 + c10 * this.c11
val fc11 = c01 * this.c10 + c11 * this.c11
this.c00 = fc00
this.c01 = fc01
this.c10 = fc10
this.c11 = fc11
return this
}
final override fun add(other: Float): Matrix2f {
return super.add(other) as Matrix2f
}
final override fun sub(other: Float): Matrix2f {
return super.sub(other) as Matrix2f
}
final override fun mul(other: Float): Matrix2f {
return super.mul(other) as Matrix2f
}
final override fun div(other: Float): Matrix2f {
return super.div(other) as Matrix2f
}
final override fun add(other: Float2DArray): Matrix2f {
return super.add(other) as Matrix2f
}
final override fun sub(other: Float2DArray): Matrix2f {
return super.sub(other) as Matrix2f
}
fun to3f(filler: Float) = Matrix3f.from(this, filler)
fun to3f() = Matrix3f.from(this)
fun to4f(filler: Float) = Matrix4f.from(this, filler)
fun to4f() = Matrix4f.from(this)
fun copy(): Matrix2f {
return Impl(c00, c01, c10, c11)
}
@JvmOverloads
fun scale(x: Float = 1f, y: Float = 1f): Matrix2f {
return mul(c00 = x, c11 = y)
}
fun scale(value: IStruct2f) = scale(value.component1(), value.component2())
fun scale(value: Vector2f) = scale(value.component1(), value.component2())
@JvmOverloads
fun preScale(x: Float = 1f, y: Float = 1f): Matrix2f {
return mulIntoThis(c00 = x, c11 = y)
}
fun preScale(value: IStruct2f) = preScale(value.component1(), value.component2())
fun preScale(value: Vector2f) = preScale(value.component1(), value.component2())
fun translate(x: Float) = mul(c10 = x)
fun preTranslate(x: Float) = mulIntoThis(c10 = x)
private data class Impl(
override var c00: Float = 1f,
override var c01: Float = 0f,
override var c10: Float = 0f,
override var c11: Float = 1f,
) : Matrix2f() {
override fun toString(): String {
return "Matrix2f" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix2f) return false
return this === other || c00 == other.c00 &&
c01 == other.c01 &&
c10 == other.c10 &&
c11 == other.c11
}
}
private class View(private val parent: Matrix2f) : Matrix2f() {
override var c00: Float get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Float get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Float get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Float get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Float) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Float) = construct2(value, ::columnMajor)
@JvmStatic
fun zero() = all(0f)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix2f): Matrix2f {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Float = 1f,
c01: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
): Matrix2f {
return Impl(c00, c01, c10, c11)
}
@JvmStatic
fun rowMajor(
r00: Float = 1f, r01: Float = 0f,
r10: Float = 0f, r11: Float = 1f,
): Matrix2f {
return Impl(
r00, r10,
r01, r11,
)
}
@JvmStatic
fun from(matrix: Float2DArray, filler: Float) = construct2(matrix, Float2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Float2DArray) = construct2(matrix, Float2DArray::get, ::columnMajor, 0f)
@JvmStatic
fun from(matrix: Matrix2f) = construct2(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix3f) = construct2(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix4f) = construct2(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Float2DArray) = construct2(matrix, Float2DArray::get, Companion::rowMajor, 0f)
@JvmStatic
fun fromTransposed(matrix: Float2DArray, filler: Float) = construct2(matrix, Float2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Matrix2f) = construct2(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix3f) = construct2(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix4f) = construct2(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: FloatBuffer) = construct2(buffer, FloatBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct2(buffer, ByteBuffer::getFloat, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: FloatBuffer) = construct2(buffer, FloatBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct2(buffer, ByteBuffer::getFloat, Companion::rowMajor)
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 1))
const val C01 = (0 or (1 shl 1))
const val C10 = (1 or (0 shl 1))
const val C11 = (1 or (1 shl 1))
}
}

View File

@ -1,496 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Double2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector3d
import java.nio.ByteBuffer
import java.nio.DoubleBuffer
import kotlin.math.cos
import kotlin.math.sin
sealed class Matrix3d : Double2DArray() {
abstract var c00: Double
abstract var c01: Double
abstract var c02: Double
abstract var c10: Double
abstract var c11: Double
abstract var c12: Double
abstract var c20: Double
abstract var c21: Double
abstract var c22: Double
fun c00() = c00
fun c00(value: Double): Matrix3d { c00 = value; return this }
fun c01() = c01
fun c01(value: Double): Matrix3d { c01 = value; return this }
fun c02() = c02
fun c02(value: Double): Matrix3d { c02 = value; return this }
fun c10() = c10
fun c10(value: Double): Matrix3d { c10 = value; return this }
fun c11() = c11
fun c11(value: Double): Matrix3d { c11 = value; return this }
fun c12() = c12
fun c12(value: Double): Matrix3d { c12 = value; return this }
fun c20() = c20
fun c20(value: Double): Matrix3d { c20 = value; return this }
fun c21() = c21
fun c21(value: Double): Matrix3d { c21 = value; return this }
fun c22() = c22
fun c22(value: Double): Matrix3d { c22 = value; return this }
var r00: Double get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Double get() = c10; set(value) { c10 = value } // row 1 column 0
var r02: Double get() = c20; set(value) { c20 = value } // row 2 column 0
var r10: Double get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Double get() = c11; set(value) { c11 = value } // row 1 column 1
var r12: Double get() = c21; set(value) { c21 = value } // row 2 column 1
var r20: Double get() = c02; set(value) { c02 = value } // row 0 column 2
var r21: Double get() = c12; set(value) { c12 = value } // row 1 column 2
var r22: Double get() = c22; set(value) { c22 = value } // row 2 column 2
fun r00() = r00
fun r00(value: Double): Matrix3d { r00 = value; return this }
fun r01() = r01
fun r01(value: Double): Matrix3d { r01 = value; return this }
fun r02() = r02
fun r02(value: Double): Matrix3d { r02 = value; return this }
fun r10() = r10
fun r10(value: Double): Matrix3d { r10 = value; return this }
fun r11() = r11
fun r11(value: Double): Matrix3d { r11 = value; return this }
fun r12() = r12
fun r12(value: Double): Matrix3d { r12 = value; return this }
fun r20() = r20
fun r20(value: Double): Matrix3d { r20 = value; return this }
fun r21() = r21
fun r21(value: Double): Matrix3d { r21 = value; return this }
fun r22() = r22
fun r22(value: Double): Matrix3d { r22 = value; return this }
final override val rows: Int
get() = 3
final override val columns: Int
get() = 3
final override val determinant: Double
get() = super.determinant!!
final override val cofactorMatrix
get() = from(super.cofactorMatrix!!)
final override val adjugateMatrix
get() = from(super.adjugateMatrix!!)
final override val inversed
get() = super.inversed?.let { from(it) }
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c02 = r02,
c10 = r10,
c11 = r11,
c12 = r12,
c20 = r20,
c21 = r21,
c22 = r22,
)
final override fun get(column: Int, row: Int): Double {
return when (column or (row shl 2)) {
C00 -> c00
C01 -> c01
C02 -> c02
C10 -> c10
C11 -> c11
C12 -> c12
C20 -> c20
C21 -> c21
C22 -> c22
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Double) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C02 -> c02 = value
C10 -> c10 = value
C11 -> c11 = value
C12 -> c12 = value
C20 -> c20 = value
C21 -> c21 = value
C22 -> c22 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
fun mul(other: Matrix3d): Matrix3d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
this.c00 = c00
this.c01 = c01
this.c02 = c02
this.c10 = c10
this.c11 = c11
this.c12 = c12
this.c20 = c20
this.c21 = c21
this.c22 = c22
return this
}
fun mulIntoOther(other: Matrix3d): Matrix3d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
other.c00 = c00
other.c01 = c01
other.c02 = c02
other.c10 = c10
other.c11 = c11
other.c12 = c12
other.c20 = c20
other.c21 = c21
other.c22 = c22
return other
}
fun mul(
c00: Double = 1.0,
c01: Double = 0.0,
c02: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
c12: Double = 0.0,
c20: Double = 0.0,
c21: Double = 0.0,
c22: Double = 1.0,
): Matrix3d {
val fc00 = this.c00 * c00 + this.c10 * c01 + this.c20 * c02
val fc01 = this.c01 * c00 + this.c11 * c01 + this.c21 * c02
val fc02 = this.c02 * c00 + this.c12 * c01 + this.c22 * c02
val fc10 = this.c00 * c10 + this.c10 * c11 + this.c20 * c12
val fc11 = this.c01 * c10 + this.c11 * c11 + this.c21 * c12
val fc12 = this.c02 * c10 + this.c12 * c11 + this.c22 * c12
val fc20 = this.c00 * c20 + this.c10 * c21 + this.c20 * c22
val fc21 = this.c01 * c20 + this.c11 * c21 + this.c21 * c22
val fc22 = this.c02 * c20 + this.c12 * c21 + this.c22 * c22
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
return this
}
fun mulIntoThis(
c00: Double = 1.0,
c01: Double = 0.0,
c02: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
c12: Double = 0.0,
c20: Double = 0.0,
c21: Double = 0.0,
c22: Double = 1.0,
): Matrix3d {
val fc00 = c00 * this.c00 + c10 * this.c01 + c20 * this.c02
val fc01 = c01 * this.c00 + c11 * this.c01 + c21 * this.c02
val fc02 = c02 * this.c00 + c12 * this.c01 + c22 * this.c02
val fc10 = c00 * this.c10 + c10 * this.c11 + c20 * this.c12
val fc11 = c01 * this.c10 + c11 * this.c11 + c21 * this.c12
val fc12 = c02 * this.c10 + c12 * this.c11 + c22 * this.c12
val fc20 = c00 * this.c20 + c10 * this.c21 + c20 * this.c22
val fc21 = c01 * this.c20 + c11 * this.c21 + c21 * this.c22
val fc22 = c02 * this.c20 + c12 * this.c21 + c22 * this.c22
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
return this
}
final override fun add(other: Double): Matrix3d {
return super.add(other) as Matrix3d
}
final override fun sub(other: Double): Matrix3d {
return super.sub(other) as Matrix3d
}
final override fun mul(other: Double): Matrix3d {
return super.mul(other) as Matrix3d
}
final override fun div(other: Double): Matrix3d {
return super.div(other) as Matrix3d
}
final override fun add(other: Double2DArray): Matrix3d {
return super.add(other) as Matrix3d
}
final override fun sub(other: Double2DArray): Matrix3d {
return super.sub(other) as Matrix3d
}
fun to2d() = Matrix2d.from(this)
fun to4d(filler: Double) = Matrix4d.from(this, filler)
fun to4d() = Matrix4d.from(this)
fun copy(): Matrix3d {
return Impl(c00, c01, c02, c10, c11, c12, c20, c21, c22)
}
@JvmOverloads
fun translate(x: Double = 0.0, y: Double = 0.0): Matrix3d {
return mul(c20 = x, c21 = y)
}
fun translate(value: IStruct2d) = translate(value.component1(), value.component2())
fun translate(value: Vector2d) = translate(value.component1(), value.component2())
@JvmOverloads
fun preTranslate(x: Double = 0.0, y: Double = 0.0): Matrix3d {
return mulIntoThis(c20 = x, c21 = y)
}
fun preTranslate(value: IStruct2d) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: Vector2d) = preTranslate(value.component1(), value.component2())
@JvmOverloads
fun scale(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0): Matrix3d {
return mul(c00 = x, c11 = y, c22 = z)
}
fun scale(value: IStruct2d) = scale(value.component1(), value.component2())
fun scale(value: IStruct3d) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: Vector2d) = scale(value.component1(), value.component2())
fun scale(value: Vector3d) = scale(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun preScale(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0): Matrix3d {
return mulIntoThis(c00 = x, c11 = y, c22 = z)
}
fun preScale(value: IStruct2d) = preScale(value.component1(), value.component2())
fun preScale(value: IStruct3d) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: Vector2d) = preScale(value.component1(), value.component2())
fun preScale(value: Vector3d) = preScale(value.component1(), value.component2(), value.component3())
fun rotateAroundZ(angle: Double): Matrix3d {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
fun preRotateAroundZ(angle: Double): Matrix3d {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
private data class Impl(
override var c00: Double,
override var c01: Double,
override var c02: Double,
override var c10: Double,
override var c11: Double,
override var c12: Double,
override var c20: Double,
override var c21: Double,
override var c22: Double,
) : Matrix3d() {
override fun toString(): String {
return "Matrix3d" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix3d) return false
return this === other || c00 == other.c00 &&
c01 == other.c01 &&
c02 == other.c02 &&
c10 == other.c10 &&
c11 == other.c11 &&
c12 == other.c12 &&
c20 == other.c20 &&
c21 == other.c21 &&
c22 == other.c22
}
}
private class View(private val parent: Matrix3d) : Matrix3d() {
override var c00: Double get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Double get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c02: Double get() = parent.c02; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Double get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Double get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c12: Double get() = parent.c12; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c20: Double get() = parent.c20; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c21: Double get() = parent.c21; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c22: Double get() = parent.c22; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Double) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Double) = construct3(value, ::columnMajor)
@JvmStatic
fun zero() = all(0.0)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix3d): Matrix3d {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Double = 1.0, c01: Double = 0.0, c02: Double = 0.0,
c10: Double = 0.0, c11: Double = 1.0, c12: Double = 0.0,
c20: Double = 0.0, c21: Double = 0.0, c22: Double = 1.0,
): Matrix3d {
return Impl(c00, c01, c02, c10, c11, c12, c20, c21, c22)
}
@JvmStatic
fun rowMajor(
r00: Double = 1.0, r01: Double = 0.0, r02: Double = 0.0,
r10: Double = 0.0, r11: Double = 1.0, r12: Double = 0.0,
r20: Double = 0.0, r21: Double = 0.0, r22: Double = 1.0,
): Matrix3d {
return Impl(
r00, r10, r20,
r01, r11, r21,
r02, r12, r22,
)
}
@JvmStatic
fun from(matrix: Double2DArray, filler: Double) = construct3(matrix, Double2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Double2DArray) = construct3(matrix, Double2DArray::get, ::columnMajor, 0.0)
@JvmStatic
fun from(matrix: Matrix3d) = construct3(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix4d) = construct3(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Double2DArray, filler: Double) = construct3(matrix, Double2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Double2DArray) = construct3(matrix, Double2DArray::get, Companion::rowMajor, 0.0)
@JvmStatic
fun fromTransposed(matrix: Matrix3d) = construct3(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix4d) = construct3(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: DoubleBuffer) = construct3(buffer, DoubleBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct3(buffer, ByteBuffer::getDouble, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: DoubleBuffer) = construct3(buffer, DoubleBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct3(buffer, ByteBuffer::getDouble, Companion::rowMajor)
/**
* Constructs new ortho projection matrix, with Y coordinate flipped (useful for OpenGL GUI drawing).
*
* Inversion of Y means that X 0 Y 0 will be top left position on screen (in OpenGL), not bottom left.
*/
@JvmStatic
fun ortho(left: Double, right: Double, bottom: Double, top: Double): Matrix3d {
return rowMajor(
r00 = 2.0 / (right - left),
r11 = -2.0 / (top - bottom),
r02 = -(right + left) / (right - left),
r12 = -(top + bottom) / (top - bottom) + 2f,
)
}
/**
* Constructs new ortho projection matrix
*/
@JvmStatic
fun orthoDirect(left: Double, right: Double, bottom: Double, top: Double): Matrix3d {
return rowMajor(
r00 = 2.0 / (right - left),
r11 = 2.0 / (top - bottom),
r02 = -(right + left) / (right - left),
r12 = -(top + bottom) / (top - bottom),
)
}
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 2))
const val C01 = (0 or (1 shl 2))
const val C02 = (0 or (2 shl 2))
const val C10 = (1 or (0 shl 2))
const val C11 = (1 or (1 shl 2))
const val C12 = (1 or (2 shl 2))
const val C20 = (2 or (0 shl 2))
const val C21 = (2 or (1 shl 2))
const val C22 = (2 or (2 shl 2))
}
}

View File

@ -1,55 +0,0 @@
package ru.dbotthepony.kommons.matrix
class Matrix3dStack {
private val stack = ArrayDeque<Matrix3d>()
init {
stack.addLast(Matrix3d.identity())
}
fun clear(top: Matrix3d): Matrix3dStack {
stack.clear()
stack.addLast(top.copy())
return this
}
fun push(): Matrix3dStack {
stack.addLast(stack.last().copy())
return this
}
fun pop(): Matrix3d {
return stack.removeLast()
}
fun last(): Matrix3d {
return stack.last()
}
fun push(matrix: Matrix3d): Matrix3dStack {
stack.addLast(matrix.copy())
return this
}
fun identity() = push(Matrix3d.identity())
fun zero() = push(Matrix3d.all(0.0))
fun all(value: Double) = push(Matrix3d.all(value))
inline fun <T> with(block: Matrix3d.() -> T): T {
return try {
push()
block(last())
} finally {
pop()
}
}
inline fun <T> with(matrix: Matrix3d, block: Matrix3d.() -> T): T {
return try {
push(matrix)
block(last())
} finally {
pop()
}
}
}

View File

@ -1,496 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Float2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.vector.Vector2f
import ru.dbotthepony.kommons.vector.Vector3f
import java.nio.ByteBuffer
import java.nio.FloatBuffer
import kotlin.math.cos
import kotlin.math.sin
sealed class Matrix3f : Float2DArray() {
abstract var c00: Float
abstract var c01: Float
abstract var c02: Float
abstract var c10: Float
abstract var c11: Float
abstract var c12: Float
abstract var c20: Float
abstract var c21: Float
abstract var c22: Float
fun c00() = c00
fun c00(value: Float): Matrix3f { c00 = value; return this }
fun c01() = c01
fun c01(value: Float): Matrix3f { c01 = value; return this }
fun c02() = c02
fun c02(value: Float): Matrix3f { c02 = value; return this }
fun c10() = c10
fun c10(value: Float): Matrix3f { c10 = value; return this }
fun c11() = c11
fun c11(value: Float): Matrix3f { c11 = value; return this }
fun c12() = c12
fun c12(value: Float): Matrix3f { c12 = value; return this }
fun c20() = c20
fun c20(value: Float): Matrix3f { c20 = value; return this }
fun c21() = c21
fun c21(value: Float): Matrix3f { c21 = value; return this }
fun c22() = c22
fun c22(value: Float): Matrix3f { c22 = value; return this }
var r00: Float get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Float get() = c10; set(value) { c10 = value } // row 1 column 0
var r02: Float get() = c20; set(value) { c20 = value } // row 2 column 0
var r10: Float get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Float get() = c11; set(value) { c11 = value } // row 1 column 1
var r12: Float get() = c21; set(value) { c21 = value } // row 2 column 1
var r20: Float get() = c02; set(value) { c02 = value } // row 0 column 2
var r21: Float get() = c12; set(value) { c12 = value } // row 1 column 2
var r22: Float get() = c22; set(value) { c22 = value } // row 2 column 2
fun r00() = r00
fun r00(value: Float): Matrix3f { r00 = value; return this }
fun r01() = r01
fun r01(value: Float): Matrix3f { r01 = value; return this }
fun r02() = r02
fun r02(value: Float): Matrix3f { r02 = value; return this }
fun r10() = r10
fun r10(value: Float): Matrix3f { r10 = value; return this }
fun r11() = r11
fun r11(value: Float): Matrix3f { r11 = value; return this }
fun r12() = r12
fun r12(value: Float): Matrix3f { r12 = value; return this }
fun r20() = r20
fun r20(value: Float): Matrix3f { r20 = value; return this }
fun r21() = r21
fun r21(value: Float): Matrix3f { r21 = value; return this }
fun r22() = r22
fun r22(value: Float): Matrix3f { r22 = value; return this }
final override val rows: Int
get() = 3
final override val columns: Int
get() = 3
final override val determinant: Float
get() = super.determinant!!
final override val cofactorMatrix
get() = from(super.cofactorMatrix!!)
final override val adjugateMatrix
get() = from(super.adjugateMatrix!!)
final override val inversed
get() = super.inversed?.let { from(it) }
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c02 = r02,
c10 = r10,
c11 = r11,
c12 = r12,
c20 = r20,
c21 = r21,
c22 = r22,
)
final override fun get(column: Int, row: Int): Float {
return when (column or (row shl 2)) {
C00 -> c00
C01 -> c01
C02 -> c02
C10 -> c10
C11 -> c11
C12 -> c12
C20 -> c20
C21 -> c21
C22 -> c22
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Float) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C02 -> c02 = value
C10 -> c10 = value
C11 -> c11 = value
C12 -> c12 = value
C20 -> c20 = value
C21 -> c21 = value
C22 -> c22 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
fun mul(other: Matrix3f): Matrix3f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
this.c00 = c00
this.c01 = c01
this.c02 = c02
this.c10 = c10
this.c11 = c11
this.c12 = c12
this.c20 = c20
this.c21 = c21
this.c22 = c22
return this
}
fun mulIntoOther(other: Matrix3f): Matrix3f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
other.c00 = c00
other.c01 = c01
other.c02 = c02
other.c10 = c10
other.c11 = c11
other.c12 = c12
other.c20 = c20
other.c21 = c21
other.c22 = c22
return other
}
fun mul(
c00: Float = 1f,
c01: Float = 0f,
c02: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
c12: Float = 0f,
c20: Float = 0f,
c21: Float = 0f,
c22: Float = 1f,
): Matrix3f {
val fc00 = this.c00 * c00 + this.c10 * c01 + this.c20 * c02
val fc01 = this.c01 * c00 + this.c11 * c01 + this.c21 * c02
val fc02 = this.c02 * c00 + this.c12 * c01 + this.c22 * c02
val fc10 = this.c00 * c10 + this.c10 * c11 + this.c20 * c12
val fc11 = this.c01 * c10 + this.c11 * c11 + this.c21 * c12
val fc12 = this.c02 * c10 + this.c12 * c11 + this.c22 * c12
val fc20 = this.c00 * c20 + this.c10 * c21 + this.c20 * c22
val fc21 = this.c01 * c20 + this.c11 * c21 + this.c21 * c22
val fc22 = this.c02 * c20 + this.c12 * c21 + this.c22 * c22
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
return this
}
fun mulIntoThis(
c00: Float = 1f,
c01: Float = 0f,
c02: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
c12: Float = 0f,
c20: Float = 0f,
c21: Float = 0f,
c22: Float = 1f,
): Matrix3f {
val fc00 = c00 * this.c00 + c10 * this.c01 + c20 * this.c02
val fc01 = c01 * this.c00 + c11 * this.c01 + c21 * this.c02
val fc02 = c02 * this.c00 + c12 * this.c01 + c22 * this.c02
val fc10 = c00 * this.c10 + c10 * this.c11 + c20 * this.c12
val fc11 = c01 * this.c10 + c11 * this.c11 + c21 * this.c12
val fc12 = c02 * this.c10 + c12 * this.c11 + c22 * this.c12
val fc20 = c00 * this.c20 + c10 * this.c21 + c20 * this.c22
val fc21 = c01 * this.c20 + c11 * this.c21 + c21 * this.c22
val fc22 = c02 * this.c20 + c12 * this.c21 + c22 * this.c22
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
return this
}
final override fun add(other: Float): Matrix3f {
return super.add(other) as Matrix3f
}
final override fun sub(other: Float): Matrix3f {
return super.sub(other) as Matrix3f
}
final override fun mul(other: Float): Matrix3f {
return super.mul(other) as Matrix3f
}
final override fun div(other: Float): Matrix3f {
return super.div(other) as Matrix3f
}
final override fun add(other: Float2DArray): Matrix3f {
return super.add(other) as Matrix3f
}
final override fun sub(other: Float2DArray): Matrix3f {
return super.sub(other) as Matrix3f
}
fun to2f() = Matrix2f.from(this)
fun to4f(filler: Float) = Matrix4f.from(this, filler)
fun to4f() = Matrix4f.from(this)
fun copy(): Matrix3f {
return Impl(c00, c01, c02, c10, c11, c12, c20, c21, c22)
}
@JvmOverloads
fun translate(x: Float = 0f, y: Float = 0f): Matrix3f {
return mul(c20 = x, c21 = y)
}
fun translate(value: IStruct2f) = translate(value.component1(), value.component2())
fun translate(value: Vector2f) = translate(value.component1(), value.component2())
@JvmOverloads
fun preTranslate(x: Float = 0f, y: Float = 0f): Matrix3f {
return mulIntoThis(c20 = x, c21 = y)
}
fun preTranslate(value: IStruct2f) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: Vector2f) = preTranslate(value.component1(), value.component2())
@JvmOverloads
fun scale(x: Float = 1f, y: Float = 1f, z: Float = 1f): Matrix3f {
return mul(c00 = x, c11 = y, c22 = z)
}
fun scale(value: IStruct2f) = scale(value.component1(), value.component2())
fun scale(value: IStruct3f) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: Vector2f) = scale(value.component1(), value.component2())
fun scale(value: Vector3f) = scale(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun preScale(x: Float = 1f, y: Float = 1f, z: Float = 1f): Matrix3f {
return mulIntoThis(c00 = x, c11 = y, c22 = z)
}
fun preScale(value: IStruct2f) = preScale(value.component1(), value.component2())
fun preScale(value: IStruct3f) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: Vector2f) = preScale(value.component1(), value.component2())
fun preScale(value: Vector3f) = preScale(value.component1(), value.component2(), value.component3())
fun rotateAroundZ(angle: Float): Matrix3f {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
fun preRotateAroundZ(angle: Float): Matrix3f {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
private data class Impl(
override var c00: Float,
override var c01: Float,
override var c02: Float,
override var c10: Float,
override var c11: Float,
override var c12: Float,
override var c20: Float,
override var c21: Float,
override var c22: Float,
) : Matrix3f() {
override fun toString(): String {
return "Matrix3f" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix3f) return false
return c00 == other.c00 &&
c01 == other.c01 &&
c02 == other.c02 &&
c10 == other.c10 &&
c11 == other.c11 &&
c12 == other.c12 &&
c20 == other.c20 &&
c21 == other.c21 &&
c22 == other.c22
}
}
private class View(private val parent: Matrix3f) : Matrix3f() {
override var c00: Float get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Float get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c02: Float get() = parent.c02; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Float get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Float get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c12: Float get() = parent.c12; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c20: Float get() = parent.c20; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c21: Float get() = parent.c21; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c22: Float get() = parent.c22; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Float) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Float) = construct3(value, ::columnMajor)
@JvmStatic
fun zero() = all(0f)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix3f): Matrix3f {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Float = 1f, c01: Float = 0f, c02: Float = 0f,
c10: Float = 0f, c11: Float = 1f, c12: Float = 0f,
c20: Float = 0f, c21: Float = 0f, c22: Float = 1f,
): Matrix3f {
return Impl(c00, c01, c02, c10, c11, c12, c20, c21, c22)
}
@JvmStatic
fun rowMajor(
r00: Float = 1f, r01: Float = 0f, r02: Float = 0f,
r10: Float = 0f, r11: Float = 1f, r12: Float = 0f,
r20: Float = 0f, r21: Float = 0f, r22: Float = 1f,
): Matrix3f {
return Impl(
r00, r10, r20,
r01, r11, r21,
r02, r12, r22,
)
}
@JvmStatic
fun from(matrix: Float2DArray, filler: Float) = construct3(matrix, Float2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Float2DArray) = construct3(matrix, Float2DArray::get, ::columnMajor, 0f)
@JvmStatic
fun from(matrix: Matrix3f) = construct3(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun from(matrix: Matrix4f) = construct3(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Float2DArray, filler: Float) = construct3(matrix, Float2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Float2DArray) = construct3(matrix, Float2DArray::get, Companion::rowMajor, 0f)
@JvmStatic
fun fromTransposed(matrix: Matrix3f) = construct3(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromTransposed(matrix: Matrix4f) = construct3(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: FloatBuffer) = construct3(buffer, FloatBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct3(buffer, ByteBuffer::getFloat, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: FloatBuffer) = construct3(buffer, FloatBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct3(buffer, ByteBuffer::getFloat, Companion::rowMajor)
/**
* Constructs new ortho projection matrix, with Y coordinate flipped (useful for OpenGL GUI drawing).
*
* Inversion of Y means that X 0 Y 0 will be top left position on screen (in OpenGL), not bottom left.
*/
@JvmStatic
fun ortho(left: Float, right: Float, bottom: Float, top: Float): Matrix3f {
return rowMajor(
r00 = 2f / (right - left),
r11 = -2f / (top - bottom),
r02 = -(right + left) / (right - left),
r12 = -(top + bottom) / (top - bottom) + 2f,
)
}
/**
* Constructs new ortho projection matrix
*/
@JvmStatic
fun orthoDirect(left: Float, right: Float, bottom: Float, top: Float): Matrix3f {
return rowMajor(
r00 = 2f / (right - left),
r11 = 2f / (top - bottom),
r02 = -(right + left) / (right - left),
r12 = -(top + bottom) / (top - bottom),
)
}
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 2))
const val C01 = (0 or (1 shl 2))
const val C02 = (0 or (2 shl 2))
const val C10 = (1 or (0 shl 2))
const val C11 = (1 or (1 shl 2))
const val C12 = (1 or (2 shl 2))
const val C20 = (2 or (0 shl 2))
const val C21 = (2 or (1 shl 2))
const val C22 = (2 or (2 shl 2))
}
}

View File

@ -1,55 +0,0 @@
package ru.dbotthepony.kommons.matrix
class Matrix3fStack {
private val stack = ArrayDeque<Matrix3f>()
init {
stack.addLast(Matrix3f.identity())
}
fun clear(top: Matrix3f): Matrix3fStack {
stack.clear()
stack.addLast(top.copy())
return this
}
fun push(): Matrix3fStack {
stack.addLast(stack.last().copy())
return this
}
fun pop(): Matrix3f {
return stack.removeLast()
}
fun last(): Matrix3f {
return stack.last()
}
fun push(matrix: Matrix3f): Matrix3fStack {
stack.addLast(matrix.copy())
return this
}
fun identity() = push(Matrix3f.identity())
fun zero() = push(Matrix3f.all(0f))
fun all(value: Float) = push(Matrix3f.all(value))
inline fun <T> with(block: Matrix3f.() -> T): T {
return try {
push()
block(last())
} finally {
pop()
}
}
inline fun <T> with(matrix: Matrix3f, block: Matrix3f.() -> T): T {
return try {
push(matrix)
block(last())
} finally {
pop()
}
}
}

View File

@ -1,734 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Double2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct4d
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector3d
import ru.dbotthepony.kommons.vector.Vector4d
import java.nio.ByteBuffer
import java.nio.DoubleBuffer
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.tan
sealed class Matrix4d : Double2DArray() {
abstract var c00: Double
abstract var c01: Double
abstract var c02: Double
abstract var c03: Double
abstract var c10: Double
abstract var c11: Double
abstract var c12: Double
abstract var c13: Double
abstract var c20: Double
abstract var c21: Double
abstract var c22: Double
abstract var c23: Double
abstract var c30: Double
abstract var c31: Double
abstract var c32: Double
abstract var c33: Double
fun c00() = c00
fun c00(value: Double): Matrix4d { c00 = value; return this }
fun c01() = c01
fun c01(value: Double): Matrix4d { c01 = value; return this }
fun c02() = c02
fun c02(value: Double): Matrix4d { c02 = value; return this }
fun c03() = c03
fun c03(value: Double): Matrix4d { c03 = value; return this }
fun c10() = c10
fun c10(value: Double): Matrix4d { c10 = value; return this }
fun c11() = c11
fun c11(value: Double): Matrix4d { c11 = value; return this }
fun c12() = c12
fun c12(value: Double): Matrix4d { c12 = value; return this }
fun c13() = c13
fun c13(value: Double): Matrix4d { c13 = value; return this }
fun c20() = c20
fun c20(value: Double): Matrix4d { c20 = value; return this }
fun c21() = c21
fun c21(value: Double): Matrix4d { c21 = value; return this }
fun c22() = c22
fun c22(value: Double): Matrix4d { c22 = value; return this }
fun c23() = c23
fun c23(value: Double): Matrix4d { c23 = value; return this }
fun c30() = c30
fun c30(value: Double): Matrix4d { c30 = value; return this }
fun c31() = c31
fun c31(value: Double): Matrix4d { c31 = value; return this }
fun c32() = c32
fun c32(value: Double): Matrix4d { c32 = value; return this }
fun c33() = c33
fun c33(value: Double): Matrix4d { c33 = value; return this }
var r00: Double get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Double get() = c10; set(value) { c10 = value } // row 1 column 0
var r02: Double get() = c20; set(value) { c20 = value } // row 2 column 0
var r03: Double get() = c30; set(value) { c30 = value } // row 3 column 0
var r10: Double get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Double get() = c11; set(value) { c11 = value } // row 1 column 1
var r12: Double get() = c21; set(value) { c21 = value } // row 2 column 1
var r13: Double get() = c31; set(value) { c31 = value } // row 3 column 1
var r20: Double get() = c02; set(value) { c02 = value } // row 0 column 2
var r21: Double get() = c12; set(value) { c12 = value } // row 1 column 2
var r22: Double get() = c22; set(value) { c22 = value } // row 2 column 2
var r23: Double get() = c32; set(value) { c32 = value } // row 3 column 2
var r30: Double get() = c03; set(value) { c03 = value } // row 0 column 3
var r31: Double get() = c13; set(value) { c13 = value } // row 1 column 3
var r32: Double get() = c23; set(value) { c23 = value } // row 2 column 3
var r33: Double get() = c33; set(value) { c33 = value } // row 3 column 3
fun r00() = r00
fun r00(value: Double): Matrix4d { r00 = value; return this }
fun r01() = r01
fun r01(value: Double): Matrix4d { r01 = value; return this }
fun r02() = r02
fun r02(value: Double): Matrix4d { r02 = value; return this }
fun r03() = r03
fun r03(value: Double): Matrix4d { r03 = value; return this }
fun r10() = r10
fun r10(value: Double): Matrix4d { r10 = value; return this }
fun r11() = r11
fun r11(value: Double): Matrix4d { r11 = value; return this }
fun r12() = r12
fun r12(value: Double): Matrix4d { r12 = value; return this }
fun r13() = r13
fun r13(value: Double): Matrix4d { r13 = value; return this }
fun r20() = r20
fun r20(value: Double): Matrix4d { r20 = value; return this }
fun r21() = r21
fun r21(value: Double): Matrix4d { r21 = value; return this }
fun r22() = r22
fun r22(value: Double): Matrix4d { r22 = value; return this }
fun r23() = r23
fun r23(value: Double): Matrix4d { r23 = value; return this }
fun r30() = r30
fun r30(value: Double): Matrix4d { r30 = value; return this }
fun r31() = r31
fun r31(value: Double): Matrix4d { r31 = value; return this }
fun r32() = r32
fun r32(value: Double): Matrix4d { r32 = value; return this }
fun r33() = r33
fun r33(value: Double): Matrix4d { r33 = value; return this }
final override val rows: Int
get() = 4
final override val columns: Int
get() = 4
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c02 = r02,
c03 = r03,
c10 = r10,
c11 = r11,
c12 = r12,
c13 = r13,
c20 = r20,
c21 = r21,
c22 = r22,
c23 = r23,
c30 = r30,
c31 = r31,
c32 = r32,
c33 = r33,
)
final override fun get(column: Int, row: Int): Double {
return when (column or (row shl 2)) {
C00 -> c00
C01 -> c01
C02 -> c02
C03 -> c03
C10 -> c10
C11 -> c11
C12 -> c12
C13 -> c13
C20 -> c20
C21 -> c21
C22 -> c22
C23 -> c23
C30 -> c30
C31 -> c31
C32 -> c32
C33 -> c33
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Double) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C02 -> c02 = value
C03 -> c03 = value
C10 -> c10 = value
C11 -> c11 = value
C12 -> c12 = value
C13 -> c13 = value
C20 -> c20 = value
C21 -> c21 = value
C22 -> c22 = value
C23 -> c23 = value
C30 -> c30 = value
C31 -> c31 = value
C32 -> c32 = value
C33 -> c33 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
fun mul(other: Matrix4d): Matrix4d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c03 = mulMatrixComponents(this, other, 0, 3)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c13 = mulMatrixComponents(this, other, 1, 3)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
val c23 = mulMatrixComponents(this, other, 2, 3)
val c30 = mulMatrixComponents(this, other, 3, 0)
val c31 = mulMatrixComponents(this, other, 3, 1)
val c32 = mulMatrixComponents(this, other, 3, 2)
val c33 = mulMatrixComponents(this, other, 3, 3)
this.c00 = c00
this.c01 = c01
this.c02 = c02
this.c03 = c03
this.c10 = c10
this.c11 = c11
this.c12 = c12
this.c13 = c13
this.c20 = c20
this.c21 = c21
this.c22 = c22
this.c23 = c23
this.c30 = c30
this.c31 = c31
this.c32 = c32
this.c33 = c33
return this
}
fun mulIntoOther(other: Matrix4d): Matrix4d {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c03 = mulMatrixComponents(this, other, 0, 3)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c13 = mulMatrixComponents(this, other, 1, 3)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
val c23 = mulMatrixComponents(this, other, 2, 3)
val c30 = mulMatrixComponents(this, other, 3, 0)
val c31 = mulMatrixComponents(this, other, 3, 1)
val c32 = mulMatrixComponents(this, other, 3, 2)
val c33 = mulMatrixComponents(this, other, 3, 3)
other.c00 = c00
other.c01 = c01
other.c02 = c02
other.c03 = c03
other.c10 = c10
other.c11 = c11
other.c12 = c12
other.c13 = c13
other.c20 = c20
other.c21 = c21
other.c22 = c22
other.c23 = c23
other.c30 = c30
other.c31 = c31
other.c32 = c32
other.c33 = c33
return other
}
/**
* this * other, writes result into this
*/
fun mul(
c00: Double = 1.0,
c01: Double = 0.0,
c02: Double = 0.0,
c03: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
c12: Double = 0.0,
c13: Double = 0.0,
c20: Double = 0.0,
c21: Double = 0.0,
c22: Double = 1.0,
c23: Double = 0.0,
c30: Double = 0.0,
c31: Double = 0.0,
c32: Double = 0.0,
c33: Double = 1.0,
): Matrix4d {
val fc00 = this.c00 * c00 + this.c10 * c01 + this.c20 * c02 + this.c30 * c03
val fc01 = this.c01 * c00 + this.c11 * c01 + this.c21 * c02 + this.c31 * c03
val fc02 = this.c02 * c00 + this.c12 * c01 + this.c22 * c02 + this.c32 * c03
val fc03 = this.c03 * c00 + this.c13 * c01 + this.c23 * c02 + this.c33 * c03
val fc10 = this.c00 * c10 + this.c10 * c11 + this.c20 * c12 + this.c30 * c13
val fc11 = this.c01 * c10 + this.c11 * c11 + this.c21 * c12 + this.c31 * c13
val fc12 = this.c02 * c10 + this.c12 * c11 + this.c22 * c12 + this.c32 * c13
val fc13 = this.c03 * c10 + this.c13 * c11 + this.c23 * c12 + this.c33 * c13
val fc20 = this.c00 * c20 + this.c10 * c21 + this.c20 * c22 + this.c30 * c23
val fc21 = this.c01 * c20 + this.c11 * c21 + this.c21 * c22 + this.c31 * c23
val fc22 = this.c02 * c20 + this.c12 * c21 + this.c22 * c22 + this.c32 * c23
val fc23 = this.c03 * c20 + this.c13 * c21 + this.c23 * c22 + this.c33 * c23
val fc30 = this.c00 * c30 + this.c10 * c31 + this.c20 * c32 + this.c30 * c33
val fc31 = this.c01 * c30 + this.c11 * c31 + this.c21 * c32 + this.c31 * c33
val fc32 = this.c02 * c30 + this.c12 * c31 + this.c22 * c32 + this.c32 * c33
val fc33 = this.c03 * c30 + this.c13 * c31 + this.c23 * c32 + this.c33 * c33
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c03 = fc03
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c13 = fc13
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
this.c23 = fc23
this.c30 = fc30
this.c31 = fc31
this.c32 = fc32
this.c33 = fc33
return this
}
/**
* other * this, writes result into this
*/
fun mulIntoThis(
c00: Double = 1.0,
c01: Double = 0.0,
c02: Double = 0.0,
c03: Double = 0.0,
c10: Double = 0.0,
c11: Double = 1.0,
c12: Double = 0.0,
c13: Double = 0.0,
c20: Double = 0.0,
c21: Double = 0.0,
c22: Double = 1.0,
c23: Double = 0.0,
c30: Double = 0.0,
c31: Double = 0.0,
c32: Double = 0.0,
c33: Double = 1.0,
): Matrix4d {
val fc00 = c00 * this.c00 + c10 * this.c01 + c20 * this.c02 + c30 * this.c03
val fc01 = c01 * this.c00 + c11 * this.c01 + c21 * this.c02 + c31 * this.c03
val fc02 = c02 * this.c00 + c12 * this.c01 + c22 * this.c02 + c32 * this.c03
val fc03 = c03 * this.c00 + c13 * this.c01 + c23 * this.c02 + c33 * this.c03
val fc10 = c00 * this.c10 + c10 * this.c11 + c20 * this.c12 + c30 * this.c13
val fc11 = c01 * this.c10 + c11 * this.c11 + c21 * this.c12 + c31 * this.c13
val fc12 = c02 * this.c10 + c12 * this.c11 + c22 * this.c12 + c32 * this.c13
val fc13 = c03 * this.c10 + c13 * this.c11 + c23 * this.c12 + c33 * this.c13
val fc20 = c00 * this.c20 + c10 * this.c21 + c20 * this.c22 + c30 * this.c23
val fc21 = c01 * this.c20 + c11 * this.c21 + c21 * this.c22 + c31 * this.c23
val fc22 = c02 * this.c20 + c12 * this.c21 + c22 * this.c22 + c32 * this.c23
val fc23 = c03 * this.c20 + c13 * this.c21 + c23 * this.c22 + c33 * this.c23
val fc30 = c00 * this.c30 + c10 * this.c31 + c20 * this.c32 + c30 * this.c33
val fc31 = c01 * this.c30 + c11 * this.c31 + c21 * this.c32 + c31 * this.c33
val fc32 = c02 * this.c30 + c12 * this.c31 + c22 * this.c32 + c32 * this.c33
val fc33 = c03 * this.c30 + c13 * this.c31 + c23 * this.c32 + c33 * this.c33
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c03 = fc03
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c13 = fc13
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
this.c23 = fc23
this.c30 = fc30
this.c31 = fc31
this.c32 = fc32
this.c33 = fc33
return this
}
final override fun add(other: Double): Matrix4d {
return super.add(other) as Matrix4d
}
final override fun sub(other: Double): Matrix4d {
return super.sub(other) as Matrix4d
}
final override fun mul(other: Double): Matrix4d {
return super.mul(other) as Matrix4d
}
final override fun div(other: Double): Matrix4d {
return super.div(other) as Matrix4d
}
final override fun add(other: Double2DArray): Matrix4d {
return super.add(other) as Matrix4d
}
final override fun sub(other: Double2DArray): Matrix4d {
return super.sub(other) as Matrix4d
}
fun to2d() = Matrix2d.from(this)
fun to3d() = Matrix3d.from(this)
fun copy(): Matrix4d {
return Impl(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33)
}
@JvmOverloads
fun translate(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0): Matrix4d {
return mul(c30 = x, c31 = y, c32 = z)
}
fun translate(value: IStruct2d) = translate(value.component1(), value.component2())
fun translate(value: IStruct3d) = translate(value.component1(), value.component2(), value.component3())
fun translate(value: Vector2d) = translate(value.component1(), value.component2())
fun translate(value: Vector3d) = translate(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun preTranslate(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0): Matrix4d {
return mulIntoThis(c30 = x, c31 = y, c32 = z)
}
fun preTranslate(value: IStruct2d) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: IStruct3d) = preTranslate(value.component1(), value.component2(), value.component3())
fun preTranslate(value: Vector2d) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: Vector3d) = preTranslate(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun scale(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0): Matrix4d {
return mul(c00 = x, c11 = y, c22 = z, c33 = w)
}
fun scale(value: IStruct2d) = scale(value.component1(), value.component2())
fun scale(value: IStruct3d) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: IStruct4d) = scale(value.component1(), value.component2(), value.component3(), value.component3())
fun scale(value: Vector2d) = scale(value.component1(), value.component2())
fun scale(value: Vector3d) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: Vector4d) = scale(value.component1(), value.component2(), value.component3(), value.component3())
@JvmOverloads
fun preScale(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0): Matrix4d {
return mulIntoThis(c00 = x, c11 = y, c22 = z, c33 = w)
}
fun preScale(value: IStruct2d) = preScale(value.component1(), value.component2())
fun preScale(value: IStruct3d) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: IStruct4d) = preScale(value.component1(), value.component2(), value.component3(), value.component3())
fun preScale(value: Vector2d) = preScale(value.component1(), value.component2())
fun preScale(value: Vector3d) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: Vector4d) = preScale(value.component1(), value.component2(), value.component3(), value.component3())
fun rotateAroundX(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c11 = cos,
c21 = -sin,
c12 = sin,
c22 = cos,
)
}
fun rotateAroundY(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c20 = sin,
c02 = -sin,
c22 = cos,
)
}
fun rotateAroundZ(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
fun preRotateAroundX(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c11 = cos,
c21 = -sin,
c12 = sin,
c22 = cos,
)
}
fun preRotateAroundY(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c20 = sin,
c02 = -sin,
c22 = cos,
)
}
fun preRotateAroundZ(angle: Double): Matrix4d {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
private data class Impl(
override var c00: Double,
override var c01: Double,
override var c02: Double,
override var c03: Double,
override var c10: Double,
override var c11: Double,
override var c12: Double,
override var c13: Double,
override var c20: Double,
override var c21: Double,
override var c22: Double,
override var c23: Double,
override var c30: Double,
override var c31: Double,
override var c32: Double,
override var c33: Double,
) : Matrix4d() {
override fun toString(): String {
return "Matrix4d" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix4d) return false
return this === other || c00 == other.c00 &&
c01 == other.c01 &&
c02 == other.c02 &&
c03 == other.c03 &&
c10 == other.c10 &&
c11 == other.c11 &&
c12 == other.c12 &&
c13 == other.c13 &&
c20 == other.c20 &&
c21 == other.c21 &&
c22 == other.c22 &&
c23 == other.c23 &&
c30 == other.c30 &&
c31 == other.c31 &&
c32 == other.c32 &&
c33 == other.c33
}
}
private class View(private val parent: Matrix4d) : Matrix4d() {
override var c00: Double get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Double get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c02: Double get() = parent.c02; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c03: Double get() = parent.c03; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Double get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Double get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c12: Double get() = parent.c12; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c13: Double get() = parent.c13; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c20: Double get() = parent.c20; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c21: Double get() = parent.c21; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c22: Double get() = parent.c22; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c23: Double get() = parent.c23; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c30: Double get() = parent.c30; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c31: Double get() = parent.c31; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c32: Double get() = parent.c32; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c33: Double get() = parent.c33; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Double) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Double) = construct4(value, ::columnMajor)
@JvmStatic
fun zero() = all(0.0)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix4d): Matrix4d {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Double = 1.0, c01: Double = 0.0, c02: Double = 0.0, c03: Double = 0.0,
c10: Double = 0.0, c11: Double = 1.0, c12: Double = 0.0, c13: Double = 0.0,
c20: Double = 0.0, c21: Double = 0.0, c22: Double = 1.0, c23: Double = 0.0,
c30: Double = 0.0, c31: Double = 0.0, c32: Double = 0.0, c33: Double = 1.0,
): Matrix4d {
return Impl(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33)
}
@JvmStatic
fun rowMajor(
r00: Double = 1.0, r01: Double = 0.0, r02: Double = 0.0, r03: Double = 0.0,
r10: Double = 0.0, r11: Double = 1.0, r12: Double = 0.0, r13: Double = 0.0,
r20: Double = 0.0, r21: Double = 0.0, r22: Double = 1.0, r23: Double = 0.0,
r30: Double = 0.0, r31: Double = 0.0, r32: Double = 0.0, r33: Double = 1.0
): Matrix4d {
return Impl(
r00, r10, r20, r30,
r01, r11, r21, r31,
r02, r12, r22, r32,
r03, r13, r23, r33
)
}
@JvmStatic
fun from(matrix: Double2DArray, filler: Double) = construct4(matrix, Double2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Double2DArray) = construct4(matrix, Double2DArray::get, ::columnMajor, 0.0)
@JvmStatic
fun from(matrix: Matrix4d) = construct4(matrix, Double2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Double2DArray) = construct4(matrix, Double2DArray::get, Companion::rowMajor, 0.0)
@JvmStatic
fun fromTransposed(matrix: Double2DArray, filler: Double) = construct4(matrix, Double2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Matrix4d) = construct4(matrix, Double2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: DoubleBuffer) = construct4(buffer, DoubleBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct4(buffer, ByteBuffer::getDouble, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: DoubleBuffer) = construct4(buffer, DoubleBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct4(buffer, ByteBuffer::getDouble, Companion::rowMajor)
/**
* Constructs new ortho projection matrix, with Y coordinate flipped (useful for OpenGL GUI drawing).
*
* Inversion of Y means that X 0 Y 0 will be top left position on screen (in OpenGL), not bottom left.
*/
@JvmStatic
fun ortho(left: Double, right: Double, bottom: Double, top: Double, zNear: Double, zFar: Double): Matrix4d {
return rowMajor(
r00 = 2.0 / (right - left),
r11 = -2.0 / (top - bottom),
r22 = 2.0 / (zFar - zNear),
r03 = -(right + left) / (right - left),
r13 = -(top + bottom) / (top - bottom) + 2.0,
r23 = -(zFar + zNear) / (zFar - zNear)
)
}
/**
* Constructs new ortho projection matrix
*/
@JvmStatic
fun orthoDirect(left: Double, right: Double, bottom: Double, top: Double, zNear: Double, zFar: Double): Matrix4d {
return rowMajor(
r00 = 2.0 / (right - left),
r11 = 2.0 / (top - bottom),
r22 = 2.0 / (zFar - zNear),
r03 = -(right + left) / (right - left),
r13 = -(top + bottom) / (top - bottom),
r23 = -(zFar + zNear) / (zFar - zNear)
)
}
/**
* Constructs new perspective matrix
*/
@JvmStatic
fun perspective(fov: Double, zFar: Double, zNear: Double): Matrix4d {
val scale = (1.0 / (tan(Math.toRadians(fov.toDouble()) / 2.0))).toDouble()
val r = zFar - zNear
return rowMajor(
r00 = scale,
r11 = scale,
r22 = -zFar / r,
r23 = -1.0,
r32 = -zFar * zNear / r,
)
}
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 2))
const val C01 = (0 or (1 shl 2))
const val C02 = (0 or (2 shl 2))
const val C03 = (0 or (3 shl 2))
const val C10 = (1 or (0 shl 2))
const val C11 = (1 or (1 shl 2))
const val C12 = (1 or (2 shl 2))
const val C13 = (1 or (3 shl 2))
const val C20 = (2 or (0 shl 2))
const val C21 = (2 or (1 shl 2))
const val C22 = (2 or (2 shl 2))
const val C23 = (2 or (3 shl 2))
const val C30 = (3 or (0 shl 2))
const val C31 = (3 or (1 shl 2))
const val C32 = (3 or (2 shl 2))
const val C33 = (3 or (3 shl 2))
}
}

View File

@ -1,55 +0,0 @@
package ru.dbotthepony.kommons.matrix
class Matrix4dStack {
private val stack = ArrayDeque<Matrix4d>()
init {
stack.addLast(Matrix4d.identity())
}
fun clear(top: Matrix4d): Matrix4dStack {
stack.clear()
stack.addLast(top.copy())
return this
}
fun push(): Matrix4dStack {
stack.addLast(stack.last().copy())
return this
}
fun pop(): Matrix4d {
return stack.removeLast()
}
fun last(): Matrix4d {
return stack.last()
}
fun push(matrix: Matrix4d): Matrix4dStack {
stack.addLast(matrix.copy())
return this
}
fun identity() = push(Matrix4d.identity())
fun zero() = push(Matrix4d.all(0.0))
fun all(value: Double) = push(Matrix4d.all(value))
inline fun <T> with(block: Matrix4d.() -> T): T {
return try {
push()
block(last())
} finally {
pop()
}
}
inline fun <T> with(matrix: Matrix4d, block: Matrix4d.() -> T): T {
return try {
push(matrix)
block(last())
} finally {
pop()
}
}
}

View File

@ -1,734 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Float2DArray
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct4f
import ru.dbotthepony.kommons.vector.Vector2f
import ru.dbotthepony.kommons.vector.Vector3f
import ru.dbotthepony.kommons.vector.Vector4f
import java.nio.ByteBuffer
import java.nio.FloatBuffer
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.tan
sealed class Matrix4f : Float2DArray() {
abstract var c00: Float
abstract var c01: Float
abstract var c02: Float
abstract var c03: Float
abstract var c10: Float
abstract var c11: Float
abstract var c12: Float
abstract var c13: Float
abstract var c20: Float
abstract var c21: Float
abstract var c22: Float
abstract var c23: Float
abstract var c30: Float
abstract var c31: Float
abstract var c32: Float
abstract var c33: Float
fun c00() = c00
fun c00(value: Float): Matrix4f { c00 = value; return this }
fun c01() = c01
fun c01(value: Float): Matrix4f { c01 = value; return this }
fun c02() = c02
fun c02(value: Float): Matrix4f { c02 = value; return this }
fun c03() = c03
fun c03(value: Float): Matrix4f { c03 = value; return this }
fun c10() = c10
fun c10(value: Float): Matrix4f { c10 = value; return this }
fun c11() = c11
fun c11(value: Float): Matrix4f { c11 = value; return this }
fun c12() = c12
fun c12(value: Float): Matrix4f { c12 = value; return this }
fun c13() = c13
fun c13(value: Float): Matrix4f { c13 = value; return this }
fun c20() = c20
fun c20(value: Float): Matrix4f { c20 = value; return this }
fun c21() = c21
fun c21(value: Float): Matrix4f { c21 = value; return this }
fun c22() = c22
fun c22(value: Float): Matrix4f { c22 = value; return this }
fun c23() = c23
fun c23(value: Float): Matrix4f { c23 = value; return this }
fun c30() = c30
fun c30(value: Float): Matrix4f { c30 = value; return this }
fun c31() = c31
fun c31(value: Float): Matrix4f { c31 = value; return this }
fun c32() = c32
fun c32(value: Float): Matrix4f { c32 = value; return this }
fun c33() = c33
fun c33(value: Float): Matrix4f { c33 = value; return this }
var r00: Float get() = c00; set(value) { c00 = value } // row 0 column 0
var r01: Float get() = c10; set(value) { c10 = value } // row 1 column 0
var r02: Float get() = c20; set(value) { c20 = value } // row 2 column 0
var r03: Float get() = c30; set(value) { c30 = value } // row 3 column 0
var r10: Float get() = c01; set(value) { c01 = value } // row 0 column 1
var r11: Float get() = c11; set(value) { c11 = value } // row 1 column 1
var r12: Float get() = c21; set(value) { c21 = value } // row 2 column 1
var r13: Float get() = c31; set(value) { c31 = value } // row 3 column 1
var r20: Float get() = c02; set(value) { c02 = value } // row 0 column 2
var r21: Float get() = c12; set(value) { c12 = value } // row 1 column 2
var r22: Float get() = c22; set(value) { c22 = value } // row 2 column 2
var r23: Float get() = c32; set(value) { c32 = value } // row 3 column 2
var r30: Float get() = c03; set(value) { c03 = value } // row 0 column 3
var r31: Float get() = c13; set(value) { c13 = value } // row 1 column 3
var r32: Float get() = c23; set(value) { c23 = value } // row 2 column 3
var r33: Float get() = c33; set(value) { c33 = value } // row 3 column 3
fun r00() = r00
fun r00(value: Float): Matrix4f { r00 = value; return this }
fun r01() = r01
fun r01(value: Float): Matrix4f { r01 = value; return this }
fun r02() = r02
fun r02(value: Float): Matrix4f { r02 = value; return this }
fun r03() = r03
fun r03(value: Float): Matrix4f { r03 = value; return this }
fun r10() = r10
fun r10(value: Float): Matrix4f { r10 = value; return this }
fun r11() = r11
fun r11(value: Float): Matrix4f { r11 = value; return this }
fun r12() = r12
fun r12(value: Float): Matrix4f { r12 = value; return this }
fun r13() = r13
fun r13(value: Float): Matrix4f { r13 = value; return this }
fun r20() = r20
fun r20(value: Float): Matrix4f { r20 = value; return this }
fun r21() = r21
fun r21(value: Float): Matrix4f { r21 = value; return this }
fun r22() = r22
fun r22(value: Float): Matrix4f { r22 = value; return this }
fun r23() = r23
fun r23(value: Float): Matrix4f { r23 = value; return this }
fun r30() = r30
fun r30(value: Float): Matrix4f { r30 = value; return this }
fun r31() = r31
fun r31(value: Float): Matrix4f { r31 = value; return this }
fun r32() = r32
fun r32(value: Float): Matrix4f { r32 = value; return this }
fun r33() = r33
fun r33(value: Float): Matrix4f { r33 = value; return this }
final override val rows: Int
get() = 4
final override val columns: Int
get() = 4
final override val transposed get() =
columnMajor(
c00 = r00,
c01 = r01,
c02 = r02,
c03 = r03,
c10 = r10,
c11 = r11,
c12 = r12,
c13 = r13,
c20 = r20,
c21 = r21,
c22 = r22,
c23 = r23,
c30 = r30,
c31 = r31,
c32 = r32,
c33 = r33,
)
final override fun get(column: Int, row: Int): Float {
return when (column or (row shl 2)) {
C00 -> c00
C01 -> c01
C02 -> c02
C03 -> c03
C10 -> c10
C11 -> c11
C12 -> c12
C13 -> c13
C20 -> c20
C21 -> c21
C22 -> c22
C23 -> c23
C30 -> c30
C31 -> c31
C32 -> c32
C33 -> c33
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
override fun set(column: Int, row: Int, value: Float) {
when (column or (row shl 2)) {
C00 -> c00 = value
C01 -> c01 = value
C02 -> c02 = value
C03 -> c03 = value
C10 -> c10 = value
C11 -> c11 = value
C12 -> c12 = value
C13 -> c13 = value
C20 -> c20 = value
C21 -> c21 = value
C22 -> c22 = value
C23 -> c23 = value
C30 -> c30 = value
C31 -> c31 = value
C32 -> c32 = value
C33 -> c33 = value
else -> throw IndexOutOfBoundsException("Column $column; Row $row; while size of this matrix are 4x4")
}
}
fun mul(other: Matrix4f): Matrix4f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c03 = mulMatrixComponents(this, other, 0, 3)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c13 = mulMatrixComponents(this, other, 1, 3)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
val c23 = mulMatrixComponents(this, other, 2, 3)
val c30 = mulMatrixComponents(this, other, 3, 0)
val c31 = mulMatrixComponents(this, other, 3, 1)
val c32 = mulMatrixComponents(this, other, 3, 2)
val c33 = mulMatrixComponents(this, other, 3, 3)
this.c00 = c00
this.c01 = c01
this.c02 = c02
this.c03 = c03
this.c10 = c10
this.c11 = c11
this.c12 = c12
this.c13 = c13
this.c20 = c20
this.c21 = c21
this.c22 = c22
this.c23 = c23
this.c30 = c30
this.c31 = c31
this.c32 = c32
this.c33 = c33
return this
}
fun mulIntoOther(other: Matrix4f): Matrix4f {
val c00 = mulMatrixComponents(this, other, 0, 0)
val c01 = mulMatrixComponents(this, other, 0, 1)
val c02 = mulMatrixComponents(this, other, 0, 2)
val c03 = mulMatrixComponents(this, other, 0, 3)
val c10 = mulMatrixComponents(this, other, 1, 0)
val c11 = mulMatrixComponents(this, other, 1, 1)
val c12 = mulMatrixComponents(this, other, 1, 2)
val c13 = mulMatrixComponents(this, other, 1, 3)
val c20 = mulMatrixComponents(this, other, 2, 0)
val c21 = mulMatrixComponents(this, other, 2, 1)
val c22 = mulMatrixComponents(this, other, 2, 2)
val c23 = mulMatrixComponents(this, other, 2, 3)
val c30 = mulMatrixComponents(this, other, 3, 0)
val c31 = mulMatrixComponents(this, other, 3, 1)
val c32 = mulMatrixComponents(this, other, 3, 2)
val c33 = mulMatrixComponents(this, other, 3, 3)
other.c00 = c00
other.c01 = c01
other.c02 = c02
other.c03 = c03
other.c10 = c10
other.c11 = c11
other.c12 = c12
other.c13 = c13
other.c20 = c20
other.c21 = c21
other.c22 = c22
other.c23 = c23
other.c30 = c30
other.c31 = c31
other.c32 = c32
other.c33 = c33
return other
}
/**
* this * other, writes result into this
*/
fun mul(
c00: Float = 1f,
c01: Float = 0f,
c02: Float = 0f,
c03: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
c12: Float = 0f,
c13: Float = 0f,
c20: Float = 0f,
c21: Float = 0f,
c22: Float = 1f,
c23: Float = 0f,
c30: Float = 0f,
c31: Float = 0f,
c32: Float = 0f,
c33: Float = 1f,
): Matrix4f {
val fc00 = this.c00 * c00 + this.c10 * c01 + this.c20 * c02 + this.c30 * c03
val fc01 = this.c01 * c00 + this.c11 * c01 + this.c21 * c02 + this.c31 * c03
val fc02 = this.c02 * c00 + this.c12 * c01 + this.c22 * c02 + this.c32 * c03
val fc03 = this.c03 * c00 + this.c13 * c01 + this.c23 * c02 + this.c33 * c03
val fc10 = this.c00 * c10 + this.c10 * c11 + this.c20 * c12 + this.c30 * c13
val fc11 = this.c01 * c10 + this.c11 * c11 + this.c21 * c12 + this.c31 * c13
val fc12 = this.c02 * c10 + this.c12 * c11 + this.c22 * c12 + this.c32 * c13
val fc13 = this.c03 * c10 + this.c13 * c11 + this.c23 * c12 + this.c33 * c13
val fc20 = this.c00 * c20 + this.c10 * c21 + this.c20 * c22 + this.c30 * c23
val fc21 = this.c01 * c20 + this.c11 * c21 + this.c21 * c22 + this.c31 * c23
val fc22 = this.c02 * c20 + this.c12 * c21 + this.c22 * c22 + this.c32 * c23
val fc23 = this.c03 * c20 + this.c13 * c21 + this.c23 * c22 + this.c33 * c23
val fc30 = this.c00 * c30 + this.c10 * c31 + this.c20 * c32 + this.c30 * c33
val fc31 = this.c01 * c30 + this.c11 * c31 + this.c21 * c32 + this.c31 * c33
val fc32 = this.c02 * c30 + this.c12 * c31 + this.c22 * c32 + this.c32 * c33
val fc33 = this.c03 * c30 + this.c13 * c31 + this.c23 * c32 + this.c33 * c33
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c03 = fc03
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c13 = fc13
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
this.c23 = fc23
this.c30 = fc30
this.c31 = fc31
this.c32 = fc32
this.c33 = fc33
return this
}
/**
* other * this, writes result into this
*/
fun mulIntoThis(
c00: Float = 1f,
c01: Float = 0f,
c02: Float = 0f,
c03: Float = 0f,
c10: Float = 0f,
c11: Float = 1f,
c12: Float = 0f,
c13: Float = 0f,
c20: Float = 0f,
c21: Float = 0f,
c22: Float = 1f,
c23: Float = 0f,
c30: Float = 0f,
c31: Float = 0f,
c32: Float = 0f,
c33: Float = 1f,
): Matrix4f {
val fc00 = c00 * this.c00 + c10 * this.c01 + c20 * this.c02 + c30 * this.c03
val fc01 = c01 * this.c00 + c11 * this.c01 + c21 * this.c02 + c31 * this.c03
val fc02 = c02 * this.c00 + c12 * this.c01 + c22 * this.c02 + c32 * this.c03
val fc03 = c03 * this.c00 + c13 * this.c01 + c23 * this.c02 + c33 * this.c03
val fc10 = c00 * this.c10 + c10 * this.c11 + c20 * this.c12 + c30 * this.c13
val fc11 = c01 * this.c10 + c11 * this.c11 + c21 * this.c12 + c31 * this.c13
val fc12 = c02 * this.c10 + c12 * this.c11 + c22 * this.c12 + c32 * this.c13
val fc13 = c03 * this.c10 + c13 * this.c11 + c23 * this.c12 + c33 * this.c13
val fc20 = c00 * this.c20 + c10 * this.c21 + c20 * this.c22 + c30 * this.c23
val fc21 = c01 * this.c20 + c11 * this.c21 + c21 * this.c22 + c31 * this.c23
val fc22 = c02 * this.c20 + c12 * this.c21 + c22 * this.c22 + c32 * this.c23
val fc23 = c03 * this.c20 + c13 * this.c21 + c23 * this.c22 + c33 * this.c23
val fc30 = c00 * this.c30 + c10 * this.c31 + c20 * this.c32 + c30 * this.c33
val fc31 = c01 * this.c30 + c11 * this.c31 + c21 * this.c32 + c31 * this.c33
val fc32 = c02 * this.c30 + c12 * this.c31 + c22 * this.c32 + c32 * this.c33
val fc33 = c03 * this.c30 + c13 * this.c31 + c23 * this.c32 + c33 * this.c33
this.c00 = fc00
this.c01 = fc01
this.c02 = fc02
this.c03 = fc03
this.c10 = fc10
this.c11 = fc11
this.c12 = fc12
this.c13 = fc13
this.c20 = fc20
this.c21 = fc21
this.c22 = fc22
this.c23 = fc23
this.c30 = fc30
this.c31 = fc31
this.c32 = fc32
this.c33 = fc33
return this
}
final override fun add(other: Float): Matrix4f {
return super.add(other) as Matrix4f
}
final override fun sub(other: Float): Matrix4f {
return super.sub(other) as Matrix4f
}
final override fun mul(other: Float): Matrix4f {
return super.mul(other) as Matrix4f
}
final override fun div(other: Float): Matrix4f {
return super.div(other) as Matrix4f
}
final override fun add(other: Float2DArray): Matrix4f {
return super.add(other) as Matrix4f
}
final override fun sub(other: Float2DArray): Matrix4f {
return super.sub(other) as Matrix4f
}
fun to2f() = Matrix2f.from(this)
fun to3f() = Matrix3f.from(this)
fun copy(): Matrix4f {
return Impl(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33)
}
@JvmOverloads
fun translate(x: Float = 0f, y: Float = 0f, z: Float = 0f): Matrix4f {
return mul(c30 = x, c31 = y, c32 = z)
}
fun translate(value: IStruct2f) = translate(value.component1(), value.component2())
fun translate(value: IStruct3f) = translate(value.component1(), value.component2(), value.component3())
fun translate(value: Vector2f) = translate(value.component1(), value.component2())
fun translate(value: Vector3f) = translate(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun preTranslate(x: Float = 0f, y: Float = 0f, z: Float = 0f): Matrix4f {
return mulIntoThis(c30 = x, c31 = y, c32 = z)
}
fun preTranslate(value: IStruct2f) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: IStruct3f) = preTranslate(value.component1(), value.component2(), value.component3())
fun preTranslate(value: Vector2f) = preTranslate(value.component1(), value.component2())
fun preTranslate(value: Vector3f) = preTranslate(value.component1(), value.component2(), value.component3())
@JvmOverloads
fun scale(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f): Matrix4f {
return mul(c00 = x, c11 = y, c22 = z, c33 = w)
}
fun scale(value: IStruct2f) = scale(value.component1(), value.component2())
fun scale(value: IStruct3f) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: IStruct4f) = scale(value.component1(), value.component2(), value.component3(), value.component3())
fun scale(value: Vector2f) = scale(value.component1(), value.component2())
fun scale(value: Vector3f) = scale(value.component1(), value.component2(), value.component3())
fun scale(value: Vector4f) = scale(value.component1(), value.component2(), value.component3(), value.component3())
@JvmOverloads
fun preScale(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f): Matrix4f {
return mulIntoThis(c00 = x, c11 = y, c22 = z, c33 = w)
}
fun preScale(value: IStruct2f) = preScale(value.component1(), value.component2())
fun preScale(value: IStruct3f) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: IStruct4f) = preScale(value.component1(), value.component2(), value.component3(), value.component3())
fun preScale(value: Vector2f) = preScale(value.component1(), value.component2())
fun preScale(value: Vector3f) = preScale(value.component1(), value.component2(), value.component3())
fun preScale(value: Vector4f) = preScale(value.component1(), value.component2(), value.component3(), value.component3())
fun rotateAroundX(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c11 = cos,
c21 = -sin,
c12 = sin,
c22 = cos,
)
}
fun rotateAroundY(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c20 = sin,
c02 = -sin,
c22 = cos,
)
}
fun rotateAroundZ(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mul(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
fun preRotateAroundX(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c11 = cos,
c21 = -sin,
c12 = sin,
c22 = cos,
)
}
fun preRotateAroundY(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c20 = sin,
c02 = -sin,
c22 = cos,
)
}
fun preRotateAroundZ(angle: Float): Matrix4f {
val cos = cos(angle)
val sin = sin(angle)
return mulIntoThis(
c00 = cos,
c10 = -sin,
c01 = sin,
c11 = cos,
)
}
private data class Impl(
override var c00: Float,
override var c01: Float,
override var c02: Float,
override var c03: Float,
override var c10: Float,
override var c11: Float,
override var c12: Float,
override var c13: Float,
override var c20: Float,
override var c21: Float,
override var c22: Float,
override var c23: Float,
override var c30: Float,
override var c31: Float,
override var c32: Float,
override var c33: Float,
) : Matrix4f() {
override fun toString(): String {
return "Matrix4f" + super.toString()
}
override fun equals(other: Any?): Boolean {
if (other !is Matrix4f) return false
return this === other || c00 == other.c00 &&
c01 == other.c01 &&
c02 == other.c02 &&
c03 == other.c03 &&
c10 == other.c10 &&
c11 == other.c11 &&
c12 == other.c12 &&
c13 == other.c13 &&
c20 == other.c20 &&
c21 == other.c21 &&
c22 == other.c22 &&
c23 == other.c23 &&
c30 == other.c30 &&
c31 == other.c31 &&
c32 == other.c32 &&
c33 == other.c33
}
}
private class View(private val parent: Matrix4f) : Matrix4f() {
override var c00: Float get() = parent.c00; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c01: Float get() = parent.c01; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c02: Float get() = parent.c02; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c03: Float get() = parent.c03; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c10: Float get() = parent.c10; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c11: Float get() = parent.c11; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c12: Float get() = parent.c12; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c13: Float get() = parent.c13; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c20: Float get() = parent.c20; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c21: Float get() = parent.c21; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c22: Float get() = parent.c22; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c23: Float get() = parent.c23; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c30: Float get() = parent.c30; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c31: Float get() = parent.c31; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c32: Float get() = parent.c32; set(_) { throw UnsupportedOperationException("Read-Only view") }
override var c33: Float get() = parent.c33; set(_) { throw UnsupportedOperationException("Read-Only view") }
override fun set(column: Int, row: Int, value: Float) {
throw UnsupportedOperationException("Read-Only view")
}
override fun equals(other: Any?): Boolean {
return other === this || parent == other
}
override fun hashCode(): Int {
return parent.hashCode()
}
override fun toString(): String {
return "View = $parent"
}
}
companion object {
@JvmStatic
fun all(value: Float) = construct4(value, ::columnMajor)
@JvmStatic
fun zero() = all(0f)
@JvmStatic
fun identity() = columnMajor()
@JvmStatic
fun unmodifiable(value: Matrix4f): Matrix4f {
if (value is View)
return value
else
return View(value)
}
@JvmStatic
fun columnMajor(
c00: Float = 1f, c01: Float = 0f, c02: Float = 0f, c03: Float = 0f,
c10: Float = 0f, c11: Float = 1f, c12: Float = 0f, c13: Float = 0f,
c20: Float = 0f, c21: Float = 0f, c22: Float = 1f, c23: Float = 0f,
c30: Float = 0f, c31: Float = 0f, c32: Float = 0f, c33: Float = 1f,
): Matrix4f {
return Impl(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33)
}
@JvmStatic
fun rowMajor(
r00: Float = 1f, r01: Float = 0f, r02: Float = 0f, r03: Float = 0f,
r10: Float = 0f, r11: Float = 1f, r12: Float = 0f, r13: Float = 0f,
r20: Float = 0f, r21: Float = 0f, r22: Float = 1f, r23: Float = 0f,
r30: Float = 0f, r31: Float = 0f, r32: Float = 0f, r33: Float = 1f
): Matrix4f {
return Impl(
r00, r10, r20, r30,
r01, r11, r21, r31,
r02, r12, r22, r32,
r03, r13, r23, r33
)
}
@JvmStatic
fun from(matrix: Float2DArray, filler: Float) = construct4(matrix, Float2DArray::get, ::columnMajor, filler)
@JvmStatic
fun from(matrix: Float2DArray) = construct4(matrix, Float2DArray::get, ::columnMajor, 0f)
@JvmStatic
fun from(matrix: Matrix4f) = construct4(matrix, Float2DArray::get, ::columnMajor)
@JvmStatic
fun fromTransposed(matrix: Float2DArray) = construct4(matrix, Float2DArray::get, Companion::rowMajor, 0f)
@JvmStatic
fun fromTransposed(matrix: Float2DArray, filler: Float) = construct4(matrix, Float2DArray::get, Companion::rowMajor, filler)
@JvmStatic
fun fromTransposed(matrix: Matrix4f) = construct4(matrix, Float2DArray::get, Companion::rowMajor)
@JvmStatic
fun fromColumnMajor(buffer: FloatBuffer) = construct4(buffer, FloatBuffer::get, ::columnMajor)
@JvmStatic
fun fromColumnMajor(buffer: ByteBuffer) = construct4(buffer, ByteBuffer::getFloat, ::columnMajor)
@JvmStatic
fun fromRowMajor(buffer: FloatBuffer) = construct4(buffer, FloatBuffer::get, Companion::rowMajor)
@JvmStatic
fun fromRowMajor(buffer: ByteBuffer) = construct4(buffer, ByteBuffer::getFloat, Companion::rowMajor)
/**
* Constructs new ortho projection matrix, with Y coordinate flipped (useful for OpenGL GUI drawing).
*
* Inversion of Y means that X 0 Y 0 will be top left position on screen (in OpenGL), not bottom left.
*/
@JvmStatic
fun ortho(left: Float, right: Float, bottom: Float, top: Float, zNear: Float, zFar: Float): Matrix4f {
return rowMajor(
r00 = 2f / (right - left),
r11 = -2f / (top - bottom),
r22 = 2f / (zFar - zNear),
r03 = -(right + left) / (right - left),
r13 = -(top + bottom) / (top - bottom) + 2f,
r23 = -(zFar + zNear) / (zFar - zNear)
)
}
/**
* Constructs new ortho projection matrix
*/
@JvmStatic
fun orthoDirect(left: Float, right: Float, bottom: Float, top: Float, zNear: Float, zFar: Float): Matrix4f {
return rowMajor(
r00 = 2f / (right - left),
r11 = 2f / (top - bottom),
r22 = 2f / (zFar - zNear),
r03 = -(right + left) / (right - left),
r13 = -(top + bottom) / (top - bottom),
r23 = -(zFar + zNear) / (zFar - zNear)
)
}
/**
* Constructs new perspective matrix
*/
@JvmStatic
fun perspective(fov: Float, zFar: Float, zNear: Float): Matrix4f {
val scale = (1.0 / (tan(Math.toRadians(fov.toDouble()) / 2.0))).toFloat()
val r = zFar - zNear
return rowMajor(
r00 = scale,
r11 = scale,
r22 = -zFar / r,
r23 = -1f,
r32 = -zFar * zNear / r,
)
}
// kotlin compiler bug? it refuses to use TABLESWITCH if these are inlined
const val C00 = (0 or (0 shl 2))
const val C01 = (0 or (1 shl 2))
const val C02 = (0 or (2 shl 2))
const val C03 = (0 or (3 shl 2))
const val C10 = (1 or (0 shl 2))
const val C11 = (1 or (1 shl 2))
const val C12 = (1 or (2 shl 2))
const val C13 = (1 or (3 shl 2))
const val C20 = (2 or (0 shl 2))
const val C21 = (2 or (1 shl 2))
const val C22 = (2 or (2 shl 2))
const val C23 = (2 or (3 shl 2))
const val C30 = (3 or (0 shl 2))
const val C31 = (3 or (1 shl 2))
const val C32 = (3 or (2 shl 2))
const val C33 = (3 or (3 shl 2))
}
}

View File

@ -1,55 +0,0 @@
package ru.dbotthepony.kommons.matrix
class Matrix4fStack {
private val stack = ArrayDeque<Matrix4f>()
init {
stack.addLast(Matrix4f.identity())
}
fun clear(top: Matrix4f): Matrix4fStack {
stack.clear()
stack.addLast(top.copy())
return this
}
fun push(): Matrix4fStack {
stack.addLast(stack.last().copy())
return this
}
fun pop(): Matrix4f {
return stack.removeLast()
}
fun last(): Matrix4f {
return stack.last()
}
fun push(matrix: Matrix4f): Matrix4fStack {
stack.addLast(matrix.copy())
return this
}
fun identity() = push(Matrix4f.identity())
fun zero() = push(Matrix4f.all(0f))
fun all(value: Float) = push(Matrix4f.all(value))
inline fun <T> with(block: Matrix4f.() -> T): T {
return try {
push()
block(last())
} finally {
pop()
}
}
inline fun <T> with(matrix: Matrix4f, block: Matrix4f.() -> T): T {
return try {
push(matrix)
block(last())
} finally {
pop()
}
}
}

View File

@ -1,518 +0,0 @@
package ru.dbotthepony.kommons.matrix
import ru.dbotthepony.kommons.arrays.Array2D
import ru.dbotthepony.kommons.arrays.mulMatrixComponents
import java.nio.Buffer
private inline fun <N : Number, F : Array2D> getOrElse(
get: (F, Int, Int) -> N,
input: F,
column: Int,
row: Int,
orElse: N
): N {
if (column < input.columns && row < input.rows) {
return get(input, column, row)
} else {
return orElse
}
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct4(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R,
filler: N
): R {
return factory(
getOrElse(get, from, 0, 0, filler),
getOrElse(get, from, 0, 1, filler),
getOrElse(get, from, 0, 2, filler),
getOrElse(get, from, 0, 3, filler),
getOrElse(get, from, 1, 0, filler),
getOrElse(get, from, 1, 1, filler),
getOrElse(get, from, 1, 2, filler),
getOrElse(get, from, 1, 3, filler),
getOrElse(get, from, 2, 0, filler),
getOrElse(get, from, 2, 1, filler),
getOrElse(get, from, 2, 2, filler),
getOrElse(get, from, 2, 3, filler),
getOrElse(get, from, 3, 0, filler),
getOrElse(get, from, 3, 1, filler),
getOrElse(get, from, 3, 2, filler),
getOrElse(get, from, 3, 3, filler),
)
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct3(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R,
filler: N
): R {
return factory(
getOrElse(get, from, 0, 0, filler), getOrElse(get, from, 0, 1, filler), getOrElse(get, from, 0, 2, filler),
getOrElse(get, from, 1, 0, filler), getOrElse(get, from, 1, 1, filler), getOrElse(get, from, 1, 2, filler),
getOrElse(get, from, 2, 0, filler), getOrElse(get, from, 2, 1, filler), getOrElse(get, from, 2, 2, filler),
)
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct2(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N,
N, N,
) -> R,
filler: N
): R {
return factory(
getOrElse(get, from, 0, 0, filler), getOrElse(get, from, 0, 1, filler),
getOrElse(get, from, 1, 0, filler), getOrElse(get, from, 1, 1, filler),
)
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct4(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
require(from.columns >= 4 && from.rows >= 4) { "Can't use ${from.dimensionsString} matrix to construct 4x4 matrix" }
return factory(
get(from, 0, 0), get(from, 0, 1), get(from, 0, 2), get(from, 0, 3),
get(from, 1, 0), get(from, 1, 1), get(from, 1, 2), get(from, 1, 3),
get(from, 2, 0), get(from, 2, 1), get(from, 2, 2), get(from, 2, 3),
get(from, 3, 0), get(from, 3, 1), get(from, 3, 2), get(from, 3, 3),
)
}
internal inline fun <N : Number, R : Array2D> construct4(
value: N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
return factory(
value, value, value, value,
value, value, value, value,
value, value, value, value,
value, value, value, value,
)
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct3(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
require(from.columns >= 3 && from.rows >= 3) { "Can't use ${from.dimensionsString} matrix to construct 3x3 matrix" }
return factory(
get(from, 0, 0), get(from, 0, 1), get(from, 0, 2),
get(from, 1, 0), get(from, 1, 1), get(from, 1, 2),
get(from, 2, 0), get(from, 2, 1), get(from, 2, 2),
)
}
internal inline fun <N : Number, R : Array2D> construct3(
value: N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
return factory(
value, value, value,
value, value, value,
value, value, value,
)
}
internal inline fun <N : Number, F : Array2D, R : Array2D> construct2(
from: F,
get: (F, Int, Int) -> N,
factory: (
N, N,
N, N,
) -> R
): R {
require(from.columns >= 2 && from.rows >= 2) { "Can't use ${from.dimensionsString} matrix to construct 2x2 matrix" }
return factory(
get(from, 0, 0), get(from, 0, 1),
get(from, 1, 0), get(from, 1, 1),
)
}
internal inline fun <N : Number, R : Array2D> construct2(
value: N,
factory: (
N, N,
N, N,
) -> R
): R {
return factory(
value, value,
value, value,
)
}
internal inline fun <N : Number, F : Buffer, R : Array2D> construct4(
from: F,
get: (F) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
return factory(
get(from), get(from), get(from), get(from),
get(from), get(from), get(from), get(from),
get(from), get(from), get(from), get(from),
get(from), get(from), get(from), get(from),
)
}
internal inline fun <N : Number, F : Buffer, R : Array2D> construct3(
from: F,
get: (F) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
return factory(
get(from), get(from), get(from),
get(from), get(from), get(from),
get(from), get(from), get(from),
)
}
internal inline fun <N : Number, F : Buffer, R : Array2D> construct2(
from: F,
get: (F) -> N,
factory: (
N, N,
N, N,
) -> R
): R {
return factory(
get(from), get(from),
get(from), get(from),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator4(
a: F, b: F,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), get(b, 0, 0)), operator(get(a, 0, 1), get(b, 0, 1)), operator(get(a, 0, 2), get(b, 0, 2)), operator(get(a, 0, 3), get(b, 0, 3)),
operator(get(a, 1, 0), get(b, 1, 0)), operator(get(a, 1, 1), get(b, 1, 1)), operator(get(a, 1, 2), get(b, 1, 2)), operator(get(a, 1, 3), get(b, 1, 3)),
operator(get(a, 2, 0), get(b, 2, 0)), operator(get(a, 2, 1), get(b, 2, 1)), operator(get(a, 2, 2), get(b, 2, 2)), operator(get(a, 2, 3), get(b, 2, 3)),
operator(get(a, 3, 0), get(b, 3, 0)), operator(get(a, 3, 1), get(b, 3, 1)), operator(get(a, 3, 2), get(b, 3, 2)), operator(get(a, 3, 3), get(b, 3, 3)),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator4(
a: F, b: N,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), b), operator(get(a, 0, 1), b), operator(get(a, 0, 2), b), operator(get(a, 0, 3), b),
operator(get(a, 1, 0), b), operator(get(a, 1, 1), b), operator(get(a, 1, 2), b), operator(get(a, 1, 3), b),
operator(get(a, 2, 0), b), operator(get(a, 2, 1), b), operator(get(a, 2, 2), b), operator(get(a, 2, 3), b),
operator(get(a, 3, 0), b), operator(get(a, 3, 1), b), operator(get(a, 3, 2), b), operator(get(a, 3, 3), b),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator3(
a: F, b: F,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), get(b, 0, 0)), operator(get(a, 0, 1), get(b, 0, 1)), operator(get(a, 0, 2), get(b, 0, 2)),
operator(get(a, 1, 0), get(b, 1, 0)), operator(get(a, 1, 1), get(b, 1, 1)), operator(get(a, 1, 2), get(b, 1, 2)),
operator(get(a, 2, 0), get(b, 2, 0)), operator(get(a, 2, 1), get(b, 2, 1)), operator(get(a, 2, 2), get(b, 2, 2)),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator3(
a: F, b: N,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), b), operator(get(a, 0, 1), b), operator(get(a, 0, 2), b),
operator(get(a, 1, 0), b), operator(get(a, 1, 1), b), operator(get(a, 1, 2), b),
operator(get(a, 2, 0), b), operator(get(a, 2, 1), b), operator(get(a, 2, 2), b),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator2(
a: F, b: F,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N,
N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), get(b, 0, 0)), operator(get(a, 0, 1), get(b, 0, 1)),
operator(get(a, 1, 0), get(b, 1, 0)), operator(get(a, 1, 1), get(b, 1, 1)),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator2(
a: F, b: N,
get: (F, Int, Int) -> N,
operator: (N, N) -> N,
factory: (
N, N,
N, N,
) -> R
): R {
return factory(
operator(get(a, 0, 0), b), operator(get(a, 0, 1), b),
operator(get(a, 1, 0), b), operator(get(a, 1, 1), b),
)
}
internal inline fun <N : Number, F : Array2D, R : F> times4(
a: F, b: F,
get: (F, Int, Int) -> N,
times: (N, N) -> N,
plus: (N, N) -> N,
factory: (
N, N, N, N,
N, N, N, N,
N, N, N, N,
N, N, N, N,
) -> R
): R {
return factory(
mulMatrixComponents(a, b, get, times, plus, 0, 0),
mulMatrixComponents(a, b, get, times, plus, 0, 1),
mulMatrixComponents(a, b, get, times, plus, 0, 2),
mulMatrixComponents(a, b, get, times, plus, 0, 3),
mulMatrixComponents(a, b, get, times, plus, 1, 0),
mulMatrixComponents(a, b, get, times, plus, 1, 1),
mulMatrixComponents(a, b, get, times, plus, 1, 2),
mulMatrixComponents(a, b, get, times, plus, 1, 3),
mulMatrixComponents(a, b, get, times, plus, 2, 0),
mulMatrixComponents(a, b, get, times, plus, 2, 1),
mulMatrixComponents(a, b, get, times, plus, 2, 2),
mulMatrixComponents(a, b, get, times, plus, 2, 3),
mulMatrixComponents(a, b, get, times, plus, 3, 0),
mulMatrixComponents(a, b, get, times, plus, 3, 1),
mulMatrixComponents(a, b, get, times, plus, 3, 2),
mulMatrixComponents(a, b, get, times, plus, 3, 3),
)
}
internal inline fun <N : Number, F : Array2D, R : F> times3(
a: F, b: F,
get: (F, Int, Int) -> N,
times: (N, N) -> N,
plus: (N, N) -> N,
factory: (
N, N, N,
N, N, N,
N, N, N,
) -> R
): R {
return factory(
mulMatrixComponents(a, b, get, times, plus, 0, 0),
mulMatrixComponents(a, b, get, times, plus, 0, 1),
mulMatrixComponents(a, b, get, times, plus, 0, 2),
mulMatrixComponents(a, b, get, times, plus, 1, 0),
mulMatrixComponents(a, b, get, times, plus, 1, 1),
mulMatrixComponents(a, b, get, times, plus, 1, 2),
mulMatrixComponents(a, b, get, times, plus, 2, 0),
mulMatrixComponents(a, b, get, times, plus, 2, 1),
mulMatrixComponents(a, b, get, times, plus, 2, 2),
)
}
internal inline fun <N : Number, F : Array2D, R : F> times2(
a: F, b: F,
get: (F, Int, Int) -> N,
times: (N, N) -> N,
plus: (N, N) -> N,
factory: (
N, N,
N, N,
) -> R
): R {
return factory(
mulMatrixComponents(a, b, get, times, plus, 0, 0), mulMatrixComponents(a, b, get, times, plus, 0, 1),
mulMatrixComponents(a, b, get, times, plus, 1, 0), mulMatrixComponents(a, b, get, times, plus, 1, 1),
)
}
internal inline fun <N : Number, F : Array2D, R : F> operator4(
a: R, b: F,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
a.requireSizeEquals(b)
set(a, 0, 0, operator(get(a, 0, 0), get(b, 0, 0)))
set(a, 0, 1, operator(get(a, 0, 1), get(b, 0, 1)))
set(a, 0, 2, operator(get(a, 0, 2), get(b, 0, 2)))
set(a, 0, 3, operator(get(a, 0, 3), get(b, 0, 3)))
set(a, 1, 0, operator(get(a, 1, 0), get(b, 1, 0)))
set(a, 1, 1, operator(get(a, 1, 1), get(b, 1, 1)))
set(a, 1, 2, operator(get(a, 1, 2), get(b, 1, 2)))
set(a, 1, 3, operator(get(a, 1, 3), get(b, 1, 3)))
set(a, 2, 0, operator(get(a, 2, 0), get(b, 2, 0)))
set(a, 2, 1, operator(get(a, 2, 1), get(b, 2, 1)))
set(a, 2, 2, operator(get(a, 2, 2), get(b, 2, 2)))
set(a, 2, 3, operator(get(a, 2, 3), get(b, 2, 3)))
set(a, 3, 0, operator(get(a, 3, 0), get(b, 3, 0)))
set(a, 3, 1, operator(get(a, 3, 1), get(b, 3, 1)))
set(a, 3, 2, operator(get(a, 3, 2), get(b, 3, 2)))
set(a, 3, 3, operator(get(a, 3, 3), get(b, 3, 3)))
return a
}
internal inline fun <N : Number, F : Array2D, R : F> operator4(
a: R, b: N,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
set(a, 0, 0, operator(get(a, 0, 0), b))
set(a, 0, 1, operator(get(a, 0, 1), b))
set(a, 0, 2, operator(get(a, 0, 2), b))
set(a, 0, 3, operator(get(a, 0, 3), b))
set(a, 1, 0, operator(get(a, 1, 0), b))
set(a, 1, 1, operator(get(a, 1, 1), b))
set(a, 1, 2, operator(get(a, 1, 2), b))
set(a, 1, 3, operator(get(a, 1, 3), b))
set(a, 2, 0, operator(get(a, 2, 0), b))
set(a, 2, 1, operator(get(a, 2, 1), b))
set(a, 2, 2, operator(get(a, 2, 2), b))
set(a, 2, 3, operator(get(a, 2, 3), b))
set(a, 3, 0, operator(get(a, 3, 0), b))
set(a, 3, 1, operator(get(a, 3, 1), b))
set(a, 3, 2, operator(get(a, 3, 2), b))
set(a, 3, 3, operator(get(a, 3, 3), b))
return a
}
internal inline fun <N : Number, F : Array2D, R : F> operator3(
a: R, b: F,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
a.requireSizeEquals(b)
set(a, 0, 0, operator(get(a, 0, 0), get(b, 0, 0)))
set(a, 0, 1, operator(get(a, 0, 1), get(b, 0, 1)))
set(a, 0, 2, operator(get(a, 0, 2), get(b, 0, 2)))
set(a, 1, 0, operator(get(a, 1, 0), get(b, 1, 0)))
set(a, 1, 1, operator(get(a, 1, 1), get(b, 1, 1)))
set(a, 1, 2, operator(get(a, 1, 2), get(b, 1, 2)))
set(a, 2, 0, operator(get(a, 2, 0), get(b, 2, 0)))
set(a, 2, 1, operator(get(a, 2, 1), get(b, 2, 1)))
set(a, 2, 2, operator(get(a, 2, 2), get(b, 2, 2)))
return a
}
internal inline fun <N : Number, F : Array2D, R : F> operator3(
a: R, b: N,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
set(a, 0, 0, operator(get(a, 0, 0), b))
set(a, 0, 1, operator(get(a, 0, 1), b))
set(a, 0, 2, operator(get(a, 0, 2), b))
set(a, 1, 0, operator(get(a, 1, 0), b))
set(a, 1, 1, operator(get(a, 1, 1), b))
set(a, 1, 2, operator(get(a, 1, 2), b))
set(a, 2, 0, operator(get(a, 2, 0), b))
set(a, 2, 1, operator(get(a, 2, 1), b))
set(a, 2, 2, operator(get(a, 2, 2), b))
return a
}
internal inline fun <N : Number, F : Array2D, R : F> operator2(
a: R, b: F,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
a.requireSizeEquals(b)
set(a, 0, 0, operator(get(a, 0, 0), get(b, 0, 0)))
set(a, 0, 1, operator(get(a, 0, 1), get(b, 0, 1)))
set(a, 1, 0, operator(get(a, 1, 0), get(b, 1, 0)))
set(a, 1, 1, operator(get(a, 1, 1), get(b, 1, 1)))
return a
}
internal inline fun <N : Number, F : Array2D, R : F> operator2(
a: R, b: N,
get: (F, Int, Int) -> N,
set: (R, Int, Int, N) -> Unit,
operator: (N, N) -> N,
): R {
set(a, 0, 0, operator(get(a, 0, 0), b))
set(a, 0, 1, operator(get(a, 0, 1), b))
set(a, 1, 0, operator(get(a, 1, 0), b))
set(a, 1, 1, operator(get(a, 1, 1), b))
return a
}

View File

@ -1,230 +0,0 @@
@file:Suppress("unused", "LiftReturnOrAssignment", "MemberVisibilityCanBePrivate")
package ru.dbotthepony.kommons.util
import ru.dbotthepony.kommons.math.intersectRectangles
import ru.dbotthepony.kommons.math.rectangleContainsRectangle
import ru.dbotthepony.kommons.vector.Vector2d
import kotlin.math.absoluteValue
/**
* Axis Aligned Bounding Box, represented by two points, [mins] as lowermost corner of BB,
* and [maxs] as uppermost corner of BB
*/
data class AABB(val mins: Vector2d, val maxs: Vector2d) {
init {
require(mins.x <= maxs.x) { "mins.x ${mins.x} is more than maxs.x ${maxs.x}" }
require(mins.y <= maxs.y) { "mins.y ${mins.y} is more than maxs.y ${maxs.y}" }
}
operator fun plus(other: AABB) = AABB(mins + other.mins, maxs + other.maxs)
operator fun minus(other: AABB) = AABB(mins - other.mins, maxs - other.maxs)
operator fun times(other: AABB) = AABB(mins * other.mins, maxs * other.maxs)
operator fun div(other: AABB) = AABB(mins / other.mins, maxs / other.maxs)
operator fun plus(other: Vector2d) = AABB(mins + other, maxs + other)
operator fun minus(other: Vector2d) = AABB(mins - other, maxs - other)
operator fun times(other: Vector2d) = AABB(mins * other, maxs * other)
operator fun div(other: Vector2d) = AABB(mins / other, maxs / other)
operator fun times(other: Double) = AABB(mins * other, maxs * other)
operator fun div(other: Double) = AABB(mins / other, maxs / other)
val xSpan get() = maxs.x - mins.x
val ySpan get() = maxs.y - mins.y
val centre get() = (mins + maxs) * 0.5
val A get() = mins
val B get() = Vector2d(mins.x, maxs.y)
val C get() = maxs
val D get() = Vector2d(maxs.x, mins.y)
val bottomLeft get() = A
val topLeft get() = B
val topRight get() = C
val bottomRight get() = D
val width get() = maxs.x - mins.x
val height get() = maxs.y - mins.y
val extents get() = Vector2d(width * 0.5, height * 0.5)
val diameter get() = mins.distance(maxs)
val radius get() = diameter / 2.0
val perimeter get() = (xSpan + ySpan) * 2.0
fun isInside(point: IStruct2d): Boolean {
return point.component1() in mins.x .. maxs.x && point.component2() in mins.y .. maxs.y
}
fun isInside(x: Double, y: Double): Boolean {
return x in mins.x .. maxs.x && y in mins.y .. maxs.y
}
operator fun contains(point: IStruct2d) = isInside(point)
/**
* Checks whenever is this AABB intersect with [other]
*
* This method consider they intersect even if only one of axis are equal
*/
fun intersect(other: AABB): Boolean {
return intersectRectangles(mins, maxs, other.mins, other.maxs)
}
/**
* Returns whenever [other] is contained (encased) inside this AABB
*/
operator fun contains(other: AABB): Boolean {
return rectangleContainsRectangle(mins, maxs, other.mins, other.maxs)
}
/**
* Checks whenever is this AABB intersect with [other]
*
* This method DOES NOT consider they intersect if only one of axis are equal
*/
fun intersectWeak(other: AABB): Boolean {
if (maxs.x == other.mins.x || mins.x == other.maxs.x || maxs.y == other.mins.y || mins.y == other.maxs.y)
return false
return intersectRectangles(mins, maxs, other.mins, other.maxs)
}
fun intersectionDepth(other: AABB): Vector2d {
val xDepth: Double
val yDepth: Double
val thisCentre = centre
val otherCentre = other.centre
if (thisCentre.x > otherCentre.x) {
// считаем, что мы вошли справа
xDepth = mins.x - other.maxs.x
} else {
// считаем, что мы вошли слева
xDepth = maxs.x - other.mins.x
}
if (thisCentre.y > otherCentre.y) {
// считаем, что мы вошли сверху
yDepth = mins.y - other.maxs.y
} else {
// считаем, что мы вошли снизу
yDepth = maxs.x - other.mins.x
}
return Vector2d(xDepth, yDepth)
}
fun distance(other: AABB): Double {
val intersectX: Boolean
val intersectY: Boolean
if (ySpan <= other.ySpan)
intersectY = mins.y in other.mins.y .. other.maxs.y || maxs.y in other.mins.y .. other.maxs.y
else
intersectY = other.mins.y in mins.y .. maxs.y || other.maxs.y in mins.y .. maxs.y
if (xSpan <= other.xSpan)
intersectX = mins.x in other.mins.x .. other.maxs.x || maxs.x in other.mins.x .. other.maxs.x
else
intersectX = other.mins.x in mins.x .. maxs.x || other.maxs.x in mins.x .. maxs.x
if (intersectY && intersectX) {
return 0.0
}
if (intersectX) {
return (mins.y - other.maxs.y).absoluteValue.coerceAtMost((maxs.y - other.mins.y).absoluteValue)
} else {
return (mins.x - other.maxs.x).absoluteValue.coerceAtMost((maxs.x - other.mins.x).absoluteValue)
}
}
fun pushOutFrom(other: AABB): Vector2d {
if (!intersect(other))
return Vector2d.ZERO
val depth = intersectionDepth(other)
if (depth.x.absoluteValue < depth.y.absoluteValue) {
return Vector2d(x = depth.x)
} else {
return Vector2d(y = depth.y)
}
}
/**
* Returns AABB which contains both AABBs
*/
fun combine(other: AABB): AABB {
if (contains(other)) return this
val minX = mins.x.coerceAtMost(other.mins.x)
val minY = mins.y.coerceAtMost(other.mins.y)
val maxX = maxs.x.coerceAtLeast(other.maxs.x)
val maxY = maxs.y.coerceAtLeast(other.maxs.y)
return AABB(Vector2d(minX, minY), Vector2d(maxX, maxY))
}
/**
* Returns AABB which contains this AABB and specified point
*/
fun expand(x: Double, y: Double): AABB {
if (isInside(x, y))
return this
return AABB(
mins.coerceAtMost(x, y),
maxs.coerceAtLeast(x, y)
)
}
fun expand(value: IStruct2d) = expand(value.component1(), value.component2())
fun padded(value: IStruct2d) = expand(value.component1(), value.component2())
fun padded(x: Double, y: Double) = expand(x, y)
/**
* Returns AABB which edges are expanded by [x] and [y] along their normals
*/
fun enlarge(x: Double, y: Double): AABB {
if (x == 0.0 && y == 0.0) return this
return AABB(
Vector2d(mins.x - x, mins.y - y),
Vector2d(maxs.x + x, maxs.y + y),
)
}
companion object {
/**
* Rectangle with given [width] and [height]
*/
fun rectangle(pos: IStruct2d, width: Double, height: Double = width): AABB {
val (x, y) = pos
return AABB(
Vector2d(x - width / 2.0, y - height / 2.0),
Vector2d(x + width / 2.0, y + height / 2.0),
)
}
/**
* Rectangle with given [width] * 2 and [height] * 2
*/
fun withSide(pos: IStruct2d, width: Double, height: Double = width): AABB {
val (x, y) = pos
return AABB(
Vector2d(x - width, y - height),
Vector2d(x + width, y + height),
)
}
@JvmField val ZERO = AABB(Vector2d.ZERO, Vector2d.ZERO)
}
}

View File

@ -1,147 +0,0 @@
package ru.dbotthepony.kommons.util
import ru.dbotthepony.kommons.math.intersectRectangles
import ru.dbotthepony.kommons.math.rectangleContainsRectangle
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i
data class AABBi(val mins: Vector2i, val maxs: Vector2i) {
init {
require(mins.x <= maxs.x) { "mins.x ${mins.x} is more than maxs.x ${maxs.x}" }
require(mins.y <= maxs.y) { "mins.y ${mins.y} is more than maxs.y ${maxs.y}" }
}
operator fun plus(other: AABBi) = AABBi(mins + other.mins, maxs + other.maxs)
operator fun minus(other: AABBi) = AABBi(mins - other.mins, maxs - other.maxs)
operator fun times(other: AABBi) = AABBi(mins * other.mins, maxs * other.maxs)
operator fun div(other: AABBi) = AABBi(mins / other.mins, maxs / other.maxs)
operator fun plus(other: Vector2i) = AABBi(mins + other, maxs + other)
operator fun minus(other: Vector2i) = AABBi(mins - other, maxs - other)
operator fun times(other: Vector2i) = AABBi(mins * other, maxs * other)
operator fun div(other: Vector2i) = AABBi(mins / other, maxs / other)
operator fun times(other: Int) = AABBi(mins * other, maxs * other)
operator fun div(other: Int) = AABBi(mins / other, maxs / other)
val xSpan get() = maxs.x - mins.x
val ySpan get() = maxs.y - mins.y
val centre get() = (mins.toDoubleVector() + maxs.toDoubleVector()) * 0.5
val A get() = mins
val B get() = Vector2i(mins.x, maxs.y)
val C get() = maxs
val D get() = Vector2i(maxs.x, mins.y)
val bottomLeft get() = A
val topLeft get() = B
val topRight get() = C
val bottomRight get() = D
val width get() = (maxs.x - mins.x) / 2
val height get() = (maxs.y - mins.y) / 2
val diameter get() = mins.distance(maxs)
val radius get() = diameter / 2.0
val perimeter get() = (xSpan + ySpan) * 2
fun isInside(point: IStruct2i): Boolean {
return point.component1() in mins.x .. maxs.x && point.component2() in mins.y .. maxs.y
}
fun isInside(x: Int, y: Int): Boolean {
return x in mins.x .. maxs.x && y in mins.y .. maxs.y
}
operator fun contains(point: IStruct2i) = isInside(point)
/**
* Checks whenever is this AABBi intersect with [other]
*
* This method consider they intersect even if only one of axis are equal
*/
fun intersect(other: AABBi): Boolean {
return intersectRectangles(mins, maxs, other.mins, other.maxs)
}
/**
* Returns whenever [other] is contained (encased) inside this AABBi
*/
operator fun contains(other: AABBi): Boolean {
return rectangleContainsRectangle(mins, maxs, other.mins, other.maxs)
}
/**
* Checks whenever is this AABB intersect with [other]
*
* This method DOES NOT consider they intersect if only one of axis are equal
*/
fun intersectWeak(other: AABBi): Boolean {
if (maxs.x == other.mins.x || mins.x == other.maxs.x || maxs.y == other.mins.y || mins.y == other.maxs.y)
return false
return intersectRectangles(mins, maxs, other.mins, other.maxs)
}
fun toDoubleAABB() = AABB(mins.toDoubleVector(), maxs.toDoubleVector())
/**
* Returns AABB which contains this AABB and specified point
*/
fun expand(x: Int, y: Int): AABBi {
if (isInside(x, y))
return this
return AABBi(
mins.coerceAtMost(x, y),
maxs.coerceAtLeast(x, y)
)
}
fun padded(x: Int, y: Int) = expand(x, y)
fun padded(value: IStruct2i) = expand(value.component1(), value.component2())
fun expand(value: IStruct2i) = expand(value.component1(), value.component2())
/**
* Returns AABB which contains both AABBs
*/
fun combine(other: AABBi): AABBi {
if (contains(other)) return this
val minX = mins.x.coerceAtMost(other.mins.x)
val minY = mins.y.coerceAtMost(other.mins.y)
val maxX = maxs.x.coerceAtLeast(other.maxs.x)
val maxY = maxs.y.coerceAtLeast(other.maxs.y)
return AABBi(Vector2i(minX, minY), Vector2i(maxX, maxY))
}
companion object {
/**
* Rectangle with given [width] and [height]
*/
fun rectangle(pos: IStruct2i, width: Int, height: Int = width): AABBi {
val (x, y) = pos
return AABBi(
Vector2i(x - width / 2, y - height / 2),
Vector2i(x + width / 2, y + height / 2),
)
}
/**
* Rectangle with given [width] * 2 and [height] * 2
*/
fun withSide(pos: IStruct2i, width: Int, height: Int = width): AABBi {
val (x, y) = pos
return AABBi(
Vector2i(x - width, y - height),
Vector2i(x + width, y + height),
)
}
@JvmField val ZERO = AABBi(Vector2i.ZERO, Vector2i.ZERO)
}
}

View File

@ -1,58 +0,0 @@
package ru.dbotthepony.kommons.vector
operator fun Int.times(value: Vector2i) = value.times(this)
operator fun Int.div(value: Vector2i) = Vector2i(this / value.x, this / value.y)
operator fun Int.times(value: Vector2d) = value.times(this)
operator fun Int.div(value: Vector2d) = Vector2d(this / value.x, this / value.y)
operator fun Int.times(value: Vector2f) = value.times(this)
operator fun Int.div(value: Vector2f) = Vector2f(this / value.x, this / value.y)
operator fun Int.times(value: Vector3i) = value.times(this)
operator fun Int.div(value: Vector3i) = Vector3i(this / value.x, this / value.y, this / value.z)
operator fun Int.times(value: Vector3d) = value.times(this)
operator fun Int.div(value: Vector3d) = Vector3d(this / value.x, this / value.y, this / value.z)
operator fun Int.times(value: Vector3f) = value.times(this)
operator fun Int.div(value: Vector3f) = Vector3f(this / value.x, this / value.y, this / value.z)
operator fun Int.times(value: Vector4i) = value.times(this)
operator fun Int.div(value: Vector4i) = Vector4i(this / value.x, this / value.y, this / value.z)
operator fun Int.times(value: Vector4d) = value.times(this)
operator fun Int.div(value: Vector4d) = Vector4d(this / value.x, this / value.y, this / value.z)
operator fun Int.times(value: Vector4f) = value.times(this)
operator fun Int.div(value: Vector4f) = Vector4f(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector2i) = value.times(this)
operator fun Float.div(value: Vector2i) = Vector2f(this / value.x, this / value.y)
operator fun Float.times(value: Vector2d) = value.times(this)
operator fun Float.div(value: Vector2d) = Vector2d(this / value.x, this / value.y)
operator fun Float.times(value: Vector2f) = value.times(this)
operator fun Float.div(value: Vector2f) = Vector2f(this / value.x, this / value.y)
operator fun Float.times(value: Vector3i) = value.times(this)
operator fun Float.div(value: Vector3i) = Vector3f(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector3d) = value.times(this)
operator fun Float.div(value: Vector3d) = Vector3d(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector3f) = value.times(this)
operator fun Float.div(value: Vector3f) = Vector3f(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector4i) = value.times(this)
operator fun Float.div(value: Vector4i) = Vector4f(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector4d) = value.times(this)
operator fun Float.div(value: Vector4d) = Vector4d(this / value.x, this / value.y, this / value.z)
operator fun Float.times(value: Vector4f) = value.times(this)
operator fun Float.div(value: Vector4f) = Vector4f(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector2i) = value.times(this)
operator fun Double.div(value: Vector2i) = Vector2d(this / value.x, this / value.y)
operator fun Double.times(value: Vector2d) = value.times(this)
operator fun Double.div(value: Vector2d) = Vector2d(this / value.x, this / value.y)
operator fun Double.times(value: Vector2f) = value.times(this)
operator fun Double.div(value: Vector2f) = Vector2d(this / value.x, this / value.y)
operator fun Double.times(value: Vector3i) = value.times(this)
operator fun Double.div(value: Vector3i) = Vector3d(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector3d) = value.times(this)
operator fun Double.div(value: Vector3d) = Vector3d(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector3f) = value.times(this)
operator fun Double.div(value: Vector3f) = Vector3d(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector4i) = value.times(this)
operator fun Double.div(value: Vector4i) = Vector4d(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector4d) = value.times(this)
operator fun Double.div(value: Vector4d) = Vector4d(this / value.x, this / value.y, this / value.z)
operator fun Double.times(value: Vector4f) = value.times(this)
operator fun Double.div(value: Vector4f) = Vector4d(this / value.x, this / value.y, this / value.z)

View File

@ -1,119 +0,0 @@
package ru.dbotthepony.kommons.vector
import kotlin.math.sqrt
/**
* Vectors are exclusively immutable
*/
sealed class Vector {
val length: Double get() = sqrt(lengthSquared)
val isValid: Boolean get() = isFinite && !isNaN
abstract val isFinite: Boolean
abstract val isNaN: Boolean
abstract val lengthSquared: Double
/**
* @throws IllegalArgumentException if matrix is not finite
*/
inline fun requireIsFinite(lambda: () -> Any) {
if (!isFinite) {
throw IllegalArgumentException(lambda.invoke().toString())
}
}
/**
* @throws IllegalArgumentException if matrix is not finite
*/
fun requireIsFinite() {
if (!isFinite) {
throw IllegalArgumentException("Matrix is not finite")
}
}
/**
* @throws IllegalStateException if matrix is not finite
*/
inline fun checkIsFinite(lambda: () -> Any) {
if (!isFinite) {
throw IllegalStateException(lambda.invoke().toString())
}
}
/**
* @throws IllegalStateException if matrix is not finite
*/
fun checkIsFinite() {
if (!isFinite) {
throw IllegalStateException("Matrix is not finite")
}
}
/**
* @throws IllegalArgumentException if vector has NaN component
*/
inline fun requireNotNaN(lambda: () -> Any) {
if (isNaN) {
throw IllegalArgumentException(lambda.invoke().toString())
}
}
/**
* @throws IllegalArgumentException if matrix has NaN component
*/
fun requireNotNaN() {
if (isNaN) {
throw IllegalArgumentException("Matrix has NaN component")
}
}
/**
* @throws IllegalStateException if matrix has NaN component
*/
inline fun checkNotNaN(lambda: () -> Any) {
if (!isFinite) {
throw IllegalStateException(lambda.invoke().toString())
}
}
/**
* @throws IllegalStateException if matrix has NaN component
*/
fun checkNotNaN() {
if (!isFinite) {
throw IllegalStateException("Matrix has NaN component")
}
}
/**
* @throws IllegalArgumentException if matrix has NaN or infinite component
*/
fun requireIsValid() {
requireIsFinite()
requireNotNaN()
}
/**
* @throws IllegalStateException if matrix has NaN or infinite component
*/
fun checkIsValid() {
requireIsFinite()
requireNotNaN()
}
/**
* @throws IllegalArgumentException if matrix has NaN or infinite component
*/
inline fun requireIsValid(lambda: () -> Any) {
requireIsFinite(lambda)
requireNotNaN(lambda)
}
/**
* @throws IllegalStateException if matrix has NaN or infinite component
*/
inline fun checkIsValid(lambda: () -> Any) {
requireIsFinite(lambda)
requireNotNaN(lambda)
}
}

View File

@ -1,247 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.matrix.Matrix2d
import ru.dbotthepony.kommons.matrix.Matrix3d
import ru.dbotthepony.kommons.matrix.Matrix4d
import ru.dbotthepony.kommons.matrix.Matrix4dStack
import kotlin.math.absoluteValue
import kotlin.math.acos
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
data class Vector2d(
val x: Double = 0.0,
val y: Double = 0.0,
) : IStruct2d, Vector() {
constructor(value: IStruct2d) : this(value.component1(), value.component2())
constructor(value: Vector2d) : this(value.x, value.y)
override val lengthSquared: Double
get() = x * x + y * y
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN()
val unitVector: Vector2d get() {
var length = lengthSquared
if (length == 0.0 || length == 1.0) return this
length = sqrt(length)
return Vector2d(x / length, y / length)
}
val absoluteValue: Vector2d get() {
val x = x.absoluteValue
val y = y.absoluteValue
if (x != this.x || y != this.y) return Vector2d(x, y)
return this
}
val r get() = x
val g get() = y
val s get() = x
val t get() = y
fun plus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x + x, this.y + y)
fun minus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x - x, this.y - y)
fun times(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x * x, this.y * y)
fun div(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x / x, this.y / y)
operator fun plus(value: IStruct2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value)
operator fun minus(value: Double) = minus(value, value)
operator fun times(value: Double) = times(value, value)
operator fun div(value: Double) = div(value, value)
fun plus(x: Int = 0, y: Int = 0) = Vector2d(this.x + x, this.y + y)
fun minus(x: Int = 0, y: Int = 0) = Vector2d(this.x - x, this.y - y)
fun times(x: Int = 1, y: Int = 1) = Vector2d(this.x * x, this.y * y)
fun div(x: Int = 1, y: Int = 1) = Vector2d(this.x / x, this.y / y)
operator fun plus(value: IStruct2i): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2i): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value)
operator fun minus(value: Int) = minus(value, value)
operator fun times(value: Int) = times(value, value)
operator fun div(value: Int) = div(value, value)
fun plus(x: Float = 0f, y: Float = 0f) = Vector2d(this.x + x, this.y + y)
fun minus(x: Float = 0f, y: Float = 0f) = Vector2d(this.x - x, this.y - y)
fun times(x: Float = 1f, y: Float = 1f) = Vector2d(this.x * x, this.y * y)
fun div(x: Float = 1f, y: Float = 1f) = Vector2d(this.x / x, this.y / y)
operator fun plus(value: IStruct2f): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2f): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value)
operator fun minus(value: Float) = minus(value, value)
operator fun times(value: Float) = times(value, value)
operator fun div(value: Float) = div(value, value)
operator fun unaryMinus(): Vector2d = Vector2d(-x, -y)
override fun equals(other: Any?): Boolean {
return other is Vector2d && x == other.x && y == other.y
}
override fun hashCode(): Int {
var x = x.hashCode().rotateLeft(16) xor y.hashCode()
// avalanche bits using murmur3 hash
x = x xor (x ushr 16)
x *= -0x7a143595
x = x xor (x ushr 13)
x *= -0x3d4d51cb
x = x xor (x ushr 16)
return x
}
override fun toString(): String {
return "[$x, $y]"
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2d): Double {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2f): Double {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2i): Double {
return x * other.component2() - other.component1() * y
}
fun dot(x: Double, y: Double) = this.x * x + this.y * y
fun dot(value: IStruct2d): Double { val (x, y) = value; return dot(x, y) }
fun dot(value: Vector2d): Double { val (x, y) = value; return dot(x, y) }
fun distanceSquared(x: Double, y: Double): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
return dx * dx + dy * dy
}
fun distanceSquared(value: IStruct2d): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distanceSquared(value: Vector2d): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distance(x: Double, y: Double) = sqrt(distanceSquared(x, y))
fun distance(value: IStruct2d): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun distance(value: Vector2d): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun coerceAtLeast(x: Double, y: Double) = Vector2d(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y))
fun coerceAtMost(x: Double, y: Double) = Vector2d(this.x.coerceAtMost(x), this.y.coerceAtMost(y))
fun coerceIn(minimum: Vector2d, maximum: Vector2d) = Vector2d(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y))
fun coerceIn(minimum: IStruct2d, maximum: IStruct2d) = Vector2d(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()))
fun coerceAtLeast(value: IStruct2d): Vector2d { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: IStruct2d): Vector2d { val (x, y) = value; return coerceAtMost(x, y) }
fun coerceAtLeast(value: Vector2d): Vector2d { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: Vector2d): Vector2d { val (x, y) = value; return coerceAtMost(x, y) }
fun rotate(angle: Double): Vector2d {
val s = sin(angle)
val c = cos(angle)
return Vector2d(x * c - s * y, s * x + c * y)
}
fun toAngle(zeroAngle: Vector2d): Double {
val dot = unitVector.dot(zeroAngle.unitVector)
return if (y > 0.0) {
acos(dot)
} else {
-acos(dot)
}
}
fun toAngle(zeroAngle: IStruct2d): Double {
return toAngle(Vector2d(zeroAngle))
}
fun toAngle(): Double {
return atan2(y, x)
}
operator fun times(value: Matrix4d): Vector2d {
return Vector2d(
x * value.c00 + y * value.c10 + value.c30,
x * value.c01 + y * value.c11 + value.c31,
)
}
operator fun times(value: Matrix3d): Vector2d {
return Vector2d(
x * value.c00 + y * value.c10 + value.c20,
x * value.c01 + y * value.c11 + value.c21,
)
}
operator fun times(value: Matrix2d): Vector2d {
return Vector2d(
x * value.c00 + y * value.c10,
x * value.c01 + y * value.c11,
)
}
operator fun times(value: Matrix4dStack) = times(value.last())
fun toDoubleVector() = this
fun toFloatVector() = Vector2f(x.toFloat(), y.toFloat())
companion object {
@JvmField val ZERO = Vector2d()
@JvmField val POSITIVE_X = Vector2d(x = 1.0)
@JvmField val NEGATIVE_X = Vector2d(x = -1.0)
@JvmField val POSITIVE_Y = Vector2d(y = 1.0)
@JvmField val NEGATIVE_Y = Vector2d(y = -1.0)
@JvmField val POSITIVE_XY = Vector2d(1.0, 1.0)
@JvmField val NEGATIVE_XY = Vector2d(-1.0, -1.0)
}
}

View File

@ -1,247 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.matrix.Matrix2f
import ru.dbotthepony.kommons.matrix.Matrix3f
import ru.dbotthepony.kommons.matrix.Matrix4f
import ru.dbotthepony.kommons.matrix.Matrix4fStack
import kotlin.math.absoluteValue
import kotlin.math.acos
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
data class Vector2f(
val x: Float = 0f,
val y: Float = 0f,
) : IStruct2f, Vector() {
constructor(value: IStruct2f) : this(value.component1(), value.component2())
constructor(value: Vector2f) : this(value.x, value.y)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN()
val unitVector: Vector2f get() {
var length = lengthSquared.toFloat()
if (length == 0f || length == 1f) return this
length = sqrt(length)
return Vector2f(x / length, y / length)
}
val absoluteValue: Vector2f get() {
val x = x.absoluteValue
val y = y.absoluteValue
if (x != this.x || y != this.y) return Vector2f(x, y)
return this
}
val r get() = x
val g get() = y
val s get() = x
val t get() = y
fun plus(x: Float = 0f, y: Float = 0f) = Vector2f(this.x + x, this.y + y)
fun minus(x: Float = 0f, y: Float = 0f) = Vector2f(this.x - x, this.y - y)
fun times(x: Float = 1f, y: Float = 1f) = Vector2f(this.x * x, this.y * y)
fun div(x: Float = 1f, y: Float = 1f) = Vector2f(this.x / x, this.y / y)
operator fun plus(value: IStruct2f): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2f): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value)
operator fun minus(value: Float) = minus(value, value)
operator fun times(value: Float) = times(value, value)
operator fun div(value: Float) = div(value, value)
fun plus(x: Int = 0, y: Int = 0) = Vector2f(this.x + x, this.y + y)
fun minus(x: Int = 0, y: Int = 0) = Vector2f(this.x - x, this.y - y)
fun times(x: Int = 1, y: Int = 1) = Vector2f(this.x * x, this.y * y)
fun div(x: Int = 1, y: Int = 1) = Vector2f(this.x / x, this.y / y)
operator fun plus(value: IStruct2i): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2i): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value)
operator fun minus(value: Int) = minus(value, value)
operator fun times(value: Int) = times(value, value)
operator fun div(value: Int) = div(value, value)
fun plus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x + x, this.y + y)
fun minus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x - x, this.y - y)
fun times(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x * x, this.y * y)
fun div(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x / x, this.y / y)
operator fun plus(value: IStruct2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value)
operator fun minus(value: Double) = minus(value, value)
operator fun times(value: Double) = times(value, value)
operator fun div(value: Double) = div(value, value)
operator fun unaryMinus(): Vector2f = Vector2f(-x, -y)
override fun equals(other: Any?): Boolean {
return other is Vector2f && x == other.x && y == other.y
}
override fun hashCode(): Int {
var x = x.hashCode().rotateLeft(16) xor y.hashCode()
// avalanche bits using murmur3 hash
x = x xor (x ushr 16)
x *= -0x7a143595
x = x xor (x ushr 13)
x *= -0x3d4d51cb
x = x xor (x ushr 16)
return x
}
override fun toString(): String {
return "[$x, $y]"
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2f): Float {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2i): Float {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2d): Double {
return x * other.component2() - other.component1() * y
}
fun dot(x: Float, y: Float) = this.x * x + this.y * y
fun dot(value: IStruct2f): Float { val (x, y) = value; return dot(x, y) }
fun dot(value: Vector2f): Float { val (x, y) = value; return dot(x, y) }
fun distanceSquared(x: Float, y: Float): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
return dx * dx + dy * dy
}
fun distanceSquared(value: IStruct2f): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distanceSquared(value: Vector2f): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distance(x: Float, y: Float) = sqrt(distanceSquared(x, y))
fun distance(value: IStruct2f): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun distance(value: Vector2f): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun coerceAtLeast(x: Float, y: Float) = Vector2f(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y))
fun coerceAtMost(x: Float, y: Float) = Vector2f(this.x.coerceAtMost(x), this.y.coerceAtMost(y))
fun coerceIn(minimum: Vector2f, maximum: Vector2f) = Vector2f(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y))
fun coerceIn(minimum: IStruct2f, maximum: IStruct2f) = Vector2f(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()))
fun coerceAtLeast(value: IStruct2f): Vector2f { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: IStruct2f): Vector2f { val (x, y) = value; return coerceAtMost(x, y) }
fun coerceAtLeast(value: Vector2f): Vector2f { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: Vector2f): Vector2f { val (x, y) = value; return coerceAtMost(x, y) }
fun rotate(angle: Float): Vector2f {
val s = sin(angle)
val c = cos(angle)
return Vector2f(x * c - s * y, s * x + c * y)
}
fun toAngle(zeroAngle: Vector2f): Float {
val dot = unitVector.dot(zeroAngle.unitVector)
return if (y > 0.0) {
acos(dot)
} else {
-acos(dot)
}
}
fun toAngle(zeroAngle: IStruct2f): Float {
return toAngle(Vector2f(zeroAngle))
}
fun toAngle(): Float {
return atan2(y, x)
}
operator fun times(value: Matrix4f): Vector2f {
return Vector2f(
x * value.c00 + y * value.c10 + value.c30,
x * value.c01 + y * value.c11 + value.c31,
)
}
operator fun times(value: Matrix3f): Vector2f {
return Vector2f(
x * value.c00 + y * value.c10 + value.c20,
x * value.c01 + y * value.c11 + value.c21,
)
}
operator fun times(value: Matrix2f): Vector2f {
return Vector2f(
x * value.c00 + y * value.c10,
x * value.c01 + y * value.c11,
)
}
operator fun times(value: Matrix4fStack) = times(value.last())
fun toDoubleVector() = Vector2d(x.toDouble(), y.toDouble())
fun toFloatVector() = this
companion object {
@JvmField val ZERO = Vector2f()
@JvmField val POSITIVE_X = Vector2f(x = 1.0f)
@JvmField val NEGATIVE_X = Vector2f(x = -1.0f)
@JvmField val POSITIVE_Y = Vector2f(y = 1.0f)
@JvmField val NEGATIVE_Y = Vector2f(y = -1.0f)
@JvmField val POSITIVE_XY = Vector2f(1.0f, 1.0f)
@JvmField val NEGATIVE_XY = Vector2f(-1.0f, -1.0f)
}
}

View File

@ -1,176 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import kotlin.math.sqrt
data class Vector2i(
val x: Int = 0,
val y: Int = 0,
) : IStruct2i, Vector() {
constructor(value: IStruct2i) : this(value.component1(), value.component2())
constructor(value: Vector2i) : this(value.x, value.y)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y
override val isFinite: Boolean
get() = true
override val isNaN: Boolean
get() = false
val r get() = x
val g get() = y
val s get() = x
val t get() = y
fun plus(x: Int = 0, y: Int = 0) = Vector2i(this.x + x, this.y + y)
fun minus(x: Int = 0, y: Int = 0) = Vector2i(this.x - x, this.y - y)
fun times(x: Int = 1, y: Int = 1) = Vector2i(this.x * x, this.y * y)
fun div(x: Int = 1, y: Int = 1) = Vector2i(this.x / x, this.y / y)
operator fun plus(value: IStruct2i): Vector2i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector2i { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector2i { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector2i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2i): Vector2i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector2i { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector2i { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector2i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value)
operator fun minus(value: Int) = minus(value, value)
operator fun times(value: Int) = times(value, value)
operator fun div(value: Int) = div(value, value)
fun plus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x + x, this.y + y)
fun minus(x: Double = 0.0, y: Double = 0.0) = Vector2d(this.x - x, this.y - y)
fun times(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x * x, this.y * y)
fun div(x: Double = 1.0, y: Double = 1.0) = Vector2d(this.x / x, this.y / y)
operator fun plus(value: IStruct2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2d): Vector2d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector2d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector2d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector2d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value)
operator fun minus(value: Double) = minus(value, value)
operator fun times(value: Double) = times(value, value)
operator fun div(value: Double) = div(value, value)
fun plus(x: Float = 0f, y: Float = 0f) = Vector2f(this.x + x, this.y + y)
fun minus(x: Float = 0f, y: Float = 0f) = Vector2f(this.x - x, this.y - y)
fun times(x: Float = 1f, y: Float = 1f) = Vector2f(this.x * x, this.y * y)
fun div(x: Float = 1f, y: Float = 1f) = Vector2f(this.x / x, this.y / y)
operator fun plus(value: IStruct2f): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector2f): Vector2f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector2f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector2f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector2f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value)
operator fun minus(value: Float) = minus(value, value)
operator fun times(value: Float) = times(value, value)
operator fun div(value: Float) = div(value, value)
operator fun unaryMinus(): Vector2i = Vector2i(-x, -y)
override fun equals(other: Any?): Boolean {
return other is Vector2i && x == other.x && y == other.y
}
override fun hashCode(): Int {
var x = x.rotateLeft(16) xor y
// avalanche bits using murmur3 hash
x = x xor (x ushr 16)
x *= -0x7a143595
x = x xor (x ushr 13)
x *= -0x3d4d51cb
x = x xor (x ushr 16)
return x
}
override fun toString(): String {
return "[$x, $y]"
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2f): Float {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2i): Int {
return x * other.component2() - other.component1() * y
}
/**
* 2D vector cross product (Z coordinate)
*/
fun cross(other: IStruct2d): Double {
return x * other.component2() - other.component1() * y
}
fun dot(x: Int, y: Int) = this.x * x + this.y * y
fun dot(value: IStruct2i): Int { val (x, y) = value; return dot(x, y) }
fun dot(value: Vector2i): Int { val (x, y) = value; return dot(x, y) }
fun distanceSquared(x: Int, y: Int): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
return dx * dx + dy * dy
}
fun distanceSquared(value: IStruct2i): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distanceSquared(value: Vector2i): Double { val (x, y) = value; return distanceSquared(x, y) }
fun distance(x: Int, y: Int) = sqrt(distanceSquared(x, y))
fun distance(value: IStruct2i): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun distance(value: Vector2i): Double { val (x, y) = value; return sqrt(distanceSquared(x, y)) }
fun coerceAtLeast(x: Int, y: Int) = Vector2i(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y))
fun coerceAtMost(x: Int, y: Int) = Vector2i(this.x.coerceAtMost(x), this.y.coerceAtMost(y))
fun coerceIn(minimum: Vector2i, maximum: Vector2i) = Vector2i(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y))
fun coerceIn(minimum: IStruct2i, maximum: IStruct2i) = Vector2i(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()))
fun coerceAtLeast(value: IStruct2i): Vector2i { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: IStruct2i): Vector2i { val (x, y) = value; return coerceAtMost(x, y) }
fun coerceAtLeast(value: Vector2i): Vector2i { val (x, y) = value; return coerceAtLeast(x, y) }
fun coerceAtMost(value: Vector2i): Vector2i { val (x, y) = value; return coerceAtMost(x, y) }
fun toDoubleVector() = Vector2d(x.toDouble(), y.toDouble())
fun toFloatVector() = Vector2f(x.toFloat(), y.toFloat())
companion object {
@JvmField val ZERO = Vector2i()
@JvmField val POSITIVE_X = Vector2i(x = 1)
@JvmField val NEGATIVE_X = Vector2i(x = -1)
@JvmField val POSITIVE_Y = Vector2i(y = 1)
@JvmField val NEGATIVE_Y = Vector2i(y = -1)
@JvmField val POSITIVE_XY = Vector2i(1, 1)
@JvmField val NEGATIVE_XY = Vector2i(-1, -1)
}
}

View File

@ -1,227 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import ru.dbotthepony.kommons.matrix.Matrix3d
import ru.dbotthepony.kommons.matrix.Matrix4d
import ru.dbotthepony.kommons.matrix.Matrix4dStack
import kotlin.math.absoluteValue
import kotlin.math.sqrt
data class Vector3d(
val x: Double = 0.0,
val y: Double = 0.0,
val z: Double = 0.0,
) : IStruct3d, Vector() {
constructor(value: IStruct2d) : this(value.component1(), value.component2())
constructor(value: Vector2d) : this(value.x, value.y)
constructor(value: IStruct2d, z: Double) : this(value.component1(), value.component2(), z)
constructor(value: Vector2d, z: Double) : this(value.x, value.y, z)
constructor(value: IStruct3d) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3d) : this(value.x, value.y, value.z)
override val lengthSquared: Double
get() = x * x + y * y + z * z
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite() && z.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN() || z.isNaN()
val unitVector: Vector3d get() {
var length = lengthSquared
if (length == 0.0 || length == 1.0) return this
length = sqrt(length)
return Vector3d(x / length, y / length, z / length)
}
val absoluteValue: Vector3d get() {
val x = x.absoluteValue
val y = y.absoluteValue
val z = z.absoluteValue
if (x != this.x || y != this.y || z != this.z) return Vector3d(x, y, z)
return this
}
val r get() = x
val g get() = y
val b get() = z
val s get() = x
val t get() = y
val p get() = z
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x + x, this.y + y, this.z + z)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x - x, this.y - y, this.z - z)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x * x, this.y * y, this.z * z)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value)
operator fun minus(value: Double) = minus(value, value, value)
operator fun times(value: Double) = times(value, value, value)
operator fun div(value: Double) = div(value, value, value)
fun plus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3d(this.x + x, this.y + y, this.z + z)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3d(this.x - x, this.y - y, this.z - z)
fun times(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3d(this.x * x, this.y * y, this.z * z)
fun div(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3d(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3i): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3i): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value)
operator fun minus(value: Int) = minus(value, value, value)
operator fun times(value: Int) = times(value, value, value)
operator fun div(value: Int) = div(value, value, value)
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3d(this.x + x, this.y + y, this.z + z)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3d(this.x - x, this.y - y, this.z - z)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3d(this.x * x, this.y * y, this.z * z)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3d(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3f): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3f): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value)
operator fun minus(value: Float) = minus(value, value, value)
operator fun times(value: Float) = times(value, value, value)
operator fun div(value: Float) = div(value, value, value)
operator fun unaryMinus(): Vector3d = Vector3d(-x, -y, -z)
fun dot(x: Double, y: Double, z: Double) = this.x * x + this.y * y + this.z * z
fun dot(value: IStruct3d): Double { val (x, y, z) = value; return dot(x, y, z) }
fun dot(value: Vector3d): Double { val (x, y, z) = value; return dot(x, y, z) }
fun distanceSquared(x: Double, y: Double, z: Double): Double {
val dx = (this.x - x)
val dy = (this.y - y)
val dz = (this.z - z)
return dx * dx + dy * dy + dz * dz
}
fun distanceSquared(value: IStruct3d): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distanceSquared(value: Vector3d): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distance(x: Double, y: Double, z: Double) = sqrt(distanceSquared(x, y, z))
fun distance(value: IStruct3d): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun distance(value: Vector3d): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun coerceAtLeast(x: Double, y: Double, z: Double) = Vector3d(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z))
fun coerceAtMost(x: Double, y: Double, z: Double) = Vector3d(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z))
fun coerceIn(minimum: Vector3d, maximum: Vector3d) = Vector3d(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z))
fun coerceIn(minimum: IStruct3d, maximum: IStruct3d) = Vector3d(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()))
fun coerceAtLeast(value: IStruct3d): Vector3d { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: IStruct3d): Vector3d { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun coerceAtLeast(value: Vector3d): Vector3d { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: Vector3d): Vector3d { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun cross(x: Double, y: Double, z: Double): Vector3d {
return Vector3d(
this.y * z - this.z * y,
this.z * x - this.x * z,
this.x * y - this.y * x,
)
}
fun cross(value: IStruct3d): Vector3d { val (x, y, z) = value; return cross(x, y, z) }
fun cross(value: Vector3d): Vector3d { val (x, y, z) = value; return cross(x, y, z) }
operator fun times(value: Matrix4d): Vector3d {
return Vector3d(
x * value.c00 + y * value.c10 + z * value.c20 + value.c30,
x * value.c01 + y * value.c11 + z * value.c21 + value.c31,
x * value.c02 + y * value.c12 + z * value.c22 + value.c32,
)
}
operator fun times(value: Matrix3d): Vector3d {
return Vector3d(
x * value.c00 + y * value.c10 + z * value.c20,
x * value.c01 + y * value.c11 + z * value.c21,
x * value.c02 + y * value.c12 + z * value.c22,
)
}
operator fun times(value: Matrix4dStack) = times(value.last())
fun toDoubleVector() = this
fun toFloatVector() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
override fun toString(): String {
return "[$x, $y, $z]"
}
companion object {
@JvmField val ZERO = Vector3d()
@JvmField val POSITIVE_X = Vector3d(x = 1.0)
@JvmField val NEGATIVE_X = Vector3d(x = -1.0)
@JvmField val POSITIVE_Y = Vector3d(y = 1.0)
@JvmField val NEGATIVE_Y = Vector3d(y = -1.0)
@JvmField val POSITIVE_Z = Vector3d(z = 1.0)
@JvmField val NEGATIVE_Z = Vector3d(z = -1.0)
@JvmField val POSITIVE_XYZ = Vector3d(1.0, 1.0, 1.0)
@JvmField val NEGATIVE_XYZ = Vector3d(-1.0, -1.0, -1.0)
}
}

View File

@ -1,227 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import ru.dbotthepony.kommons.matrix.Matrix3f
import ru.dbotthepony.kommons.matrix.Matrix4f
import ru.dbotthepony.kommons.matrix.Matrix4fStack
import kotlin.math.absoluteValue
import kotlin.math.sqrt
data class Vector3f(
val x: Float = 0f,
val y: Float = 0f,
val z: Float = 0f,
) : IStruct3f, Vector() {
constructor(value: IStruct2f) : this(value.component1(), value.component2())
constructor(value: Vector2f) : this(value.x, value.y)
constructor(value: IStruct2f, z: Float) : this(value.component1(), value.component2(), z)
constructor(value: Vector2f, z: Float) : this(value.x, value.y, z)
constructor(value: IStruct3f) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3f) : this(value.x, value.y, value.z)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y + z.toDouble() * z
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite() && z.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN() || z.isNaN()
val unitVector: Vector3f get() {
var length = lengthSquared.toFloat()
if (length == 0f || length == 1f) return this
length = sqrt(length)
return Vector3f(x / length, y / length, z / length)
}
val absoluteValue: Vector3f get() {
val x = x.absoluteValue
val y = y.absoluteValue
val z = z.absoluteValue
if (x != this.x || y != this.y || z != this.z) return Vector3f(x, y, z)
return this
}
val r get() = x
val g get() = y
val b get() = z
val s get() = x
val t get() = y
val p get() = z
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3f(this.x + x, this.y + y, this.z + z)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3f(this.x - x, this.y - y, this.z - z)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3f(this.x * x, this.y * y, this.z * z)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3f(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3f): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3f): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value)
operator fun minus(value: Float) = minus(value, value, value)
operator fun times(value: Float) = times(value, value, value)
operator fun div(value: Float) = div(value, value, value)
fun plus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3f(this.x + x, this.y + y, this.z + z)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3f(this.x - x, this.y - y, this.z - z)
fun times(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3f(this.x * x, this.y * y, this.z * z)
fun div(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3f(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3i): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3i): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value)
operator fun minus(value: Int) = minus(value, value, value)
operator fun times(value: Int) = times(value, value, value)
operator fun div(value: Int) = div(value, value, value)
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x + x, this.y + y, this.z + z)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x - x, this.y - y, this.z - z)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x * x, this.y * y, this.z * z)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value)
operator fun minus(value: Double) = minus(value, value, value)
operator fun times(value: Double) = times(value, value, value)
operator fun div(value: Double) = div(value, value, value)
operator fun unaryMinus(): Vector3f = Vector3f(-x, -y, -z)
fun dot(x: Float, y: Float, z: Float) = this.x * x + this.y * y + this.z * z
fun dot(value: IStruct3f): Float { val (x, y, z) = value; return dot(x, y, z) }
fun dot(value: Vector3f): Float { val (x, y, z) = value; return dot(x, y, z) }
fun distanceSquared(x: Float, y: Float, z: Float): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
val dz = (this.z - z).toDouble()
return dx * dx + dy * dy + dz * dz
}
fun distanceSquared(value: IStruct3f): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distanceSquared(value: Vector3f): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distance(x: Float, y: Float, z: Float) = sqrt(distanceSquared(x, y, z))
fun distance(value: IStruct3f): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun distance(value: Vector3f): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun coerceAtLeast(x: Float, y: Float, z: Float) = Vector3f(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z))
fun coerceAtMost(x: Float, y: Float, z: Float) = Vector3f(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z))
fun coerceIn(minimum: Vector3f, maximum: Vector3f) = Vector3f(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z))
fun coerceIn(minimum: IStruct3f, maximum: IStruct3f) = Vector3f(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()))
fun coerceAtLeast(value: IStruct3f): Vector3f { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: IStruct3f): Vector3f { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun coerceAtLeast(value: Vector3f): Vector3f { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: Vector3f): Vector3f { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun cross(x: Float, y: Float, z: Float): Vector3f {
return Vector3f(
this.y * z - this.z * y,
this.z * x - this.x * z,
this.x * y - this.y * x,
)
}
fun cross(value: IStruct3f): Vector3f { val (x, y, z) = value; return cross(x, y, z) }
fun cross(value: Vector3f): Vector3f { val (x, y, z) = value; return cross(x, y, z) }
operator fun times(value: Matrix4f): Vector3f {
return Vector3f(
x * value.c00 + y * value.c10 + z * value.c20 + value.c30,
x * value.c01 + y * value.c11 + z * value.c21 + value.c31,
x * value.c02 + y * value.c12 + z * value.c22 + value.c32,
)
}
operator fun times(value: Matrix3f): Vector3f {
return Vector3f(
x * value.c00 + y * value.c10 + z * value.c20,
x * value.c01 + y * value.c11 + z * value.c21,
x * value.c02 + y * value.c12 + z * value.c22,
)
}
operator fun times(value: Matrix4fStack) = times(value.last())
fun toDoubleVector() = Vector3d(x.toDouble(), y.toDouble(), z.toDouble())
fun toFloatVector() = this
override fun toString(): String {
return "[$x, $y, $z]"
}
companion object {
@JvmField val ZERO = Vector3f()
@JvmField val POSITIVE_X = Vector3f(x = 1.0f)
@JvmField val NEGATIVE_X = Vector3f(x = -1.0f)
@JvmField val POSITIVE_Y = Vector3f(y = 1.0f)
@JvmField val NEGATIVE_Y = Vector3f(y = -1.0f)
@JvmField val POSITIVE_Z = Vector3f(z = 1.0f)
@JvmField val NEGATIVE_Z = Vector3f(z = -1.0f)
@JvmField val POSITIVE_XYZ = Vector3f(1.0f, 1.0f, 1f)
@JvmField val NEGATIVE_XYZ = Vector3f(-1.0f, -1.0f, -1f)
}
}

View File

@ -1,190 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import kotlin.math.sqrt
data class Vector3i(
val x: Int = 0,
val y: Int = 0,
val z: Int = 0,
) : IStruct3i, Vector() {
constructor(value: IStruct2i) : this(value.component1(), value.component2())
constructor(value: Vector2i) : this(value.x, value.y)
constructor(value: IStruct2i, z: Int) : this(value.component1(), value.component2(), z)
constructor(value: Vector2i, z: Int) : this(value.x, value.y, z)
constructor(value: IStruct3i) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3i) : this(value.x, value.y, value.z)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y + z.toDouble() * z
override val isFinite: Boolean
get() = true
override val isNaN: Boolean
get() = false
val r get() = x
val g get() = y
val b get() = z
val s get() = x
val t get() = y
val p get() = z
fun plus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3i(this.x + x, this.y + y, this.z + z)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0) = Vector3i(this.x - x, this.y - y, this.z - z)
fun times(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3i(this.x * x, this.y * y, this.z * z)
fun div(x: Int = 1, y: Int = 1, z: Int = 1) = Vector3i(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3i): Vector3i { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector3i { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector3i { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector3i { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector3i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector3i { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector3i { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector3i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3i): Vector3i { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector3i { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector3i { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector3i { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector3i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector3i { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector3i { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector3i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value)
operator fun minus(value: Int) = minus(value, value, value)
operator fun times(value: Int) = times(value, value, value)
operator fun div(value: Int) = div(value, value, value)
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3f(this.x + x, this.y + y, this.z + z)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f) = Vector3f(this.x - x, this.y - y, this.z - z)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3f(this.x * x, this.y * y, this.z * z)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f) = Vector3f(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3f): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3f): Vector3f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector3f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector3f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector3f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector3f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector3f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector3f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector3f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value)
operator fun minus(value: Float) = minus(value, value, value)
operator fun times(value: Float) = times(value, value, value)
operator fun div(value: Float) = div(value, value, value)
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x + x, this.y + y, this.z + z)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0) = Vector3d(this.x - x, this.y - y, this.z - z)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x * x, this.y * y, this.z * z)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0) = Vector3d(this.x / x, this.y / y, this.z / z)
operator fun plus(value: IStruct3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector3d): Vector3d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector3d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector3d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector3d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector3d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector3d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector3d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector3d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value)
operator fun minus(value: Double) = minus(value, value, value)
operator fun times(value: Double) = times(value, value, value)
operator fun div(value: Double) = div(value, value, value)
operator fun unaryMinus(): Vector3i = Vector3i(-x, -y, -z)
fun dot(x: Int, y: Int, z: Int) = this.x * x + this.y * y + this.z * z
fun dot(value: IStruct3i): Int { val (x, y, z) = value; return dot(x, y, z) }
fun dot(value: Vector3i): Int { val (x, y, z) = value; return dot(x, y, z) }
fun distanceSquared(x: Int, y: Int, z: Int): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
val dz = (this.z - z).toDouble()
return dx * dx + dy * dy + dz * dz
}
fun distanceSquared(value: IStruct3i): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distanceSquared(value: Vector3i): Double { val (x, y, z) = value; return distanceSquared(x, y, z) }
fun distance(x: Int, y: Int, z: Int) = sqrt(distanceSquared(x, y, z))
fun distance(value: IStruct3i): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun distance(value: Vector3i): Double { val (x, y, z) = value; return sqrt(distanceSquared(x, y, z)) }
fun coerceAtLeast(x: Int, y: Int, z: Int) = Vector3i(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z))
fun coerceAtMost(x: Int, y: Int, z: Int) = Vector3i(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z))
fun coerceIn(minimum: Vector3i, maximum: Vector3i) = Vector3i(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z))
fun coerceIn(minimum: IStruct3i, maximum: IStruct3i) = Vector3i(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()))
fun coerceAtLeast(value: IStruct3i): Vector3i { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: IStruct3i): Vector3i { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun coerceAtLeast(value: Vector3i): Vector3i { val (x, y, z) = value; return coerceAtLeast(x, y, z) }
fun coerceAtMost(value: Vector3i): Vector3i { val (x, y, z) = value; return coerceAtMost(x, y, z) }
fun cross(x: Int, y: Int, z: Int): Vector3i {
return Vector3i(
this.y * z - this.z * y,
this.z * x - this.x * z,
this.x * y - this.y * x,
)
}
fun cross(value: IStruct3i): Vector3i { val (x, y, z) = value; return cross(x, y, z) }
fun cross(value: Vector3i): Vector3i { val (x, y, z) = value; return cross(x, y, z) }
fun toDoubleVector() = Vector3d(x.toDouble(), y.toDouble(), z.toDouble())
fun toFloatVector() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
override fun toString(): String {
return "[$x, $y, $z]"
}
companion object {
@JvmField val ZERO = Vector3i()
@JvmField val POSITIVE_X = Vector3i(x = 1)
@JvmField val NEGATIVE_X = Vector3i(x = -1)
@JvmField val POSITIVE_Y = Vector3i(y = 1)
@JvmField val NEGATIVE_Y = Vector3i(y = -1)
@JvmField val POSITIVE_Z = Vector3i(z = 1)
@JvmField val NEGATIVE_Z = Vector3i(z = -1)
@JvmField val POSITIVE_XYZ = Vector3i(1, 1, 1)
@JvmField val NEGATIVE_XYZ = Vector3i(-1, -1, -1)
}
}

View File

@ -1,247 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import ru.dbotthepony.kommons.util.IStruct4d
import ru.dbotthepony.kommons.util.IStruct4f
import ru.dbotthepony.kommons.util.IStruct4i
import ru.dbotthepony.kommons.matrix.Matrix4d
import ru.dbotthepony.kommons.matrix.Matrix4dStack
import kotlin.math.absoluteValue
import kotlin.math.sqrt
data class Vector4d(
val x: Double = 0.0,
val y: Double = 0.0,
val z: Double = 0.0,
val w: Double = 0.0,
) : IStruct4d, Vector() {
constructor(value: IStruct2d) : this(value.component1(), value.component2())
constructor(value: Vector2d) : this(value.x, value.y)
constructor(value: IStruct2d, z: Double) : this(value.component1(), value.component2(), z)
constructor(value: Vector2d, z: Double) : this(value.x, value.y, z)
constructor(value: IStruct2d, z: Double, w: Double) : this(value.component1(), value.component2(), z, w)
constructor(value: Vector2d, z: Double, w: Double) : this(value.x, value.y, z, w)
constructor(value: IStruct3d) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3d) : this(value.x, value.y, value.z)
constructor(value: IStruct3d, w: Double) : this(value.component1(), value.component2(), value.component3(), w)
constructor(value: Vector3d, w: Double) : this(value.x, value.y, value.z, w)
constructor(value: IStruct4d) : this(value.component1(), value.component2(), value.component3(), value.component4())
constructor(value: Vector4d) : this(value.x, value.y, value.z, value.w)
override val lengthSquared: Double
get() = x * x + y * y + z * z + w * w
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite() && z.isFinite() && w.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN() || z.isNaN() || w.isNaN()
val unitVector: Vector4d get() {
var length = lengthSquared
if (length == 0.0 || length == 1.0) return this
length = sqrt(length)
return Vector4d(x / length, y / length, z / length, w / length)
}
val absoluteValue: Vector4d get() {
val x = x.absoluteValue
val y = y.absoluteValue
val z = z.absoluteValue
val w = w.absoluteValue
if (x != this.x || y != this.y || z != this.z || w != this.w) return Vector4d(x, y, z, w)
return this
}
val r get() = x
val g get() = y
val b get() = z
val a get() = w
val s get() = x
val t get() = y
val p get() = z
val q get() = w
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value, value)
operator fun minus(value: Double) = minus(value, value, value, value)
operator fun times(value: Double) = times(value, value, value, value)
operator fun div(value: Double) = div(value, value, value, value)
fun plus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4d(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4d(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4d(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4d(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4i): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4i): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4i): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4i): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3i): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4i): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4i): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4i): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4i): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3i): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value, value)
operator fun minus(value: Int) = minus(value, value, value, value)
operator fun times(value: Int) = times(value, value, value, value)
operator fun div(value: Int) = div(value, value, value, value)
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4d(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4d(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4d(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4d(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4f): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4f): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4f): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4f): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3f): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4f): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4f): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4f): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4f): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3f): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value, value)
operator fun minus(value: Float) = minus(value, value, value, value)
operator fun times(value: Float) = times(value, value, value, value)
operator fun div(value: Float) = div(value, value, value, value)
operator fun unaryMinus(): Vector4d = Vector4d(-x, -y, -z, -w)
fun dot(x: Double, y: Double, z: Double, w: Double) = this.x * x + this.y * y + this.z * z + this.w * w
fun dot(value: IStruct4d): Double { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun dot(value: Vector4d): Double { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun distanceSquared(x: Double, y: Double, z: Double, w: Double): Double {
val dx = (this.x - x)
val dy = (this.y - y)
val dz = (this.z - z)
val dw = (this.w - w)
return dx * dx + dy * dy + dz * dz + dw * dw
}
fun distanceSquared(value: IStruct4d): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distanceSquared(value: Vector4d): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distance(x: Double, y: Double, z: Double, w: Double) = sqrt(distanceSquared(x, y, z, w))
fun distance(value: IStruct4d): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun distance(value: Vector4d): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun coerceAtLeast(x: Double, y: Double, z: Double, w: Double) = Vector4d(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z), this.w.coerceAtLeast(w))
fun coerceAtMost(x: Double, y: Double, z: Double, w: Double) = Vector4d(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z), this.w.coerceAtMost(w))
fun coerceIn(minimum: Vector4d, maximum: Vector4d) = Vector4d(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z),
this.w.coerceIn(minimum.w, maximum.w))
fun coerceIn(minimum: IStruct4d, maximum: IStruct4d) = Vector4d(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()),
this.w.coerceIn(minimum.component4(), maximum.component4()))
fun coerceAtLeast(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
fun coerceAtLeast(value: Vector4d): Vector4d { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: Vector4d): Vector4d { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
operator fun times(value: Matrix4d): Vector4d {
return Vector4d(
x * value.c00 + y * value.c10 + z * value.c20 + w * value.c30,
x * value.c01 + y * value.c11 + z * value.c21 + w * value.c31,
x * value.c02 + y * value.c12 + z * value.c22 + w * value.c32,
x * value.c03 + y * value.c13 + z * value.c23 + w * value.c33,
)
}
operator fun times(value: Matrix4dStack) = times(value.last())
fun toDoubleVector() = this
fun toFloatVector() = Vector4f(x.toFloat(), y.toFloat(), z.toFloat(), w.toFloat())
override fun toString(): String {
return "[$x, $y, $z, $w]"
}
companion object {
@JvmField val ZERO = Vector4d()
@JvmField val POSITIVE_X = Vector4d(x = 1.0)
@JvmField val NEGATIVE_X = Vector4d(x = -1.0)
@JvmField val POSITIVE_Y = Vector4d(y = 1.0)
@JvmField val NEGATIVE_Y = Vector4d(y = -1.0)
@JvmField val POSITIVE_Z = Vector4d(z = 1.0)
@JvmField val NEGATIVE_Z = Vector4d(z = -1.0)
@JvmField val POSITIVE_W = Vector4d(w = 1.0)
@JvmField val NEGATIVE_W = Vector4d(w = -1.0)
}
}

View File

@ -1,249 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import ru.dbotthepony.kommons.util.IStruct4d
import ru.dbotthepony.kommons.util.IStruct4f
import ru.dbotthepony.kommons.util.IStruct4i
import ru.dbotthepony.kommons.matrix.Matrix4f
import ru.dbotthepony.kommons.matrix.Matrix4fStack
import kotlin.math.absoluteValue
import kotlin.math.sqrt
data class Vector4f(
val x: Float = 0f,
val y: Float = 0f,
val z: Float = 0f,
val w: Float = 0f,
) : IStruct4f, Vector() {
constructor(value: IStruct2f) : this(value.component1(), value.component2())
constructor(value: Vector2f) : this(value.x, value.y)
constructor(value: IStruct2f, z: Float) : this(value.component1(), value.component2(), z)
constructor(value: Vector2f, z: Float) : this(value.x, value.y, z)
constructor(value: IStruct2f, z: Float, w: Float) : this(value.component1(), value.component2(), z, w)
constructor(value: Vector2f, z: Float, w: Float) : this(value.x, value.y, z, w)
constructor(value: IStruct3f) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3f) : this(value.x, value.y, value.z)
constructor(value: IStruct3f, w: Float) : this(value.component1(), value.component2(), value.component3(), w)
constructor(value: Vector3f, w: Float) : this(value.x, value.y, value.z, w)
constructor(value: IStruct4f) : this(value.component1(), value.component2(), value.component3(), value.component4())
constructor(value: Vector4f) : this(value.x, value.y, value.z, value.w)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y + z.toDouble() * z + w.toDouble() * w
override val isFinite: Boolean
get() = x.isFinite() && y.isFinite() && z.isFinite() && w.isFinite()
override val isNaN: Boolean
get() = x.isNaN() || y.isNaN() || z.isNaN() || w.isNaN()
val unitVector: Vector4f
get() {
var length = lengthSquared.toFloat()
if (length == 0f || length == 1f) return this
length = sqrt(length)
return Vector4f(x / length, y / length, z / length, w / length)
}
val absoluteValue: Vector4f
get() {
val x = x.absoluteValue
val y = y.absoluteValue
val z = z.absoluteValue
val w = w.absoluteValue
if (x != this.x || y != this.y || z != this.z || w != this.w) return Vector4f(x, y, z, w)
return this
}
val r get() = x
val g get() = y
val b get() = z
val a get() = w
val s get() = x
val t get() = y
val p get() = z
val q get() = w
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4f(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4f(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4f(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4f(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3f): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4f): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4f): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4f): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4f): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3f): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value, value)
operator fun minus(value: Float) = minus(value, value, value, value)
operator fun times(value: Float) = times(value, value, value, value)
operator fun div(value: Float) = div(value, value, value, value)
fun plus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4f(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4f(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4f(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4f(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4i): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4i): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4i): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4i): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3i): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4i): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4i): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4i): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4i): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3i): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value, value)
operator fun minus(value: Int) = minus(value, value, value, value)
operator fun times(value: Int) = times(value, value, value, value)
operator fun div(value: Int) = div(value, value, value, value)
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value, value)
operator fun minus(value: Double) = minus(value, value, value, value)
operator fun times(value: Double) = times(value, value, value, value)
operator fun div(value: Double) = div(value, value, value, value)
operator fun unaryMinus(): Vector4f = Vector4f(-x, -y, -z, -w)
fun dot(x: Float, y: Float, z: Float, w: Float) = this.x * x + this.y * y + this.z * z + this.w * w
fun dot(value: IStruct4f): Float { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun dot(value: Vector4f): Float { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun distanceSquared(x: Float, y: Float, z: Float, w: Float): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
val dz = (this.z - z).toDouble()
val dw = (this.w - w).toDouble()
return dx * dx + dy * dy + dz * dz + dw * dw
}
fun distanceSquared(value: IStruct4f): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distanceSquared(value: Vector4f): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distance(x: Float, y: Float, z: Float, w: Float) = sqrt(distanceSquared(x, y, z, w))
fun distance(value: IStruct4f): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun distance(value: Vector4f): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun coerceAtLeast(x: Float, y: Float, z: Float, w: Float) = Vector4f(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z), this.w.coerceAtLeast(w))
fun coerceAtMost(x: Float, y: Float, z: Float, w: Float) = Vector4f(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z), this.w.coerceAtMost(w))
fun coerceIn(minimum: Vector4f, maximum: Vector4f) = Vector4f(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z),
this.w.coerceIn(minimum.w, maximum.w))
fun coerceIn(minimum: IStruct4f, maximum: IStruct4f) = Vector4f(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()),
this.w.coerceIn(minimum.component4(), maximum.component4()))
fun coerceAtLeast(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
fun coerceAtLeast(value: Vector4f): Vector4f { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: Vector4f): Vector4f { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
operator fun times(value: Matrix4f): Vector4f {
return Vector4f(
x * value.c00 + y * value.c10 + z * value.c20 + w * value.c30,
x * value.c01 + y * value.c11 + z * value.c21 + w * value.c31,
x * value.c02 + y * value.c12 + z * value.c22 + w * value.c32,
x * value.c03 + y * value.c13 + z * value.c23 + w * value.c33,
)
}
operator fun times(value: Matrix4fStack) = times(value.last())
fun toDoubleVector() = Vector4d(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble())
fun toFloatVector() = this
override fun toString(): String {
return "[$x, $y, $z, $w]"
}
companion object {
@JvmField val ZERO = Vector4f()
@JvmField val POSITIVE_X = Vector4f(x = 1.0f)
@JvmField val NEGATIVE_X = Vector4f(x = -1.0f)
@JvmField val POSITIVE_Y = Vector4f(y = 1.0f)
@JvmField val NEGATIVE_Y = Vector4f(y = -1.0f)
@JvmField val POSITIVE_Z = Vector4f(z = 1.0f)
@JvmField val NEGATIVE_Z = Vector4f(z = -1.0f)
@JvmField val POSITIVE_W = Vector4f(w = 1.0f)
@JvmField val NEGATIVE_W = Vector4f(w = -1.0f)
}
}

View File

@ -1,217 +0,0 @@
package ru.dbotthepony.kommons.vector
import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.IStruct3d
import ru.dbotthepony.kommons.util.IStruct3f
import ru.dbotthepony.kommons.util.IStruct3i
import ru.dbotthepony.kommons.util.IStruct4d
import ru.dbotthepony.kommons.util.IStruct4f
import ru.dbotthepony.kommons.util.IStruct4i
import kotlin.math.sqrt
data class Vector4i(
val x: Int = 0,
val y: Int = 0,
val z: Int = 0,
val w: Int = 0,
) : IStruct4i, Vector() {
constructor(value: IStruct2i) : this(value.component1(), value.component2())
constructor(value: Vector2i) : this(value.x, value.y)
constructor(value: IStruct2i, z: Int) : this(value.component1(), value.component2(), z)
constructor(value: Vector2i, z: Int) : this(value.x, value.y, z)
constructor(value: IStruct2i, z: Int, w: Int) : this(value.component1(), value.component2(), z, w)
constructor(value: Vector2i, z: Int, w: Int) : this(value.x, value.y, z, w)
constructor(value: IStruct3i) : this(value.component1(), value.component2(), value.component3())
constructor(value: Vector3i) : this(value.x, value.y, value.z)
constructor(value: IStruct3i, w: Int) : this(value.component1(), value.component2(), value.component3(), w)
constructor(value: Vector3i, w: Int) : this(value.x, value.y, value.z, w)
constructor(value: IStruct4i) : this(value.component1(), value.component2(), value.component3(), value.component4())
constructor(value: Vector4i) : this(value.x, value.y, value.z, value.w)
override val lengthSquared: Double
get() = x.toDouble() * x + y.toDouble() * y + z.toDouble() * z + w.toDouble() * w
override val isFinite: Boolean
get() = true
override val isNaN: Boolean
get() = false
val r get() = x
val g get() = y
val b get() = z
val a get() = w
val s get() = x
val t get() = y
val p get() = z
val q get() = w
fun plus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4i(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Int = 0, y: Int = 0, z: Int = 0, w: Int = 0) = Vector4i(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4i(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Int = 1, y: Int = 1, z: Int = 1, w: Int = 1) = Vector4i(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3i): Vector4i { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3i): Vector4i { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3i): Vector4i { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3i): Vector4i { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2i): Vector4i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2i): Vector4i { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2i): Vector4i { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2i): Vector4i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4i): Vector4i { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4i): Vector4i { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4i): Vector4i { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4i): Vector4i { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3i): Vector4i { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3i): Vector4i { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3i): Vector4i { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3i): Vector4i { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2i): Vector4i { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2i): Vector4i { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2i): Vector4i { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2i): Vector4i { val (x, y) = value; return div(x, y) }
operator fun plus(value: Int) = plus(value, value, value, value)
operator fun minus(value: Int) = minus(value, value, value, value)
operator fun times(value: Int) = times(value, value, value, value)
operator fun div(value: Int) = div(value, value, value, value)
fun plus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Double = 0.0, y: Double = 0.0, z: Double = 0.0, w: Double = 0.0) = Vector4d(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Double = 1.0, y: Double = 1.0, z: Double = 1.0, w: Double = 1.0) = Vector4d(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4d): Vector4d { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4d): Vector4d { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4d): Vector4d { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3d): Vector4d { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3d): Vector4d { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3d): Vector4d { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3d): Vector4d { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2d): Vector4d { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2d): Vector4d { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2d): Vector4d { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2d): Vector4d { val (x, y) = value; return div(x, y) }
operator fun plus(value: Double) = plus(value, value, value, value)
operator fun minus(value: Double) = minus(value, value, value, value)
operator fun times(value: Double) = times(value, value, value, value)
operator fun div(value: Double) = div(value, value, value, value)
fun plus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4f(this.x + x, this.y + y, this.z + z, this.w + w)
fun minus(x: Float = 0f, y: Float = 0f, z: Float = 0f, w: Float = 0f) = Vector4f(this.x - x, this.y - y, this.z - z, this.w - w)
fun times(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4f(this.x * x, this.y * y, this.z * z, this.w * w)
fun div(x: Float = 1f, y: Float = 1f, z: Float = 1f, w: Float = 1f) = Vector4f(this.x / x, this.y / y, this.z / z, this.w / w)
operator fun plus(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: IStruct4f): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: IStruct3f): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: IStruct3f): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: IStruct3f): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: IStruct3f): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: IStruct2f): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: IStruct2f): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: IStruct2f): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: IStruct2f): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Vector4f): Vector4f { val (x, y, z, w) = value; return plus(x, y, z, w) }
operator fun minus(value: Vector4f): Vector4f { val (x, y, z, w) = value; return minus(x, y, z, w) }
operator fun times(value: Vector4f): Vector4f { val (x, y, z, w) = value; return times(x, y, z, w) }
operator fun div(value: Vector4f): Vector4f { val (x, y, z, w) = value; return div(x, y, z, w) }
operator fun plus(value: Vector3f): Vector4f { val (x, y, z) = value; return plus(x, y, z) }
operator fun minus(value: Vector3f): Vector4f { val (x, y, z) = value; return minus(x, y, z) }
operator fun times(value: Vector3f): Vector4f { val (x, y, z) = value; return times(x, y, z) }
operator fun div(value: Vector3f): Vector4f { val (x, y, z) = value; return div(x, y, z) }
operator fun plus(value: Vector2f): Vector4f { val (x, y) = value; return plus(x, y) }
operator fun minus(value: Vector2f): Vector4f { val (x, y) = value; return minus(x, y) }
operator fun times(value: Vector2f): Vector4f { val (x, y) = value; return times(x, y) }
operator fun div(value: Vector2f): Vector4f { val (x, y) = value; return div(x, y) }
operator fun plus(value: Float) = plus(value, value, value, value)
operator fun minus(value: Float) = minus(value, value, value, value)
operator fun times(value: Float) = times(value, value, value, value)
operator fun div(value: Float) = div(value, value, value, value)
operator fun unaryMinus(): Vector4i = Vector4i(-x, -y, -z, -w)
fun dot(x: Int, y: Int, z: Int, w: Int) = this.x * x + this.y * y + this.z * z + this.w * w
fun dot(value: IStruct4i): Int { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun dot(value: Vector4i): Int { val (x, y, z, w) = value; return dot(x, y, z, w) }
fun distanceSquared(x: Int, y: Int, z: Int, w: Int): Double {
val dx = (this.x - x).toDouble()
val dy = (this.y - y).toDouble()
val dz = (this.z - z).toDouble()
val dw = (this.w - w).toDouble()
return dx * dx + dy * dy + dz * dz + dw * dw
}
fun distanceSquared(value: IStruct4i): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distanceSquared(value: Vector4i): Double { val (x, y, z, w) = value; return distanceSquared(x, y, z, w) }
fun distance(x: Int, y: Int, z: Int, w: Int) = sqrt(distanceSquared(x, y, z, w))
fun distance(value: IStruct4i): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun distance(value: Vector4i): Double { val (x, y, z, w) = value; return sqrt(distanceSquared(x, y, z, w)) }
fun coerceAtLeast(x: Int, y: Int, z: Int, w: Int) = Vector4i(this.x.coerceAtLeast(x), this.y.coerceAtLeast(y), this.z.coerceAtLeast(z), this.w.coerceAtLeast(w))
fun coerceAtMost(x: Int, y: Int, z: Int, w: Int) = Vector4i(this.x.coerceAtMost(x), this.y.coerceAtMost(y), this.z.coerceAtMost(z), this.w.coerceAtMost(w))
fun coerceIn(minimum: Vector4i, maximum: Vector4i) = Vector4i(
this.x.coerceIn(minimum.x, maximum.x),
this.y.coerceIn(minimum.y, maximum.y),
this.z.coerceIn(minimum.z, maximum.z),
this.w.coerceIn(minimum.w, maximum.w))
fun coerceIn(minimum: IStruct4i, maximum: IStruct4i) = Vector4i(
this.x.coerceIn(minimum.component1(), maximum.component1()),
this.y.coerceIn(minimum.component2(), maximum.component2()),
this.z.coerceIn(minimum.component3(), maximum.component3()),
this.w.coerceIn(minimum.component4(), maximum.component4()))
fun coerceAtLeast(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: IStruct4i): Vector4i { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
fun coerceAtLeast(value: Vector4i): Vector4i { val (x, y, z, w) = value; return coerceAtLeast(x, y, z, w) }
fun coerceAtMost(value: Vector4i): Vector4i { val (x, y, z, w) = value; return coerceAtMost(x, y, z, w) }
fun toDoubleVector() = Vector4d(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble())
fun toFloatVector() = Vector4f(x.toFloat(), y.toFloat(), z.toFloat(), w.toFloat())
override fun toString(): String {
return "[$x, $y, $z, $w]"
}
companion object {
@JvmField val ZERO = Vector4i()
@JvmField val POSITIVE_X = Vector4i(x = 1)
@JvmField val NEGATIVE_X = Vector4i(x = -1)
@JvmField val POSITIVE_Y = Vector4i(y = 1)
@JvmField val NEGATIVE_Y = Vector4i(y = -1)
@JvmField val POSITIVE_Z = Vector4i(z = 1)
@JvmField val NEGATIVE_Z = Vector4i(z = -1)
@JvmField val POSITIVE_W = Vector4i(w = 1)
@JvmField val NEGATIVE_W = Vector4i(w = -1)
}
}

View File

@ -22,6 +22,4 @@ plugins {
rootProject.name = "kommons"
include("guava")
include("gson")
include("linear-algebra")
include("gson-linear-algebra")
include("kommons-mc")