Skip to content

Camera position at origin causes silent failure #629

@johnperry-math

Description

@johnperry-math

Describe the bug

CameraControls divides by zero if camera position is initially at the origin. This is because this._spherical is computed from this._camera_position and gets a radius of 0. Subsequently, anything that calls _getTargetDirection will encounter a divide by 0:

return out.setFromSpherical(this._spherical).divideScalar(this._spherical.radius).applyQuaternion(this._yAxisUpSpaceInverse);

This is problematic because:

  • New users they may not know to set the camera position.
  • Veteran users may forget to do so.
  • Spherical computes the radius with respect to the origin. When the camera position is the origin, you get a value of zero, which causes the division by 0.

To Reproduce

Steps to reproduce the behavior:

  1. Take the minimal example below.
  2. Run the example and try to dolly.
  3. The example will seem to blank the screen and freeze.
  4. Inspect the console. You will see that the camera matrix now has null values.

Code

import * as THREE from './three/three_0_157_0.js';
import CameraControls from './three/camera-controls.module.js';

const scene = new THREE.Scene();

const camera = new THREE.OrthographicCamera(-10, 10, -10, 10, 0.1, 10000);
// uncomment the next line to make things happy
// camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

CameraControls.install({ THREE: THREE })
const controls = new CameraControls(camera, renderer.domElement)
controls.dollyToCursor = true
controls.dollySpeed = 2
controls.smoothTime = 0.1
controls.draggingSmoothTime = 0.1

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

function animate(time) {

    controls.update(time)
    if (isNaN(camera.position.x)) {
        console.log("position", camera.position)
        console.log("matrix", camera.matrix)
        throw new Error("baseball");

    }

    renderer.render(scene, camera);
}
renderer.setAnimationLoop(animate);

Live example

No response

Expected behavior

I think the best behavior here is to throw an exception with an explanatory message when the camera position is at the origin.

Screenshots or Video

No response

Device

No response

OS

No response

Browser

Firefox

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions