007 - Physics System

Das Physics System bietet Verlet-basierte Physik-Simulation.

Warum Physik in Creative Coding?

Physik macht generative Kunst lebendig. Ein Partikel, das der Schwerkraft folgt, wirkt natürlicher als einer, der linear fliegt. Ein Schwarm, dessen Individuen aufeinander reagieren, erzeugt emergente Muster, die man nicht hätte programmieren können.

Warum Verlet?

Es gibt viele Physik-Ansätze. Ich nutze Verlet-Integration, weil sie:

  • Stabil ist – Auch bei großen Zeitschritten explodiert nichts
  • Einfach ist – Position + vorherige Position = Geschwindigkeit (implizit)
  • Constraint-freundlich ist – "Diese zwei Punkte sollen Abstand X haben" → einfach Positionen korrigieren

Klassische Euler-Integration (position += velocity * dt) akkumuliert Fehler und braucht kleine Zeitschritte. Verlet (position_new = 2*position - position_old + acceleration*dt²) ist stabiler und erlaubt größere Zeitschritte.

Warum zwei Ebenen?

Das System hat zwei getrennte Physik-Welten:

  1. PhysicsWorld – Für Partikel, Schwärme, Ketten. Jeder Punkt ist ein Particle.
  2. SoftShape – Für deformierbare Formen. Die Vertices haben eigene Mini-Physik.

Warum getrennt? Weil ein Soft Circle seine interne Jelly-Physik behält, auch wenn er als Ganzes in der PhysicsWorld herumfliegt. Der ShapePhysicsAdapter verbindet beide Welten.

Zwei-Ebenen-Architektur

┌─────────────────────────────────────────────────────────────────────────┐
│                       Ebene 1: PhysicsWorld                             │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │                        PhysicsWorld                               │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│         │              │              │              │                  │
│         ▼              ▼              ▼              ▼                  │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐            │
│  │ Particles  │ │ Behaviors  │ │Constraints │ │  Springs   │            │
│  └────────────┘ └────────────┘ └────────────┘ └────────────┘            │
└─────────────────────────────────────────────────────────────────────────┘
                                    ▲
┌───────────────────────────────────┼─────────────────────────────────────┐
│                       Adapter     │                                     │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │                    ShapePhysicsAdapter                            │  │
│  └───────────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────┼─────────────────────────────────────┘
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        Ebene 2: SoftShape                               │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │                          SoftShape                                │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                │                              │                         │
│                ▼                              ▼                         │
│      ┌─────────────────┐          ┌────────────────────────┐            │
│      │    Vertices     │          │  Internal Constraints  │            │
│      └─────────────────┘          └────────────────────────┘            │
└─────────────────────────────────────────────────────────────────────────┘

Ebene 1: PhysicsWorld

  • Globale Punkt-basierte Simulation
  • Particles mit Position, Velocity, Mass
  • Für: Partikel-Systeme, Schwärme, Ketten

Ebene 2: SoftShape

  • Shape-interne Simulation
  • Für: Deformierbare Formen (Blob, SoftCircle)

Komponenten

Klasse Datei Funktion
PhysicsWorld PhysicsWorld.ts Container für Simulation
Particle Particle.ts Verlet-Partikel
Behavior Behavior.ts Kraft-Interface
Constraint Constraint.ts Regel-Interface
Spring Spring.ts Feder-Verbindung
ParticleString ParticleString.ts Partikel-Kette
CollisionZone CollisionZone.ts Kollisions-Bereiche
ProximityConnection ProximityConnection.ts Nähe-basierte Linien

PhysicsWorld

Container und Update-Loop.

Update-Reihenfolge:

  1. Behaviors anwenden (Kräfte)
  2. Particles updaten (Verlet)
  3. Springs aktualisieren
  4. Constraints anwenden

API:

Methode Beschreibung
addParticle(p) Particle hinzufügen
addBehavior(b) Behavior hinzufügen
addConstraint(c) Constraint hinzufügen
addSpring(s) Spring hinzufügen
update(dt) Simulation updaten
clear() Alles entfernen

Particle

Verlet-Partikel.

Properties:

Property Typ Beschreibung
position Vector Aktuelle Position
previousPosition Vector Letzte Position
mass number Masse
locked boolean Fixiert?
damping number Dämpfung (0-1)
radius number Für Kollisionen

Methoden:

Methode Beschreibung
addForce(f) Kraft hinzufügen
update(dt) Verlet-Integration
velocity Getter/Setter für Velocity

Behaviors

Kräfte die auf Particles wirken.

GravityBehavior

Option Typ Default Beschreibung
strength number 9.81 Stärke
direction Vector (0, 1) Richtung

FrictionBehavior

Option Typ Default Beschreibung
coefficient number 0.02 Reibungskoeffizient

AttractionBehavior

Option Typ Default Beschreibung
target Vector - Anziehungspunkt
strength number 0.1 Stärke
radius number 200 Wirkungsradius

ConstantForceBehavior

Option Typ Beschreibung
force Vector Konstante Kraft

Presets: createWindBehavior(), createUpdraftBehavior()

