Hie Dev, I’m trying to build a Virtual Gallery like Infinity - Interactive Gallery
I’m facing an issue with managing the controls:
- WASD
- Rotation (Drag mouse)
- Click on the ground and lerp camera
- Mobile controls joystick
The issue im currently facing is that the drei camera-controls and keyboard-controls seem to be pulling on the camera as the same time. I’m planning on using react-three/fiber for the same but so far no luck.
Reference:
App.js
import { Canvas, useThree, useFrame, extend } from "@react-three/fiber"
import * as THREE from "three"
import { Sky,KeyboardControls, CameraControls } from "@react-three/drei"
import { Physics } from "@react-three/rapier"
import { Ground } from "./Ground"
import { Player } from "./Player"
import { Cube, Cubes } from "./Cube"
import { useEffect, useRef, useState } from "react"
function CustomCameraControls({ position, setPosition, pos = new THREE.Vector3(), look = new THREE.Vector3() }) {
const cameraControlsRef = useRef()
useEffect(() => {
cameraControlsRef.current.azimuthRotateSpeed = -0.3 // negative value to invert rotation direction
cameraControlsRef.current.polarRotateSpeed = -0.3 // negative value to invert rotation direction
})
useEffect(() => {
console.log(position)
if (position !== null) {
console.log(position)
pos.set(position.x, 1.24, position.z + 0.2)
console.log(pos)
look.set(position.x, 1.24, position.z - 0.2)
console.log(look)
}
}, [position])
useFrame((state, delta) => {
if (position !== null) {
console.log("LERP")
state.camera.position.lerp(pos, 0.5)
state.camera.updateProjectionMatrix()
cameraControlsRef.current.setLookAt(state.camera.position.x, state.camera.position.y, state.camera.position.z, look.x, look.y, look.z, true)
cameraControlsRef.current.update(delta)
setTimeout(() => {
setPosition(null)
console.log(position)
}, "5000")
// setPosition(null)
}
console.log(cameraControlsRef.current.getPosition())
console.log(cameraControlsRef.current.getTarget())
console.log(state.camera.position)
state.camera.updateProjectionMatrix()
cameraControlsRef.current.update(delta)
})
return <CameraControls enabled={true} ref={cameraControlsRef} />
}
export default function App() {
const [pos, setPos] = useState(null)
return (
<KeyboardControls
map={[
{ name: "forward", keys: ["ArrowUp", "w", "W"] },
{ name: "backward", keys: ["ArrowDown", "s", "S"] },
{ name: "left", keys: ["ArrowLeft", "a", "A"] },
{ name: "right", keys: ["ArrowRight", "d", "D"] },
]}>
<Canvas shadows camera={{ fov: 45, position: [0, 0, 0.5] }}>
<Sky sunPosition={[100, 20, 100]} />
<ambientLight intensity={0.3} />
<pointLight castShadow intensity={0.8} position={[100, 100, 100]} />
<Physics gravity={[0, -30, 0]}>
<Ground pos={pos} setPos={setPos} />
<Player pos={pos} />
<Cube position={[0, 0.5, -10]} />
<Cubes />
</Physics>
{pos !== null && <CustomCameraControls position={pos} setPosition={setPos} />}
</Canvas>
</KeyboardControls>
)
}
Player.js
import * as THREE from "three"
import { useRef } from "react"
import { useFrame } from "@react-three/fiber"
import { useKeyboardControls } from "@react-three/drei"
import { CapsuleCollider, RigidBody } from "@react-three/rapier"
const SPEED = 5
const direction = new THREE.Vector3()
const frontVector = new THREE.Vector3()
const sideVector = new THREE.Vector3()
export function Player({ pos }) {
const ref = useRef()
const [, get] = useKeyboardControls()
useFrame((state) => {
const { forward, backward, left, right, jump } = get()
const velocity = ref.current.linvel()
console.log(pos)
console.log(state.camera.position)
// update camera
state.camera.position.set(...ref.current.translation())
// movement
frontVector.set(0, 0, backward - forward)
sideVector.set(left - right, 0, 0)
direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(SPEED).applyEuler(state.camera.rotation)
ref.current.setLinvel({ x: direction.x, y: velocity.y, z: direction.z })
})
return (
<>
<RigidBody ref={ref} colliders={false} mass={1} type="dynamic" position={[0, 0, 0]} enabledRotations={[false, false, false]}>
<CapsuleCollider args={[0.75, 0.5]} />
</RigidBody>
</>
)
}
Any assistance is much appreciated.