use crate::bvh3::Bvh3;
use crate::implicit_surface3::*;
use crate::surface3::*;
use crate::vector3::Vector3D;
use crate::transform3::Transform3;
use crate::bounding_box3::BoundingBox3D;
use crate::ray3::Ray3D;
use crate::surface_to_implicit3::SurfaceToImplicit3;
use crate::nearest_neighbor_query_engine3::NearestNeighborQueryEngine3;
use crate::intersection_query_engine3::IntersectionQueryEngine3;
use std::sync::{RwLock, Arc};
pub struct ImplicitSurfaceSet3 {
_surfaces: Vec<ImplicitSurface3Ptr>,
_unbounded_surfaces: Vec<ImplicitSurface3Ptr>,
_bvh: RwLock<Bvh3<ImplicitSurface3Ptr>>,
_bvh_invalidated: RwLock<bool>,
pub surface_data: Surface3Data,
}
impl ImplicitSurfaceSet3 {
pub fn new_default() -> ImplicitSurfaceSet3 {
return ImplicitSurfaceSet3 {
_surfaces: vec![],
_unbounded_surfaces: vec![],
_bvh: RwLock::new(Bvh3::new()),
_bvh_invalidated: RwLock::new(true),
surface_data: Surface3Data::new(None, None),
};
}
pub fn new(surfaces: Vec<ImplicitSurface3Ptr>,
transform: Option<Transform3>,
is_normal_flipped: Option<bool>) -> ImplicitSurfaceSet3 {
let mut unbounded_surfaces: Vec<ImplicitSurface3Ptr> = vec![];
for surface in &surfaces {
if !surface.read().unwrap().is_bounded() {
unbounded_surfaces.push(surface.clone());
}
}
return ImplicitSurfaceSet3 {
_surfaces: surfaces,
_unbounded_surfaces: unbounded_surfaces,
_bvh: RwLock::new(Bvh3::new()),
_bvh_invalidated: RwLock::new(true),
surface_data: Surface3Data::new(transform, is_normal_flipped),
};
}
pub fn new_explicit(surfaces: Vec<Surface3Ptr>,
transform: Option<Transform3>,
is_normal_flipped: Option<bool>) -> ImplicitSurfaceSet3 {
let mut set = ImplicitSurfaceSet3::new_default();
set.surface_data.transform = transform.unwrap_or(Transform3::new_default());
set.surface_data.is_normal_flipped = is_normal_flipped.unwrap_or(false);
for surface in &surfaces {
set.add_explicit_surface(surface.clone());
}
return set;
}
pub fn builder() -> Builder {
return Builder::new();
}
pub fn number_of_surfaces(&self) -> usize {
return self._surfaces.len();
}
pub fn surface_at(&self, i: usize) -> ImplicitSurface3Ptr {
return self._surfaces[i].clone();
}
pub fn add_explicit_surface(&mut self, surface: Surface3Ptr) {
self.add_surface(Arc::new(RwLock::new(SurfaceToImplicit3::new(surface, None, None))));
}
pub fn add_surface(&mut self, surface: ImplicitSurface3Ptr) {
self._surfaces.push(surface.clone());
if !surface.read().unwrap().is_bounded() {
self._unbounded_surfaces.push(surface);
}
self.invalidate_bvh();
}
fn invalidate_bvh(&self) {
*(self._bvh_invalidated.write().unwrap()) = true;
}
fn build_bvh(&self) {
if *self._bvh_invalidated.read().unwrap() {
let mut surfs: Vec<ImplicitSurface3Ptr> = Vec::new();
let mut bounds: Vec<BoundingBox3D> = Vec::new();
for i in 0..self._surfaces.len() {
if self._surfaces[i].read().unwrap().is_bounded() {
surfs.push(self._surfaces[i].clone());
bounds.push(self._surfaces[i].read().unwrap().bounding_box());
}
}
self._bvh.write().unwrap().build(&surfs, &bounds);
*(self._bvh_invalidated.write().unwrap()) = false;
}
}
}
impl Surface3 for ImplicitSurfaceSet3 {
fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D {
self.build_bvh();
let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
return surface.read().unwrap().closest_distance(pt);
};
let mut result = Vector3D::new(f64::MAX, f64::MAX, f64::MAX);
let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);
if let Some(item) = query_result.item {
result = item.read().unwrap().closest_point(other_point);
}
let mut min_dist = query_result.distance;
for surface in &self._unbounded_surfaces {
let pt = surface.read().unwrap().closest_point(other_point);
let dist = pt.distance_to(*other_point);
if dist < min_dist {
min_dist = dist;
result = surface.read().unwrap().closest_point(other_point);
}
}
return result;
}
fn bounding_box_local(&self) -> BoundingBox3D {
self.build_bvh();
return self._bvh.read().unwrap().bounding_box();
}
fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
self.build_bvh();
let mut test_func = |surface: &ImplicitSurface3Ptr, ray: &Ray3D| {
let result = surface.read().unwrap().closest_intersection(ray);
return result.distance;
};
let query_result = self._bvh.read().unwrap().closest_intersection(ray, &mut test_func);
let mut result = SurfaceRayIntersection3::new();
result.distance = query_result.distance;
result.is_intersecting = match query_result.item {
None => false,
Some(_) => true
};
if let Some(item) = query_result.item {
result.point = ray.point_at(query_result.distance);
result.normal = item.read().unwrap().closest_normal(&result.point);
}
for surface in &self._unbounded_surfaces {
let local_result = surface.read().unwrap().closest_intersection(ray);
if local_result.distance < result.distance {
result = local_result;
}
}
return result;
}
fn closest_normal_local(&self, other_point: &Vector3D) -> Vector3D {
self.build_bvh();
let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
return surface.read().unwrap().closest_distance(pt);
};
let mut result = Vector3D::new(1.0, 0.0, 0.0);
let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);
if let Some(item) = query_result.item {
result = item.read().unwrap().closest_normal(other_point);
}
let mut min_dist = query_result.distance;
for surface in &self._unbounded_surfaces {
let pt = surface.read().unwrap().closest_point(other_point);
let dist = pt.distance_to(*other_point);
if dist < min_dist {
min_dist = dist;
result = surface.read().unwrap().closest_normal(other_point);
}
}
return result;
}
fn intersects_local(&self, ray: &Ray3D) -> bool {
self.build_bvh();
let mut test_func = |surface: &ImplicitSurface3Ptr, ray: &Ray3D| {
return surface.read().unwrap().intersects(ray);
};
let mut result = self._bvh.read().unwrap().intersects_ray(ray, &mut test_func);
for surface in &self._unbounded_surfaces {
result |= surface.read().unwrap().intersects(ray);
}
return result;
}
fn closest_distance_local(&self, other_point: &Vector3D) -> f64 {
self.build_bvh();
let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
return surface.read().unwrap().closest_distance(pt);
};
let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);
let mut min_dist = query_result.distance;
for surface in &self._unbounded_surfaces {
let pt = surface.read().unwrap().closest_point(other_point);
let dist = pt.distance_to(*other_point);
if dist < min_dist {
min_dist = dist;
}
}
return min_dist;
}
fn update_query_engine(&self) {
self.invalidate_bvh();
self.build_bvh();
}
fn is_bounded(&self) -> bool {
for surface in &self._surfaces {
if !surface.read().unwrap().is_bounded() {
return false;
}
}
return !self._surfaces.is_empty();
}
fn is_valid_geometry(&self) -> bool {
for surface in &self._surfaces {
if !surface.read().unwrap().is_valid_geometry() {
return false;
}
}
return !self._surfaces.is_empty();
}
fn view(&self) -> &Surface3Data {
return &self.surface_data;
}
}
impl ImplicitSurface3 for ImplicitSurfaceSet3 {
fn signed_distance_local(&self, other_point: &Vector3D) -> f64 {
let mut sdf = f64::MAX;
for surface in &self._surfaces {
sdf = f64::min(sdf, surface.read().unwrap().signed_distance(other_point));
}
return sdf;
}
fn is_inside_local(&self, other_point: &Vector3D) -> bool {
for surface in &self._surfaces {
if surface.read().unwrap().is_inside(other_point) {
return true;
}
}
return false;
}
}
pub type ImplicitSurfaceSet3Ptr = Arc<RwLock<ImplicitSurfaceSet3>>;
pub struct Builder {
_surfaces: Vec<ImplicitSurface3Ptr>,
_surface_data: Surface3Data,
}
impl Builder {
pub fn with_surfaces(&mut self, surfaces: Vec<ImplicitSurface3Ptr>) -> &mut Self {
self._surfaces = surfaces;
return self;
}
pub fn with_explicit_surfaces(&mut self, surfaces: Vec<Surface3Ptr>) -> &mut Self {
self._surfaces.clear();
for surface in surfaces {
self._surfaces.push(Arc::new(RwLock::new(SurfaceToImplicit3::new(surface, None, None))));
}
return self;
}
pub fn build(&mut self) -> ImplicitSurfaceSet3 {
return ImplicitSurfaceSet3::new(self._surfaces.clone(),
Some(self._surface_data.transform.clone()),
Some(self._surface_data.is_normal_flipped));
}
pub fn make_shared(&mut self) -> ImplicitSurfaceSet3Ptr {
return ImplicitSurfaceSet3Ptr::new(RwLock::new(self.build()));
}
pub fn new() -> Builder {
return Builder {
_surfaces: vec![],
_surface_data: Surface3Data::new(None, None),
};
}
}
impl SurfaceBuilderBase3 for Builder {
fn view(&mut self) -> &mut Surface3Data {
return &mut self._surface_data;
}
}