///|
/// Post-process camera samples with screen-safe and optical policies.
pub struct CameraPostSettings2 {
safe_margin : Double
shake : Point2
exposure : Double
focus_depth : Double
vignette : Double
} derive(Debug)
///|
pub fn camera_post_settings2() -> CameraPostSettings2 {
{
safe_margin: 0.05,
shake: point2(x=0.0, y=0.0),
exposure: 0.0,
focus_depth: 1.0,
vignette: 0.0,
}
}
///|
pub fn CameraPostSettings2::safe_margin(self : CameraPostSettings2) -> Double {
self.safe_margin
}
///|
pub fn CameraPostSettings2::shake(self : CameraPostSettings2) -> Point2 {
self.shake
}
///|
pub fn CameraPostSettings2::exposure(self : CameraPostSettings2) -> Double {
self.exposure
}
///|
pub fn CameraPostSettings2::focus_depth(self : CameraPostSettings2) -> Double {
self.focus_depth
}
///|
pub fn CameraPostSettings2::vignette(self : CameraPostSettings2) -> Double {
self.vignette
}
///|
pub fn CameraPostSettings2::with_safe_margin(
self : CameraPostSettings2,
value : Double,
) -> CameraPostSettings2 {
{
safe_margin: clamp01(value),
shake: self.shake,
exposure: self.exposure,
focus_depth: self.focus_depth,
vignette: self.vignette,
}
}
///|
pub fn CameraPostSettings2::with_shake(
self : CameraPostSettings2,
value : Point2,
) -> CameraPostSettings2 {
{
safe_margin: self.safe_margin,
shake: value,
exposure: self.exposure,
focus_depth: self.focus_depth,
vignette: self.vignette,
}
}
///|
pub fn CameraPostSettings2::with_exposure(
self : CameraPostSettings2,
value : Double,
) -> CameraPostSettings2 {
{
safe_margin: self.safe_margin,
shake: self.shake,
exposure: value,
focus_depth: self.focus_depth,
vignette: self.vignette,
}
}
///|
pub fn CameraPostSettings2::with_focus(
self : CameraPostSettings2,
value : Double,
) -> CameraPostSettings2 {
{
safe_margin: self.safe_margin,
shake: self.shake,
exposure: self.exposure,
focus_depth: value.max(0.000001),
vignette: self.vignette,
}
}
///|
pub fn CameraPostSettings2::with_vignette(
self : CameraPostSettings2,
value : Double,
) -> CameraPostSettings2 {
{
safe_margin: self.safe_margin,
shake: self.shake,
exposure: self.exposure,
focus_depth: self.focus_depth,
vignette: clamp01(value),
}
}
///|
pub fn apply_camera_post(
camera : CameraRig,
settings : CameraPostSettings2,
) -> CameraRig {
camera.with_jitter(settings.shake)
}
///|
pub fn screen_safe_bounds(viewport : Viewport, margin : Double) -> Bounds2D {
let horizontal = viewport.width() * clamp01(margin)
let vertical = viewport.height() * clamp01(margin)
{
minimum: point2(x=horizontal, y=vertical),
maximum: point2(
x=viewport.width() - horizontal,
y=viewport.height() - vertical,
),
}
}
///|
pub fn screen_safe_contains(
viewport : Viewport,
point : Point2,
margin : Double,
) -> Bool {
let bounds = screen_safe_bounds(viewport, margin)
point.x() >= bounds.minimum().x() &&
point.x() <= bounds.maximum().x() &&
point.y() >= bounds.minimum().y() &&
point.y() <= bounds.maximum().y()
}
///|
pub fn camera_depth_of(camera : CameraRig, point : Point3) -> Double {
let position = camera.pose().position()
let delta = point3(
x=point.x() - position.x(),
y=point.y() - position.y(),
z=point.z() - position.z(),
)
point3_dot(delta, camera.pose().forward())
}
///|
pub fn camera_focus_weight(
camera : CameraRig,
point : Point3,
focus : Double,
falloff : Double,
) -> Double {
let distance = (camera_depth_of(camera, point) - focus).abs()
if falloff <= 0.0 {
if distance == 0.0 {
1.0
} else {
0.0
}
} else {
@math.pow(clamp01(1.0 - distance / falloff), 2.0)
}
}
///|
pub fn project_safe(
camera : CameraRig,
point : Point3,
margin : Double,
) -> (Point2, Bool) {
let screen = camera.project(point)
(
screen,
camera.visible(point) &&
screen_safe_contains(camera.viewport(), screen, margin),
)
}
///|
pub fn camera_motion_delta(
first : CameraRig,
second : CameraRig,
) -> (Double, Double) {
(
point3_distance(first.pose().position(), second.pose().position()),
first.pose().forward().lerp(second.pose().forward(), 0.5).x(),
)
}