Skip to main content Skip to docs navigation

Geometry 3D

KorMA provides some geometry utilities: Vector3D, Matrix3D, AABB3D, Ray3D, EulerRotation, Quaternion, BVH3D...

Document not reviewed yet, might be outdated. Please, let us know if you find something invalid here.

Vector3D and Matrix3D

Vector3D and Matrix3D are vectors and matrices of 4 components / 4 rows and 4 columns. They can also be used as 2, 3 and 4 component vectors, and 2x2, 3x3 and 4x4 matrices.

CylindricalVector

CylindricalVector represents a coordinate in a cylinder.

val cylindricalVector = CylindricalVector(radius = 10.0, angle = 45.degrees, y = 10.0)
val vector: Vector3F = cylindricalVector.toVector3()
val again: CylindricalVector = vector.toCylindrical()

val radius = cylindricalVector.radius
val angle = cylindricalVector.angle
val y = cylindricalVector.y

AABB3D & Sphere3D

data class Sphere3D(val origin: Vector3, val radius: Float) {
}

data class AABB3D(val min: Vector3 = Vector3(), val max: Vector3) {
    var minX: Float
    var minY: Float
    var minZ: Float
    var maxX: Float
    var maxY: Float
    var maxZ: Float
    val sizeX: Float
    val sizeY: Float
    val sizeZ: Float

    companion object {
        operator fun invoke(min: Float = Float.POSITIVE_INFINITY, max: Float = Float.NEGATIVE_INFINITY): AABB3D
        fun fromSphere(pos: IVector3, radius: Float): AABB3D
    }

    fun setX(min: Float, max: Float)
    fun setY(min: Float, max: Float)
    fun setZ(min: Float, max: Float)
    fun copyFrom(other: AABB3D)
    fun expandBy(that: AABB3D)
    fun expandToFit(that: AABB3D)
    fun expandedBy(that: AABB3D, out: AABB3D = AABB3D()): AABB3D
    fun intersectsSphere(sphere: Sphere3D): Boolean
    fun intersectsSphere(origin: Vector3, radius: Float): Boolean
    fun intersectsAABB(box: AABB3D): Boolean
    fun clone(): AABB3D
}

Ray3D

class Ray3D {
	val pos: Vector3D
	val dir: Vector3D
	
    fun transformed(mat: Matrix3D): Ray3D
    
	companion object {
        fun fromPoints(p1: Vector3D, p2: Vector3D): Ray3D
    }
}

fun Ray3D.intersectRayAABox1(box: AABB3D) : Boolean 

EulerRotation


class EulerRotation {
    var x: Angle = 0.degrees,
    var y: Angle = 0.degrees,
    var z: Angle = 0.degrees

    companion object {
        fun toQuaternion(roll: Angle, pitch: Angle, yaw: Angle, out: Quaternion = Quaternion()): Quaternion
        fun toQuaternion(euler: EulerRotation, out: Quaternion = Quaternion()): Quaternion
    }

    fun toQuaternion(out: Quaternion = Quaternion()): Quaternion
    fun setQuaternion(x: Double, y: Double, z: Double, w: Double): EulerRotation
    fun setQuaternion(x: Int, y: Int, z: Int, w: Int): EulerRotation
    fun setQuaternion(x: Float, y: Float, z: Float, w: Float): EulerRotation

    fun setQuaternion(quaternion: Quaternion): EulerRotation
    fun setTo(x: Angle, y: Angle, z: Angle): EulerRotation
    fun setTo(other: EulerRotation): EulerRotation
    fun toMatrix(out: Matrix3D = Matrix3D()): Matrix3D
}

Quaternion

A Quaternion is a kind of vector that represent a rotation in a 3D space. It can be converted from/to EulerRotation, and can also be converted to/from a rotation Matrix4.

Constructing a Quaternion:

The Quaternion identity (no rotation) can be obtained with:

Quaternion.IDENTITY

You can also construct it from two vectors: an original vector plus a resultant vector after the rotation. For example:

Quaternion.fromVectors(Vector3.UP, Vector3.RIGHT) // A Quaternion that would rotate to the right

Code:

// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
class Quaternion {
    var x: Double = 0.0,
    var y: Double = 0.0,
    var z: Double = 0.0,
    var w: Double = 1.0

    val xyz: Vector3D

    constructor(xyz: IVector3, w: Double)

    val lengthSquared: Double
    val length: Double

    companion object {
        fun dotProduct(l: Quaternion, r: Quaternion): Double
        operator fun invoke(x: Float, y: Float, z: Float, w: Float): Quaternion
        operator fun invoke(x: Int, y: Int, z: Int, w: Int): Quaternion
        fun toEuler(q: Quaternion, out: EulerRotation = EulerRotation()): EulerRotation
        fun toEuler(x: Double, y: Double, z: Double, w: Double, euler: EulerRotation
        fun toEuler(x: Int, y: Int, z: Int, w: Int, euler: EulerRotation = EulerRotation()): EulerRotation
        fun toEuler(x: Float, y: Float, z: Float, w: Float, out: EulerRotation = EulerRotation()): EulerRotation
    }

    operator fun get(index: Int): Double
    inline fun setToFunc(callback: (Int) -> Double)
    fun setTo(x: Double, y: Double, z: Double, w: Double): Quaternion
    fun setTo(x: Int, y: Int, z: Int, w: Int): Quaternion
    fun setTo(x: Float, y: Float, z: Float, w: Float): Quaternion
    fun setTo(euler: EulerRotation): Quaternion
    fun setTo(other: Quaternion): Quaternion

    fun setEuler(x: Angle, y: Angle, z: Angle): Quaternion
    fun setEuler(euler: EulerRotation): Quaternion

    fun copyFrom(other: Quaternion): Quaternion

    operator fun unaryMinus(): Quaternion
    operator fun plus(other: Quaternion): Quaternion
    operator fun minus(other: Quaternion): Quaternion
    operator fun times(scale: Double): Quaternion

    fun negate()

    inline fun setToFunc(l: Quaternion, r: Quaternion, func: (l: Double, r: Double) -> Double)
    fun setToSlerp(left: Quaternion, right: Quaternion, t: Double, tleft: Quaternion = Quaternion(), tright: Quaternion = Quaternion()): Quaternion
    fun setToNlerp(left: Quaternion, right: Quaternion, t: Double): Quaternion
    fun setToInterpolated(left: Quaternion, right: Quaternion, t: Double): Quaternion
    fun setFromRotationMatrix(m: Matrix3D): Quaternion
    fun normalize(v: Quaternion = this): Quaternion
    fun toMatrix(out: Matrix3D = Matrix3D()): Matrix3D
    fun inverted(out: Quaternion = Quaternion()): Quaternion

    operator fun times(other: Quaternion): Quaternion
    fun transform(vec: Vector3D, out: Vector3D = Vector3D()): Vector3D
}

BVH

N-dimensional Bounding Volume Hierarchy implementation

BVH3D

A Bounding Volume Hierarchy implementation for 3D. It uses AABB3D to describe volumes and Ray3D for raycasting.

open class BVH3D<T>(val allowUpdateObjects: Boolean = true) {
    val bvh = BVH<T>(allowUpdateObjects = allowUpdateObjects)
    fun intersectRay(ray: Ray3D, rect: AABB3D? = null): BVHIntervals?
    fun envelope(): AABB3D
    fun intersect(ray: Ray3D, return_array = fastArrayListOf()): FastArrayList<BVH.IntersectResult<T>>
    fun search(rect: AABB3D, return_array = fastArrayListOf()): FastArrayList<BVH.Node<T>>
    fun insertOrUpdate(rect: AABB3D, obj: T)
    fun remove(rect: AABB3D, obj: T? = null)
    fun remove(obj: T)
    fun getObjectBounds(obj: T, out: AABB3D = AABB3D()): AABB3D?
    fun debug()
}

fun BVHIntervals.toAABB3D(out: AABB3D = AABB3D()): AABB3D
fun AABB3D.toBVH(out: BVHIntervals = BVHIntervals(3)): BVHIntervals
fun Ray3D.toBVH(out: BVHIntervals = BVHIntervals(3)): BVHIntervals
Was this article useful?