I'm using CameraControls from React Three Drei, but I imagine my question is about three.js in general. https://drei.docs.pmnd.rs/controls/camera-controls#cameracontrols
I need to be able to move around in my scene. E.g. if my scene was a cube I would be able to "zoom out" and view the entire cube and also move inside of the cube and look out so I would just see one side.
I've found this easy to do with the PerspectiveCamera, e.g:
import {
CameraControls,
} from "@react-three/drei";
const cameraControlsRef = useRef<CameraControls | null>(null);
function zoom(){
cameraControlsRef.current.truck(camera.zoom / 2, 0, true);
}
But I can't get it working with an Orthographic cameara. dolly
has no effect. zoom
does zoom in but the camera's position appears to stay the same, so I can't move inside of the cube.
function zoom(){
cameraControlsRef.current.zoom(camera.zoom / 2, true);
}
Here is a full example showing the issue:
import { Canvas } from "@react-three/fiber";
import { generateCubePoints } from "./generateCubePoints";
import {
CameraControls,
OrthographicCamera,
PerspectiveCamera,
Edges,
} from "@react-three/drei";
export const ITEMS_PER_ROW = 3;
function App() {
return (
<div style={{ height: "100vh", width: "100vw", background: "blue" }}>
<Canvas>
{/* <PerspectiveCamera
position={[150, 150, 150]}
makeDefault
far={10000}
near={0.1}
/> */}
<OrthographicCamera makeDefault position={[150, 150, 150]} />
<CameraControls />
<ambientLight intensity={0.1} />
<directionalLight color="red" position={[0, 0, 5]} />
<mesh>
<boxGeometry args={[100, 100, 100]} />
<meshStandardMaterial opacity={0.5} />
<Edges />
</mesh>
</Canvas>
</div>
);
}
export default App;
As you have said, the problem comes down to how Orthographic Cameras work in Three.js.
The CameraControls fakes the movement by applying a zoom while keeping the position (especially the Z) static as it is. It is essentially hard to view the inside of the cube and be able to look around!
To work around it, you need to update the position of the camera. It is not easy at all and I can't suggest creating a function that will move the orthographic camera, but you can add a condition and check if the zoom is more than 10, for example, so that you will change the position of the camera to clip everything (something like position={[1, 1, 1]}
)
But the best solution I would have personally went to is to add a button that will move the camera inside the cube and zoom automatically. You can also interpolate the values to animate it smoothly.
That way, end users can rotate around the model from outside and once they want to see the inside, they will be able to do so with a click of a button.