Flocking Behaviors (Boids)

Behavior Beschreibung
SeparationBehavior Abstand halten
AlignmentBehavior Gleiche Richtung
CohesionBehavior Zusammenbleiben
FlockingBehavior Kombiniert alle drei

Flocking Presets:

Preset Beschreibung
birds Vogelschwarm
fish Fischschwarm
insects Insektenschwarm
tight Enger Zusammenhalt
loose Loser Zusammenhalt

Constraints

Regeln die Particles einhalten müssen.

RectConstraint

Hält Particles in einem Rechteck.

Option Typ Beschreibung
bounds {x,y,w,h} Rechteck
mode RectConstraintMode 'contain' oder 'repel'
bounce number Bounciness (0-1)

CircularConstraint

Hält Particles in/außerhalb eines Kreises.

Option Typ Beschreibung
center Vector Mittelpunkt
radius number Radius
mode CircularConstraintMode 'contain' oder 'exclude'

DistanceConstraint

Fester Abstand zwischen zwei Particles.

Option Typ Beschreibung
particleA Particle Erster Particle
particleB Particle Zweiter Particle
distance number Ziel-Abstand
stiffness number Steifigkeit (0-1)

AxisConstraint

Beschränkt auf eine Achse.

Option Typ Beschreibung
axis 'x' | 'y' Achse
value number Feste Position

Presets: createHorizontalRail(), createVerticalRail()

MinConstraint / MaxConstraint

Minimum/Maximum-Grenze.

Presets: createFloor(), createCeiling(), createLeftWall(), createRightWall()

Springs

Federkräfte zwischen Particles.

Klasse Beschreibung
Spring Standard Feder
MinDistanceSpring Mindestabstand
MaxDistanceSpring Maximalabstand

Optionen:

Option Typ Default Beschreibung
particleA Particle - Erster Particle
particleB Particle - Zweiter Particle
restLength number auto Ruhelänge
stiffness number 0.5 Steifigkeit
damping number 0.1 Dämpfung

ParticleString

Kette von Particles mit Constraints.

Factory-Funktionen:

Funktion Beschreibung
createRope(opts) Seil (viele Segmente, weich)
createTautLine(opts) Gespannte Linie (steif)
createChain(opts) Kette (mit Springs)

CollisionZone

Bereiche mit speziellem Verhalten.

Option Typ Beschreibung
shape 'rect' | 'circle' Form
behavior ZoneBehavior Verhalten beim Eintritt

Behaviors:

Behavior Beschreibung
slow Verlangsamen
accelerate Beschleunigen
kill Particle entfernen
bounce Abprallen
attract Anziehen

ProximityConnection

Zeichnet Linien zwischen nahen Particles.

Option Typ Default Beschreibung
maxDistance number 100 Max. Verbindungsdistanz
minOpacity number 0 Opacity bei maxDistance
maxOpacity number 1 Opacity bei Kontakt
strokeWidth number 1 Linienbreite

Presets:

Preset Beschreibung
network Netzwerk-Look
constellation Sternbild-Look
web Spinnennetz-Look

Presets & Factory-Funktionen

Funktion Beschreibung
createDefaultPhysicsWorld() Standard-World mit Gravity
createRandomParticle(bounds) Zufälliger Particle
createParticleChain(n, opts) Verkettete Particles
addFlockingToWorld(world, preset) Flocking hinzufügen

Soft Body Kollisionen

Das Soft Body System (siehe 004-Shapes) unterstützt Shape-zu-Shape Kollisionen.

Kollisions-Pipeline

┌─────────────────┐    ┌─────────────────┐    ┌─────────────┐
│   Broad-Phase   │ -> │  Narrow-Phase   │ -> │  Response   │
│      AABB       │    │      SAT        │    │   Impulse   │
└─────────────────┘    └─────────────────┘    └─────────────┘

Phasen:

Phase Algorithmus Beschreibung
Broad-Phase AABB Schneller Bounding-Box Test - filtert nicht-kollidierende Shapes
Narrow-Phase SAT Separating Axis Theorem - präzise Polygon-Überlappung
Response Impulse Shapes separieren + elastischer Bounce anwenden

Aktivieren

import { ShapeStateManager } from '@carstennichte/cc-toolbox';

// Shapes erstellen und konfigurieren...
const shapes: ShapeStateManager[] = [...];

// Alle Shapes kennen alle anderen
const decorators = shapes.map(s => s.getDecorator());
for (const shape of shapes) {
  shape.setCollisionBodies(decorators);
}

Parameter-Einfluss

Parameter Einfluss auf Kollision
elasticity Bounce-Stärke (Durchschnitt beider Shapes)
stiffness Wie schnell sich Shape nach Kollision stabilisiert
damping Dämpft Kollisions-Bounce

Performance-Hinweise

  • Alle-gegen-Alle: Bei n Shapes → n² Checks
  • Empfehlung: ~20-30 Shapes mit Kollision, ~50 ohne
  • Konkave Shapes: SAT funktioniert nur zuverlässig für konvexe Polygone