Backed up from a local Blogger export (113891334837561811/113891334837561811.html) on 2026-01-01.

Time to take a crack at a dynamic particle system API. First off some basic requirements:

  1. Ability to operate on single particles or groups of particles. Groups are of a single type.
  2. Not strictly static emitter/blocker driven. Must still have ability to define emitters.
  3. Few basic particle types, re-targetable particle renders
  4. Verlet or Euler integration? Probably Verlet.

**Particle types: ** Point Line (Aggregate of point with a different renderer) Billboard Beam Plane Sphere Cube Field (for cloth effects, built-in spring simulation is required for this) Mesh

**Sampling of group settings: ** Type RenderMethod Active (current active count) MaxActive (clipping auto-recycle?) BufferPool (recycle particles, overkill for single particle groups?) SrcColor DstColor Life

**Sampling of some types of per-particle settings: ** LastPosition Position (Velocity is implicit) ColorInterp [0, 1] LifeLeft RotationInterp [0, 1] (for billboards) FrameInterp [0, 1] (for animation)

To use these ideas I am working off the idea of having a more procedural than declerative particle system. The main persistent actors that store state in this system are the particle group which contains 1 or more particles and the particle brush which provides a way to persist and modify geometric primitives that will effect the particle groups in different ways.

Particle group management: Particle groups act as a container and global property set for the particles they contain. Particle groups can be manually tweaked with a few functions. Particle groups own all their own graphics data some of which most likely will be referenced out of the scene (materials) but some of which will actually be stored locally (vertex buffers).

gid ParticleGroupCreate(type, count, maxactive) ParticleGroupDestroy(gid) ParticleGroupApplyForce(gid, x, y, z) ParticleGroupKill(gid, age)

Particle brush management: The behavior of the particle brush is polymophic, emission behaviors and effector behaviors will change based on the shape and parameters of the brush being rendered.

id ParticleBrushCreatePoint(pos) id ParticleBrushCreateLine(pos1, pos2) id ParticleBrushCreateSpline(controlPoints[]) id ParticleBrushCreatePlane(pos, normal, width, height) id ParticleBrushCreateCircle(pos, normal, radius) id ParticleBrushCreateBox(pos, bounds) id ParticleBrushCreateSphere(pos, radius) id ParticleBrushCreateCylinder(pos, radius, height) id ParticleBrushCreateModel(modelName) ParticleBrushDestroy(id)

Changing brush properties: Important for brushes is to be able to change their properties in real time and to have control the range of particles that the brush actually has an effect on. There may be some mature optimization to do here in order to avoid O(n) for each effector.

ParticleBrushSetPosition(id, pos) ParticleBrushSetProperty(id, propid, value) <– I currently don’t like the implications of this ParticleBrushSetLifeFilter(id, min, max) Using a brush as an effector:

ParticleBrushAccelerate(id, gid, acc, max) ParticleBrushMagnet(id, gid, attract)

Using a brush as an emitter: Brushes define some basic types of emission. Depending on the shape of the brush the underlying implementation will choose to emit differently depending on the style of emission chosen by the selected routine. There is a default emission, random (distribution) emission, directed emission, interpolated in the x, y, and z domains.

ParticleBrushEmit(id, gid, count) ParticleBrushEmitRand(id, gid, count) ParticleBrushEmitDir(id, gid, count, dir) ParticleBrushEmitInterp1(id, gid, count, tx) ParticleBrushEmitInterp2(id, gid, count, tx, ty) ParticleBrushEmitInterp3(id, gid, count, tx, ty, tz)

Using a brush as a collider: In order to do collision detection you first have to register a brush with the collision system otherwise you’re asking the particle system to due a potentially expensive collision operation without any kind of warning up front which can result in O(n^2) type performance.

ParticleBrushEnableCollisions(id) ParticleBrushBounce(id, gid,krest) ParticleBrushFriction(id, gid, kfriction)

So that’s the basic idea. I think that based on my lua experiments it will be up to running chunks at animation event time without too much trouble. Most of what I’m doing here is just executing chunks which contain bridged C functions. There may be some math glue in there as well which is one of the benefits of using an actual language.