轨道控制使场景在一段时间后消失

Orbit controls make scene disappear after a while

我正在使用 JOGL 构建点云查看器,并且我已经实现了自己的轨道控制。它在一段时间内运行良好,但在某些时候(我认为在非常快速地左右拖动鼠标后)场景完全消失了。这是我的代码:

public void mouseDragged(MouseEvent e) {
    if (oldX < 0.0005 && oldY < 0.0005) {
        // when the mouse drag starts initially           

        oldX = e.getX();
        oldY = e.getY();
    } else {
        float differenceX = e.getX() - oldX;
        float differenceY = e.getY() - oldY;

        oldX = e.getX();
        oldY = e.getY();

        float speedX = differenceX / 2;
        float speedY = differenceY / 2;

        Vector3f velocityX = new Vector3f();
        Vector3f velocityY = new Vector3f();

        Vector3f oldTarget = camera.getTarget();
        Vector3f cameraRight = new Vector3f();

        // getting right vector of the camera in the world space

        camera.getDirection().cross(camera.getWorldUp(), cameraRight);

        /* moving the camera first along its right vector
         * then setting its target to what it was originally
         * looking at */

        cameraRight.mul(-speedX, velocityX);
        camera.translate(velocityX);
        camera.setTarget(oldTarget);

        /* moving the camera second along its up vector
         * then setting its target to what it was originally
         * looking at */

        camera.getUp().mul(-speedY, velocityY);
        camera.translate(velocityY);
        camera.setTarget(oldTarget);
    }
}

我首先想到的是,当摄像机方向矢量和世界上方向矢量相同时,摄像机右矢量(两者之间的叉积)将为零,但这仅意味着控件失去运动的一个维度;这不应该导致整个场景消失。

我最初提出的想法是在每次旋转时将相机与其焦点分开(在远平面之外的某个点)。解决这个问题的方法是使用极坐标系来实现轨道控制。因此,在您的 mouseDragged() 方法中:

if (oldX < 0.0005 && oldY < 0.0005) {
    oldX = e.getX();
    oldY = e.getY();
} else {
    float differenceX = e.getX() - oldX;
    float differenceY = e.getY() - oldY;

    oldX = e.getX();
    oldY = e.getY();

    // getting the current position of the camera in the spherical coordinate system

    Vector3f sphericalCoords = MathUtils.toSphericalCoords(camera.getPosition());

    float speedY = (float)Math.toRadians(differenceY / 4.0f);
    float speedX = (float)Math.toRadians(differenceX / 4.0f);

    // adding speedY to the theta angle and speedX to the phi angle

    sphericalCoords.add(new Vector3f(0, speedY, speedX));

    // making sure the angles are not outside the [0, 2 * PI] interval

    polarCoords.y = MathUtils.wrapTo2Pi(sphericalCoords.y);
    polarCoords.z = MathUtils.wrapTo2Pi(sphericalCoords.z);

    // updating the position of the camera

    camera.setPosition(MathUtils.toCartesianCoords(sphericalCoords));
}