Hi,
I know Volume Analysis SOP does this but is it possible to do it in Volume VOP? Is it a matter of evaluating 26 neighbours of any given voxel? Can anyone post a simple example of how this could be done?
Thanks
How to calculate divergence of a vector in Volume VOP?
8747 12 1- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
Divergence is commonly a property of a vector volume. This becomes some what trivial to calculate if your vector volume is sampled on a MAC grid. This is something that is non-trivial to figure out in the Volume VOP.
The idea of divergence is to look at a small volume around your sample point. You want to determine if there is a net inflow or outflow of material from that point. A simple mental model is to consider a cubic voxel there. The amount flowing through the face of a cube will be
dot (velocity(face center), face_normal) * face_area
The dot with the face normal is thus selecting the x/y/z components. Note opposing faces have opposite signs, which results in what is quite similar to the definition of a gradient.
You can thus do
vector gradx = volumegradient(.., ‘vel.x’, @P);
vector grady = volumegradient(.., ‘vel.y’, @P);
vector gradz = volumegradient(.., ‘vel.z’, @P);
float divergence = gradx.x() + grady.y() + gradz.z();
The divergence is thus the trace of the 3x3 gradient matrix for the vector field. You can optimize this by computing the gradient on each axis yourself with volume sample, cutting the total number of volume samples to 6.
The idea of divergence is to look at a small volume around your sample point. You want to determine if there is a net inflow or outflow of material from that point. A simple mental model is to consider a cubic voxel there. The amount flowing through the face of a cube will be
dot (velocity(face center), face_normal) * face_area
The dot with the face normal is thus selecting the x/y/z components. Note opposing faces have opposite signs, which results in what is quite similar to the definition of a gradient.
You can thus do
vector gradx = volumegradient(.., ‘vel.x’, @P);
vector grady = volumegradient(.., ‘vel.y’, @P);
vector gradz = volumegradient(.., ‘vel.z’, @P);
float divergence = gradx.x() + grady.y() + gradz.z();
The divergence is thus the trace of the 3x3 gradient matrix for the vector field. You can optimize this by computing the gradient on each axis yourself with volume sample, cutting the total number of volume samples to 6.
- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
Thanks Jeff for replying. I didn't understand the last part completely. This operation you showed:
float divergence = gradx.x() + grady.y() + gradz.z();
You have to do it for 26 neighbours or just 6? Because you also said:
“You can optimize this by computing the gradient on each axis yourself with volume sample, cutting the total number of volume samples to 6.”
How does that happen? Sorry I couldn't understand these points. Everything else made a lot of sense.
float divergence = gradx.x() + grady.y() + gradz.z();
You have to do it for 26 neighbours or just 6? Because you also said:
“You can optimize this by computing the gradient on each axis yourself with volume sample, cutting the total number of volume samples to 6.”
How does that happen? Sorry I couldn't understand these points. Everything else made a lot of sense.
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
- pezetko
- Member
- 392 posts
- Joined: Nov. 2008
- Offline
- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
Thanks Jeff it works as expected now
Btw if I want to calculate the voxel size, can I just get an dimension of the volume and divide it by volumeres(that_dimension)? I assume not directly because the volume might have a transform.
In that case I will multiply bbox.min and bbox.max by the inverse of this transform and then calculate the distance between these points in one 1 axis, then use that as the volume size.
If I am being an idiot and there is a simple way, please let me know
Btw if I want to calculate the voxel size, can I just get an dimension of the volume and divide it by volumeres(that_dimension)? I assume not directly because the volume might have a transform.
In that case I will multiply bbox.min and bbox.max by the inverse of this transform and then calculate the distance between these points in one 1 axis, then use that as the volume size.
If I am being an idiot and there is a simple way, please let me know
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
Transforms can have tapers, so volume size can vary per voxel.
However, if you know you have cubic voxels, you can just do volumeindextopos() on 0,0,0 and 1,0,0, get the length, and cube.
If you have rectilinear voxels, do it three times for x/y/z.
If you have taper or shear, run on your ix/iy/ix and +1 variants to get eight points and compute the volume of that distorted cube.
However, if you know you have cubic voxels, you can just do volumeindextopos() on 0,0,0 and 1,0,0, get the length, and cube.
If you have rectilinear voxels, do it three times for x/y/z.
If you have taper or shear, run on your ix/iy/ix and +1 variants to get eight points and compute the volume of that distorted cube.
- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
Thanks Jeff, I did what you said but I am getting volume division size cubed. So I just take the distance between voxel(0,0,0) and voxel(1,0,0), which gives me the division size i.e. 0.1.
It seems like volume of a volume primitive is already available but I can't access it in VEX builder VOP using volume name.
Also how do you taper a volume? Shear works but for taper you need to scale a single face which is not possible for a volume primitive, right?
It seems like volume of a volume primitive is already available but I can't access it in VEX builder VOP using volume name.
Also how do you taper a volume? Shear works but for taper you need to scale a single face which is not possible for a volume primitive, right?
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
Well, “voxel size” may mean division size or it may mean voxel volume :> You are getting the cubed as I answered the latter question.
findattribval() can let you look up by name (That is what the volume() functions do internally)
I'm not sure I want to tell you how to taper volumes as you'll find what goes wrong with them :>
Using a Volume SOP you can point it to a camera to get a frustum volume which is thus tapered. Or you can use a Primitive SOP and manually adjust the taper. It works the exact same way as Tubes - a taperx/y value represents the scaling along the Z axis.
findattribval() can let you look up by name (That is what the volume() functions do internally)
I'm not sure I want to tell you how to taper volumes as you'll find what goes wrong with them :>
Using a Volume SOP you can point it to a camera to get a frustum volume which is thus tapered. Or you can use a Primitive SOP and manually adjust the taper. It works the exact same way as Tubes - a taperx/y value represents the scaling along the Z axis.
- magneto
- Member
- 131 posts
- Joined: Oct. 2011
- Offline
Thanks Jeff, everything fit into place now.
Lastly can I just use primitive intrinsic “measuredvolume” for the volume? Does it calculate the volume of a primitive using the 8 points or just a simple bbox?
I did some experiments other than tapering, it updated this volume as I transformed the volume, except shear though because it keeps the volume I guess?
Something like this:
divsize = cbrt((voxelcountx * voxelcounty * voxelcountz) / measuredvolume)
Lastly can I just use primitive intrinsic “measuredvolume” for the volume? Does it calculate the volume of a primitive using the 8 points or just a simple bbox?
I did some experiments other than tapering, it updated this volume as I transformed the volume, except shear though because it keeps the volume I guess?
Something like this:
divsize = cbrt((voxelcountx * voxelcounty * voxelcountz) / measuredvolume)
- jlait
- Staff
- 6413 posts
- Joined: July 2005
- Offline
-
- Quick Links