Relintai / voxelman

A voxel engine for godot. I'ts a c++ engine module.
MIT License
97 stars 8 forks source link

Ideas for Voxelman to move it forward in a sensible direction, properties #8

Open ghost opened 2 years ago

ghost commented 2 years ago

Voxel Properties

Naming: States, Properties, Params

Properties/params are int, bool, enum, string variables that are manually defined for specific Voxel ids using a property_name keyword. Properties are used to define custom behavior or looks for Voxels and although are associated with an id, are actually stored per x,y,z Voxel in the VoxelChunk.

A dictionary with key params["x,y,z:property_name"] can be used to store properties in addition to the ch[] array used for Voxels.

Examples:

References: Forge Blockstates Minecraft Wiki Block states Minetest Wiki for register_node

Voxels can rotate

Naming: dir, direction, facing, facedir, orientation

With the implementation of properties/params above, we can now add more customization to specific Voxels. Adding a facing int property allows Voxels to specify a texture rotation. Mesher can now render the texture to follow the facing specified by the property. By default all Voxels face NORTH.

A utility class Facing stores all the facings for example Facing.NORTH, Facing.SOUTH, Facing.EAST, Facing.WEST, Facing.UP, Facing.DOWN and also allows for additional functions such as rotate(Vector3, Facing.LEFT), give a Vector3 for a facing Facing.to_vec3(Facing.NORTH) etc.

Voxels can change material/look/texture

Naming: look, texture, tex, alt, mat, material

When a voxel has a look string property defined, the mesher will use that string as the material for that specific Voxel. This parameter can be dynamically updated from Script.

Look would store only a name and not the full path. A material path can now be declared per Voxel id.

Voxels can use custom 3D meshes

A property/param called mesh defines the name of the 3D mesh that the meshes will use instead of the regular block/marching cube mesher. Such a voxel is declared as being transparent internally and is not processed by the mesher and will not mix in with the rest of regular voxel terrain.

A mesh path can now be declared per Voxel id.

I know that there is a mesh_data_tool support which appears to allow for custom meshing but perhaps built in meshes .tres meshes should also be supported by default as is simply adding a mesh into the world as is without any rotation at a specific x,y,z location. So is upt to the user to manipualte this mesh so it looks good at 1:1 scaling and correct rotation.

Conclusion

Thank you for reading and for all your contribution and work thus far. And sorry for the long post. Just wanted to be thorough.

Relintai commented 2 years ago

To be honest all of these can be added on top of the current system by extending your VoxelWorld + VoxelChunk + VoxelMesher of choice, without messing around with the current core classes. In fact I'd probably do it like that.

For example Voxel(World + Chunk + Mesher)BlockyExtended which inherit from the Voxel(World + Chunk + Mesher)Blocky, could be easily created that can handle all of these.

VoxelSurface would need some improvements. Like it should have 6 texture slots, and probably an exposed editable dict, but other than that, it should be fine. (And even that is implementable without touching the core if someone really wants to do it.)

The problem is my hands are already way too full to do these, and as I'm not going to use them they'll just probably end up being in a buggy state fairly quickly.

I'll leave this open, if you (or someone) wants to do these, I have no issue of having it (or changes necessary to have these as features) in the module, but I unfortunately won't have the energy required to do these in a competent way for the foreseeable future.

ghost commented 2 years ago

Hi, thank you taking the time to reply. 😃 That is true that you can in fact implement all these from Script as is simply a dictionary associated with a chunk.

I can take a stab at this see what I can do. I personally prefer a simpler and more bare minimum and well tested approach. The problem is I don't fully understand how everything works especially mesher code and I wonder if is at all possible to reach out if I have any questions.

Relintai commented 2 years ago

I wonder if is at all possible to reach out if I have any questions.

Sure, it's not a problem.

By the way, it you only want to mess with the generated base voxel mesh, you really only need to look at VoxelMesher's _add_chunk(Ref<VoxelChunk> p_chunk) method.

For example, VoxelMesherBlocky, if you strip out the vertex color (light) calculation stuff, you will see it's a standard minecraft like mesher. You should be able to add all of the mentioned features to a copy this method. This is why you need a new VoxelMesher.

The reason why you need to create a VoxelChunk, is to store and manage the additional data (like facing) easily. If you look at VoxelChunkBlocky it just adds a property, so the compressed data channel gets saved by godot automatically.

The reason why you need a World is so it can create the appropriate chunks. (if you look at VoxelWorldBlocky, it only implements one method.)

Complexity will start to come into play if you (for example) want to do raycasts into the world during mesh generation. Because raycasting from a different thread can crash the engine (if I remember correctly, but adding physics colliders can definitely do it.). Then you need to use the jobs, and mess with job update types. (Like here.)