Skip to content

Commit

Permalink
fix: camera aspect
Browse files Browse the repository at this point in the history
* Update orthographic camera aspect when screen size updates
* Give user a "manual" flag to keep Tres from updating camera
  • Loading branch information
andretchen0 committed Feb 5, 2024
1 parent 898a8b1 commit 52dad5c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
21 changes: 13 additions & 8 deletions playground/src/pages/cameras/Cameras.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ const gl = {
outputColorSpace: SRGBColorSpace,
toneMapping: NoToneMapping,
}
type Cam = (PerspectiveCamera | OrthographicCamera) & { manual?: boolean }
const state = reactive({
cameraType: 'perspective',
camera: new PerspectiveCamera(75, 1, 0.1, 1000),
camera: new PerspectiveCamera(75, 1, 0.1, 1000) as Cam,
})
state.camera.position.set(5, 5, 5)
state.camera.lookAt(0, 0, 0)
const { value: cameraType } = useControls({
const { cameraType, manual } = useControls({
cameraType: {
label: 'CameraType',
options: [{
Expand All @@ -31,19 +32,23 @@ const { value: cameraType } = useControls({
}, {
text: 'Orthographic',
value: 'orthographic',
}],
},
],
value: state.cameraType,
},
manual: false,
})
watch(cameraType, ({ value }) => {
state.cameraType = value
if (value === 'perspective') {
watch(() => [cameraType.value.value, manual.value.value], () => {
state.cameraType = cameraType.value.value
if (cameraType.value.value === 'perspective') {
state.camera = new PerspectiveCamera(75, 1, 0.1, 1000)
}
else {
state.camera = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1000)
else if (cameraType.value.value === 'orthographic') {
state.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1000)
state.camera.zoom = 20
}
state.camera.manual = manual.value.value
state.camera.position.set(5, 5, 5)
state.camera.lookAt(0, 0, 0)
})
Expand Down
30 changes: 24 additions & 6 deletions src/composables/useCamera/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { computed, watchEffect, onUnmounted, ref } from 'vue'
import { Camera, OrthographicCamera, PerspectiveCamera } from 'three'
import type { OrthographicCamera } from 'three'
import { Camera, PerspectiveCamera } from 'three'

import type { TresScene } from '../../types'
import type { TresContext } from '../useTresContextProvider'
Expand Down Expand Up @@ -40,12 +41,25 @@ export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes'> & { scene

watchEffect(() => {
if (sizes.aspectRatio.value) {
cameras.value.forEach((camera: Camera) => {
if (camera instanceof PerspectiveCamera)
camera.aspect = sizes.aspectRatio.value

if (camera instanceof PerspectiveCamera || camera instanceof OrthographicCamera)
cameras.value.forEach((camera: Camera & { manual?: boolean }) => {
// NOTE: Don't mess with the camera if it belongs to the user.
// https://github.com/pmndrs/react-three-fiber/blob/0ef66a1d23bf16ecd457dde92b0517ceec9861c5/packages/fiber/src/core/utils.ts#L457
//
// To set camera as "manual":
// const myCamera = new PerspectiveCamera(); // or OrthographicCamera
// (myCamera as any).manual = true
if (!camera.manual && (camera instanceof PerspectiveCamera || isOrthographicCamera(camera))) {
if (camera instanceof PerspectiveCamera) {
camera.aspect = sizes.aspectRatio.value
}
else {
camera.left = sizes.width.value * -0.5
camera.right = sizes.width.value * 0.5
camera.top = sizes.height.value * 0.5
camera.bottom = sizes.height.value * -0.5
}
camera.updateProjectionMatrix()
}
})
}
})
Expand All @@ -61,4 +75,8 @@ export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes'> & { scene
deregisterCamera,
setCameraActive,
}
}

function isOrthographicCamera(o: any): o is OrthographicCamera {
return o.hasOwnProperty('isOrthographicCamera') && o.isOrthographicCamera
}

0 comments on commit 52dad5c

Please sign in to comment.