pub mod aabb;
pub mod addition;
pub mod multiplication;
pub mod sphere;
pub mod subtraction;
use crate::{Scalar, components::BodyAccessInfo};
use std::{
any::Any,
ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
};
use vek::{Aabb, Vec3};
pub struct DensityFieldBox(Box<dyn DensityField>);
impl DensityFieldBox {
pub fn new(field: impl DensityField + 'static) -> Self {
Self(Box::new(field))
}
pub fn as_any(&self) -> &dyn Any {
&*self.0
}
pub fn as_any_mut(&mut self) -> &mut dyn Any {
&mut *self.0
}
}
impl Deref for DensityFieldBox {
type Target = dyn DensityField;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl DerefMut for DensityFieldBox {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.0
}
}
pub trait DensityField: Send + Sync + Any {
#[allow(unused_variables)]
fn aabb(&self, info: &BodyAccessInfo) -> Aabb<Scalar>;
fn density_at_point(&self, point: Vec3<Scalar>, info: &BodyAccessInfo) -> Scalar;
fn density_at_region(&self, region: Aabb<Scalar>, info: &BodyAccessInfo) -> DensityRange {
let center = region.center();
let size = region.size().into_array().map(|size| size * 0.5);
std::iter::once(center)
.chain(
size.into_iter()
.enumerate()
.filter(|(_, size)| *size > Scalar::EPSILON)
.flat_map(|(index, size)| {
let mut offset = Vec3::zero();
offset[index] = size;
[center - offset, center + offset]
}),
)
.map(|point| DensityRange::converged(self.density_at_point(point, info)))
.reduce(|accum, range| accum.min_max(&range))
.unwrap()
}
#[allow(unused_variables)]
fn normal_at_point(
&self,
point: Vec3<Scalar>,
resolution: Vec3<Scalar>,
info: &BodyAccessInfo,
) -> Vec3<Scalar> {
Default::default()
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct DensityRange {
pub min: Scalar,
pub max: Scalar,
}
impl DensityRange {
pub fn converged(density: Scalar) -> Self {
Self {
min: density,
max: density,
}
}
pub fn separation(&self) -> Scalar {
(self.max - self.min).abs()
}
pub fn has_converged(&self) -> bool {
self.separation() < Scalar::EPSILON
}
pub fn has_separation(&self) -> bool {
!self.has_converged()
}
pub fn average(&self) -> Scalar {
(self.min + self.max) * 0.5
}
pub fn min_max(&self, other: &Self) -> Self {
Self {
min: self.min.min(other.min),
max: self.max.max(other.max),
}
}
pub fn clamp(&self) -> Self {
Self {
min: self.min.clamp(0.0, 1.0),
max: self.max.clamp(0.0, 1.0),
}
}
}
impl Add for DensityRange {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Self {
min: self.min + other.min,
max: self.max + other.max,
}
}
}
impl AddAssign for DensityRange {
fn add_assign(&mut self, other: Self) {
self.min += other.min;
self.max += other.max;
}
}
impl Sub for DensityRange {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Self {
min: self.min - other.min,
max: self.max - other.max,
}
}
}
impl SubAssign for DensityRange {
fn sub_assign(&mut self, other: Self) {
self.min -= other.min;
self.max -= other.max;
}
}
impl Mul for DensityRange {
type Output = Self;
fn mul(self, other: Self) -> Self::Output {
Self {
min: self.min * other.min,
max: self.max * other.max,
}
}
}
impl MulAssign for DensityRange {
fn mul_assign(&mut self, other: Self) {
self.min *= other.min;
self.max *= other.max;
}
}
impl Mul<Scalar> for DensityRange {
type Output = Self;
fn mul(self, scalar: Scalar) -> Self::Output {
Self {
min: self.min * scalar,
max: self.max * scalar,
}
}
}
impl MulAssign<Scalar> for DensityRange {
fn mul_assign(&mut self, scalar: Scalar) {
self.min *= scalar;
self.max *= scalar;
}
}
impl Div for DensityRange {
type Output = Self;
fn div(self, other: Self) -> Self::Output {
Self {
min: self.min / other.min,
max: self.max / other.max,
}
}
}
impl DivAssign for DensityRange {
fn div_assign(&mut self, other: Self) {
self.min /= other.min;
self.max /= other.max;
}
}
impl Div<Scalar> for DensityRange {
type Output = Self;
fn div(self, scalar: Scalar) -> Self::Output {
Self {
min: self.min / scalar,
max: self.max / scalar,
}
}
}
impl DivAssign<Scalar> for DensityRange {
fn div_assign(&mut self, scalar: Scalar) {
self.min /= scalar;
self.max /= scalar;
}
}