Replicating Solidworks style camera

I am unsure what Solidwork’s style camera is called, but essentially you zoom to the spot where your mouse cursor is located and you can rotate about the model rather than some world coordinates.

I was looking into what three js had offered and I encountered some strange phenomenon that I need to understand. I am using perspective camera and when my object is loaded into the canvas it renders on the (0,0,0) coordinates. At this point I can zoom in very close and I can move the camera by panning very quickly so everything is as I expect.

But when I drag the model far away from the world origin and try to zoom towards the model, I cannot zoom very close. Similarly with panning, it feels like I have to keep dragging and dragging for a long time to see a different perspective of the model. Furthermore, when the model is far away from the origin and I try to rotate, it is not rotating about the model so the model can quickly go out of view because the rotation appears to be about the world origin.

Hence, I wanted to know if there is a built in strategy of being able to zoom in close towards my cursor (which would be pointed towards the model if I want to zoom to the model) and rotating about the model which is what I see with other CAD model software.

The following is my current camera code that I use:

const aspect = window.innerWidth / window.innerHeight;

    cameraPersp = new THREE.PerspectiveCamera( 50, aspect, 0.01, 30000 );
    cameraOrtho = new THREE.OrthographicCamera( - 600 * aspect, 600 * aspect, 600, - 600, 0.01, 30000 );
    currentCamera = cameraPersp;

    currentCamera.position.set( 0, 500, 2000 );
    currentCamera.rotation.x = 200;
    currentCamera.lookAt( -widthTot, -heightTot, -lengthTot );

    const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
    hemiLight.position.set( 0, 100, 0 );
    scene.add( hemiLight );

    const dirLight = new THREE.DirectionalLight( 0xffffff );
    dirLight.position.set( - 0, 40, 50 );
    dirLight.castShadow = true;
    dirLight.shadow.camera.top = 50;
    dirLight.shadow.camera.bottom = - 25;
    dirLight.shadow.camera.left = - 25;
    dirLight.shadow.camera.right = 25;
    dirLight.shadow.camera.near = 0.1;
    dirLight.shadow.camera.far = 200;
    dirLight.shadow.mapSize.set( 1024, 1024 );
    scene.add( dirLight );

    orbit = new OrbitControls( currentCamera, renderer.domElement );
    orbit.update();
    orbit.addEventListener( 'change', render );

    control = new TransformControls( currentCamera, renderer.domElement );
    control.addEventListener( 'change', render );
    control.addEventListener( 'dragging-changed', function ( event ) {
        orbit.enabled = ! event.value;
    } );

Here is an example of the camera use in solidworks:
solidworkCamera.mkv (1004.9 KB)

I think you’ll need to “select” the object first, then compute its bounding box, then the center point of that bounding box and finally set the control.target to that center point.

Just imagine having more than one object in your scene: you’ll need to indicate which one you want to rotate. I’d expect typical CAD systems to follow a similar approach.

Checkout this Camera library: GitHub - yomotsu/camera-controls: A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features.
In most like this Basic Demo is an option to “Dolly to cursor” which is what you’re describing.

It has a TON of other features too so if you’re trying to match an experience from another app/environment I’d think about using it.

Things like bounding boxes, dolly vs zoom, etc etc. Even collision detection is a built in opton

You can of course do it all manually,

2 Likes