deutsch
englisch
 

Was ist Sunray2?
Warum eine eigene Engine?
Warum Sunray „2“?
Was kann Sunray2?
Was ist Sunray2 nicht?
Wie weit ist Sunray2?
Wer benutzt Sunray2?
Feature/Klassen Liste


Was ist Sunray2?     >nach oben<
  • Eine selbstgeschriebene, moderne, modulare, spielunabhängige, objektorientierte, in C++ geschriebene 3D Engine basierend auf DirectX9.
  • Nicht nur Grafik, sondern auch Sound, Input, Gui und Filehandlingskomponenten
  • Komplett Shaderbasiert in der Grafikpipeline (HLSL)
  • Zur Zeit rund 21.000 reine Codezeilen
  • Durch eine einfache PlugIn Struktur sehr flexibel und erweiterbar
  • Durch Model-Exporter für alle wichtigen 3D-Moddeling-Programme und Textur-Exporter für Photoshop sehr einfach in der Contenterstellung
Warum eine eigene Engine?     >nach oben<
  • Sunray2 ist ein Schulprojekt und in der Schule will man etwas lernen. Die Überlegung war: Am meisten lernt man, wenn man es selber macht. Daher die Entscheidung zum selberschreiben.
  • Bei einer fertigen Engine gibt es für fast alle wichtigen Funktionalitäten vorgegebene Funktionen, die man sich in der Dokumentation raussuchen kann/muss. Wir wollten aber die Materie verstehen und nicht nur anwenden.
  • Es ist ein Risiko eine eigene Engine zu entwickeln. In der Schule kann man dieses Wagnis jedoch eingehen, ohne finanzielle Verluste zu riskieren. Zudem kann man (bei Problemen) Hilfe durch die Dozenten in Anspruch nehmen. Also: Wenn nicht in der Schule, wann dann?
  • Außerdem: Eine eigene Engine zu schreiben macht einfach Spaß! ;-)
Warum Sunray „2“?     >nach oben<
  • Sunray1 wurde für das Vorgängerspiel geschrieben, war jedoch viel zu unflexibel, daher die Entscheidung zu einem kompletten Neuanfang mit den gewonnenen Erfahrungswerten
Was kann Sunray2?     >nach oben<
  • Technik auf DirectX9 Standard (Shader, X-Files, Skeletal-Animationen, 3D-Sound, DXUT-GUI, so ziemlich alle Eingabegeräte)
  • Shader sind 3D Studio Max kompatibel, dadurch guter Workflow für Artists.
  • Möglichkeit Videos abzuspielen und als Texturen zu verwenden (durch DirectShow, daher viele unterstütze Formate)
  • XML-Files (einfaches auslesen & erstellen)
  • Umfassender MultiMonitoring und SplitScreen-Support
  • Umfangreiche Erweiterbarkeit durch eigene Renderpässe
  • Schnell erste Ergebnisse durch vorgefertigte Standard Techniken (Shadowmaps, Beleuchtung...)
  • Viele entwicklungsbeschleunigende Hilftsmethoden (Konsole, Debugger, Timer...)
  • Sehr schnelle Matrix & Vektoren Klassen (mit SSE1-3 Optimierungen)
  • Einfache Parametrisierbarkeit durch XML-Config-Files
  • Schnelle GUI Erstellung durch XML-Files
  • Durch die Engine-Runlevels ist es möglich auch nur eine Untermenge der Features für ein Projekt zu nutzen
Was ist Sunray2 nicht?     >nach oben<
  • Fertig (es fehlen leider noch wichtige Features wie: Partikelsysteme, umfangreichere Dokumentation, PostProcessing FXs, Culling)
  • Die Unreal3 Engine (konnte und sollte es mit der zur Verfügung stehenden Zeit, Programmieren und Kenntnissen auch nie werden)
  • OpenSource (macht ohne ausführliche Dokumentation und Zeit für Support wenig Sinn, zudem erschwert es die weitere Entwicklung, wenn man bei größeren Änderungen Rücksprachen halten müsste)
Wie weit ist Sunray2?     >nach oben<
  • Weit genug um damit auch größere Projekte zu realisieren (siehe: ABM, Archimedes)
  • Noch viel Raum für Geschwindigkeitsoptimierungen
  • Nicht weit genug, um selbständig, ohne viele Rücksprachen, damit arbeiten zu können (keine Doku, Beispiele…)
  • Das Ziel war viel zu lernen bei der Entwicklung und von daher bereits jetzt das Ziel erreicht.
