Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Creating an SDF trait object #10

Open
sanisoclem opened this issue Dec 4, 2023 · 2 comments
Open

Question: Creating an SDF trait object #10

sanisoclem opened this issue Dec 4, 2023 · 2 comments

Comments

@sanisoclem
Copy link

sanisoclem commented Dec 4, 2023

I would like to store an SDF in a struct without making it generic. However I cannot use dyn and put in a Box or Arc because of the Self:Sized constraint (from Copy).

I would like to create a big SDF once and use it in multiple places immutably, in simple struct:

// compile error
pub struct Bounds(Arc<dyn SDF<f32, Vec2>>);

Making it generic would work but it makes it hard to work with as every single consumer would need to know what kind of SDF it is (they don't care). I would also like to put them all into a single immutable list, and generics make that very hard (impossible?).

Is it possible to drop the copy constraint from the trait itself? or any suggestions would be welcome (I'm fairly new to rust).

@sanisoclem sanisoclem changed the title Cannot box SDF trait Question: Creating an SDF trait object Dec 4, 2023
@fu5ha
Copy link
Owner

fu5ha commented Dec 4, 2023

Yeah, object safety (i.e. ability to use as a trait object) was something of an oversight, which is a downside that I realized fairly quickly when using and was playing with a few possible solutions but never fully finished any of them. You can definitely remove the Copy bound but I think that won't be all you need to do to make it actually object safe.

If you can build your actual concrete sdf type through static dispatch and only want to actually 'sample' it afterwards, then another option that wouldn't require you to change sdfu itself would be to make your own object safe trait which you implement generically for your own struct. I.e. something like this

pub struct BuiltSdfHolder<S> {
    sdf: S,
}

pub trait BuiltSdf {
    fn dist(&self, p: Vec2) -> f32;
}

impl<S: SDF<f32, Vec2>> BuiltSdf for BuiltSdfHolder<S> {
    #[inline]
    fn dist(&self, p: Vec2) -> f32 {
        self.sdf.dist(p)
    }
}

// now you can do what you wanted
pub struct Bounds(Arc<dyn BuiltSdf>);

Otherwise, you'll need to remove the Copy bound but also change all the methods from taking self to &self, which may require other changes as well, I can't really remember. If you do try to reconfigure things and find a setup that feels nice to use to you, do open a PR :)

@sanisoclem
Copy link
Author

Thanks for the response :)

I've made some changes that works for me although its not as clean as I would like:

master...sanisoclem:sdfu:master

I went the lazy route and just modified the SDF trait. I had to move the normal calculation functions to outside the trait as I needed normals too and just made them generic over any Clone + Deref<Target = dyn SDF<..> type. I hope I saw your comment first because that would be cleaner. If get around to doing it, I'll open a PR 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants