Skip to content

Scene System Testing [AARD-1938] #1217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions fission/src/systems/scene/CameraControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,6 @@ export class CustomOrbitControls extends CameraControls {
return { ...this._coords }
}

public setTargetCoordinates(coords: Partial<SphericalCoords>) {
if (coords.theta !== undefined) this._nextCoords.theta = coords.theta
if (coords.phi !== undefined) this._nextCoords.phi = coords.phi
if (coords.r !== undefined) this._nextCoords.r = coords.r
}

public setImmediateCoordinates(coords: Partial<SphericalCoords>) {
if (coords.theta !== undefined) {
this._coords.theta = coords.theta
Expand Down
170 changes: 170 additions & 0 deletions fission/src/test/scene/CameraControls.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { expect, test, beforeEach, describe } from "vitest"
import { CustomOrbitControls } from "@/systems/scene/CameraControls"
import * as THREE from "three"
import ScreenInteractionHandler, { InteractionType } from "@/systems/scene/ScreenInteractionHandler"

describe("CustomOrbitControls", () => {
let camera: THREE.PerspectiveCamera
let interactionHandler: ScreenInteractionHandler
let controls: CustomOrbitControls

beforeEach(() => {
camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
camera.position.set(0, 0, 5)

const mockElement = document.createElement("div")
interactionHandler = new ScreenInteractionHandler(mockElement)

controls = new CustomOrbitControls(camera, interactionHandler)
})

describe("Camera Position and Update", () => {
test("sets simple coordinates correctly", () => {
controls.setImmediateCoordinates({ theta: Math.PI / 2, phi: 0, r: 2.0 })
controls.update(1 / 60)

expect(camera.position.x).toBeCloseTo(2)
expect(camera.position.y).toBeCloseTo(0)
expect(camera.position.z).toBeCloseTo(0)
})

test("sets complex coordinates correctly", () => {
controls.setImmediateCoordinates({ theta: Math.PI / 3, phi: Math.PI / 6, r: 4.0 })
controls.update(1 / 60)

expect(camera.position.distanceTo(new THREE.Vector3(0, 0, 0))).toBeCloseTo(4)

expect(camera.position.x).toBeCloseTo(3)
expect(camera.position.y).toBeCloseTo(-2)
expect(camera.position.z).toBeCloseTo(1.732)
})

test("clamps extreme values", () => {
// Test r (zoom) bounds - values should be clamped
controls.setImmediateCoordinates({ r: 1000 })
controls.update(1 / 60)
const maxR = controls.getCurrentCoordinates().r

controls.setImmediateCoordinates({ r: 0.001 })
controls.update(1 / 60)
const minR = controls.getCurrentCoordinates().r

expect(maxR).toBeLessThan(1000)
expect(minR).toBeGreaterThan(0.001)
expect(minR).toBeLessThan(maxR)

// Test phi (vertical) bounds
controls.setImmediateCoordinates({ phi: Math.PI })
controls.update(1 / 60)
const maxPhi = controls.getCurrentCoordinates().phi

controls.setImmediateCoordinates({ phi: -Math.PI })
controls.update(1 / 60)
const minPhi = controls.getCurrentCoordinates().phi

expect(maxPhi).toBeLessThan(Math.PI)
expect(minPhi).toBeGreaterThan(-Math.PI)
expect(minPhi).toBeLessThan(maxPhi)
})
})

describe("Mouse Interaction", () => {
const simulateMouseInteraction = (options: {
startPosition: [number, number]
movement?: [number, number]
scale?: number
updateFrames: number
endPosition: [number, number]
interactionType?: InteractionType
}) => {
const { startPosition, movement, scale, updateFrames, endPosition, interactionType = 0 } = options

controls.interactionStart({
interactionType,
position: startPosition,
})

if (movement || scale !== undefined) {
controls.interactionMove({
interactionType,
movement,
scale,
})
}

for (let i = 0; i < updateFrames; i++) {
controls.update(1 / 60)
}

controls.interactionEnd({
interactionType,
position: endPosition,
})

for (let i = 0; i < 10; i++) {
controls.update(1 / 60)
}
}

beforeEach(() => {
controls.setImmediateCoordinates({ theta: 0, phi: 0, r: 5 })
controls.update(1 / 60)
})

test("simulate mouse drag", () => {
const initialCoords = controls.getCurrentCoordinates()

simulateMouseInteraction({
startPosition: [100, 100],
movement: [0.28, -0.105],
updateFrames: 60,
endPosition: [180, 70],
})

expect(controls.getCurrentCoordinates()).not.toEqual(initialCoords)

expect(camera.position.distanceTo(new THREE.Vector3(0, 0, 0))).toBeCloseTo(5)
})

test("should zoom in and out correctly", () => {
const initialDistance = camera.position.distanceTo(new THREE.Vector3(0, 0, 0))
expect(initialDistance).toBeCloseTo(5, 0)

simulateMouseInteraction({
scale: -1.0,
updateFrames: 1,
startPosition: [100, 100],
endPosition: [100, 100],
})

const zoomedInDistance = camera.position.distanceTo(new THREE.Vector3(0, 0, 0))

simulateMouseInteraction({
scale: 2.0,
updateFrames: 1,
startPosition: [100, 100],
endPosition: [100, 100],
})

const finalDistance = camera.position.distanceTo(new THREE.Vector3(0, 0, 0))

expect(zoomedInDistance).toBeCloseTo(4, 0)
expect(finalDistance).toBeCloseTo(5.4, 0)
})

test("should not update when disabled", () => {
const initialPosition = camera.position.clone()

controls.enabled = false

simulateMouseInteraction({
startPosition: [100, 100],
movement: [0.175, 0.35],
updateFrames: 30,
endPosition: [150, 200],
})

expect(camera.position.distanceTo(initialPosition)).toBeCloseTo(0)
})
})
})
Loading
Loading