Skip to content

Commit

Permalink
Merge pull request #1 from dwursteisen/fix_rotation
Browse files Browse the repository at this point in the history
[ROTATION] Fix rotation sign
  • Loading branch information
dwursteisen authored Jul 7, 2020
2 parents 05ad83d + c2c56fa commit a7e1874
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
14 changes: 2 additions & 12 deletions src/commonMain/kotlin/com/curiouscreature/kotlin/math/Matrix.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package com.curiouscreature.kotlin.math

import kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.tan
Expand Down Expand Up @@ -320,16 +318,8 @@ data class Mat4(
get() = w.xyz
val rotation: Float3
get() {
val x = normalize(right)
val y = normalize(up)
val z = normalize(forward)

return when {
z.y <= -1.0f -> Float3(degrees(-HALF_PI), 0.0f, degrees(atan2(x.z, y.z)))
z.y >= 1.0f -> Float3(degrees(HALF_PI), 0.0f, degrees(atan2(-x.z, -y.z)))
else -> Float3(
degrees(-asin(z.y)), degrees(-atan2(z.x, z.z)), degrees(atan2(x.y, y.y)))
}
val toEulerAngles = Quaternion.from(this).toEulerAngles()
return Float3(degrees(toEulerAngles.x), degrees(toEulerAngles.y), degrees(toEulerAngles.z))
}

inline val upperLeft: Mat3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ data class Quaternion(val x: Float, val y: Float, val z: Float, val w: Float) {
return floatArrayOf(x, y, z, w)
}

// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_Code_2
/**
* Transform a quaternion in Euler angles.
* Angles are in degrees.
*/
fun toEulerAngles(): Float3 {
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_Code_2
// roll (x-axis rotation)
val sinrCosp = 2f * (w * x + y * z)
val cosrCosp = 1f - 2f * (x * x + y * y)
val roll = atan2(sinrCosp, cosrCosp)

// pitch (y-axis rotation)
val sinp = 2f * (w * y - z * x)
val pitch = if (abs(sinp) >= 1)
val pitch = if (abs(sinp) >= 1f)
PI / 2f * sign(sinp) // use 90 degrees if out of range
else
asin(sinp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,24 @@ class MatrixTest {
)
}

@Test
fun Mat4_rotation_by_axis_x() {
val x = rotation(Float3(1f, 0f, 0f), 90f).rotation.x
assertEquals(-90f, x, delta = 0.1f)
}

@Test
fun Mat4_rotation_by_axis_y() {
val y = rotation(Float3(0f, 1f, 0f), 90f).rotation.y
assertEquals(-90f, y, delta = 0.1f)
}

@Test
fun Mat4_rotation_by_axis_z() {
val z = rotation(Float3(0f, 0f, 1f), 90f).rotation.z
assertEquals(-90f, z, delta = 0.1f)
}

@Test
fun normal() {
assertArrayEquals(
Expand Down

0 comments on commit a7e1874

Please sign in to comment.