Hi There,
In this post I'm going to give a very quick example of some cool stuff you can do with VDB's / SDF's. I'm not going to dive too deeply into this topic right now but I may come back and do more of a tutorial post about how VDB / SDF maths works, for now I'll just drop some snippets here which cover the single most common use for SDF's, collision detection.
So here's a quickest of quick summaries of how an SDF works, you can basically feed an SDF any vector position and the SDF will tell whether that position is inside the SDF volume or not, then it can also give you a vector pointing to the closest point on the surface of the SDF. Simple really.
So here's a quick demo of what you can actually do with this knowledge.
Pretty cool right? So what's happening here is that I've converted the sphere to a VDB with an SDF assigned to it.
SDF stands for Signed Distance Field and is a specific form of volume/field which stores at each voxel a vector describing the shortest distance from the voxel position to the 'surface' of the field.
I then animate the grid around to make it intersect with the sphere.
Next I perform a collision check with a point wrangle and retrieve 2 pieces of data from the SDF:
1. I retrieve the SDF scalar value, this does two things, firstly it tells me if the position I asked to check is inside the SDF or not. It also tells me, if my position is inside the SDF, the distance from my given position to the closest point on the surface.
2. I retrieve the volume gradient value of the SDF which gives us a vector pointing to the nearest point on the SDF surface.
Finally I combine these 2 pieces of data to push any points that are inside the SDF back towards the surface, job done.
All quite simple here, I'll add my VDB settings as well, the key thing for this particular demo is to use 'fill interior', it's worth trying without and seeing what the difference is.
So voxel size is the resolution of the volume, no surprises there.
'surface' is the name of the SDF we create, we can call it what ever we want but it's going to be necessary to refer to this later so pick something useful.
fill interior does exactly what it says on the tin. For very high res VDBs it can be slow to fill the whole interior so use with caution.
and here's the code:
// VDB collsion check in it's simplest form
vector sdf_dir = volumegradient(1, "surface", v@P);
float sdf_mag = volumesample(1, "surface", v@P);
if(sdf_mag < 0.001){
v@P += normalize(sdf_dir) * abs(sdf_mag);
}
So there we go, collision detection in 5 lines of VEX, not bad and incredibly useful! As an aside if you don't want to push the point back to the surface but instead want to just identify the points that are inside the VDB you can simply export that 'sdf_mag' variable as a float attribute.
Bonus Content
One final thing, by taking this setup and putting it in a solver you can get a tasty collision effect that is really useful for damage/impacts.
Here's an image of the layout
And here's what's going on inside the solver node
This point wrangle is exactly the same one that we used in the standard, non-solved version. except that by using the solver we are able to accumulate the results and create a track or impact groove.
Alright, that is all.
Good luck and happy colliding!
and remember......
Don't get mad
get vexed!
How would I write it so that I could CONTAIN an object within a volume? Rather than push it to the outside of the sphere, like in this example.