I'm using react-three-fiber
with OrbitControls
to display a textured sphere with a backside material. I want my camera to orbit inside that sphere and around it's center. OrbitControls
does that just fine, but it always points at the target which is in the center. I want it to point in exact opposite direction (to the outside) while keeping all the features of OrbitControls
<Canvas camera={{ fov: 45, position: [1, 0, 0] }}>
<Suspense fallback={null}>
<mesh>
<sphereGeometry args={[110, 32, 32]} attach="geometry" />
<meshBasicMaterial side={BackSide}>
<GradientTexture
stops={[0, 0.45, 0.5, 0.55, 1]}
colors={['red', 'green', 'black', 'blue', 'pink']}
size={1024}
/>
</meshBasicMaterial>
<OrbitControls target={[0, 0, 0]} enableZoom={false} reverseOrbit={true}/>
</mesh>
</Suspense>
</Canvas>
Right now I'm using something like this and it looks ok, but I don't have the ability to zoom in a proper way.
Ok, so for anyone who might stumble upon similar issue - don't do it like this.
I actually managed to achieve this by wrapping OrbitControls
in a component and using useFrame
:
function Controls() {
const controlsRef = useRef<OrbitControlsImpl>(null);
useFrame(({ gl, scene, camera }) => {
if (!controlsRef.current) {
return
}
const { x, y, z } = controlsRef.current.object.position
camera.lookAt(x * 2, y * 2, z * 2)
gl.render(scene, camera)
}, 1);
return <OrbitControls
target={[0, 0, 0]}
ref={controlsRef}
minDistance={10}
maxDistance={80}
/>
}
But then I got my wheel and horizontal panning reversed and couldn't find a way to work around it.
Eventually, the optimal solution was to switch to a PerspectiveCamera
, disable zoom for OrbitControls
and writing my own wheel handler that used camera.zoom
property:
const { camera, gl: { domElement } } = useThree();
function handleWheel(this, ev) {
ev.stopPropagation()
ev.preventDefault()
let newZoom = camera.zoom + -1*(ev.deltaY/1000)
if(newZoom < 1) newZoom = 1
if(newZoom > 10) newZoom = 10
camera.zoom = newZoom
camera.updateProjectionMatrix()
}
domElement.addEventListener("wheel", handleWheel);