pub trait SdfState<Scalar: Float, const DIM: usize>:
'static
+ Clone
+ Default {
type Sample;
// Required methods
fn mix(&self, other: &Self, factor: Scalar) -> Self;
fn sample(&self, position: &[Scalar; DIM]) -> Self::Sample;
}Expand description
Trait corresponding to types that can be bound to an SDF.
Examples of things that could be a state would be colors or materials (when doing 3D rendering)
§Example
// A simple Phong material model
use lightwalk::prelude::*;
use glam::{Vec3, vec3, FloatExt};
// We need to derive Clone and Default
// (default will be done manually)
#[derive(Clone)]
struct PhongMaterial {
diffuse_color: Vec3,
diffuse_factor: f32,
specular_color: Vec3,
specular_factor: f32,
specular_exponent: f32,
}
// Provide a default material
impl Default for PhongMaterial {
fn default() -> Self {
Self {
diffuse_color: Vec3::ONE,
diffuse_factor: 1.0,
specular_color: Vec3::ONE,
specular_factor: 1.0,
specular_exponent: 32.0,
}
}
}
impl SdfState<f32, 3> for PhongMaterial {
type Sample = Self;
fn mix(&self, other: &Self, factor: f32) -> Self {
// self.clone()
Self {
diffuse_color: self.diffuse_color.lerp(other.diffuse_color, factor),
diffuse_factor: self.diffuse_factor.lerp(other.diffuse_factor, factor),
specular_color: self.specular_color.lerp(other.specular_color, factor),
specular_factor: self.specular_factor.lerp(other.specular_factor, factor),
specular_exponent: self.specular_exponent.lerp(other.specular_exponent, factor),
}
}
#[inline]
fn sample(&self, _: &[f32; 3]) -> Self::Sample {
self.clone()
}
}
// We can now bind this material to a SDF:
let cube = Cube.bind(PhongMaterial {
diffuse_color: vec3(1.0, 0.0, 0.0),
..Default::default()
});
let sphere = Sphere.bind(PhongMaterial {
diffuse_color: vec3(0.0, 1.0, 0.0),
..Default::default()
});
// We can combine a sphere and a cube because their states match
let sdf = sphere.add(cube);
// And we can now fetch the state at a point:
// NOTE: This will grab the state of the closest shape (and if the union is
// smoothed, so will the states).
let state = sdf.state([2.0, 5.0, 1.0]);Required Associated Types§
Sourcetype Sample
type Sample
In the off chance the state needs to be more complex than the data we wish to query
(for example if the state holds texture information), a sample can be constructed
at some point in space. See SdfState::sample. If this is not required, just use
type Sample = Self, it’s not required anyways.
Required Methods§
Sourcefn mix(&self, other: &Self, factor: Scalar) -> Self
fn mix(&self, other: &Self, factor: Scalar) -> Self
Linear interpolation between self and other depending on factor (which ranges between 0
and 1)
Sourcefn sample(&self, position: &[Scalar; DIM]) -> Self::Sample
fn sample(&self, position: &[Scalar; DIM]) -> Self::Sample
Samples the state at some point in space. Sometimes needed for when the data contained in the state type does not directly map the state of the SDF at some coordinate, for example when using textures, or when generating the state on-the-fly (and thus not storing the data in the actual state)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.