Skip to content

Commit

Permalink
Merge pull request #18 from readyplayerme/feature/reactive-camera-zoom
Browse files Browse the repository at this point in the history
Feature - reactive camera zoom
  • Loading branch information
Zaehiel authored Nov 18, 2022
2 parents 8e303b1 + d4cbbb6 commit 1b0dbfc
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 6 deletions.
12 changes: 9 additions & 3 deletions src/components/Avatar/Avatar.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const CAMERA = {
ZOOM_TARGET: new Vector3(-0.11, 0, 0.48)
},
HALF_BODY: {
MIN_DISTANCE: 0.5,
MIN_DISTANCE: 0.4,
MAX_DISTANCE: 1.4,
ZOOM_TARGET: new Vector3(-0.15, 0, 0.55)
}
Expand Down Expand Up @@ -117,6 +117,11 @@ export interface AvatarProps extends LightingProps, Omit<BaseModelProps, 'setMod
* Enable head tracking cursor movements.
*/
headMovement?: boolean;
/**
* Initialise and update camera movement on Z-Axis.
* Defaults to full-body zoom distance.
*/
cameraZoomTarget?: Vector3;
}

/**
Expand Down Expand Up @@ -150,7 +155,8 @@ export const Avatar: FC<AvatarProps> = ({
onLoading,
dpr,
className,
headMovement = false
headMovement = false,
cameraZoomTarget = CAMERA.CONTROLS.FULL_BODY.ZOOM_TARGET
}) => {
const AvatarModel = useMemo(() => {
if (!isValidGlbFormat(modelSrc)) {
Expand Down Expand Up @@ -208,7 +214,7 @@ export const Avatar: FC<AvatarProps> = ({
<CameraLighting
cameraTarget={cameraTarget}
cameraInitialDistance={cameraInitialDistance}
cameraZoomTarget={halfBody ? CAMERA.CONTROLS.HALF_BODY.ZOOM_TARGET : CAMERA.CONTROLS.FULL_BODY.ZOOM_TARGET}
cameraZoomTarget={cameraZoomTarget}
ambientLightColor={ambientLightColor}
ambientLightIntensity={ambientLightIntensity}
dirLightPosition={dirLightPosition}
Expand Down
1 change: 1 addition & 0 deletions src/components/Avatar/Avatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Static.args = {
dirLightPosition: new Vector3(-3, 5, -5),
dirLightColor: '#002aff',
spotLightPosition: new Vector3(12, 10, 7.5),
cameraZoomTarget: CAMERA.CONTROLS.FULL_BODY.ZOOM_TARGET,
spotLightColor: '#fff5b6',
spotLightAngle: 0.314,
cameraTarget: CAMERA.TARGET.FULL_BODY.FEMALE,
Expand Down
19 changes: 16 additions & 3 deletions src/components/SceneControls/CameraLighting.component.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, FC } from 'react';
import { useEffect, FC, useRef } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import { Camera, Vector3, DirectionalLight, AmbientLight, SpotLight } from 'three';
import { OrbitControls } from 'three-stdlib';
Expand All @@ -10,9 +10,15 @@ type CameraLightingProps = Required<LightingProps> & {
headScale?: number;
cameraTarget?: number;
cameraInitialDistance?: number;
/**
* Handles camera movement on the Z-axis.
*/
cameraZoomTarget?: Vector3;
controlsMinDistance?: number;
controlsMaxDistance?: number;
/**
* Enables camera moving on Y-axis while zooming in-out.
*/
updateCameraTargetOnZoom?: boolean;
};

Expand Down Expand Up @@ -53,11 +59,17 @@ export const CameraLighting: FC<CameraLightingProps> = ({
controlsMaxDistance = 2.5,
updateCameraTargetOnZoom = false
}) => {
const cameraZoomTargetRef = useRef(cameraZoomTarget);
const { camera, gl, scene } = useThree();
const fallbackCameraTarget = cameraTarget || 1.475 + headScale / 10;
const headScaleAdjustedMinDistance = controlsMinDistance + headScale / 10;

useEffect(() => {
if (cameraZoomTargetRef.current !== cameraZoomTarget) {
cameraZoomTargetRef.current = cameraZoomTarget;
progress = 0;
}

controls = new OrbitControls(camera, gl.domElement);
controls.enablePan = false;

Expand All @@ -84,7 +96,8 @@ export const CameraLighting: FC<CameraLightingProps> = ({
controlsMaxDistance,
fallbackCameraTarget,
gl.domElement,
headScaleAdjustedMinDistance
headScaleAdjustedMinDistance,
cameraZoomTarget
]);

useEffect(() => {
Expand Down Expand Up @@ -140,7 +153,7 @@ export const CameraLighting: FC<CameraLightingProps> = ({
if (updateCameraTargetOnZoom) {
updateCameraTarget(camera, fallbackCameraTarget, headScaleAdjustedMinDistance, controlsMaxDistance);
}
updateCameraFocus(camera, delta, cameraZoomTarget);
updateCameraFocus(camera, delta, cameraZoomTargetRef.current);
controls.update();
});

Expand Down

0 comments on commit 1b0dbfc

Please sign in to comment.