Skip to content
Merged
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>) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we removing this function?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was added in the view cube pr, but it isn't actually used anywhere in the code. It also only moves the camera towards the target coordinates for only one frame and then stops.

if (coords.theta !== undefined) {
this._coords.theta = coords.theta
Expand Down
4 changes: 2 additions & 2 deletions fission/src/systems/scene/SceneRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const CLEAR_COLOR = 0x121212
const GROUND_COLOR = 0xfffef0

const STANDARD_ASPECT = 16.0 / 9.0
const STANDARD_CAMERA_FOV_X = 110.0
const STANDARD_CAMERA_FOV_Y = STANDARD_CAMERA_FOV_X / STANDARD_ASPECT
export const STANDARD_CAMERA_FOV_X = 110.0
export const STANDARD_CAMERA_FOV_Y = STANDARD_CAMERA_FOV_X / STANDARD_ASPECT

const textureLoader = new THREE.TextureLoader()

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