Representing Particle Systems with Nodes¶
The existing particle system in Blender is at the limit of its capacity with outdated design decisions. Therefore, we want a completely new particle system, instead of trying to gradually improve the existing one. A key goal of the new system is to make it more flexible for users. One way to achieve that is to think about node based solutions right from the beginning. The difficulty is to find a node based representation of a particle system, that artists can easily work with. This document proposes one possible solution.
The most fundamental node is the Particle Type node. Everyone of these represents a particle type. A particle system can have multiple particles types. All particles of the same type, have the same attributes, while particles of different types can have different attributes. Particles of different types can have completely different behavior.
In the typical case of a firework, one could have one particle type for the primary particles, and another type for the secondary particles.
The behavior of a particle simulation is defined by three components. One could even argue that this is true for every type of simulation.
- Initial State: In the case of particles, that is defined by the emitter(s).
- Continuous Modifiers: These are effects, that influence particles of a longer period of time, or even for the entire life-time. An example would be force fields.
- Discrete Events: During the simulation, different kinds of events can happen, that individual particles can react to. A typical example is a collisions with some other object.
For full control, these three aspects of the simulation have to be controlled by the user. As can be seen in the image above, a particle type has three sockets, which correspond to these three components. The following sections shows how they are used.
Every time step, an emitter is asked to create new particles and initialize their attributes. A particle type can have multiple emitters.
What the emitter nodes look like exactly is not part of this proposal. However, the goal is define a small set of emitter nodes, that can be used by artists in most cases. Of course, users should be able to completely customize the emitter, by using a "Function" (as explained in this document) to initialize attributes.
A particle type can be connected to multiple event handlers. When an event of the specified type happens, some action is triggered.
Again, the exact set of event handlers is not defined in this proposal. I expect there to be at least a collision event handler and an event handler, that triggers when a certain age is reached.
Modifiers are continuous effects. That means they influence particles over a period of time. Typical examples are force fields, simulation boundaries or even interactions between particles.
Not all particles have to use the same modifiers at the same time. A particle can turn the influence of certain modifiers on and off for itself. In this proposal it does so, using so called "Gates". Modifiers before a gate can be enabled and disabled for individual particles. The state of gates can be changed in actions after events have been triggered.
After an event happened, and there is an event handler for it, an action is triggered. Users define what happens in an action using chains of nodes that are executed one after another. Such a chain always starts at some socket with a name like "On Event" or "On Birth". Nodes are chained using the "(In)" and "(Out)" sockets. The exact naming will probably change though.
A node inside an action can do many different things. As before, the exact set of nodes is not proposed here. However, I expect there to be nodes to change the particle attributes, spawn new particles (of any type) and kill the particle. A node can also delay the time until the next node is executed. This can be useful, when e.g. something should happen 1 second after a collision.
An action is always executed within a context. This context is created by whatever node started the action. Different contexts contain different pieces of data, that can be accessed by all nodes executed in the action. For example, a context created for a collision event, can contain the collision position and the object color at that position. This data can later be used to e.g. change the color of the particle. To give users more flexibility, arbitrary functions can be called from there.