diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb90b91..c5b77a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,10 +32,13 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Run JVM tests - run: ./gradlew :phosphor-core:jvmTest :phosphor-lumos:jvmTest + run: ./gradlew jvmTest - - name: Check formatting - run: ./gradlew :phosphor-core:ktlintCheck :phosphor-lumos:ktlintCheck + - name: Verify formatting + run: ./gradlew ktlintFormat --no-rebuild + + - name: Check formatting diff + run: git diff --exit-code ios_compile: name: iOS Compile @@ -59,7 +62,7 @@ jobs: test: name: Tests - runs-on: ubuntu-latest + runs-on: macos-latest needs: [jvm, ios_compile] if: ${{ always() }} @@ -70,3 +73,21 @@ jobs: echo "Required CI jobs did not all pass." exit 1 fi + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'zulu' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Run build + run: ./gradlew build + + - name: Run all tests + run: ./gradlew allTests diff --git a/phosphor-core/src/commonMain/kotlin/link/socket/phosphor/field/VoxelSphere.kt b/phosphor-core/src/commonMain/kotlin/link/socket/phosphor/field/VoxelSphere.kt index 40dcac4..68573d7 100644 --- a/phosphor-core/src/commonMain/kotlin/link/socket/phosphor/field/VoxelSphere.kt +++ b/phosphor-core/src/commonMain/kotlin/link/socket/phosphor/field/VoxelSphere.kt @@ -159,8 +159,11 @@ class VoxelSphere(val resolution: Int) { /** * Return true when this voxel's outward direction faces a viewer on the +Z axis. + * + * [orbRotation] is an Euler-style XYZ rotation in radians, matching [Vector3.rotatedBy]. + * It is not a quaternion despite earlier naming. */ fun Voxel.facingCamera( - orbQuaternion: Vector3, + orbRotation: Vector3, threshold: Float = 0.15f, -): Boolean = unitDirection.rotatedBy(orbQuaternion).z > threshold +): Boolean = unitDirection.rotatedBy(orbRotation).z > threshold diff --git a/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/renderer/SimulationFrameTest.kt b/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/renderer/SimulationFrameTest.kt index 3938243..b5f9ca8 100644 --- a/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/renderer/SimulationFrameTest.kt +++ b/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/renderer/SimulationFrameTest.kt @@ -7,6 +7,7 @@ import kotlin.test.assertNotNull import kotlinx.serialization.json.Json import link.socket.phosphor.render.AsciiCell import link.socket.phosphor.render.CellBuffer +import link.socket.phosphor.test.assertFloatEquals class SimulationFrameTest { @Test @@ -51,10 +52,10 @@ class SimulationFrameTest { normalY = floatArrayOf(1f, 1f), ) - assertEquals(0.2f, frame.cellAt(0, 0).luminance) - assertEquals(0.8f, frame.cellAt(1, 0).luminance) - assertEquals(-0.5f, frame.cellAt(0, 0).normalX) - assertEquals(1f, frame.cellAt(1, 0).normalY) + assertFloatEquals(0.2f, frame.cellAt(0, 0).luminance) + assertFloatEquals(0.8f, frame.cellAt(1, 0).luminance) + assertFloatEquals(-0.5f, frame.cellAt(0, 0).normalX) + assertFloatEquals(1f, frame.cellAt(1, 0).normalY) } @Test diff --git a/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/test/FloatAssertions.kt b/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/test/FloatAssertions.kt new file mode 100644 index 0000000..0d797ad --- /dev/null +++ b/phosphor-core/src/commonTest/kotlin/link/socket/phosphor/test/FloatAssertions.kt @@ -0,0 +1,12 @@ +package link.socket.phosphor.test + +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +internal fun assertFloatEquals( + expected: Float, + actual: Float?, + tolerance: Float = 1e-4f, +) { + assertEquals(expected, assertNotNull(actual), absoluteTolerance = tolerance) +} diff --git a/phosphor-lumos/src/commonTest/kotlin/link/socket/phosphor/lumos/VoxelFrameBuilderTest.kt b/phosphor-lumos/src/commonTest/kotlin/link/socket/phosphor/lumos/VoxelFrameBuilderTest.kt index cdc255d..0a6b390 100644 --- a/phosphor-lumos/src/commonTest/kotlin/link/socket/phosphor/lumos/VoxelFrameBuilderTest.kt +++ b/phosphor-lumos/src/commonTest/kotlin/link/socket/phosphor/lumos/VoxelFrameBuilderTest.kt @@ -203,10 +203,10 @@ class VoxelFrameBuilderTest { repeat(200) { builder.build(snapshot(atmosphere = fast), dt = 0.5f) } - assertTrue(builder.pulsePhase in 0f..twoPi) - assertTrue(builder.patternPhase in 0f..patternWrap) - assertTrue(builder.orbRotationX in 0f..twoPi) - assertTrue(builder.orbRotationY in 0f..twoPi) + assertWrappedPhase("pulsePhase", builder.pulsePhase, twoPi) + assertWrappedPhase("patternPhase", builder.patternPhase, patternWrap) + assertWrappedPhase("orbRotationX", builder.orbRotationX, twoPi) + assertWrappedPhase("orbRotationY", builder.orbRotationY, twoPi) } @Test @@ -395,4 +395,16 @@ class VoxelFrameBuilderTest { atmosphere = atmosphere, atmosphereTransition = transition, ) + + private fun assertWrappedPhase( + name: String, + actual: Float, + upperBound: Float, + ) { + val tolerance = 1e-4f + assertTrue( + actual >= -tolerance && actual <= upperBound + tolerance, + "$name should stay in [0, $upperBound], got $actual", + ) + } }