1#![warn(missing_docs)]
32
33#[cfg(test)]
34#[macro_use]
35extern crate approx;
36
37extern crate nalgebra as na;
38
39pub use bbox::BoundingBox;
40use num_traits::Float;
41use std::fmt::Debug;
42
43pub trait RealField: alga::general::RealField + na::RealField {}
45impl RealField for f64 {}
46impl RealField for f32 {}
47
48mod transformer;
49pub use self::transformer::AffineTransformer;
50
51mod twister;
52pub use self::twister::Twister;
53
54mod bender;
55pub use self::bender::Bender;
56
57mod boolean;
58pub use self::boolean::{Intersection, Union};
59
60mod sphere;
61pub use self::sphere::Sphere;
62
63mod cylinder;
64pub use self::cylinder::{Cone, Cylinder};
65
66mod plane;
67pub use self::plane::{NormalPlane, PlaneNegX, PlaneNegY, PlaneNegZ, PlaneX, PlaneY, PlaneZ};
68
69mod mesh;
70pub use self::mesh::Mesh;
71
72#[cfg(test)]
73mod test;
74
75pub struct PrimitiveParameters<S> {
78 pub fade_range: S,
80 pub r_multiplier: S,
82}
83
84const ALWAYS_PRECISE: f32 = 1.;
85const EPSILON: f32 = 1e-10;
86
87fn normal_from_object<S: Debug + RealField + Float + From<f32>>(
90 f: &dyn Object<S>,
91 p: &na::Point3<S>,
92) -> na::Vector3<S> {
93 let null: S = From::from(0.0);
94 let e: S = From::from(EPSILON);
95 let a: S = From::from(ALWAYS_PRECISE);
96 let epsilon_x = na::Vector3::<S>::new(e, null, null);
97 let epsilon_y = na::Vector3::<S>::new(null, e, null);
98 let epsilon_z = na::Vector3::<S>::new(null, null, e);
99 let center = f.approx_value(p, a);
100 let dx = f.approx_value(&(p + epsilon_x), a) - center;
101 let dy = f.approx_value(&(p + epsilon_y), a) - center;
102 let dz = f.approx_value(&(p + epsilon_z), a) - center;
103 na::Vector3::<S>::new(dx, dy, dz).normalize()
104}
105
106pub trait Object<S: RealField + Float + From<f32>>: ObjectClone<S> + Debug + Sync + Send {
108 fn bbox(&self) -> &BoundingBox<S>;
110 fn set_bbox(&mut self, _: &BoundingBox<S>) {
112 unimplemented!();
113 }
114 fn set_parameters(&mut self, _: &PrimitiveParameters<S>) {}
116 fn approx_value(&self, _: &na::Point3<S>, _: S) -> S {
121 unimplemented!();
122 }
123 fn normal(&self, _: &na::Point3<S>) -> na::Vector3<S> {
125 unimplemented!();
126 }
127 fn translate(&self, v: &na::Vector3<S>) -> Box<dyn Object<S>> {
129 AffineTransformer::new_translate(self.clone_box(), v)
130 }
131 fn rotate(&self, r: &na::Vector3<S>) -> Box<dyn Object<S>> {
133 AffineTransformer::new_rotate(self.clone_box(), r)
134 }
135 fn scale(&self, s: &na::Vector3<S>) -> Box<dyn Object<S>> {
137 AffineTransformer::new_scale(self.clone_box(), s)
138 }
139}
140
141pub trait ObjectClone<S> {
143 fn clone_box(&self) -> Box<dyn Object<S>>;
145}
146
147impl<S: RealField + Float + From<f32>, T> ObjectClone<S> for T
148where
149 T: 'static + Object<S> + Clone,
150{
151 fn clone_box(&self) -> Box<dyn Object<S>> {
152 Box::new(self.clone())
153 }
154}
155
156impl<S> Clone for Box<dyn Object<S>> {
158 fn clone(&self) -> Box<dyn Object<S>> {
159 self.clone_box()
160 }
161}
162
163impl<S> PartialEq for Box<dyn Object<S>> {
165 fn eq(&self, _: &Box<dyn Object<S>>) -> bool {
166 false
167 }
168}
169
170impl<S> PartialOrd for Box<dyn Object<S>> {
172 fn partial_cmp(&self, _: &Box<dyn Object<S>>) -> Option<::std::cmp::Ordering> {
173 None
174 }
175}