Smash The Mesh (STM) is a Godot add-on that allows you to break a 3D mesh into multiple pieces and then apply physics to each fragment. It also offers the ability to save the results to disk (cache) and load them quickly, thereby avoiding the need for repetitive, often time-consuming computations.
Note: This is a BETA version and is still under development. It should be tested thoroughly to assess its suitability for your needs.
STM uses Godot's Constructive Solid Geometry (CSG) system to create fragments from a mesh.
- STM Nodes
- Installation
- Getting Started Example
- API Documentation
- Cache System Documentation
- Chunks Generation Documentation
- Physics Settings Documentation
- Performance Tips
- Known Issues
- Additional Resources
- Contribution
- License
-
This class is ideal for handling lightweight geometry (with few chunks) that doesn't require intensive computation. It can automatically break a mesh and apply physics to the resulting chunks. This can be done either at loading time (with
chunk_opt_preload = true
) or when thesmash_the_mesh()
method is called. For performance-critical scenarios, it is highly recommended to useSTMCachedInstance3D
. -
This class extends
STMInstance3D
by adding a caching system that only recomputes data when it becomes invalid (for example, if you change the generation parameters). The cache is stored as a compressed scene on the disk, with the default path set tores://stm_cache/
. This cache can be reused across multiple instances with the same geometry. However, be cautious when dealing with a lot of geometry and many fragments, as the size of the cache file will increase. It’s a good idea to periodically check the folder.To open a cache file, simply double-click on it. You can inspect the result and even make edits as needed, but it's important to maintain the tree structure. Note that manually modifying a cache file will invalidate it, so be sure to set
cache_write = false
to ensure your changes are not overwritten the next time the program runs.
-
Download the repository.
-
Import the addons folder into your project.
-
Activate
Smash The Mesh
under Project > Project Settings > Plugins.
-
Add a STMCachedInstance3D node to the scene.
-
Add a new
TorusMesh
in theOriginal Mesh
field. -
Add at least a
Camera3D
node in the scene and make it look the torus. -
Write this code in a
script
:
# Break the mesh when you press the SPACE key
func _input(event: InputEvent) -> void:
# Check if the event is a key press
var key_event = event as InputEventKey
# Reference to the STM instance (ensure this matches the name in your scene tree)
var stm_instance = $STMCachedInstance3D
# Return if STM instance or key event is invalid, or the key is not SPACE
if !stm_instance or !key_event or key_event.keycode != KEY_SPACE:
return
# Break the mesh when SPACE is pressed
if key_event.is_pressed():
stm_instance.smash_the_mesh()
# Apply an "explode" impulse to each fragment/chunk when SPACE is released
elif key_event.is_released():
# Define a callback to apply an impulse to a rigid body chunk
var explode_callback = func(rb: RigidBody3D, _from):
rb.apply_impulse(-rb.global_position.normalized() * Vector3(1, -1, 1) * 5.0)
# Apply the callback to each chunk of the mesh
stm_instance.chunks_iterate(explode_callback)
- Run your program and hit the SPACE to make the torus explode.
Description:
Returns true
if the current instance has been smashed, otherwise returns false
.
Description:
Hides the mesh of the current instance and spawns the physical chunks in its place.
- Note (1): The chunks will not appear until this method is called.
- Note (2): If you're applying physics (e.g.,
apply_impulse()
) immediately aftersmash_the_mesh()
, ensure that theRigidBody3D
is fully initialized in the physics space. To avoid issues, consider awaiting a process frame or usingcall_deferred()
to apply the physics after the current frame.
Description:
Automatically adds a RigidBody3D
and a CollisionShape3D
to the current instance, using the same physics settings as the chunks.
Description:
Iterates over all the chunks' RigidBody3D
instances, allowing you to perform operations on the chunks of this instance.
Example of callback
:
# Perform an action for each chunk
callback := func(rb: RigidBody3D, from: DestructableMesh):
# Get the collision shape of each chunk
var collision_shape = rb.get_child(0) as CollisionShape3D
# Get the mesh instance of each chunk
var mesh_instance = collision_shape.get_child(0) as MeshInstance3D
# ...perform additional actions with each chunk (e.g., apply a force)
Description:
Returns the time elapsed (in seconds) since smash_the_mesh()
was called.
Returns 0
if smash_the_mesh()
has not been called.
Description:
Updates the elapsed time as if smash_the_mesh()
was just called.
This is useful for restarting time-based animations without restoring the chunks to their original state.
Description:
Removes all the chunks of this mesh instance.
Description:
Resets this instance to its state before smash_the_mesh()
was called.
Description:
Freezes or unfreezes the physics simulation of the chunks.
enable
: Passtrue
to freeze the simulation, orfalse
to unfreeze it.
Description:
Reverts the chunks to their starting position.
weight
: The amount of repair, from0
(no repair) to1
(fully repaired).
This method can be called each frame with a low value ofweight
to create a backward animation to the original position.
Tip: Ensure thatchunks_freeze()
is called before using this method to avoid disrupting the physics simulation.
Description:
When enabled, the cache will be overwritten when the cached data becomes invalid.
If multiple instances use the same cache file, it is advisable to have only one instance with cache_write = true
. This allows you to modify the cache data for all instances from a single point (the instance with cache_write = true
).
Description:
When enabled, the object will attempt to load data from the cache file instead of computing it.
- If the cache isn't found, the data will be computed (either at loading time or when needed).
- If
cache_write = true
, the computed data will be saved to disk, preventing future computations. - If
cache_read = false
, the data will always be computed at run-time.
Description:
An informational property (not meant to be modified) that indicates whether this instance can read the cache from disk without the need to recompute the data.
Description:
Specifies the name of the cache file on disk.
- To have multiple instances of the same object read from the same cache, set the same
cache_name
for all instances. - In this case, it is advisable to disable
cache_write
for all instances except one, which can be used to modify the cache. - To ensure that the cache data is never overwritten, set
cache_write = false
for all objects.
Description:
When enabled, the collision shape of the chunks will be read directly from the cache without being recomputed.
- If you want to keep the chunk data from the cache but use a different collision shape, set
cache_baked_shape = false
.
Description:
When enabled, all physics data of the chunks will be read directly from the cache without being recomputed.
- If you want to keep the chunk data from the cache but use different physics settings, set
cache_baked_physics = false
.
Description:
Specifies the original (source) mesh that you want to break into chunks.
Description:
Defines the mesh used as an intersection volume for each voxel to create the chunks.
- The shape of the brush can significantly influence the result and may cause unwanted artifacts if not chosen carefully.
- If you create custom brush meshes, keep them centered on the origin of the system with a size close to
1x1x1
to avoid unpredictable results. - A set of experimental brush meshes is available in the "brushes" sub-folder. For example, the "wood" brush has been used for simulating the breaking of wood material.
Description:
Specifies the material to be used for the inner parts of the chunks.
Description:
Represents the 3D voxel grid, which also indicates the maximum number of chunks that can be created for each axis.
- The maximum number of chunks is determined by
chunk_count.x * chunk_count.y * chunk_count.z
. - Example: If your object is tall (Y axis) but thin (X, Z), you might increase the count on the Y axis while keeping the other two values low to achieve the desired effect.
Description:
Sets the minimum number of vertices required for a chunk to be retained.
- Choosing this value carefully is important to avoid creating insignificant chunks.
- Note: Higher values can reduce the number of chunks created.
- Tip: Monitor the console when generating chunks to see the vertex count for each chunk, and adjust this value accordingly.
Description:
When set to false
, chunks are removed from the mesh starting from the minimum position of the bounding box.
- Disable this flag if you need more regular and predictable chunking results.
Description:
Specifies the amount of noise applied to the brush geometry before computations.
- Adding noise can create interesting irregularities but may also cause artifacts.
- This factor is size-dependent. If you notice excessive artifacts, try setting the noise factor to
0
.
Description:
If true
, chunk computation will occur at loading time.
- When
false
, chunks will only be calculated when thesmash_the_mesh()
method is called.
Description:
If true
, the smash_the_mesh()
method will be automatically called at the start.
Description:
Specifies the collision shape to be used for each chunk.
- Options:
Sphere: 0
Box: 1
Capsule: 2
Cylinder: 3
ConvexShape: 4
- Note: If precise collisions are required, you can use
ConvexShape
, but be aware that it may cause performance loss when dealing with a large number of chunks.
Description:
Represents the mass of the entire geometry. Each chunk will have a fraction of this mass based on its volume or size.
Description:
Specifies the physical material to be applied to each chunk.
Description:
Defines the physics layers that the chunk will check for collisions.
Description:
Specifies the physics layers where the chunk will reside when another collider checks for collisions.
Description:
Represents how much a collider will be allowed to penetrate another object. This value helps determine the priority of collision handling.
- Mesh Complexity: High polygon meshes may result in slow fragmentation. Consider simplifying the mesh before fragmentation.
- Caching: Use the caching feature to save fragmented meshes and improve load times.
- Physics Settings: Adjust physics settings to balance realism and performance, especially for large numbers of fragments.
- Some meshes may not fragment as expected due to limitations in the CSG system.
- Performance may degrade significantly with very complex meshes or large numbers of fragments.
- Mesh Original Size Issue: If you encounter problems fracturing the mesh, try checking the mesh's original size. Until this issue is fixed, there may be difficulties with meshes that are not at least 1 unit in size on at least one axis (preferably larger). For example, a long but thin panel may still work if at least one dimension is sufficiently large to avoid problems with the voxel grid used for fracture computation.
- As this is a BETA version, there may be other unforeseen issues. Please report any bugs to the issue tracker.
- Tutorial Video by AntzGames: A clear and simple video tutorial on how to use the SmashTheMesh plugin. Great for beginners looking for a straightforward introduction to the fundamentals.
Contributions are welcome! Please fork the repository and submit a pull request with your improvements. Make sure to follow the project's coding standards and write clear commit messages.