Wer benutzt Sunray2?     >nach oben< Feature/Klassen Liste     >nach oben<
Feature/Klassen Liste      

Camera
Config
Console
Debugger
DebugTimer
EngineElement
GuiManager
Input
Material MemoryManager

Message System
MultiThreading classes
Plugin
Position
RenderPass
Resource Sound
Time
Virtual File System VideoTexture

AnimationManager
Bitfield
Bounding
ConSettings
CpuDetection
Entity
FastList
Findable
FpsManager
GUIConsole
Interpolation LightManager
LineObject
MainWindow
Model
ModelInst

MSXml
Renderer
RenderObject RenderPassCapture
RenderpassGUI
RenderPassObjects
RenderPassShadow
Shader
SimpleSprite
SimpleSpriteManager
Singleton
String
StringHash
TypeDef
UpdateReciever
Vector & matrix

Input
Das Ziel bei dieser Klasse war es, Spielaktionen unabhängig vom konkret vorliegenden Eingabegerät auf Tasten/Achsen/Regler legen zu können.
Die gesamte Belegung lässt sich leicht über XML Configfiles ändern, die automatisch mit Standard Werten angelegt werden, falls sie noch nicht existieren.


Bitfield
Eine Implementierung eines Bitfields, um sehr platzsparend Informationen zusammengefasst halten zu können (beispielweise Flags)

Bounding
Diese Klasse berechnet und halt alle Informationen, die sie für die unterschiedlichen Kollisionstests(Sphere,AABox,Box) braucht.

Config
Mit Hilfe dieser Klasse kann man sehr einfach Werte die im Programm per Configfile editierbar sein sollen, einrichten. Durch den Default-Wert funktioniert jedoch auch alles Ordnungsgemäß, wenn die XML-Files noch nicht existieren.

Console
Eine Klasse die sehr zur Produktivitätssteigerung beitragen kann. Bei der Ingame Konsole kann man im Code Funktionen und Variabel registrieren, die man dann zur Laufzeit des Programmes ausführen/verändern kann. So kann man beispielsweise sehr schnell verschiedene Werte für Einstellungen testen oder nützliche Informationen zur Laufzeit abrufbar machen.
Beispielsweise gibt es eine Konsolenfunktion, um die aktive Kamera festzulegen, dadurch kann man jederzeit in die freie Kamera wechseln oder Shadowmap-Kameras justieren.
Viele andere Klassen arbeiten mit der Konsole zusammen, so kann man Konsolenfunktionen auch direkt in der Input-Klasse auf bestimmte Tasten legen und so den Zugriff noch beschleunigen. Auch in der GUI-Klasse kann man auf die Bedienelemente Konsolenfunktionen legen, um sich somit viel C++ Code zu sparen.


CpuDetection
Überprüft, ob die aktuelle CPU Merkmale wie SSE unterstützt, damit dann gegebenenfalls Optimierungen an den entsprechenden Stellen vorgenommen werden können (falls erwünscht).

Debugger
Der Debugger ist äußerst flexible gestaltet. Man kann bei ihm jederzeit neue Methoden hinzufügen, mit denen geloggt werden soll. Beispielsweise gibt es Methoden zur Ausgabe in eine Datei, in das Visual Studio Output Fenster oder in das grafische Ingame GUI.
Welche Nachrichten geloggt werden sollen, kann man mit Hilfe einer Maske einschränken (beispielsweise auf nur kritische Fehler).
Der Debugger läuft in einem eigenen Thread, daher entstehen keine Framerateeinbrüche, selbst wenn die verwendeten Logmethoden viel Zeit brauchen.


DebugTimer
Der Debug Timer ist ein unersätzliches Werkzeug, wenn es darum geht, heraus zu finden, welche Enginekomponente, wieviel Zeit verschlingt und wo es sich am meisten lohnen würde noch zu optimieren.
Die Verwendung ist dabei denkbar einfach, einfach ein BeginTimer und ein EndTimer um den Bereich, den man messen will, und man erhält zur Laufzeit in übersichtlicher Form Informationen darüber, wie lange der Abschnitt durchschnittlich zur Ausführung benötigt, wie oft er ausgeführt wurde, Min+Max Werte, sowie eine Prozent Angabe, wie viel der Gesamtzeit des Frames für den Abschnitt benötigt wurde.


