Bei 3D und Physics Engines gibt es ganz verschiedene Entwurfsmuster. Als
erstes braucht man eine schnelle Mathelib, welche Arithmetische
Operationen auf Vektoren Matrizen, Quaternionen anwenden kann. Danach
muss man sich den groben Ablauf und die mit der zur Verfügung Stehenden
Hardware zu nutzenden Mittel Entscheiden.
Ablaufe könnten sein:
- Haupt-schleife, in welcher nacheinander in der Physics Engine der
Nächste Iterationsschritt, und danach das nächste Frame Gerändert wird.
- Mehrere Threads für verschiedene Aufgaben, Physics und Rendering
Parallel.
- Cloud-Computing
- ...
Nutzbare Mittel und Alternative:
- Berechnungen auf GPU auslagern:
- DirectX plus HLSL nutzen
- oder OpenGL mit GLSL für rendering und OpenCL für Physics
- Langsame Alternative:
- Software rendering, Komplette Physik auf CPU
Danach kommen Entscheidungen wie, Wovon gibt es sehr viele,
Parallelisierbare berechnungen die auf die GPU ausgelagert werden
können, und sollen diese auf die GPU ausgelagert werden?
Geeignet für die Auslagerung auf die GPU wären:
- Partikelsysteme, Ausnutzung von GLSL und transform feedback, oder
nutzung von OpenCL.
- Cloth simulation
- Hair simulation
- Ray Tracing / Rycasting un Co.
Auf der CPU würde ich überwiegend Kollision Detektion und Prüfungen zur
Möglichkeit der Interaktion zwischen Objekten ausführen. D.h. Objekte
Gruppieren, Umschliessende Box, Umschliessende Kugel berechnen.
Beispiel: Wenn die Umschliessenden Kugeln zweier Objekte nicht
Kollidieren, kollidieren auch die Objekte nicht, Man kann sich die
Kollisionsberechnungen für die Primitive der Objekte Sparen.
Allgemeine Grundlagen für Realtime-fähigen Simulationen:
- GPU nutzen
- Möglichst selten und Möglichst grosse Zusammenhängende Daten-Blöcke
an die GPU übertragen, statt viele einzelne.
- Wenn möglich die Speicherintensivere, Schnellere Methode verwenden
und Alles Mögliche Bereits bei der Initialisierung Vorausberechnen, z.B.
Key-Frames
- Überflüssige Berechnungen frühzeitig erkennen
Mit diesem Vorwissen kann man dann die Anforderungen an die Engine
festlegen und mit den Überlegungen zur Umsetzung beginnen.
Als schnelle Methode um Berechnete Daten zwischen einem rendering-Thread
und einem Physics Thread non-Blocking auszutauschen verwende ich gerne
double buffering, der rendering Thread bekommt den alten Buffer, während
der Neue fom Pysics thread beladen wird, dann werden die Pointer auf die
Buffer getauscht. Das kombiniert man dann noch mit einem Mutex und einem
trylock, und setzt ein Flag ob sich bereits etwas am buffer verändert
hat.
Zum Schluss sollte man sich noch für eine Programmiersprache
Entscheiden, welche einem dafür geeignet Erscheint (wobei ich von Java,
perl, python und Co. abraten würde und etwas Hardwarenahes empfehle, wie
z.B. Delphi, C, C++, ...)
Bei der Umsetzung fängt man dann zuerst mit den Ablauf Diagrammen an,
und hält sich danach an die üblichen Design-Patterns der gewählten
Programmiersprache.
Aber bevor man all das macht, empfehle ich Tutorials zu OpenGL, OpenCL,
GLSL, OpenAL, DirectX, ... zu machen und Erfahrung zu sammeln.
Das wird sehr viel zeit Beanspruchen.