![JAR search and dependency download from the Maven repository](/logo.png)
commonMain.ru.casperix.math.quad_matrix.float64.Matrix4d.kt Maven / Gradle / Ivy
package ru.casperix.math.quad_matrix.float64
import ru.casperix.math.quad_matrix.QuadMatrix
import ru.casperix.math.quad_matrix.QuadMatrixBuilder
import ru.casperix.math.quad_matrix.float32.Matrix4f
import ru.casperix.math.quaternion.float64.QuaternionDouble
import ru.casperix.math.vector.float64.Vector3d
import ru.casperix.misc.toFloatArray
import kotlinx.serialization.Serializable
@Serializable
data class Matrix4d(val data: DoubleArray) : QuadMatrix {
// constructor(vararg data: Double) : this(doubleArrayOf(*data))
init {
if (data.size != 16) throw Error("Source expected 16 elements, but actual ${data.size}")
}
operator fun get(x: Int, y: Int): Double {
return data[x + y * 4]
}
operator fun get(index: Int): Double {
return data[index]
}
fun transform(value: Vector3d): Vector3d {
val m = data
val rx = value.x * m[0] + value.y * m[4] + value.z * m[8] + m[12]
val ry = value.x * m[1] + value.y * m[5] + value.z * m[9] + m[13]
val rz = value.x * m[2] + value.y * m[6] + value.z * m[10] + m[14]
val rw = 1 / (value.x * m[3] + value.y * m[7] + value.z * m[11] + m[15])
return Vector3d(rx * rw, ry * rw, rz * rw)
}
override operator fun times(other: Matrix4d): Matrix4d {
val otherM = other.data
return Matrix4d(
doubleArrayOf(
data[0] * otherM[0] + data[1] * otherM[4] + data[2] * otherM[8] + data[3] * otherM[12],
data[0] * otherM[1] + data[1] * otherM[5] + data[2] * otherM[9] + data[3] * otherM[13],
data[0] * otherM[2] + data[1] * otherM[6] + data[2] * otherM[10] + data[3] * otherM[14],
data[0] * otherM[3] + data[1] * otherM[7] + data[2] * otherM[11] + data[3] * otherM[15],
data[4] * otherM[0] + data[5] * otherM[4] + data[6] * otherM[8] + data[7] * otherM[12],
data[4] * otherM[1] + data[5] * otherM[5] + data[6] * otherM[9] + data[7] * otherM[13],
data[4] * otherM[2] + data[5] * otherM[6] + data[6] * otherM[10] + data[7] * otherM[14],
data[4] * otherM[3] + data[5] * otherM[7] + data[6] * otherM[11] + data[7] * otherM[15],
data[8] * otherM[0] + data[9] * otherM[4] + data[10] * otherM[8] + data[11] * otherM[12],
data[8] * otherM[1] + data[9] * otherM[5] + data[10] * otherM[9] + data[11] * otherM[13],
data[8] * otherM[2] + data[9] * otherM[6] + data[10] * otherM[10] + data[11] * otherM[14],
data[8] * otherM[3] + data[9] * otherM[7] + data[10] * otherM[11] + data[11] * otherM[15],
data[12] * otherM[0] + data[13] * otherM[4] + data[14] * otherM[8] + data[15] * otherM[12],
data[12] * otherM[1] + data[13] * otherM[5] + data[14] * otherM[9] + data[15] * otherM[13],
data[12] * otherM[2] + data[13] * otherM[6] + data[14] * otherM[10] + data[15] * otherM[14],
data[12] * otherM[3] + data[13] * otherM[7] + data[14] * otherM[11] + data[15] * otherM[15],
)
)
}
fun toMatrix4f(): Matrix4f {
return Matrix4f(data.toFloatArray())
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as Matrix4d
if (!data.contentEquals(other.data)) return false
return true
}
override fun hashCode(): Int {
return data.hashCode()
}
override fun determinant(): Double {
return data[i30] * data[i21] * data[i12] * data[i03] - data[i20] * data[i31] * data[i12] * data[i03] - data[i30] * data[i11] * data[i22] * data[i03] + data[i10] * data[i31] * data[i22] * data[i03] + data[i20] * data[i11] * data[i32] * data[i03] - data[i10] * data[i21] * data[i32] * data[i03] - data[i30] * data[i21] * data[i02] * data[i13] + data[i20] * data[i31] * data[i02] * data[i13] + data[i30] * data[i01] * data[i22] * data[i13] - data[i00] * data[i31] * data[i22] * data[i13] - data[i20] * data[i01] * data[i32] * data[i13] + data[i00] * data[i21] * data[i32] * data[i13] + data[i30] * data[i11] * data[i02] * data[i23] - data[i10] * data[i31] * data[i02] * data[i23] - data[i30] * data[i01] * data[i12] * data[i23] + data[i00] * data[i31] * data[i12] * data[i23] + data[i10] * data[i01] * data[i32] * data[i23] - data[i00] * data[i11] * data[i32] * data[i23] - data[i20] * data[i11] * data[i02] * data[i33] + data[i10] * data[i21] * data[i02] * data[i33] + data[i20] * data[i01] * data[i12] * data[i33] - data[i00] * data[i21] * data[i12] * data[i33] - data[i10] * data[i01] * data[i22] * data[i33] + data[i00] * data[i11] * data[i22] * data[i33]
}
override fun inverse(): Matrix4d {
val l_det = data[3] * data[6] * data[9] * data[12] -
data[2] * data[7] * data[9] * data[12] -
data[3] * data[5] * data[10] * data[12] +
data[1] * data[7] * data[10] * data[12] +
data[2] * data[5] * data[11] * data[12] -
data[1] * data[6] * data[11] * data[12] -
data[3] * data[6] * data[8] * data[13] +
data[2] * data[7] * data[8] * data[13] +
data[3] * data[4] * data[10] * data[13] -
data[0] * data[7] * data[10] * data[13] -
data[2] * data[4] * data[11] * data[13] +
data[0] * data[6] * data[11] * data[13] +
data[3] * data[5] * data[8] * data[14] -
data[1] * data[7] * data[8] * data[14] -
data[3] * data[4] * data[9] * data[14] +
data[0] * data[7] * data[9] * data[14] +
data[1] * data[4] * data[11] * data[14] -
data[0] * data[5] * data[11] * data[14] -
data[2] * data[5] * data[8] * data[15] +
data[1] * data[6] * data[8] * data[15] +
data[2] * data[4] * data[9] * data[15] -
data[0] * data[6] * data[9] * data[15] -
data[1] * data[4] * data[10] * data[15] +
data[0] * data[5] * data[10] * data[15]
if (l_det == 0.0) throw RuntimeException("non-indataertible matrix");
val m0 =
data[9] * data[14] * data[7] - data[13] * data[10] * data[7] + data[13] * data[6] * data[11] - data[5] * data[14] * data[11] - data[9] * data[6] * data[15] + data[5] * data[10] * data[15]
val m4 =
data[12] * data[10] * data[7] - data[8] * data[14] * data[7] - data[12] * data[6] * data[11] + data[4] * data[14] * data[11] + data[8] * data[6] * data[15] - data[4] * data[10] * data[15]
val m8 =
data[8] * data[13] * data[7] - data[12] * data[9] * data[7] + data[12] * data[5] * data[11] - data[4] * data[13] * data[11] - data[8] * data[5] * data[15] + data[4] * data[9] * data[15]
val m12 =
data[12] * data[9] * data[6] - data[8] * data[13] * data[6] - data[12] * data[5] * data[10] + data[4] * data[13] * data[10] + data[8] * data[5] * data[14] - data[4] * data[9] * data[14]
val m1 =
data[13] * data[10] * data[3] - data[9] * data[14] * data[3] - data[13] * data[2] * data[11] + data[1] * data[14] * data[11] + data[9] * data[2] * data[15] - data[1] * data[10] * data[15]
val m5 =
data[8] * data[14] * data[3] - data[12] * data[10] * data[3] + data[12] * data[2] * data[11] - data[0] * data[14] * data[11] - data[8] * data[2] * data[15] + data[0] * data[10] * data[15]
val m9 =
data[12] * data[9] * data[3] - data[8] * data[13] * data[3] - data[12] * data[1] * data[11] + data[0] * data[13] * data[11] + data[8] * data[1] * data[15] - data[0] * data[9] * data[15]
val m13 =
data[8] * data[13] * data[2] - data[12] * data[9] * data[2] + data[12] * data[1] * data[10] - data[0] * data[13] * data[10] - data[8] * data[1] * data[14] + data[0] * data[9] * data[14]
val m2 =
data[5] * data[14] * data[3] - data[13] * data[6] * data[3] + data[13] * data[2] * data[7] - data[1] * data[14] * data[7] - data[5] * data[2] * data[15] + data[1] * data[6] * data[15]
val m6 =
data[12] * data[6] * data[3] - data[4] * data[14] * data[3] - data[12] * data[2] * data[7] + data[0] * data[14] * data[7] + data[4] * data[2] * data[15] - data[0] * data[6] * data[15]
val m10 =
data[4] * data[13] * data[3] - data[12] * data[5] * data[3] + data[12] * data[1] * data[7] - data[0] * data[13] * data[7] - data[4] * data[1] * data[15] + data[0] * data[5] * data[15]
val m14 =
data[12] * data[5] * data[2] - data[4] * data[13] * data[2] - data[12] * data[1] * data[6] + data[0] * data[13] * data[6] + data[4] * data[1] * data[14] - data[0] * data[5] * data[14]
val m3 =
data[9] * data[6] * data[3] - data[5] * data[10] * data[3] - data[9] * data[2] * data[7] + data[1] * data[10] * data[7] + data[5] * data[2] * data[11] - data[1] * data[6] * data[11]
val m7 =
data[4] * data[10] * data[3] - data[8] * data[6] * data[3] + data[8] * data[2] * data[7] - data[0] * data[10] * data[7] - data[4] * data[2] * data[11] + data[0] * data[6] * data[11]
val m11 =
data[8] * data[5] * data[3] - data[4] * data[9] * data[3] - data[8] * data[1] * data[7] + data[0] * data[9] * data[7] + data[4] * data[1] * data[11] - data[0] * data[5] * data[11]
val m15 =
data[4] * data[9] * data[2] - data[8] * data[5] * data[2] + data[8] * data[1] * data[6] - data[0] * data[9] * data[6] - data[4] * data[1] * data[10] + data[0] * data[5] * data[10]
val inv_det = 1.0 / l_det;
return Matrix4d(
doubleArrayOf(
m0 * inv_det,
m1 * inv_det,
m2 * inv_det,
m3 * inv_det,
m4 * inv_det,
m5 * inv_det,
m6 * inv_det,
m7 * inv_det,
m8 * inv_det,
m9 * inv_det,
m10 * inv_det,
m11 * inv_det,
m12 * inv_det,
m13 * inv_det,
m14 * inv_det,
m15 * inv_det,
)
)
}
override fun transpose(): Matrix4d {
return Matrix4d(
doubleArrayOf(
data[i00], data[i01], data[i02], data[i03],
data[i10], data[i11], data[i12], data[i13],
data[i20], data[i21], data[i22], data[i23],
data[i30], data[i31], data[i32], data[i33],
)
)
}
companion object : QuadMatrixBuilder {
private val i00 = 0
private val i10 = 1
private val i20 = 2
private val i30 = 3
private val i01 = 4
private val i11 = 5
private val i21 = 6
private val i31 = 7
private val i02 = 8
private val i12 = 9
private val i22 = 10
private val i32 = 11
private val i03 = 12
private val i13 = 13
private val i23 = 14
private val i33 = 15
fun byIndex(factory: (Int) -> Double): Matrix4d {
return Matrix4d(DoubleArray(16) { factory(it) })
}
fun fromValues(vararg values: Double): Matrix4d {
return byIndex { values.getOrNull(it) ?: 0.0 }
}
val IDENTITY = byIndex { if (it % 5 == 0) 1.0 else 0.0 }
override fun translate(value: Vector3d): Matrix4d {
return fromValues(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
value.x, value.y, value.z, 1.0
)
}
override fun scale(value: Vector3d): Matrix4d {
return fromValues(
value.x, 0.0, 0.0, 0.0,
0.0, value.y, 0.0, 0.0,
0.0, 0.0, value.z, 0.0,
0.0, 0.0, 0.0, 1.0
)
}
override fun rotate(value: QuaternionDouble): Matrix4d {
val xx = value.x * value.x
val yy = value.y * value.y
val zz = value.z * value.z
val xy = value.x * value.y
val zw = value.z * value.w
val zx = value.z * value.x
val yw = value.y * value.w
val yz = value.y * value.z
val xw = value.x * value.w
return Matrix4d(
doubleArrayOf(
/*0*/ (1.0 - (2.0 * (yy + zz))),
/*1*/ 2.0 * (xy + zw),
/*2*/ 2.0 * (zx - yw),
/*3*/ 0.0,
/*4*/ 2.0 * (xy - zw),
/*5*/ (1.0 - (2.0 * (zz + xx))),
/*6*/ 2.0 * (yz + xw),
/*7*/ 0.0,
/*8*/ 2.0 * (zx + yw),
/*9*/ 2.0 * (yz - xw),
/*10*/ (1.0 - (2.0 * (yy + xx))),
/*11*/ 0.0,
/*12*/ 0.0,
/*13*/ 0.0,
/*14*/ 0.0,
/*15*/ 1.0
)
)
}
fun compose(translate: Vector3d, scale: Vector3d, rotation: QuaternionDouble): Matrix4d {
val xx = rotation.x * rotation.x
val yy = rotation.y * rotation.y
val zz = rotation.z * rotation.z
val xy = rotation.x * rotation.y
val zw = rotation.z * rotation.w
val zx = rotation.z * rotation.x
val yw = rotation.y * rotation.w
val yz = rotation.y * rotation.z
val xw = rotation.x * rotation.w
return Matrix4d(
doubleArrayOf(
/*0*/ (1.0 - (2.0 * (yy + zz))) * scale.x,
/*1*/ 2.0 * (xy + zw) * scale.x,
/*2*/ 2.0 * (zx - yw) * scale.x,
/*3*/ 0.0,
/*4*/ 2.0 * (xy - zw) * scale.y,
/*5*/ (1.0 - (2.0 * (zz + xx))) * scale.y,
/*6*/ 2.0 * (yz + xw) * scale.y,
/*7*/ 0.0,
/*8*/ 2.0 * (zx + yw) * scale.z,
/*9*/ 2.0 * (yz - xw) * scale.z,
/*10*/ (1.0 - (2.0 * (yy + xx))) * scale.z,
/*11*/ 0.0,
/*12*/ translate.x,
/*13*/ translate.y,
/*14*/ translate.z,
/*15*/ 1.0
)
)
}
fun createByAxis(xAxis: Vector3d, yAxis: Vector3d, zAxis: Vector3d): Matrix4d {
return fromValues(
xAxis.x, yAxis.x, zAxis.x, 0.0,
xAxis.y, yAxis.y, zAxis.y, 0.0,
xAxis.z, yAxis.z, zAxis.z, 0.0,
0.0, 0.0, 0.0, 1.0
)
}
fun fromQuaternion(quaternion: QuaternionDouble): Matrix4d {
val xx = quaternion.x * quaternion.x
val yy = quaternion.y * quaternion.y
val zz = quaternion.z * quaternion.z
val xy = quaternion.x * quaternion.y
val zw = quaternion.z * quaternion.w
val zx = quaternion.z * quaternion.x
val yw = quaternion.y * quaternion.w
val yz = quaternion.y * quaternion.z
val xw = quaternion.x * quaternion.w
return fromValues(
/*0*/ 1.0 - (2.0 * (yy + zz)),
/*1*/ 2.0 * (xy + zw),
/*2*/ 2.0 * (zx - yw),
/*3*/ 0.0,
/*4*/ 2.0 * (xy - zw),
/*5*/ 1.0 - (2.0 * (zz + xx)),
/*6*/ 2.0 * (yz + xw),
/*7*/ 0.0,
/*8*/ 2.0 * (zx + yw),
/*9*/ 2.0 * (yz - xw),
/*10*/ 1.0 - (2.0 * (yy + xx)),
/*11*/ 0.0,
/*12*/ 0.0,
/*13*/ 0.0,
/*14*/ 0.0,
/*15*/ 1.0
)
}
fun orthographic(
left: Double,
right: Double,
bottom: Double,
top: Double,
near: Double,
far: Double
): Matrix4d {
val tx = -(right + left) / (right - left)
val ty = -(top + bottom) / (top - bottom)
val tz = -(far + near) / (far - near)
return Matrix4d(
doubleArrayOf(
2.0 / (right - left), 0.0, 0.0, 0.0,
0.0, 2.0 / (top - bottom), 0.0, 0.0,
0.0, 0.0, -2.0 / (far - near), 0.0,
tx, ty, tz, 0.0,
)
)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy