Newer
Older
kotlin-webgl-test / src / com / persesgames / math / Matrix4.kt
rnentjes on 17 Apr 2016 7 KB Initial commit
package com.persesgames.math

import org.khronos.webgl.Float32Array

/**
 * User: rnentjes
 * Date: 17-4-16
 * Time: 15:43
 */

class Matrix4 {

    internal var matrix = Float32Array(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).toTypedArray())

    internal var temp = Float32Array(16)

    private val translateMatrix = Float32Array(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).toTypedArray())

    private val scaleMatrix = Float32Array(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).toTypedArray())

    private val rotateXMatrix = Float32Array(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).toTypedArray())

    private val rotateYMatrix = Float32Array(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).toTypedArray())

    private val rotateZMatrix = Float32Array(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).toTypedArray())

    fun get(): Float32Array {
        return matrix
    }

    fun set(values: Float32Array) {
        if (values.length != 16) {
            throw IllegalArgumentException("FloatArray must hava 16 entries!")
        }
        //assert(values.size == 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.set(0,f / imageAspectRatio)
        matrix.set(1,0.0f)
        matrix.set(2,0.0f)
        matrix.set(3,0.0f)

        matrix.set(4, 0.0f)
        matrix.set(5, f)
        matrix.set(6, 0.0f)
        matrix.set(7, 0.0f)
        matrix.set(8, 0.0f)
        matrix.set(9, 0.0f)
        matrix.set(10, -(far + near) / (far - near))
        matrix.set(11, -1.0f)
        matrix.set(12, 0.0f)
        matrix.set(13, 0.0f)
        matrix.set(14, -(2.0f * far * near) / (far - near))
        matrix.set(15, 0.0f)
    }

    fun setToIdentity() {
        matrix.set(0, 1.0f)
        matrix.set(1, 0.0f)
        matrix.set(2, 0.0f)
        matrix.set(3, 0.0f)
        matrix.set(4, 0.0f)
        matrix.set(5, 1.0f)
        matrix.set(6, 0.0f)
        matrix.set(7, 0.0f)
        matrix.set(8, 0.0f)
        matrix.set(9, 0.0f)
        matrix.set(10, 1.0f)
        matrix.set(11, 0.0f)
        matrix.set(12, 0.0f)
        matrix.set(13, 0.0f)
        matrix.set(14, 0.0f)
        matrix.set(15, 1.0f)
    }

    fun mul(other: Matrix4) {
        mul(other.get())
    }

    protected fun mul(other: Float32Array) {
        if (other.length != 16) {
            throw IllegalArgumentException("FloatArray must hava 16 entries!")
        }

        temp.set(0, matrix.get(0) * other.get(0) + matrix.get(1) * other.get(4) + matrix.get(2) * other.get(8) + matrix.get(3) * other.get(12))
        temp.set(1, matrix.get(0) * other.get(1) + matrix.get(1) * other.get(5) + matrix.get(2) * other.get(9) + matrix.get(3) * other.get(13))
        temp.set(2, matrix.get(0) * other.get(2) + matrix.get(1) * other.get(6) + matrix.get(2) * other.get(10) + matrix.get(3) * other.get(14))
        temp.set(3, matrix.get(0) * other.get(3) + matrix.get(1) * other.get(7) + matrix.get(2) * other.get(11) + matrix.get(3) * other.get(15))
        temp.set(4, matrix.get(4) * other.get(0) + matrix.get(5) * other.get(4) + matrix.get(6) * other.get(8) + matrix.get(7) * other.get(12))
        temp.set(5, matrix.get(4) * other.get(1) + matrix.get(5) * other.get(5) + matrix.get(6) * other.get(9) + matrix.get(7) * other.get(13))
        temp.set(6, matrix.get(4) * other.get(2) + matrix.get(5) * other.get(6) + matrix.get(6) * other.get(10) + matrix.get(7) * other.get(14))
        temp.set(7, matrix.get(4) * other.get(3) + matrix.get(5) * other.get(7) + matrix.get(6) * other.get(11) + matrix.get(7) * other.get(15))
        temp.set(8, matrix.get(8) * other.get(0) + matrix.get(9) * other.get(4) + matrix.get(10) * other.get(8) + matrix.get(11) * other.get(12))
        temp.set(9, matrix.get(8) * other.get(1) + matrix.get(9) * other.get(5) + matrix.get(10) * other.get(9) + matrix.get(11) * other.get(13))
        temp.set(10, matrix.get(8)* other.get(2) + matrix.get(9) * other.get(6) + matrix.get(10) * other.get(10) + matrix.get(11) * other.get(14))
        temp.set(11, matrix.get(8)* other.get(3) + matrix.get(9) * other.get(7) + matrix.get(10) * other.get(11) + matrix.get(11) * other.get(15))
        temp.set(12, matrix.get(12) * other.get(0) + matrix.get(13) * other.get(4) + matrix.get(14) * other.get(8) + matrix.get(15) * other.get(12))
        temp.set(13, matrix.get(12) * other.get(1) + matrix.get(13) * other.get(5) + matrix.get(14) * other.get(9) + matrix.get(15) * other.get(13))
        temp.set(14, matrix.get(12) * other.get(2) + matrix.get(13) * other.get(6) + matrix.get(14) * other.get(10) + matrix.get(15) * other.get(14))
        temp.set(15, matrix.get(12) * other.get(3) + matrix.get(13) * other.get(7) + matrix.get(14) * other.get(11) + matrix.get(15) * other.get(15))

        matrix.set(0 , temp.get(0))
        matrix.set(1 , temp.get(1))
        matrix.set(2 , temp.get(2))
        matrix.set(3 , temp.get(3))
        matrix.set(4 , temp.get(4))
        matrix.set(5 , temp.get(5))
        matrix.set(6 , temp.get(6))
        matrix.set(7 , temp.get(7))
        matrix.set(8 , temp.get(8))
        matrix.set(9 , temp.get(9))
        matrix.set(10, temp.get(10))
        matrix.set(11, temp.get(11))
        matrix.set(12, temp.get(12))
        matrix.set(13, temp.get(13))
        matrix.set(14, temp.get(14))
        matrix.set(15, temp.get(15))
    }

    fun translate(x: Float, y: Float, z: Float) {
        translateMatrix.set(12, x)
        translateMatrix.set(13, y)
        translateMatrix.set(14, z)

        mul(translateMatrix)
    }

    fun scale(x: Float, y: Float, z: Float) {
        scaleMatrix.set(0, x)
        scaleMatrix.set(5, y)
        scaleMatrix.set(10, z)

        mul(scaleMatrix)
    }

    fun rotateX(angle: Float) {
        rotateXMatrix.set(5, Math.cos(angle.toDouble()).toFloat())
        rotateXMatrix.set(6, (-Math.sin(angle.toDouble())).toFloat())
        rotateXMatrix.set(9, Math.sin(angle.toDouble()).toFloat())
        rotateXMatrix.set(10, Math.cos(angle.toDouble()).toFloat())

        mul(rotateXMatrix)
    }

    fun rotateY(angle: Float) {
        rotateYMatrix.set(0, Math.cos(angle.toDouble()).toFloat())
        rotateYMatrix.set(2, Math.sin(angle.toDouble()).toFloat())
        rotateYMatrix.set(8, (-Math.sin(angle.toDouble())).toFloat())
        rotateYMatrix.set(10, Math.cos(angle.toDouble()).toFloat())

        mul(rotateYMatrix)
    }

    fun rotateZ(angle: Float) {
        rotateZMatrix.set(0, Math.cos(angle.toDouble()).toFloat())
        rotateZMatrix.set(1, Math.sin(angle.toDouble()).toFloat())
        rotateZMatrix.set(4, (-Math.sin(angle.toDouble())).toFloat())
        rotateZMatrix.set(5, Math.cos(angle.toDouble()).toFloat())

        mul(rotateZMatrix)
    }
}