Patina is a C++23 material simulation library for modeling physical and chemical interactions between materials. It handles thermal transfer, chemical reactions, phase changes, structural integrity, combustion, and saturation.
The library is completely stateless. It takes material data and simulation parameters as input, performs calculations, and returns results. It makes no assumptions about how you store your materials, update your world, or render your game. This makes it suitable for a falling sand simulation, a first person immersive sim, a factory builder, or anything else that would benefit from emergent gameplay through interactive material reactions.
Patina uses CMake and requires C++23 support.
cmake -B build -S .
cmake --build buildWhen used as the top-level project, dependencies (GoogleTest, nlohmann_json) are fetched automatically. When consumed as a subdirectory, you are responsible for providing these dependencies.
cd build
ctestTo run a specific test suite:
./build/tests/patina_tests --gtest_filter=ThermalTest.*The core library lives in the patina namespace. All functions are pure calculations that take materials and parameters, returning result structs.
#include <patina/thermal.hpp>
#include <patina/chemical.hpp>
#include <patina/state.hpp>
float iron_temp = 500.0f; // Kelvin
float water_temp = 300.0f;
float delta_time = 1.0f; // seconds
// Heat transfer between two materials
auto thermal = patina::calculate_heat_transfer(iron, water, iron_temp, water_temp, delta_time);
// Chemical interaction (corrosion, reactions)
auto chemical = patina::calculate_chemical_interaction(acid, iron, iron_temp, delta_time);
// Phase changes based on temperature
auto state = patina::calculate_state_change(water, water_temp);Additional modules:
integrity.hppfor collision damage between materialscombustion.hppfor burning, ignition, and heat generationsaturation.hppfor liquid absorption and evaporation in porous materials
Materials are defined by their properties and reactions. The assets/materials.json file contains a starting set of materials including metals, liquids, gases, and combustibles. You can use this as a reference or starting point for your own material definitions.
The patina_utils library provides a JSON loader:
#include <patina_utils/loader.hpp>
auto materials = patina_utils::LoadMaterials("path/to/materials.json");This returns a map from material ID to material data. The loader is separate from the core library so that patina itself has no dependencies.
Each material has:
- Basic info: id, name, state (Solid, Liquid, Gas), tags
- Phase transitions: references to solid/liquid/gas variants
- Reactions: what happens when this material interacts with others
- Properties: thermal conductivity, density, hardness, melting point, etc.
Reactions support conditions like temperature thresholds and pH levels. A reaction with with: 0 acts as a wildcard, matching any material that meets the other conditions.
- Thermal transfer calculations
- Chemical reactions and corrosion
- Phase state changes
- Structural integrity and collision damage
- Combustion and heat generation
- Saturation, absorption, and evaporation
- JSON material loader
- Conditional reactions (temperature, pH, tags)
- Graph editor for materials.json
- Demo project
MIT