EngineElement
Die Engine hat 9 Runlevel, dadurch ist es beispielsweise möglich, nur einen Teil der Engine zu nutzen, ohne aufwändige Elemente wie Grafik überhaupt zu starten. Jede Komponente der Engine ist von EngineElement abgeleitet und weiß dadurch, in welchem Runlevel sie sich initalisieren und wann sie runterfahren muss.

Entity
So ziemlich alles, was ein konkretes Verhalten in der Spielwelt hat, ist im Gameplay Code von Entity abgeleitet. Über die Factory lassen sich einfach neue Instanzen über einen String (zum Beispiel eingelesen aus einer Leveldatei) erstellen.

FastList
Eine auf Performance optimierte Version eines dynamischen Arrays. Mit einigen nützlichen Funktionen, wie sortieren, einfügen und suchen. Für alle Arten von Klassen einsetzbar, da als Template implementiert. Für spezielle Anwendungen gibt es beispielsweise eine Variante bei der die Elemente stets an der selben Position bleiben (falls man beispielsweise die Indexe der Elemente in der Liste speichern muss). Eine weitere etwas langsamere Variante bietet durch die Verwendung von new/delete sichere Unterstützung von Klassen, die relevante Dinge im Konstruktor ausführen.

Findable
Von Findable abgeleitete Klassen lassen sich über ihren Namen suchen. Dadurch kann man es sich oftmals sparen, Zeiger auf nur selten verwendete Objekte zu speichern und man kann prüfen, ob bestimmte Objekte schon existieren.

GUIConsole
Mit der GUIConsole kann man sich auf schnelle und unkomplizierte Weise Variabelwerte zur Laufzeit ausgeben lassen, was sie zu einem mächtigen Debugwerkzeug macht. Sie bietet mehre Anzeigemodi, wobei die ersten 3 von der Engine selbst genutzt werden (für Konsolenausgaben, Soundinformationen und die Debugtimer).

Interpolation
Hilfsklasse die es auf einfache Weise ermöglicht auf unterschiedliche Weise zwischen Werten zu interpolieren. Wird zum Beispiel für Splines verwendet.

MainWindow
Erstellt das/die Engine Fenster. Sorgt auf Wunsch für Resizing oder Maximieren und informiert die Grafikklasse in solchen Fällen, damit sie auf die Informationen entsprechend reagieren kann.

MemManager
In den Memory Manager ist eine Menge Arbeit investiert worden, er vermindert Speicherfragmentierung und meldet Speicherkorruptionen, wie Memory Leaks oder Grenzüberschreitungen bei Arrays.
Für die Nutzung muss man nichts am Code ändern, er überlädt die Standard Speicherallokierungsfunktionen.


MessageSystem
Ein sehr nützliches System, um Klassen übergreifend zu kommunizieren, ohne dass die Klassen selbst sich gegenseitig kennen müssen.
Man kann Message Groups anlegen und jede Komponente die an Nachrichten aus dieser Gruppe interessiert ist, schreibt sich einfach ein und erhält dann ab sofort alle Nachrichten. Das können Beispielsweise Nachrichten über GUI-Events sein, WindowsMessages oder Spielzustandänderungen. An die Nachrichten können auch noch weitere Informationen gehängt werden.


MSXml
Ein Wrapper um MSXML, der das Arbeiten deutlich vereinfacht und beschleunigt. Die meisten Operationen werden dadurch zu Einzeilern.

Plugin
Eine wichtige Entscheidung beim Design der Engine war es, unabhängig von irgendeinem bestimmten Spiel zu sein. Daher wurde von Anfang an, eine strikte Trennung, zwischen Spiel und Engine eingehalten. Jede Anwendung die die Sunray2 Engine verwendet, ist von daher ein PlugIn, welches von der Engine gestartet und auch wieder beendet wird. Die PlugIns sind seperate dll-Files die sich im PlugIn Order der Engine befinden, und auch manuell deaktiviert werden können. Dadurch können häufig gebrauchte PlugIns (wie beispielsweise eine Freie Kamera) einfach zu anderen Projekten hinzugefügt werden, ohne auch nur eine Zeile Code ändern zu müssen.

Position
Eine sehr praktische Konstruktion, das einen viel Arbeit ersparen kann. Alle Engineelement die auf irgendeine Weise eine Position im Raum haben (seien es Sounds, Listener, Renderobjekte, Bones, Lichtquellen oder Kameras) sind von der Positionsklasse abgeleitet und können daher alle auf die gleiche Weise beeinflusst werden. Darüber hinaus können Positionselement aneinander gehängt werden, wodurch es sehr einfach ist, beispielsweise eine Kamera an ein 3D-Model zu hängen, zusätzlich vielleicht noch Soundquellen und eine Lichtquelle und diese dann gemeinsam zu bewegen.

Singleton
Eine einfache Implementierung eines Singleton, als Templateklasse. Zu beachten ist, dass man nicht nur GetInstance aufrufen sollte, sondern am Ende auch Release, damit ein geregeltes Löschen gewährleistet ist.

Sound
Für die Soundausgabe setzen wir auf DirectSound. Was auch für modernen Sourround Sound sorgt und einfach verwendet werden kann. Dabei haben wir eine Struktur gewählt, die es uns ermöglicht, schnell und unkompliziert neue Formate (wie beispielsweise Mp3 oder Ogg) nachzurüsten.

String
Bietet alle Funktionen, die man von einem Stringobjekt erwartet. Darüber hinaus noch einige nützliche Funktionen, die den Umgang mit Dateinamen erleichtern (Endungen finden, abschneiden, ersetzen…)

StringHash
Ein Klasse mit mehrfach überladenen Konstruktor, so dass man an Stellen wo ein Stringhash aus Performancegründen benötigt wird, auch eine Zeichenkette angeben kann und diese implizit gecastet wird. Die Hashes selber werden sehr schnell erzeugt und können dann auf Gleichheit geprüft werden.

MultiThreading classes
Um uns das schwierige Thema MultiThreading etwas zu erleichtern, haben wir einige Helferklassen geschrieben, die den Umgang mit den Standardelementen wie Critical Sections und Events unkomplizierter machen und/oder neue praktische Funktionen bieten.

Time & TimeSource
Auf den PerformanceTimer ist in Zeiten von DualCore Systemen die dynamisch ihre Taktung ändern, nicht mehr immer zuverlässig Verlass. Daher haben wir mit der TimeSource eine Klasse erstellt, die sich auf andere Quellen anpassen lässt. Die Time Klasse selbst speichert alle Zeitangaben als 64Bit Integer, wodurch die Ungenauigkeiten des float-Datenformat umgangen wurden.

TypeDef
Definiert einige häufiger verwendete Datentypen, wie zum Beispiel “unsigned char” kürzer in der Form “uint8”.

UpdateReciever
Ein Interface welches eine virtuelle Update-Methode besitzt. Abgeleitete Klassen können diese nun implementieren und die Engine ruft diese jedes Frame auf.

Vector & matrix
Sehr schnelle Implemtierungen dieser für 3D-Anwendungen sehr wichtigen Klassen. Verwenden (falls auf dem System verfügbar) SSE1-SSE3 an den Stellen, an denen es sich anbietet. Alle wichtigen Operatoren wurden überladen.

Virtual File System
Das virtuelle Dateisystem ermöglicht einen komfortablen und schnellen Zugriff auf alle Datein die sich im Data der Engine befinden, selbst wenn diese sich in Unterordnern oder in Zip-Archiven befinden.

AnimationManager
Für die Animationen verwendet die Engine das Animations System von D3DX. Der Animationsmanager nimmt dem Gameplaycode jedoch einige Arbeit ab, indem er sich um das Updaten der Animation jeden Frame kümmert.

Camera
Unsere Kamera bietet einige coolen Funktionen. Zum einen sind ihre Position und ihr Look-At Objekte der Positionklasse und können daher direkt an andere Positionselemente gehangen werden, wodurch sich Verfolgerkameras mit zwei Zeilen Code erstellen lassen. Zum anderen bieten sie direkte Unterstützung für MultiMonitoring und SplitScreen. Dadurch ist es ohne weiteres möglich, Grafikausgaben auf mehre Monitore zu verteilen oder Splitscreenspiele mit mehren Kameraansichten auf einem Monitor zu erstellen.

FpsManager
Mit ihm lässt sich bei Bedarf die Framerate künstlich verändern. Dadurch kann man beispielsweise Code unter unterschiedlichen Bedingungen testen, um das Verhalten auf langsameren Systemen zu prüfen.

LightManager
Erstellt und verwaltet die unterschiedlichen Arten von Lichtquellen (Spot, Point, Directional).

LineObject
Eine Klasse die Linien im 3D-Raum darstellt. Erstrangig für die Darstellung von Splines gedacht.

