All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.math.camera.CameraTransform3f.kt Maven / Gradle / Ivy

package ru.casperix.math.camera

import ru.casperix.math.axis_aligned.float32.Box2f
import ru.casperix.math.axis_aligned.int32.Dimension2i
import ru.casperix.math.quad_matrix.float32.Matrix4f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.float32.Vector3f

data class CameraTransform3f(
    val projection: Matrix4f,
    val view: Matrix4f,
    val viewport: Dimension2i,
    val near: Float,
    val far: Float,
) {
    private val projectionView = view * projection
    private val projectionViewInversed = projectionView.inverse()

    fun unproject(screenPosition: Vector2f): Vector3f {
        return unproject(screenPosition.expand(0f))
    }

    fun unproject(screenPosition: Vector3f): Vector3f {
        val screenPositionNormalized = Vector3f(
            2.0f * screenPosition.x / viewport.width - 1.0f,
            2.0f * (viewport.height - screenPosition.y) / viewport.height - 1.0f,
            2.0f * screenPosition.z - 1.0f,
        )
        val worldPosition = projection(screenPositionNormalized, projectionViewInversed)
        if (worldPosition.isFinite()) return worldPosition
        return Vector3f.ZERO
    }

    fun project(worldPosition: Vector2f): Vector3f {
        return project(worldPosition.expand(0f))
    }

    fun project(worldPosition: Vector3f): Vector3f {
        val screenPositionNormalized = projection(worldPosition, projectionView)
        val screenPosition = Vector3f(
            viewport.width * (screenPositionNormalized.x + 1.0f) / 2.0f,
            viewport.height * (screenPositionNormalized.y + 1.0f) / 2.0f,
            (screenPositionNormalized.z + 1.0f) / 2.0f,
        )

        if (screenPosition.isFinite()) return screenPosition
        return Vector3f.ZERO
    }

    fun getViewportInObjectSpace(): Box2f {
        val start = unproject(Vector3f.ZERO)
        val finish = unproject(viewport.toVector2f().expand(0f))
        return Box2f.byCorners(start.getXY(), finish.getXY())
    }

    fun getViewport(): Box2f {
        val start = Vector2f.ZERO
        val finish = viewport.toVector2f()
        return Box2f.byCorners(start, finish)
    }

    fun getTranslate(): Vector3f {
        return view.getTranslate()
    }

    private fun projection(self: Vector3f, matrix: Matrix4f): Vector3f {
        val table = matrix.data
        val factor = 1.0f / (self.x * table[3] + self.y * table[7] + self.z * table[11] + table[15])
        return Vector3f(
            (self.x * table[0] + self.y * table[4] + self.z * table[8] + table[12]) * factor,
            (self.x * table[1] + self.y * table[5] + self.z * table[9] + table[13]) * factor,
            (self.x * table[2] + self.y * table[6] + self.z * table[10] + table[14]) * factor
        )
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy