Zylann / godot_voxel

Voxel module for Godot Engine
MIT License
2.59k stars 244 forks source link

Meshers as resources #220

Closed Zylann closed 2 years ago

Zylann commented 3 years ago

This is a change I'm working on:

How meshers worked

Meshers are what turns voxel data into meshes. They can produce colored cubes, batched models, or smooth meshes like transvoxel does, and they are used from multiple threads at once. So far, these meshers were hardcoded. They were chosen only based on the voxel data. If your voxels had SDF, smooth meshes were produced. If they had TYPE data, batched models would be used (aka "Blocky"). Their parameters were hardcoded as well. Recently, a new mesher for colored cube voxels was added and making it available to the terrain system would have required hardcoding it too, if you put data in the COLOR channel. All those meshers are already available to the script API as standalone classes, but only a few can be used with the terrain system. Furthermore, the way things are going, it might no longer be possible to determine which mesher to use solely from the channels.

The changes

So instead of keeping this pattern, I decided to generalize the way meshers are used. Meshers will now be resources. You'll be able to create them in the inspector, set their parameters, save them as files and re-use them. You'll be able to choose which mesher will be used for a given node. It will also be much easier to introduce a new type of mesher, since all it takes is to derive the VoxelMesher class, and implement methods accordingly. This also brings the module closer to integrating MagicaVoxel models into the terrain system.

The breaking changes

Usage notes

Note 1: you still need to use voxel data the mesher can handle. For example, a blocky mesher still won't be able to do anything with only SDF data.

Note 2: this change allows you to set a blocky mesher on VoxelTerrainLod. However, it is still not officially supported. So it's possible that this still won't work.

Note 3: this brings back access to the old DMC mesher which was preceding Transvoxel in this module. I still don't plan to maintain this one further though.

Implementation notes

This required to introduce a special pattern in the way meshers are implemented, to allow multithreading to remain safe and fast. Indeed, it's common for a mesher to be constantly churning data in all threads, so if the user changes a parameter at that moment, we don't want the interface to freeze. Every mesher divides its data in two sections:

Finally, after several changes are made, it's possible the terrain will contain a mishmash of meshes that used old and new parameters. Typically, the user may want to remesh the whole volume once they are done tweaking parameters.

Zylann commented 3 years ago

This got implemented in 791bdafff1e67f783cf8d2287a1ca4ccd9889e11 I'm leaving this open for a moment because there is no docs about it yet, since the docs need to be rewritten anyways

slapin commented 3 years ago

Yay! this one is really cool! Now I think running multiple meshers on same data is important when you implement mesher for terrain and supplemental mesher for grass without need to duplicate stuff and implementing single mesher for terrain + grass...

Thanks a lot for your hard work!

ex5 commented 3 years ago

Could you share an example of how to add grass with a custom VoxelMesherTransvoxel or describe in some more details how to do this? Is it possible to do something like this with GD scripting alone, without creating a new mesher (e.g. with MultiMeshInstance by somehow getting access to coords of the surface voxels)? Or, alternatively, is is possible to somehow get access to their coordinates in a particle shader to generate grass and other surface clutter? (my c++ skill are not up to par, and it wasn't clear from the available docs what'd be the most appropriate way to implement this kind of stuff, so apologies for jumbled questions)

P.S. This module is totally awesome, thank you :heart:

Zylann commented 3 years ago

You might be able to put grass geometry from a mesher, but you currently have to modify that mesher to do so, and it has to be a vertex array, it can't be a node. Chaining two meshers would be a cleaner way, but it's not available yet.

There is however another feature I'm working on currently, which may help doing that: https://github.com/Zylann/godot_voxel/issues/223

Zylann commented 2 years ago

Closing as this was done a while ago