Skip to content

Commit 221efd9

Browse files
committed
Add interpolation to Quaternion
1 parent 1de068b commit 221efd9

File tree

6 files changed

+120
-24
lines changed

6 files changed

+120
-24
lines changed

src/commonMain/kotlin/com/curiouscreature/kotlin/math/Matrix.kt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,68 @@ data class Mat4(
239239
}
240240

241241
fun identity() = Mat4()
242+
243+
fun from(quaternion: Quaternion): Mat4 = quaternion.let {
244+
val xx: Float = it.x * it.x
245+
val xy: Float = it.x * it.y
246+
val xz: Float = it.x * it.z
247+
val xw: Float = it.x * it.w
248+
val yy: Float = it.y * it.y
249+
val yz: Float = it.y * it.z
250+
val yw: Float = it.y * it.w
251+
val zz: Float = it.z * it.z
252+
val zw: Float = it.z * it.w
253+
val mx = Float4(
254+
1f - 2f * (yy + zz),
255+
2f * (xy - zw),
256+
2f * (xz + yw),
257+
0f
258+
)
259+
val my = Float4(
260+
2f * (xy + zw),
261+
1f - 2f * (xx + zz),
262+
2f * (yz - xw),
263+
0f
264+
)
265+
val mz = Float4(
266+
2f * (xz - yw),
267+
2f * (yz + xw),
268+
1f - 2f * (xx + yy),
269+
0f
270+
)
271+
val mw = Float4(
272+
0f,
273+
0f,
274+
0f,
275+
1f
276+
)
277+
return Mat4(
278+
x = mx,
279+
y = my,
280+
z = mz,
281+
w = mw
282+
)
283+
/*
284+
// Set matrix from quaternion
285+
matrix.get(Matrix4.M00) = 1 - 2 * (yy + zz)
286+
matrix.get(Matrix4.M01) = 2 * (xy - zw)
287+
matrix.get(Matrix4.M02) = 2 * (xz + yw)
288+
matrix.get(Matrix4.M03) = 0
289+
matrix.get(Matrix4.M10) = 2 * (xy + zw)
290+
matrix.get(Matrix4.M11) = 1 - 2 * (xx + zz)
291+
matrix.get(Matrix4.M12) = 2 * (yz - xw)
292+
matrix.get(Matrix4.M13) = 0
293+
matrix.get(Matrix4.M20) = 2 * (xz - yw)
294+
matrix.get(Matrix4.M21) = 2 * (yz + xw)
295+
matrix.get(Matrix4.M22) = 1 - 2 * (xx + yy)
296+
matrix.get(Matrix4.M23) = 0
297+
matrix.get(Matrix4.M30) = 0
298+
matrix.get(Matrix4.M31) = 0
299+
matrix.get(Matrix4.M32) = 0
300+
matrix.get(Matrix4.M33) = 1
301+
302+
*/
303+
}
242304
}
243305

244306
inline var right: Float3

src/commonMain/kotlin/com/curiouscreature/kotlin/math/Quaternion.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,22 @@ fun normalize(quaternion: Quaternion): Quaternion {
6262
val mag = sqrt(w * w + x * x + y * y + z * z)
6363
return Quaternion(x / mag, y / mag, z / mag, w / mag)
6464
}
65+
66+
fun interpolate(a: Quaternion, b: Quaternion, blend: Float): Quaternion {
67+
val dot = a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z
68+
val blendI = 1f - blend
69+
val result = if (dot < 0) {
70+
val w = blendI * a.w + blend * -b.w
71+
val x = blendI * a.x + blend * -b.x
72+
val y = blendI * a.y + blend * -b.y
73+
val z = blendI * a.z + blend * -b.z
74+
Quaternion(x, y, z, w)
75+
} else {
76+
val w = blendI * a.w + blend * b.w
77+
val x = blendI * a.x + blend * b.x
78+
val y = blendI * a.y + blend * b.y
79+
val z = blendI * a.z + blend * b.z
80+
Quaternion(x, y, z, w)
81+
}
82+
return normalize(result)
83+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.curiouscreature.kotlin.math
2+
3+
import kotlin.math.abs
4+
import kotlin.test.fail
5+
6+
fun assertEquals(
7+
expected: Float,
8+
actual: Float,
9+
delta: Float = 0.000001f,
10+
message: String = "$expected != $actual (𝝙 $delta)"
11+
) {
12+
if (abs(expected - actual) > delta) {
13+
fail(message)
14+
}
15+
}
16+
17+
fun assertArrayEquals(expected: FloatArray, actual: FloatArray, delta: Float = 0.0001f) {
18+
expected.zip(actual).forEach {
19+
assertEquals(it.first, it.second, delta)
20+
}
21+
}

src/jvmTest/kotlin/com/curiouscreature/kotlin/math/MatrixTest.kt renamed to src/commonTest/kotlin/com/curiouscreature/kotlin/math/MatrixTest.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616

1717
package com.curiouscreature.kotlin.math
1818

19+
import kotlin.test.Test
1920
import kotlin.test.assertEquals
20-
import org.junit.Test
21+
import kotlin.test.assertFails
2122

2223
class MatrixTest {
2324
@Test
@@ -32,9 +33,11 @@ class MatrixTest {
3233
)
3334
}
3435

35-
@Test(expected = IllegalArgumentException::class)
36+
@Test
3637
fun `Mat3 of fails if less than 9 arguments`() {
37-
Mat3.of(*8.floatArray())
38+
assertFails {
39+
Mat3.of(*8.floatArray())
40+
}
3841
}
3942

4043
@Test
@@ -55,9 +58,11 @@ class MatrixTest {
5558
)
5659
}
5760

58-
@Test(expected = IllegalArgumentException::class)
61+
@Test
5962
fun `Mat4 of fails if less than 16 arguments`() {
60-
Mat4.of(*15.floatArray())
63+
assertFails {
64+
Mat4.of(*15.floatArray())
65+
}
6166
}
6267

6368
@Test
@@ -339,6 +344,14 @@ class MatrixTest {
339344
)
340345
}
341346

347+
@Test
348+
fun fromQuaternion() {
349+
val fromQuaternion = Mat4.from(Quaternion(-0.5f, 0f, -0.5f, 0.70710677f))
350+
val fromRotation = rotation(normalize(Float3(1f, 0f, 1f)), 90f)
351+
352+
assertArrayEquals(fromQuaternion.toFloatArray(), fromRotation.toFloatArray())
353+
}
354+
342355
companion object {
343356
private val MAT_3 = Mat3(
344357
Float3(1f, 4f, 7f),

src/commonTest/kotlin/com/curiouscreature/kotlin/math/QuaternionTest.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.curiouscreature.kotlin.math
22

3-
import kotlin.math.abs
43
import kotlin.test.Test
54
import kotlin.test.assertTrue
6-
import kotlin.test.fail
75

86
class QuaternionTest {
97

@@ -48,16 +46,5 @@ class QuaternionTest {
4846
assertEquals(expected.z, actual.z)
4947
assertEquals(expected.w, actual.w)
5048
}
51-
52-
fun assertEquals(
53-
expected: Float,
54-
actual: Float,
55-
delta: Float = 0.000001f,
56-
message: String = "$expected != $actual (𝝙 $delta)"
57-
) {
58-
if (abs(expected - actual) > delta) {
59-
fail(message)
60-
}
61-
}
6249
}
6350
}

src/jvmTest/kotlin/com/curiouscreature/kotlin/math/Assertions.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)