Maybe we can discuss this on a bigger project before identifying the more general problem?
I do have a struct (called TabulatedBssrdf
) which implements two traits:
-
Bssrdf
which in C++ would be the base class -
SeparableBssrdf
which is already more specific (in C++ derived fromBssrdf
), but basically just adds some more trait functions.
The C++ version uses another class (which in Rust is a struct implementing another trait) to basically store a pointer, which is used to call functions:
class SeparableBSSRDFAdapter : public BxDF {
public:
...
Spectrum f(const Vector3f &wo, const Vector3f &wi) const {
...
}
...
private:
const SeparableBSSRDF *bssrdf;
};
The pointer is used here:
Spectrum f(const Vector3f &wo, const Vector3f &wi) const {
Spectrum f = bssrdf->Sw(wi);
// Update BSSRDF transmission term to account for adjoint light
// transport
if (bssrdf->mode == TransportMode::Radiance)
f *= bssrdf->eta * bssrdf->eta;
return f;
}
The Rust counterpart would have to turn a &self
reference (to a struct TabulatedBssrdf
) into some kind of pointer to the SeparableBssrdf trait, so it's SeparableBssrdf::sw() function can be called:
impl Bssrdf for TabulatedBssrdf {
...
fn sample_s(
&self,
...
) -> Spectrum {
...
// initialize material model at sampled surface interaction
let mut bxdfs: Vec<Arc<Bxdf + Send + Sync>> = Vec::new();
bxdfs.push(Arc::new(SeparableBssrdfAdapter::new( // pointer needed here !!!
)));
si.bsdf = Some(Arc::new(Bsdf::new(&si, 1.0, bxdfs)));
...
}
}
Here is what needs to be done (commented out for now):
pub struct SeparableBssrdfAdapter {
// TODO: pub bssrdf: "some pointer to a" SeparableBssrdf;
}
impl SeparableBssrdfAdapter {
pub fn new(
// TODO: bssrdf pointer parameter
) -> Self {
SeparableBssrdfAdapter {
// TODO: store pointer and maybe eta?
}
}
}
impl Bxdf for SeparableBssrdfAdapter {
fn f(&self, wo: &Vector3f, wi: &Vector3f) -> Spectrum {
// let mut f: Spectrum = self.bssrdf.sw(wi);
// update BSSRDF transmission term to account for adjoint light transport
// if (self.bssrdf.mode == TransportMode::Radiance) {
// f *= self.bssrdf.eta * self.bssrdf.eta;
// }
// f
// WORK
Spectrum::default()
}
fn get_type(&self) -> u8 {
BxdfType::BsdfDiffuse as u8 | BxdfType::BsdfReflection as u8
}
}
Maybe this is really easy and I just can't wrap my head around it? Any suggestions how to do this?