How do I write to a specific voxel in a volume?

   5938   12   3
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
I can't decide if this is a stupid question.

Vol Wrangles are great for doing something to every voxel as fast as possible, where you don't really care what order they're processed in.

I need to go through the voxels in a specific order, though, updating surrounding voxels as I go. I can sample any voxel I like (with volumesample), so I can iterate through in the order I need, but how do I write out new values to other voxels?

Or am I going to need to convert it to points or some other data form first?

(I'm doing a kinda flood-fill based cloud pruner. Imagine filling a volume with some nice fluffy clouds with space between them - a bit of tweaked turb noise. Some of the clouds will be cut off hard by the volume's bounds: I want to go round each side of the volume and remove any clouds that are cut off, without affecting any clouds that are fully contained in the volume.

Which means I need to do a kinda of “voxel connectivity” thing: start at one edge, anywhere in that first slice that there's a voxel > 0.0, set it to 0, but then mark the neighbouring voxels on the next slice as needing inspection. Then carry on through the slices of volume, but only checking the marked voxels each time. Do this process from each side of the volume in turn and you should be left with only 100% unchopped clouds.

There are other ways of approaching this particular problem but this'd be the simplest way to create the tool I want. Not least: I could do it in reverse - mark a position within a nice cloudy volume, and fill outward to select just that single cloud and ditch anything not connected by “active” voxels)
User Avatar
Member
2561 posts
Joined: 6月 2008
Offline
I think I would start with points and assign a density value that represents your final value for any given frame. Once you have the points the way you want, rasterize them in to a volume.
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
User Avatar
Member
175 posts
Joined: 1月 2014
Offline
sounds quite complicated, try to think about creating your clouds with spheres/points and then convert it to volumes
I contribute to the beauty of this world
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Yep, there's other ways to skin this particular cat. But this is only one cat. I have others, and they're not all as easily subdued.

And besides… being able to directly write to a voxel in a volume seems like something one ought to be able to do on those odd occasions where you want to tweak values directly. Seems needlessly complex to have to create and rasterize points just because I want to change the value of the voxel at index 972.

Are points the only way of storing multidimensional data in Houdini? Seems horribly inefficient, but I'm not sure there's a way to do it in VEX directly in an array without cheating: an array stored in an attrib on a 2 dimensional grid of points, maybe. Eww.

We can read voxels, get their index number, convert between that and the voxel position, etc etc - gotta be a way to write one surely?

I'd like to put it forward as an RFE, but if I've missed the obvious, please let me know and save my embarrassment
User Avatar
Member
8599 posts
Joined: 7月 2007
Offline
this kind of spreading algorithm you can do multithreaded
- create new volume storing 1 for nonzero density voxels at boundaries
- every iteration lookup neighbours of each nonzero density voxel and set to 1 if at least 1 nbr voxel has boundary value 1, etc..

if you however wish to deal with individual voxels there is always python sop (hou.Volume.setVoxel()) and also numpy for multidimensional arrays ans (hou.Volume.setAllVoxels())
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
8599 posts
Joined: 7月 2007
Offline
but you can also think outside of (bounding) box and use VDB Segment By Connectivity to split your volume into individual cloud volume primitives and delete the ones that touch or reach out of the original bounding box, then mask out original densities
Edited by tamte - 2020年1月24日 15:42:52

Attachments:
vdb_segment_remove_border_clouds.hip (151.4 KB)

Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Tamte, that’s spectacular. You’ve not only answered my question but given me a whole technique to explore I hadn’t thought of. Thanks
User Avatar
Member
2561 posts
Joined: 6月 2008
Offline
You can do a direct write to a single voxel using a Volume Wrangle. You have to remap your voxel index into a vector location which is the x,y,z location within the volume. You can use the built-in @ix, @iy and @iz attributes to target any voxel within the grid.

if((@ix+@iy+@iz)==972) {
// Found my special voxel index.
@density = -3.14159; //my_special_value
}
Edited by Enivob - 2020年1月24日 21:21:26
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Heh - that is akin to the postman knocking on every door in the country to see whether it happens to be 96 Birchwood Crescent, Croydon, so he can deliver a letter. But yep, technically possible

I’m gonna submit an RFE for a vex equivalent of hou.Volume.setVoxel() though: not least because it gives me a cheap way of having a rudimentary 3 dimensional array
User Avatar
Member
5 posts
Joined: 8月 2017
Offline
howiem
Heh - that is akin to the postman knocking on every door in the country to see whether it happens to be 96 Birchwood Crescent, Croydon, so he can deliver a letter. But yep, technically possible

I’m gonna submit an RFE for a vex equivalent of hou.Volume.setVoxel() though: not least because it gives me a cheap way of having a rudimentary 3 dimensional array

Hello howlem, any news on that RFE? I also felt the need for this many times and I could use it right now. It seems like this would be useful to a lot of users, not only a few of us. My guess is that it is not possible or it would have been there for a long time.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Sorry cman - never got round to it. Naughty. But I have now. I'll report back if there's any news... just typing out the RFE got my imagination going with things I wanna play with if/when it gets implemented
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Logged an RFE and got a very swift and comprehensive response. I used the "postman checking every address in the country in order to deliver one letter" analogy:

Developer response:
"It actually maybe faster to send the postman to every address than it is to try and send to specific addresses in serial. VEX and multithreading gets a bit weird about what is "fast".

Note that if vex had a setvoxel() it would actually be much slower than you may envision. Because we don't know the order, we'd have to record all voxel writes into a large list; sort that list; then play back a second time.

You can actually get a first-order approxmiation of this by just creating a point for each "setvoxel" and using volumerasterizeparticles to copy all those points into voxels. As crazy as it sounds, this might not even be that much slower than if we added directly to VEX, as we'd pretty much have to do exactly this internally anyways."

Interesting, huh - makes me curious about how the data is stored internally, and what layers of obfuscation sit between it and us.

So the fastest way to play with things at the voxel level will probably come down to the specifics of what you want to do. If it's a single voxel you want to access, then a vol wrangle will probably be fast enough. If you're trying to write to lots of single voxels, then creating particles and rasterising them may be fastest.
User Avatar
Member
5 posts
Joined: 8月 2017
Offline
Ohhh! So it makes sense why there's not such a function. I finally ended up doing my setup using that auxiliary voxel to point step. But like you, I thought it was a waste of resources. I could avoid it in the past because I could calculate the value of the voxel. This time I am translating voxels and the inverse function is not easy to calculate from the destination. It was actually faster than I thought - translating around 5 million voxels took less than a second.

And actually, I am using around 40% of the voxels in the container so this 'voxel to point' system might save some computation time. If calculate from the destination I would have to query every single voxel to see if the origin is active.

Thanks for the feedback, howiem!!
  • Quick Links