use glam::Vec3;
use serde::{Deserialize, Serialize};
use super::SdfNode;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SdfTree {
pub version: String,
pub root: SdfNode,
pub metadata: Option<SdfMetadata>,
}
impl SdfTree {
pub fn new(root: SdfNode) -> Self {
Self {
version: env!("CARGO_PKG_VERSION").to_string(),
root,
metadata: None,
}
}
pub fn with_metadata(root: SdfNode, metadata: SdfMetadata) -> Self {
Self {
version: env!("CARGO_PKG_VERSION").to_string(),
root,
metadata: Some(metadata),
}
}
pub fn node_count(&self) -> u32 {
self.root.node_count()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SdfMetadata {
pub name: Option<String>,
pub description: Option<String>,
pub author: Option<String>,
pub bounds: Option<(Vec3, Vec3)>,
pub custom: Option<std::collections::HashMap<String, String>>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Aabb {
pub min: Vec3,
pub max: Vec3,
}
impl Aabb {
pub const fn new(min: Vec3, max: Vec3) -> Self {
Self { min, max }
}
pub fn from_center_extents(center: Vec3, half_extents: Vec3) -> Self {
Self {
min: center - half_extents,
max: center + half_extents,
}
}
pub fn center(&self) -> Vec3 {
(self.min + self.max) * 0.5
}
pub fn size(&self) -> Vec3 {
self.max - self.min
}
pub fn half_extents(&self) -> Vec3 {
self.size() * 0.5
}
pub fn contains(&self, point: Vec3) -> bool {
point.x >= self.min.x
&& point.x <= self.max.x
&& point.y >= self.min.y
&& point.y <= self.max.y
&& point.z >= self.min.z
&& point.z <= self.max.z
}
pub fn union(&self, other: &Self) -> Self {
Self {
min: self.min.min(other.min),
max: self.max.max(other.max),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ray {
pub origin: Vec3,
pub direction: Vec3,
}
impl Ray {
pub fn new(origin: Vec3, direction: Vec3) -> Self {
Self {
origin,
direction: direction.normalize(),
}
}
pub fn at(&self, t: f32) -> Vec3 {
self.origin + self.direction * t
}
}
#[derive(Debug, Clone, Copy)]
pub struct Hit {
pub distance: f32,
pub point: Vec3,
pub normal: Vec3,
pub steps: u32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sdf_tree() {
let tree = SdfTree::new(SdfNode::sphere(1.0));
assert_eq!(tree.node_count(), 1);
}
#[test]
fn test_aabb() {
let aabb = Aabb::new(Vec3::new(-1.0, -1.0, -1.0), Vec3::new(1.0, 1.0, 1.0));
assert!(aabb.contains(Vec3::ZERO));
assert!(!aabb.contains(Vec3::new(2.0, 0.0, 0.0)));
}
}