nmarshall's picture
geometry: nearest ray hits
72b1843
Raw History Blame Contribute Delete
2.92 kB
//! Native analytic geometry policy; original-editor numerical parity is unverified.
pub mod math;
pub use math::{Aabb, DVec3, Equation, Policy};
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Error {
NonFinite,
Degenerate,
InvalidPolicy,
InvalidDimensions,
InvalidBrush,
Limit,
Allocation,
Overflow,
FloatRange,
InconsistentData,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "geometry: {self:?}")
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
pub(crate) fn alloc<T>(n: usize) -> Result<Vec<T>> {
let mut out = Vec::new();
out.try_reserve_exact(n).map_err(|_| Error::Allocation)?;
Ok(out)
}
pub mod brush;
#[derive(Clone, Copy, Debug)]
pub struct ComputeLimits {
pub max_planes: usize,
pub max_vertices: usize,
pub max_work: usize,
pub max_owned_bytes: usize,
}
impl Default for ComputeLimits {
fn default() -> Self {
Self {
max_planes: 64,
max_vertices: 100_000,
max_work: 10_000_000,
max_owned_bytes: 128 * 1024 * 1024,
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Stats {
pub work: usize,
pub owned: usize,
pub vertices: usize,
}
pub(crate) struct Budget {
pub limits: ComputeLimits,
pub stats: Stats,
}
impl Budget {
fn work(&mut self, n: usize) -> Result<()> {
self.stats.work = self.stats.work.checked_add(n).ok_or(Error::Overflow)?;
if self.stats.work > self.limits.max_work {
Err(Error::Limit)
} else {
Ok(())
}
}
fn bytes(&mut self, n: usize) -> Result<()> {
self.stats.owned = self.stats.owned.checked_add(n).ok_or(Error::Overflow)?;
if self.stats.owned > self.limits.max_owned_bytes {
Err(Error::Limit)
} else {
Ok(())
}
}
fn reserve<T>(&mut self, n: usize) -> Result<Vec<T>> {
self.bytes(
n.checked_mul(std::mem::size_of::<T>())
.ok_or(Error::Overflow)?,
)?;
alloc(n)
}
fn push<T>(&mut self, out: &mut Vec<T>, v: T) -> Result<()> {
if out.len() == out.capacity() {
let cap = out
.capacity()
.saturating_mul(2)
.max(1)
.min(self.limits.max_vertices);
if cap <= out.len() {
return Err(Error::Limit);
}
self.bytes(
(cap - out.capacity())
.checked_mul(std::mem::size_of::<T>())
.ok_or(Error::Overflow)?,
)?;
out.try_reserve_exact(cap - out.len())
.map_err(|_| Error::Allocation)?;
}
out.push(v);
Ok(())
}
}
pub mod patch;
pub mod ray;
pub mod world;