lightwalk/combinators/binary/smooth/smooth_exponential/
union.rs1use std::{fmt::Display, marker::PhantomData};
2
3use num::Float;
4
5use crate::{math::smooth_functions::smooth_min_exponential, prelude::*};
6
7#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct SUnionExponential<
13 Lhs,
14 Rhs,
15 Scalar: Float,
16 State: SdfState<Scalar, DIM>,
17 const DIM: usize,
18> where
19 Lhs: Sdf<Scalar, DIM, State = State>,
20 Rhs: Sdf<Scalar, DIM, State = State>,
21{
22 lhs: Lhs,
23 rhs: Rhs,
24 factor: Scalar,
25 marker: PhantomData<State>,
26}
27
28impl<Lhs, Rhs, Scalar: Display + Float, State: SdfState<Scalar, DIM>, const DIM: usize>
29 Sdf<Scalar, DIM> for SUnionExponential<Lhs, Rhs, Scalar, State, DIM>
30where
31 Lhs: Sdf<Scalar, DIM, State = State>,
32 Rhs: Sdf<Scalar, DIM, State = State>,
33{
34 type State = State;
35
36 #[inline]
37 fn distance(&self, position: [Scalar; DIM]) -> Scalar {
38 let lhs = self.lhs.distance(position);
39 let rhs = self.rhs.distance(position);
40 smooth_min_exponential(lhs, rhs, self.factor)
41 }
42
43 #[inline]
44 fn state(&self, position: [Scalar; DIM]) -> Self::State {
45 let (lhs, lhs_state) = self.lhs.distance_and_state(position);
46 let (rhs, rhs_state) = self.rhs.distance_and_state(position);
47
48 let lhs_weight = (-lhs / self.factor).exp2();
49 let rhs_weight = (-rhs / self.factor).exp2();
50 let fac = rhs_weight / (lhs_weight + rhs_weight);
51
52 lhs_state.mix(&rhs_state, fac)
53 }
54
55 #[inline]
56 fn distance_and_state(&self, position: [Scalar; DIM]) -> (Scalar, Self::State) {
57 let (lhs_distance, lhs_state) = self.lhs.distance_and_state(position);
58 let (rhs_distance, rhs_state) = self.rhs.distance_and_state(position);
59
60 let distance = smooth_min_exponential(lhs_distance, rhs_distance, self.factor);
61
62 let state = {
63 let lhs_weight = (-lhs_distance / self.factor).exp2();
64 let rhs_weight = (-rhs_distance / self.factor).exp2();
65 let fac = rhs_weight / (lhs_weight + rhs_weight);
66
67 lhs_state.mix(&rhs_state, fac)
68 };
69
70 (distance, state)
71 }
72}
73
74impl<Lhs, Rhs, Scalar: Float, State: SdfState<Scalar, DIM>, const DIM: usize>
75 SUnionExponential<Lhs, Rhs, Scalar, State, DIM>
76where
77 Lhs: Sdf<Scalar, DIM, State = State>,
78 Rhs: Sdf<Scalar, DIM, State = State>,
79{
80 #[inline]
81 pub const fn new(lhs: Lhs, rhs: Rhs, factor: Scalar) -> Self {
82 Self {
83 lhs,
84 rhs,
85 factor,
86 marker: PhantomData,
87 }
88 }
89}