package com.persesgames.math import org.khronos.webgl.Float32Array /** * User: rnentjes * Date: 17-4-16 * Time: 15:43 */ class Matrix4 { internal var matrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) internal var temp = FloatArray(16) private val translateMatrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) private val scaleMatrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) private val rotateXMatrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) private val rotateYMatrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) private val rotateZMatrix = floatArrayOf(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f) fun get(): FloatArray { return matrix } fun getFloat32Array() = Float32Array(get().toTypedArray()) fun set(values: FloatArray) { if (values.size != 16) { throw IllegalArgumentException("Matrix size should be 16!") } matrix = values } fun setPerspectiveProjection(angle: Float, imageAspectRatio: Float, near: Float, far: Float) { val r = (angle / 180f * Math.PI).toFloat() val f = (1.0f / Math.tan((r / 2.0f).toDouble())).toFloat() matrix[0] = f / imageAspectRatio matrix[1] = 0.0f matrix[2] = 0.0f matrix[3] = 0.0f matrix[4] = 0.0f matrix[5] = f matrix[6] = 0.0f matrix[7] = 0.0f matrix[8] = 0.0f matrix[9] = 0.0f matrix[10] = -(far + near) / (far - near) matrix[11] = -1.0f matrix[12] = 0.0f matrix[13] = 0.0f matrix[14] = -(2.0f * far * near) / (far - near) matrix[15] = 0.0f } fun setOrthographicProjection(left: Float, right: Float, bottom: Float, top: Float, near: Float, far: Float) { matrix[0] = 2f / (right - left) matrix[1] = 0f matrix[2] = 0f matrix[3] = 0f matrix[4] = 0f matrix[5] = 2f / (top - bottom) matrix[6] = 0f matrix[7] = 0f matrix[8] = 0f matrix[9] = 0f matrix[10] = -2f / (far - near) matrix[11] = 0f matrix[12] = - (right + left) / (right - left) matrix[13] = - (top + bottom) / (top - bottom) matrix[14] = - (far + near) / (far - near) matrix[15] = 1f } fun setToIdentity() { matrix[0] = 1.0f matrix[1] = 0.0f matrix[2] = 0.0f matrix[3] = 0.0f matrix[4] = 0.0f matrix[5] = 1.0f matrix[6] = 0.0f matrix[7] = 0.0f matrix[8] = 0.0f matrix[9] = 0.0f matrix[10] = 1.0f matrix[11] = 0.0f matrix[12] = 0.0f matrix[13] = 0.0f matrix[14] = 0.0f matrix[15] = 1.0f } fun mul(other: Matrix4) { mul(other.get()) } protected fun mul(other: FloatArray) { if (other.size != 16) { throw IllegalArgumentException("Matrix size should be 16!") } temp[0] = matrix[0] * other[0] + matrix[1] * other[4] + matrix[2] * other[8] + matrix[3] * other[12] temp[1] = matrix[0] * other[1] + matrix[1] * other[5] + matrix[2] * other[9] + matrix[3] * other[13] temp[2] = matrix[0] * other[2] + matrix[1] * other[6] + matrix[2] * other[10] + matrix[3] * other[14] temp[3] = matrix[0] * other[3] + matrix[1] * other[7] + matrix[2] * other[11] + matrix[3] * other[15] temp[4] = matrix[4] * other[0] + matrix[5] * other[4] + matrix[6] * other[8] + matrix[7] * other[12] temp[5] = matrix[4] * other[1] + matrix[5] * other[5] + matrix[6] * other[9] + matrix[7] * other[13] temp[6] = matrix[4] * other[2] + matrix[5] * other[6] + matrix[6] * other[10] + matrix[7] * other[14] temp[7] = matrix[4] * other[3] + matrix[5] * other[7] + matrix[6] * other[11] + matrix[7] * other[15] temp[8] = matrix[8] * other[0] + matrix[9] * other[4] + matrix[10] * other[8] + matrix[11] * other[12] temp[9] = matrix[8] * other[1] + matrix[9] * other[5] + matrix[10] * other[9] + matrix[11] * other[13] temp[10] = matrix[8] * other[2] + matrix[9] * other[6] + matrix[10] * other[10] + matrix[11] * other[14] temp[11] = matrix[8] * other[3] + matrix[9] * other[7] + matrix[10] * other[11] + matrix[11] * other[15] temp[12] = matrix[12] * other[0] + matrix[13] * other[4] + matrix[14] * other[8] + matrix[15] * other[12] temp[13] = matrix[12] * other[1] + matrix[13] * other[5] + matrix[14] * other[9] + matrix[15] * other[13] temp[14] = matrix[12] * other[2] + matrix[13] * other[6] + matrix[14] * other[10] + matrix[15] * other[14] temp[15] = matrix[12] * other[3] + matrix[13] * other[7] + matrix[14] * other[11] + matrix[15] * other[15] matrix[0] = temp[0] matrix[1] = temp[1] matrix[2] = temp[2] matrix[3] = temp[3] matrix[4] = temp[4] matrix[5] = temp[5] matrix[6] = temp[6] matrix[7] = temp[7] matrix[8] = temp[8] matrix[9] = temp[9] matrix[10] = temp[10] matrix[11] = temp[11] matrix[12] = temp[12] matrix[13] = temp[13] matrix[14] = temp[14] matrix[15] = temp[15] } fun translate(x: Float, y: Float, z: Float) { translateMatrix[12] = x translateMatrix[13] = y translateMatrix[14] = z mul(translateMatrix) } fun scale(x: Float, y: Float, z: Float) { scaleMatrix[0] = x scaleMatrix[5] = y scaleMatrix[10] = z mul(scaleMatrix) } fun rotateX(angle: Float) { rotateXMatrix[5] = Math.cos(angle.toDouble()).toFloat() rotateXMatrix[6] = (-Math.sin(angle.toDouble())).toFloat() rotateXMatrix[9] = Math.sin(angle.toDouble()).toFloat() rotateXMatrix[10] = Math.cos(angle.toDouble()).toFloat() mul(rotateXMatrix) } fun rotateY(angle: Float) { rotateYMatrix[0] = Math.cos(angle.toDouble()).toFloat() rotateYMatrix[2] = Math.sin(angle.toDouble()).toFloat() rotateYMatrix[8] = (-Math.sin(angle.toDouble())).toFloat() rotateYMatrix[10] = Math.cos(angle.toDouble()).toFloat() mul(rotateYMatrix) } fun rotateZ(angle: Float) { rotateZMatrix[0] = Math.cos(angle.toDouble()).toFloat() rotateZMatrix[1] = Math.sin(angle.toDouble()).toFloat() rotateZMatrix[4] = (-Math.sin(angle.toDouble())).toFloat() rotateZMatrix[5] = Math.cos(angle.toDouble()).toFloat() mul(rotateZMatrix) } }