mirror of
https://github.com/hannobraun/Fornjot
synced 2025-11-17 12:30:18 +00:00
Simplify API of Camera
This commit is contained in:
parent
7993d25780
commit
938808966c
@ -34,13 +34,54 @@ impl Camera {
|
|||||||
const INITIAL_FIELD_OF_VIEW_IN_X: f64 = FRAC_PI_2; // 90 degrees
|
const INITIAL_FIELD_OF_VIEW_IN_X: f64 = FRAC_PI_2; // 90 degrees
|
||||||
|
|
||||||
/// Returns a new camera aligned for viewing a bounding box
|
/// Returns a new camera aligned for viewing a bounding box
|
||||||
pub fn new() -> Self {
|
pub fn new(aabb: &Aabb<3>) -> Self {
|
||||||
|
let initial_distance = {
|
||||||
|
// Let's make sure we choose a distance, so that the model fills
|
||||||
|
// most of the screen.
|
||||||
|
//
|
||||||
|
// To do that, first compute the model's highest point, as well
|
||||||
|
// as the furthest point from the origin, in x and y.
|
||||||
|
let highest_point = aabb.max.z;
|
||||||
|
let furthest_point =
|
||||||
|
[aabb.min.x.abs(), aabb.max.x, aabb.min.y.abs(), aabb.max.y]
|
||||||
|
.into_iter()
|
||||||
|
.reduce(Scalar::max)
|
||||||
|
// `reduce` can only return `None`, if there are no items in
|
||||||
|
// the iterator. And since we're creating an array full of
|
||||||
|
// items above, we know this can't panic.
|
||||||
|
.expect("Array should have contained items");
|
||||||
|
|
||||||
|
// The actual furthest point is not far enough. We don't want
|
||||||
|
// the model to fill the whole screen.
|
||||||
|
let furthest_point = furthest_point * 2.;
|
||||||
|
|
||||||
|
// Having computed those points, figuring out how far the camera
|
||||||
|
// needs to be from the model is just a bit of trigonometry.
|
||||||
|
let distance_from_model =
|
||||||
|
furthest_point / (Self::INITIAL_FIELD_OF_VIEW_IN_X / 2.).atan();
|
||||||
|
|
||||||
|
// And finally, the distance from the origin is trivial now.
|
||||||
|
highest_point + distance_from_model
|
||||||
|
};
|
||||||
|
|
||||||
|
let initial_offset = {
|
||||||
|
let mut offset = aabb.center();
|
||||||
|
offset.z = Scalar::ZERO;
|
||||||
|
-offset
|
||||||
|
};
|
||||||
|
|
||||||
|
let translation = Transform::translation([
|
||||||
|
initial_offset.x,
|
||||||
|
initial_offset.y,
|
||||||
|
-initial_distance,
|
||||||
|
]);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
near_plane: Self::DEFAULT_NEAR_PLANE,
|
near_plane: Self::DEFAULT_NEAR_PLANE,
|
||||||
far_plane: Self::DEFAULT_FAR_PLANE,
|
far_plane: Self::DEFAULT_FAR_PLANE,
|
||||||
|
|
||||||
rotation: Transform::identity(),
|
rotation: Transform::identity(),
|
||||||
translation: Transform::identity(),
|
translation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,52 +170,6 @@ impl Camera {
|
|||||||
transform
|
transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the planes
|
|
||||||
///
|
|
||||||
/// Call this, if a shape is available for the first time.
|
|
||||||
pub fn init_planes(&mut self, aabb: &Aabb<3>) {
|
|
||||||
let initial_distance = {
|
|
||||||
// Let's make sure we choose a distance, so that the model fills
|
|
||||||
// most of the screen.
|
|
||||||
//
|
|
||||||
// To do that, first compute the model's highest point, as well
|
|
||||||
// as the furthest point from the origin, in x and y.
|
|
||||||
let highest_point = aabb.max.z;
|
|
||||||
let furthest_point =
|
|
||||||
[aabb.min.x.abs(), aabb.max.x, aabb.min.y.abs(), aabb.max.y]
|
|
||||||
.into_iter()
|
|
||||||
.reduce(Scalar::max)
|
|
||||||
// `reduce` can only return `None`, if there are no items in
|
|
||||||
// the iterator. And since we're creating an array full of
|
|
||||||
// items above, we know this can't panic.
|
|
||||||
.expect("Array should have contained items");
|
|
||||||
|
|
||||||
// The actual furthest point is not far enough. We don't want
|
|
||||||
// the model to fill the whole screen.
|
|
||||||
let furthest_point = furthest_point * 2.;
|
|
||||||
|
|
||||||
// Having computed those points, figuring out how far the camera
|
|
||||||
// needs to be from the model is just a bit of trigonometry.
|
|
||||||
let distance_from_model =
|
|
||||||
furthest_point / (Self::INITIAL_FIELD_OF_VIEW_IN_X / 2.).atan();
|
|
||||||
|
|
||||||
// And finally, the distance from the origin is trivial now.
|
|
||||||
highest_point + distance_from_model
|
|
||||||
};
|
|
||||||
|
|
||||||
let initial_offset = {
|
|
||||||
let mut offset = aabb.center();
|
|
||||||
offset.z = Scalar::ZERO;
|
|
||||||
-offset
|
|
||||||
};
|
|
||||||
|
|
||||||
self.translation = Transform::translation([
|
|
||||||
initial_offset.x,
|
|
||||||
initial_offset.y,
|
|
||||||
-initial_distance,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the max and minimum rendering distance for this camera.
|
/// Update the max and minimum rendering distance for this camera.
|
||||||
pub fn update_planes(&mut self, aabb: &Aabb<3>) {
|
pub fn update_planes(&mut self, aabb: &Aabb<3>) {
|
||||||
let view_transform = self.camera_to_model();
|
let view_transform = self.camera_to_model();
|
||||||
|
|||||||
@ -47,9 +47,7 @@ impl Window {
|
|||||||
let renderer =
|
let renderer =
|
||||||
Renderer::new(window.clone(), Vertices::from_tri_mesh(&tri_mesh))
|
Renderer::new(window.clone(), Vertices::from_tri_mesh(&tri_mesh))
|
||||||
.await?;
|
.await?;
|
||||||
let mut camera = Camera::new();
|
let camera = Camera::new(&aabb);
|
||||||
|
|
||||||
camera.init_planes(&aabb);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
new_screen_size: None,
|
new_screen_size: None,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user