Material & MaterialGroup
Die Materialklasse beschreibt entsprechend ihres Namens die Eigenschaften einer Oberfläche. Im konkreten Fall könnte dies zum Beispiel ein Shader mit all seinen Parametereinstellungen sein. Dadurch kann man diese Einstellungen praktisch zur Laufzeit verändern, unabhängig davon, ob es sich um FixedFunction oder ein Shadermaterial handelt oder um ein gänzlich anderes.

Model
Die Modelklasse lädt mit nur einer Zeile Code ein Model aus einer X-File. Dabei kann man automatisch LOD-Level generieren lassen. Auch werden automatisch Bounding Informationen erstellt.

ModelInst
Mit dieser Klasse arbeitet man, wenn man Instancing benutzen will. Die Model Instanzen halten dann die Instanz spezifischen Informationen (Positionen…) und eine Überklasse sorgt dafür, dass alle Instanzen richtig gerendet werden.

Renderer
Zur Zeit etwas im Umbau. Hält Listen von allen grafischen Objekte in der Szene und sortiert sie nach bestimmt Kriterien (verwendeter Shader, Alpha, Z-Wert), um richtige Resultate und gute Performance zu garantieren.

RenderObject
Alle grafischen Objekte sind von dieser Klasse abgeleitet. Der Renderer arbeitet mit diesen Interfacen und ruft die Before/On/After Render Methoden auf. Über Flags lässt sich beeinflussen, welche Objekte in welchen Pässen gerendert werden sollen.

RenderPass
Es gibt einige Standard-Renderpässe, die die Engine von sich auch zur verfügung stellt. Zum Beispiel ein Renderpass für das Gui, die Schatten, Beleuchtung, aber auch ein Renderpass, der die Ausgabe in eine Datei umleitet, um Spielszenen aufzuzeichnen.
Zusätzliche Renderpässe können leicht vom Gameplaycode erstellt werden und dadurch zusätzliche Effekte realisiert werden.


RenderPassCapture
Dieser spezielle Renderpass generiert kein Frame für die Ausgabe auf den Bildschirm, sondern speichert jedes Frame als Datei ab. Dadurch lassen sich Spielszenen "aufzeichnen".

RenderpassGUI
Dieser Renderpass rendert alle GUI Elemente. So wie zusätzlich die Debug Textausgabe. (siehe GUIConsole)

RenderPassObjects
Der eigentliche Hauptrenderpass, hier werden alle Objekte mit Beleuchtung gerendert.

RenderPassShadow
Erstellt Eine Shadowmap und zeichnet diese dann, um realistische Echtzeitschatten zu erzeugen.

Shader
Kapselt die Funktionalität der D3DXEffect Klasse und fügt einige praktische Funktionen hinzu.

SimpleSprite
Eine nützliche, kleine Klasse um sehr schnell und einfach 2D Elemente auf den Bildschirm zu bringen. Diese werden dann von einem Manager gebündelt gerendert.

VideoTexture
Sunray2 bietet auch Unterstützung zum stream von Videos. Dabei setzen wir auf DirectShow und unterstützen dadurch eine Vielzahl an Formaten. Die Videos werden dabei in Videoformat-Texturen gerendert, welche dann wie normale Texturen verwendet werden können. Dadurch wird es auf einfache Weise möglich, diese für 3d-Modelle in der Spielwelt zu verwenden.

GuiManager
Unser GUI baut auf dem DXUT Gui auf und bietet daher fast alle bekannten Windows-Steuerrelemte, wie Schieberegler, Listen und Editfelder. Die Dialoge selber kann man bequem in XML Files erstellen und diese dann mit einer Zeile Code automatisch erstellen lassen.
Das Gui informiert über alle relevanten Ereignisse über die engineinternen Nachrichtengruppen, wodurch auch Klassenübergreifend auf GUI-Ereignisse reagiert werden könnte. Zudem lassen sich bereits in der XML-Datei Konsolenfunktionen (siehe Abschnitte über die Konsole) auf Schaltflächen legen und sich somit Aktionen ganz ohne C++ Code definieren.


Resource
Unsere Ressourcenklasse sorgt dafür, dass alle Objekte, die geladen werden müssen, nicht mehrfach im Speicher existieren, solange dies nicht notwendig ist. Mögliche Ressourcen sind zum Beispiel 3D-Modele, Texturen, Shader oder Sounddateien. Über die Konsole kann man sich zur Laufzeit jederzeit anzeigen lassen, welche Ressourcen zur Zeit, wie oft verwendet werden. Auch beim beenden nicht freigegebene Resourcen werden direkt angemahnt.