This commit is contained in:
Miloslav Ciz 2024-03-31 20:21:22 +02:00
parent 6c86f68253
commit 491c5ff885
17 changed files with 1836 additions and 1764 deletions

View file

@ -20,7 +20,7 @@ Physics engine is a wide term even though one usually imagines the traditional 3
A typical physics engine will work something like this: we create a so called **physics world**, a [data structure](data_structure.md) that represents the space in which the simulation takes place (it is similar to a [scene](scene.md) in rendering engines). We then populate this world with physics elements such as rigid bodies (which can have attributes such as mass, elasticity etc.). These bodies are normally basic geometric shapes such as spheres, cylinders, boxes or capsules, or objects composed of several such basic shapes. This is unlike with rendering engines in which we normally have triangle meshes -- in physics engines triangle meshes are extremely slow to process, so for the sake of a physics engine we approximate this mesh with some of the above basic shapes (for example a creature in a game that's rendered as a hi-poly 3D model may in the physics engine be represented just as a simple sphere). Furthermore the bodies can be **[static](static.md)** (cannot move, this is sometimes done by setting their mass to infinity) or **[dynamic](dynamic.md)** (can move); static bodies normally represent the environment (e.g. the game level), dynamic ones the entities in it (player, NPCs, projectiles, ...). Making a body static has performance benefits as its movement doesn't have to be calculated and the engine can also precalculate some things for it that will make e.g. collision detections faster. We then simulate the physics of the world in so called *ticks* (similar to [frames](frame.md) in rendering); in simple cases one tick can be equivalent to one rendering frame, but properly it shouldn't be so (physics shouldn't be affected by the rendering speed, and also for the physics simulation we can usually get away with smaller "[FPS](fps.md)" than for rendering, saving some performance). Usually one tick has set some constant time length (e.g. 1/60th of a second). In each tick the engine performs a **[collision detection](collision.md)**, i.e. it finds out which bodies are touching or penetrating other bodies (this is accelerated with things such as [bounding spheres](bounding_volume.md)). Then it performs so called **collision resolution**, i.e. updating the positions, velocities and forces so that the bodies no longer collide and react to these collisions as they would in the real world (e.g. a ball will bounce after hitting the floor). There can be many more things, for example **constraints**: we may e.g. say that one body must never get further away from another body than 10 meters (imagine it's tied to it by a rope) and the engine will try to make it so that this always holds. The engine will also offer a number of other functions such as casting rays and calculating where it hits (obviously useful for shooter games).
**Integrating physics with graphics**: you will most likely use some kind of graphics engine along with physics engine, even if just for [debugging](debugging.md). As said above, keep in mind a graphics and physics engines should be **strictly separated** ([decoupled](coupling.md), for a number of reasons such as [reusability](reusability.md), easier debugging, being able to switch graphics and physics engines etc.), even though they closely interact and may affect each other in their design, e.g. by the data structures you choose for your program (voxel graphics will imply voxel physics etc.). In your program you will have a **physics world and a graphics scene**, both contain their own elements: the scene has graphics elements such as 3D models or particle systems, the physics world has elements such as rigid bodies and force fields. Some of the graphical and physics entities are connected, for example a 3D model of a tree may be connected to a physics rigid body of a cone shape. NOT ALL graphics elements have counterparts in the physics simulation (e.g. a smoke effect or light aren't present in the physics simulation) and vice versa (e.g. player in a first-person game has no 3D model but still has some physics shape). The connection between graphics and physics elements should be done **above** both engines (i.e. do NOT add pointers to physics object to graphics elements etc.). This means that e.g. in a game you create a higher abstract environment -- for example a level -- which stands above the graphics scene and physics world and has its own game elements, each game element may be connected to a graphics or physics element. These game elements have attributes such as a position which gets updated according to the physics engine and which is transferred to the graphics elements for rendering. Furthermore remember that **graphics and physics should often run on different "FPS"**: graphics engines normally try to render as fast as they can, i.e. reach the highest [FPS](fps.md), while physics engines often have a time step, called a **tick**, of fixed time length (e.g. 1/30th of a second) -- this is so that they stay [deterministic](determinism.md), accurate and also because physics may also run on much lower FPS without the user noticing ([interpolation](interpolation.md) can be used in the graphics engine to smooth out the physics animation for rendering). "[Modern](modern.md)" engines often implement graphics and physics in separate [threads](thread.md), however this is not [suckless](suckless.md), in most cases we recommend the [KISS](kiss.md) approach of a single thread (in the main loop keep a timer for when the next physics tick should be simulated).
**Integrating physics with graphics**: you will most likely use some kind of graphics engine along with physics engine, even if just for [debugging](debugging.md). As said above, keep in mind a graphics and physics engines should be **strictly separated** ([decoupled](coupling.md), for a number of reasons such as [reusability](reusability.md), easier debugging, being able to switch graphics and physics engines etc.), even though they closely interact and may affect each other in their design, e.g. by the data structures you choose for your program (voxel graphics will imply voxel physics etc.). In your program you will have a **physics world and a graphics scene**, both contain their own elements: the scene has graphics elements such as 3D models or particle systems, the physics world has elements such as rigid bodies and force fields. Some of the graphical and physics entities are connected, for example a 3D model of a tree may be connected to a physics rigid body of a cone shape. NOT ALL graphics elements have counterparts in the physics simulation (e.g. a smoke effect or light aren't present in the physics simulation) and vice versa (e.g. player in a first man game has no 3D model but still has some physics shape). The connection between graphics and physics elements should be done **above** both engines (i.e. do NOT add pointers to physics object to graphics elements etc.). This means that e.g. in a game you create a higher abstract environment -- for example a level -- which stands above the graphics scene and physics world and has its own game elements, each game element may be connected to a graphics or physics element. These game elements have attributes such as a position which gets updated according to the physics engine and which is transferred to the graphics elements for rendering. Furthermore remember that **graphics and physics should often run on different "FPS"**: graphics engines normally try to render as fast as they can, i.e. reach the highest [FPS](fps.md), while physics engines often have a time step, called a **tick**, of fixed time length (e.g. 1/30th of a second) -- this is so that they stay [deterministic](determinism.md), accurate and also because physics may also run on much lower FPS without the user noticing ([interpolation](interpolation.md) can be used in the graphics engine to smooth out the physics animation for rendering). "[Modern](modern.md)" engines often implement graphics and physics in separate [threads](thread.md), however this is not [suckless](suckless.md), in most cases we recommend the [KISS](kiss.md) approach of a single thread (in the main loop keep a timer for when the next physics tick should be simulated).
## Existing Engines