bonsairobo / smooth-bevy-cameras

Bevy camera controllers with buttery, exponential smoothing.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Panic when zooming all the way in or out with the built in orbit camera controller

sargunv opened this issue · comments

I have a simple scene, just the standard Bevy 3d example with the orbit controller added instead of the example's camera. When I zoom all the way in or out, I get a panic with an assertion failed in look_angles.rs:

CleanShot 2021-12-25 at 17 31 08@2x

repro scene:

use bevy::prelude::*;
use smooth_bevy_cameras::{
    controllers::orbit::{OrbitCameraBundle, OrbitCameraController, OrbitCameraPlugin},
    LookTransformPlugin,
};

fn main() {
    App::build()
        .add_plugins(DefaultPlugins)
        .add_plugin(LookTransformPlugin)
        .add_plugin(OrbitCameraPlugin::default())
        .add_startup_system(setup.system())
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // plane
    commands.spawn_bundle(PbrBundle {
        mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
        material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
        ..Default::default()
    });
    // cube
    commands.spawn_bundle(PbrBundle {
        mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
        material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
        transform: Transform::from_xyz(0.0, 0.5, 0.0),
        ..Default::default()
    });
    // light
    commands.spawn_bundle(LightBundle {
        transform: Transform::from_xyz(4.0, 8.0, 4.0),
        ..Default::default()
    });
    // camera
    commands.spawn_bundle(OrbitCameraBundle::new(
        OrbitCameraController::default(),
        PerspectiveCameraBundle::default(),
        Vec3::new(-2.0, 2.5, 5.0),
        Vec3::ZERO,
    ));
}

I'm guessing the issue is that the radius_scalar in the orbit controller is somehow dropping to 0.0 and then when you try LookAngles::from_vector(transform.look_direaction()), the direction is the zero vector (since target = eye).

So I guess we can just set a minimum positive radius scalar.

I took some time to debug it and realized it's actually an issue with normalizing very large vectors. When zoomed out very far, the LookTransform::look_direction will return zero because it is trying to normalize a large vector like:

Vec3(-5821752400000000000.0, 14554365000000000000.0, 14554375000000000000.0)

So I'm going to switch to using Vec3::try_normalize for safety. And probably just limit the zoom amount.