[Projekt] Prozedurales Universum

Hier könnt ihr euch selbst, eure Homepage, euren Entwicklerstammtisch, Termine oder eure Projekte vorstellen.
Forumsregeln
Bitte Präfixe benutzen. Das Präfix "[Projekt]" bewirkt die Aufnahme von Bildern aus den Beiträgen des Themenerstellers in den Showroom. Alle Bilder aus dem Thema Showroom erscheinen ebenfalls im Showroom auf der Frontpage. Es werden nur Bilder berücksichtigt, die entweder mit dem attachement- oder dem img-BBCode im Beitrag angezeigt werden.

Die Bildersammelfunktion muss manuell ausgeführt werden, die URL dazu und weitere Details zum Showroom sind hier zu finden.

This forum is primarily intended for German-language video game developers. Please don't post promotional information targeted at end users.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

[Projekt] Prozedurales Universum

Beitrag von sushbone »

Hi,
auf Anregung eines netten Users auf Golem.de (viele Grüße :) ) wollte ich mich hier anmelden und nach dem Stöbern aus eigenem Interesse an der Materie auch mein kleines (Hobby-)Projekt vorstellen.

Es handelt sich um die Erzeugung eines weitestgehend prozeduralem Universum, in welchem der betrachter erstmal ohne Spielgerüst drumherum sich frei bewegen können soll. Ggf. würde ich gerne später Netzcode drum herum schreiben sodaß eine gewisse Interaktion über Netz mit zwei oder mehreren Teilnehmern möglich ist, aber das käme erst später, da ich mit dieser Materie überhaupt noch nicht vertraut bin. Im Moment geht es mir erstmal darum selbst hinzuzulernen, da ich mich mit der Materie Programmierung in 3D noch nicht allzulange beschäftige. In erster Linie gehts also darum Spaß zu haben, was zu lernen, und das Gehirn fitt zu halten. ;-)

Projekt: Prozedurales Universum
Ziel: Rendern eines (verkleinerten) Universums, in welcher der Betrachter alle Objekte ansteuern kann die er sieht (d.h. weitestgehend verzicht auf Skyboxen o.ä.).
- Das Universum soll eine gewisse Anzahl an Planeten/Objekten beinhalten, weit entfernt von der echten Anzahl von Objekten im Universum, aber soviel um einigermaßen glaubhaft zu sein.
- Die Planeten sollen bereisbar sein. Detailgenauigkeit der Oberfläche mindestens ein Triangle pro Kilometer, gerne würde ich irgendwo in den Meterbereich kommen.
- Nebel, die keine bloße Textur sind sondern eine gewisse "Voluminität" darstellen.
- Weitere Objekte: Gasplaneten, Sonnen, Schwarze Löcher
- Prozedurale Elemente (bis jetzt geplant): Planetennamen, Planetenpositionen, Planetenoberfläche (Perlin Noise + Heightmap), Nebelstuktur

Zum Stand, ich hatte begonnen das Programm in Axiom3D und C# zu schreiben, und bis zu dem Punkt gearbeitet in welchem ich auf Basis einer XML Struktur (in welcher ich die prozedural ermittelte Planetenkonfiguration ablege) ein solares System mit ca. 50.000 Objekten generiert habe, die Sonnen mittels Particle-Effekt in Ogre und die Planetenoberfläche mittels PerlinNoise + Heightmap Kombination generiert habe. Sowie ein eigenes LOD ich die sichtbaren Objekte in einem separaten Thread kontinuierlich parse und weit entfernte Objekte als Point Sprite gezeichnet wurden, in einem Zwischenbereich zur Kameraposition Meshes generiert wurden mit unterschiedlichem Detailgrad, und ab Orbitdistanz der Planet einer Liste "Aktiver Planeten" hinzugefügt wurde, wo die Planeten bevorzugt berechnet werden und ich auf HorizonCulling umstelle.
Generell waren die Planeten als Cubespheres umgesetzt, mit einer dynamischen Anzahl einzelner Chunks (im Falle von Ogre als ManualObject), in meinem Falle habe ich meist 600 Chunks pro Planet verwendet um pro Element die Anzahl Vertices/Triangles zu verändern.

Bild

Zu meinem Vorgehen an dieser Stelle, ein Planet besteht also aus einer Liste von "ManualObjectContainern", wo neben dem ManualObject auch in einem Array die Vertices und TriangleIndices vorgehalten werden, auf welchen ich ständig arbeite. Allerdings kam ich an dem Punkt noch nicht weiter wo ich die Vertices ausreichend Dicht generieren konnte um die gewünschte Detailgenauigkeit zu erzeugen. Bei 600 ManualObjects kam ich auf eine maximale Dichte von 250x250 Vertices. Bei Erhöhung der Anzahl Vertices oder Anzahl ManualObjects war dann schnell schluss.

Bilder (aus der Axiom3D/C# Variante)
Bild

Bild

Bild

Bild

Das LOD/Horizon Culling eines Planeten:
Bild

Video (mit Blick auf die Triangles):
http://youtu.be/BttXQpXNNGc

Durch die Schwierigkeiten kan diesem Punkt kam der Entschluss die Engine auf Ogre3D und C++ zu portieren, da die Community um das native Ogre3D (Axiom3D ist ja ein C# Wrapper von Ogre) und generell zu C++ größer ist.
Auch gab es bei bestimmten Features (Point Sprites, um sehr weit entfernte Objekte als Point Sprite anstatt Mesh darzustellen) nicht den vollen Support beim Wrapper.

D.h. im Moment arbeite ich daran die Portierung vorzunehmen. Mit einem Punkt, der Erzeugung von Nebeln, habe ich mich während der Portierung noch beschäftigt. Ich werde voraussichtlich darauf setzen Point Sprites zu verwenden, additives blending, und die Generierung mittels Strange Attractor vorzunehmen. D.h. ich hätte eine prozedurale Generierung, der User könnte diese Nebel bereisen und sie würden quasi-volumetrisch wirken, und die Nebel blenden bei ausreichender Nähe langsam aus (im Universum haben Nebel ja eine nur sehr geringe Dichte, und der reisende würde diese nur ab einer gewissen Distanz wahrnehmen.
Ich habe dies sehr dirty und schnell getest, und werde wohl in dieser Richtung weiter machen. Allerdings muss ich mich noch mit den Algorithmen hinter Strange Attractor auseinandersetzen (ggf. in Kombination mit Perlin Noise), um glaubhaftere strukturen zu generieren, die weniger Matematisch aussehen.

Bild

Video (sorry für die schlechte Qualität, es muss schnell gehen daher hat spontan das iPhone hergehalten :) ):
http://youtu.be/v6yHGjd5zHE

Status (auf Basis Ogre3D/C++):
Portierung zu Ogre/C++ (1%)
* Generierung Prozedural eines Galaxy (80% / bleibt auf C#)
- Prozedurale Namensgenerierung (100%)
- Umstellung auf Verteilung der Obekte zu Spiralstrukturen (0%)
- Erhöhung der Anzahl auf ca. 100.000 (0%)
* Einlesen XML-Konfiguration einer Galaxie (0%)
* Umstellung der Universum-"Strategie" sodaß es nicht aus einer Galaxy besteht sondern mehreren (um den Reisebereich zu vergrößern) (0%)
* Separater Updatethreads
- für LOD Aktualisierung Universum-Objekte (0%)
- für Planetenoberfläche (0%)
* Erzeugung Planet (0%)
- mit verbesserter Strategie für Oberfläche (Horizon-Culling, ggf. Frustum Culling, verbessertes Chunking. http://acko.net/blog/making-worlds-1-of ... and-cubes/ )
- Erneutes Chunking einzelnes Chunks anstatt nur Split/Merge von Triangles (bzw. Erhöhung/Verringerung von Vertices pro Chunk)
- dynamische Texturierung
* Erzeugung Sonne (10%)
* Erzeugung Gasplanet (0%)
* Erzeugung Schwarzes Loch (0%)
* Erzeugung Nebel (1%)
- Tuning Algorithmen
- Speicherung/laden von Position und Seeds der Nebel in einer separaten XML Konfiguration

Die Portierung wird mich jetzt erstmal ein Weilchen beschäftigen... ;-)
Zuletzt geändert von sushbone am 17.02.2014, 15:41, insgesamt 1-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Du hast Dir da ein gewaltiges Ziel vorgenommen, aber Du bist anscheinend auf gutem Weg! Gefällt mir. Wie hast Du die Genauigkeitsprobleme gelöst? Für so große Strukturen, bei denen man gleichzeitig auch auf den Meter genau sein will, tun es normale floats ja nicht mehr.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Stephan Theisgen
Beiträge: 94
Registriert: 29.07.2003, 11:13

Re: [Projekt] Prozedurales Universum

Beitrag von Stephan Theisgen »

Hallo und herzlich Willkommen, falls ich das so als Nicht-Mod sagen darf!

Das Projekt gefällt mir und ich habe auch selbst großes Interesse mich mit dieser Materie näher auseinander zu setzen. Deswegen würde ich mich sehr freuen, wenn Du hier regelmäßig Updates postest und auch für Fragen zur Verfügung ständest. Das wäre super!

Viele Grüße
Stephan
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Krishty »

Schrompf hat geschrieben:Du hast Dir da ein gewaltiges Ziel vorgenommen, aber Du bist anscheinend auf gutem Weg! Gefällt mir. Wie hast Du die Genauigkeitsprobleme gelöst? Für so große Strukturen, bei denen man gleichzeitig auch auf den Meter genau sein will, tun es normale floats ja nicht mehr.
Dem schließe ich mich an.

Falls du deine Sterne verschönern willst: Wir haben hier mal darüber diskutiert, wie man aus physikalischen Sternbeschreibungen auf hübsche Bildschirmwerte kommt. Normalerweise hausiere ich bei solchen Projektvorstellungen auch gern für das hier; ich weiß aber nicht, wie sich das in Ogre realisieren lässt.

Abgesehen davon: Weiter so!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
joggel

Re: [Projekt] Prozedurales Universum

Beitrag von joggel »

Ja, Willkommen!

Ich finde das ein sehr interessantes Projekt, und wäre auch an Infos über den Fortschritt interessiert...

Eine Frage habe ich mal.
Bei 600 ManualObjects kam ich auf eine maximale Dichte von 250x250 Vertices. Bei Erhöhung der Anzahl Vertices oder Anzahl ManualObjects war dann schnell schluss.
Was meinst du damit, und meinst du mit "schluss" die Framerate sank zu tief?
Ich weis nicht, was mit "ManualObjects" gemeint ist... oder besser gesagt, die XML-Struktur ist mir noch nicht ganz klar...

Gruß
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Danke für die freundlichen Worte, man fühlt sich wohl hier :-)

Ist wie gesagt ein Hobbyprojekt mit dem ich vor kurzem begonnen habe und was mich wohl noch eine zeitlang beschäftigen wird. Daher mache ich mir auch nix vor, da stecken einige Problemstellungen drin die auch Personen vor Schwierigkeiten stellt die sich schon lange mit der Materie beschäftigen - einiges werde ich sicher dirty, manches okay, und einiges nie lösen ;-) mal sehen wo es mich hinführt...
Schrompf hat geschrieben:Du hast Dir da ein gewaltiges Ziel vorgenommen, aber Du bist anscheinend auf gutem Weg! Gefällt mir. Wie hast Du die Genauigkeitsprobleme gelöst? Für so große Strukturen, bei denen man gleichzeitig auch auf den Meter genau sein will, tun es normale floats ja nicht mehr.
Eines der Probleme welches ich noch vor mir habe und welches nach erstem ganz groben einlesen tricky wird. Meine Strategie ist zunächst einmal ein einzelnes Objekt (Planet) sauber zu rendern bei dem Genauigkeitsgrad der für eine Oberfläche glaubhaft ist, um dann das ganze auf große Strukturen auszuweiten. Herausfordernd genug ist für mich erstmal die Quadtree Strategie eines Planeten sauber umzusetzen ohne dass mir der Speicher um die Ohren fliegt ;-). Um meine Cubesphere zu erzeugen bewege ich mich ohnehin erstmal immer im Wertebereich von -1 bis +1 eines floats um die Normalisierung des Cube auf eine Sphere im Anschluss vornehmen zu können (+ Perlin Noise etc). Danach muss ich gucken wie ich mit dem Radius umgehe und auf welcher Scala ich mich tatsächlich bewegen muss. Ich arbeite mich durch die Development Journals von Ysaneya (Infinity) dessen Engine ein großes Vorbild für mich ist (wo ich never ever rankomme) und der mal einen Artikel über das Problem geschrieben hatte. Er hatte das mal auf gamedev.net gepostet, wars schon ziemlich alt, ich hoffe ich finde es noch. Generell beruhigt es mich wenn man in seinen Artikel von 2005 liest dass er auch Issues mit vollaufenden Speichern bei den ersten Versuchen und allem hatte. :-) Aber auch dass er bei seinen Neben zuletzt auch auf Pixel Sprites und Strange Attractors zurückgegriffen hatte. Und er hat seine Engine ja auch mehrmals in Teilen verworfen. Also vielleicht wirds bei mir nach mehreren Iterationen auch was ;-)

Wie gesagt, die Problematik genauer naher Strukturen bei gleichzeitig großen Weiten gehe ich nach einem ersten zufriedenstellenden Planeten richtig an. Ich hatte erst befürchtet ich wäre schon an eine Grenze gestoßen als ich bei Erhöhung der Vertices im Wertebereich -1 bis +1 auf Probleme traf, die schiebe ich mittlerweile aber (auch) auf Probleme im Zusammenspiel mit Axiom sowie dem ersten (naiven) Ansatz meines Planeten-LOD, ich bin gespannt ob es bei C++ und Ogre und dem zweiten Versuch mittels Quadtree besser klappt.
Stephan Theisgen hat geschrieben:Hallo und herzlich Willkommen, falls ich das so als Nicht-Mod sagen darf!
Das Projekt gefällt mir und ich habe auch selbst großes Interesse mich mit dieser Materie näher auseinander zu setzen. Deswegen würde ich mich sehr freuen, wenn Du hier regelmäßig Updates postest und auch für Fragen zur Verfügung ständest. Das wäre super!
Viele Grüße
Stephan
Gerne. Im Moment arbeite ich erstmal daran wieder auf den groben Status Quo zu kommen den ich in C#/Axiom3D hatte, da ist erstmal genug zu tun. Wobei ich denke ich ein paar Dinge verwerfen und nochmal anders machen werde. Werde das ganze hier gerne posten, natürlich auch in der Hoffnung auf Tips.
Krishty hat geschrieben:
Schrompf hat geschrieben:Du hast Dir da ein gewaltiges Ziel vorgenommen, aber Du bist anscheinend auf gutem Weg! Gefällt mir. Wie hast Du die Genauigkeitsprobleme gelöst? Für so große Strukturen, bei denen man gleichzeitig auch auf den Meter genau sein will, tun es normale floats ja nicht mehr.
Dem schließe ich mich an.
Falls du deine Sterne verschönern willst: Wir haben hier mal darüber diskutiert, wie man aus physikalischen Sternbeschreibungen auf hübsche Bildschirmwerte kommt. Normalerweise hausiere ich bei solchen Projektvorstellungen auch gern für das hier; ich weiß aber nicht, wie sich das in Ogre realisieren lässt.
Abgesehen davon: Weiter so!
THX für den Tip hab mir das schonmal im durchgelesen aber muss ich mir nochmal genauer anschauen (auch was damit auf Ogre transportierbar wäre), denn das Ergebnis sah in der Tat fantastisch aus (man neigt ja bei solchen Universum-Geschichten ja leider schnell dazu das mit zu viel Farben ins quitschbunt-kitschige und unrealistische abgleiten zu lassen). Denke am Ende wirds bei mir ggf. ein Mittelding zwischen glaubhaft und bunt ;-)
joggel hat geschrieben:Ja, Willkommen!
Ich finde das ein sehr interessantes Projekt, und wäre auch an Infos über den Fortschritt interessiert...
Eine Frage habe ich mal.
Bei 600 ManualObjects kam ich auf eine maximale Dichte von 250x250 Vertices. Bei Erhöhung der Anzahl Vertices oder Anzahl ManualObjects war dann schnell schluss.
Was meinst du damit, und meinst du mit "schluss" die Framerate sank zu tief?
Ich weis nicht, was mit "ManualObjects" gemeint ist... oder besser gesagt, die XML-Struktur ist mir noch nicht ganz klar...
Gruß
Zur XML Struktur zunächst.. das ist wenn man so will eine Konfigurationsdatei die ich vorher erzeuge und die dann bei Start der Planeten eingelesen wird. Ich wollte die Planeten bewusst nicht bei jedem Start völlig chaotisch / per Random verteilen, um zum einen bestimmte "Umstände" vorgehen zu können (um zum Beispiel einen Planeten zu einem bestimmten Abstand zu einer Sonne zu setzen), zum anderen, sollte ich irgendwann mal irgendwas machen wo mehrere Spieler über eine Serverkomponente interagieren, dass dann alle die gleichen "Voraussetzungen" haben was die Strukturen betrifft.
Diese Datei sieht (im Moment) im Auszug so aus:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<PlanetConfigurationList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <PlanetConfiguration>
      <GUID>3ae27657-a346-40f6-a737-1043302da17d</GUID>
      <Name>Labrad Scheehy -8596</Name>
      <Abbreviation>La-8596</Abbreviation>
      <Type>21</Type>
      <Radius>6877</Radius>
      <X>0</X>
      <Y>0</Y>
      <Z>0</Z>
      <Active>false</Active>
    </PlanetConfiguration>
    <PlanetConfiguration>
      <GUID>3ae27657-a346-40f6-a737-1043302da17d</GUID>
      <Name>Labrad Scheehy -8596</Name>
      <Abbreviation>La-8596</Abbreviation>
      <Type>11</Type>
      <Radius>200000</Radius>
      <X>1000</X>
      <Y>0</Y>
      <Z>0</Z>
      <Active>false</Active>
    </PlanetConfiguration>
    <PlanetConfiguration>
      <GUID>184c11d6-0789-47e1-8dfa-0ad57887675a</GUID>
      <Name>Ibbs 5423</Name>
      <Abbreviation>Ib5423</Abbreviation>
      <Type>27</Type>
      <Radius>8529</Radius>
      <X>-18064</X>
      <Y>4169</Y>
      <Z>-658</Z>
      <Active>false</Active>
    </PlanetConfiguration>
[....]
Im Moment lese ich ca. 50.000 <PlanetConfiguration> Tags ein. Die Namen sind mittels Markov-Namesgenerierung erzeugt, die Positionen noch per Random, später im Idealfall einer per Algorithmus sodaß ich z.B. eine Spiralpositionierung erreiche. Type gibt den Typ an (Planet (vordefiniert), Planet (prozedural), Sonne, Gasplanet, Schwarzes Loch, etc. Warschl. teile ich die Objekttypen zukünftig in unterschiedliche Listen auf, da je nach Typ unterschiedliche Zusatzeigenschaften zum Tragen kommen. Und wie Schrompf wichtig erwähnt, wegen des float Problems werde ich sicherlich an die Positionsdefinitionen nochmal ran müssen.

Jetzt zur Struktur der Planeten wie es aktuell umgesetzt ist.
Sobald ich einen Planeten (aus dem XML nach C#) eingelesen habe besitzt er neben den Informationen aus dem XML noch einige Zusatzinformationen.

Code: Alles auswählen

    class Planet : SpaceObject
    {
[...]
        string GUID{ get; set; }
        string Name{ get; set; }
        string Abbreviation { get; set; }
        string Radius { get; set; }
        PlanetType PlanetType { get; set; }
        Vector3 Vector3 { get; set; }
        boolean isRendered = false;
        int isLOD = 1000;
        ManualObjectContainer[] ManualObjectContainers;
        SceneNode node;
[...]
SceneNode ist der Node aus Axiom bzw. Ogre, isRendered bezeichnet ob der Planet schon bestandteil der Szene ist (brauche ich um Planeten sukzessive nachzuladen oder zu entfernen wenn sie eine gewisse Distanz erreicht haben), isLOD ist eine Info die ich für mein LOD brauche, und das wichtigste ist der ManualObjectContainer bzw. ein Array davon.
Ein ManualObject aus Ogre unterstützt mich bei der Arbeit mit Vertices und Indices zur Erzeugung eines indivuellen Meshs: http://www.ogre3d.org/tikiwiki/ManualObject
In einem ManualObjectContainer speichere ich neben dem ManualObject (also quasi dem Mesh) noch einige weitere Informationen, vor allem diese:

Code: Alles auswählen

    class ManualObjectContainer
    {
[...]
        VertexDefinition[] VertexDefinitionArray;
        List<int> VertexDefinitionArrayFreeSlots = new List<int> { };
        List<TriangleIndicesDefinition> TriangleIndicesList = new List<TriangleIndicesDefinition>();
        ManualObject ManualObject;
        int isLOD = 1000;
[...]
Auch hier taucht isLOD wieder auf, da ich für späteres HorizonCulling die einzelnen Meshes die die gesamte Planetenoberfläche bzw. die einzelnen Abschnitte davon (ich bin bis jetzt wie erwähnt bei 600 Stück angelangt) darstellen, unterschiedlich detailiert rendern muss.
ManualObject ist das Mesh aus Ogre. Die wichtigsten Elemente sind aber VertexDefinition (ein Array mit den Vertices), VertexDefinitionArrayFreeSlots (eine Liste welche die freien Slots in dem VertexDefinition Array speichert wenn ich Vertices hinzufüge oder entferne), und eben die TriangleIndices. Auf diesen Informationen arbeite ich kontinuierlich in einem separaten Thread, wenn ich die Planeten verändere und sobald fertig wird ein neues ManualObject, also das Mesh erzeugt.

Der vollständigkeit halber:
VerticeDefinition

Code: Alles auswählen

    class VertexDefinition
    {
[...]
        Vector3 positionVector3;
        Vector3 normalVector3;
        float TextureCoordX;
        float TextureCoordY;
[...]
TriangleIndicesDefinition

Code: Alles auswählen

class TriangleIndicesDefinition
    {
[...]
        public int v1;
        public int v2;
        public int v3;
[...]
joggel hat geschrieben:
Bei 600 ManualObjects kam ich auf eine maximale Dichte von 250x250 Vertices. Bei Erhöhung der Anzahl Vertices oder Anzahl ManualObjects war dann schnell schluss.
Was meinst du damit, und meinst du mit "schluss" die Framerate sank zu tief?
Diesen Teil der Engine werde ich neu machen müssen. Ich gehe davon aus dass bei einer Dichte von 250x250 Vertices pro "ManualObjectContainer" (also einem Planeten-Teilabschnitts-Segment) erstmal schluss ist, dann speichere ich rund 62000 Vertice-Informationen pro ManualObject in meinem Array, mehr wollte ich dort nicht reinpacken. D.h. die "Dichte" einer Planetenoberfläche muss ich durch immer wieder neue Generierung von neuen unter-ManualObject-Segmenten (also das Quadtree Ding, wo ich für ein Segment vier neue Segmente erzeuge) erhalten. In der aktuellen Version habe ich einfach naiv generell und immer 600 ManualObjects/Segmente (ich kann diese zwar pro Planet bei Generierung vorgeben für jedes LOD wenn er sich im Weltraum befindet, aber sobald ich auf das HorizonCulling umstelle arbeitet mein Culling nur noch auf den Segementen die er vorfindet. D.h. ich teile diese also nicht auf oder führe sie zusammen. Das ist zum einen unnötig (ich brauche auf der Rückseite hinter dem horizont keine hunderte Segmente), zum anderen kostet das natürlich Speicher. Ich habe einfach Stur die Anzahl der Vertices erhöht oder verringern, das funktioniert bis zu einer gewissen Genauigkeit, aber ist richtigerweise noch weeeeiiit von dem Entfernt wo ich hinwill. Ich kratze so ja nichtmal annähernd an der Kilometermarke (der Äquator hat so ca. 250x10x4 Vertices). Und bei Erhöhung der ManualObjects hat die Anwendung dann aufgegeben (die Axiom Bibliotheken haben Fehler geworfen, und ich hatte keinen Nerv mehr mich damit zu beschäftigen da zu dem Zeitpunkt der Entschluss auf C++ und Ogre schon gefallen war).

Aber d.h. Quadtree richtig zu implementieren muss zunächst mal meine erste Task sein die ich erledigen muss. D.h. nicht stur auf 600 ManualObjectContainern zu arbeiten. ich hoffe aber schon dennoch im Notfall höher kommen zu können unter C++ und Ogre. Ein User mit dem ich mich im Ogre-Forum viel austausche da er ein vergleichbares fortgeschrittenes Planetenprojekt macht (auch mit gleicher Strategie, d.h. Speichern der Vertices/Indices im Array und Updates mit separatem Thread) aber weiter ist kommt auf 1000+ Segmente pro Oberfläche, das sollte also gehen.

VG
Benutzeravatar
Top-OR
Establishment
Beiträge: 330
Registriert: 02.03.2011, 16:32
Echter Name: Jens H.
Wohnort: Esslingen/Dessau
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Top-OR »

Hahaaaa, da ist ja das prozedurale Universum: Freut mich, dich hier zu sehen!

Ja, die sache mit der "skalierbaren und detaillierten Oberfläche" ist schon sone Sache.

Wie du's auch drehst: Speicherbedarf, Bus-IO und/oder CPU-Leistung limitieren stark; irgendwie musst du die Datenmenge (in Echtzeit) reduzieren.
Ich persönlich habe für meine Engine mit Terrain-Height-Mapping/Geo-Mipmapping experimentiert.

Allein, wenn ich ne 2048x2048 per Tree (was auch immer für deine Zwecke geeignet sei, bei mir isses ein Octree) Aufblase, puste ich bei ungünstigen Baum-Parametern RAM-Speicher im GB-Bereich weg ... für eine effektive Kartengröße von ca. 6km*6km bei einer Genauigkeit von um nen Meter; vielleicht auch nen halben Meter (alles übern Daumen überschlagen). Alle Vertices mal eben pro Frame zur Kraka zu schaufeln wäre schon bei ner Heightmap 2048x2048 und daraus resultierenden 8388608 Dreiecken overkill!

Ich freue mich, drüber zu lesen, wie dein Ansatz/Implementierung das Problem "überlistet". Viel Spass bei der Portierung nach C++. :-D

Beste Grüße, Top-OR

PS: Hab mir gerade nochmal die Videos deiner Engine auf Youtube angesehen: Geile Nummer: Sieht vielversprechend aus!
--
Verallgemeinerungen sind IMMER falsch.
joggel

Re: [Projekt] Prozedurales Universum

Beitrag von joggel »

Sagt mal, ne Blöde Vermutung:

Kann man nicht ne Octree-Struktur in ner Datei halten, und die dann einfach nur bei bedarf aus der Datei streamen?
Also, sich aus der Datei nur die relevanten Notes holen?
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Krishty »

Dieses Paper besagt, dass ein Octree bei Meterauflösung und 128 km Seitenlänge bereits 256 Terabytes Speicherplatz benötigen würde. Selbst, falls deine Festplatte so eine Datei halten könnte, würde es Tage dauern, bis sie geschrieben wäre. Die Datenmengen sind also leider viel zu groß :(
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
joggel

Re: [Projekt] Prozedurales Universum

Beitrag von joggel »

Mh... na okay!!
Kenne mich wie gesagt, nicht mit Octrees/SVO's aus.
Aber irgendwo müssen doch die Vertices für ein nicht-prozedurales Gelände (also, was vorher erstellt wurden ist) gespeichert sein?
Kann man da nicht irgendwas über eine Index-Datei machen?
Oder werden die Sub-Notes on-the-fly generiert?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Es wird einfach kein nicht-prozedurales Gelände dieser Größe geben. Infinity und Konsorten generieren die Daten jedenfalls nach Bedarf prozedural, und betten nur gezielt Gebiete mit vordefiniertem Inhalt ein. Selbst Battlefield3 kriegt seine Karten schon nicht mehr komplett in den Speicher, sondern benutzt eine prozedurale Texturierung auf einer groben HeightMap und eine Lookup-Textur, in der dann unikate Gebiete eingeblendet werden. Und da reden wir grade mal von ein paar Dutzend Quadratkilometern mit FPS-Auflösung, nicht von einem ganzen Planeten.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Lange nichts passiert hier aber jetzt ein kleines Update.
Wie eingangs erwähnt plante ich ja den Umstieg auf C++ und Ogre weg von C# und Axiom3D.

Ich habe noch eine Weile mit C++ und Ogre gearbeitet und weiter an der Erzeugung prozeduraler Nebel mittels Particles und Strange Attractors experimentiert, dann wurde es aber zäh.
Bis ich auf Golem ein Video von Eve VR mit der Oculus Rift Brille entdeckte und dachte "geil, das Setting ergänzt um prozedurale Komponenten".

[youtube]J4T7KtX_FBQ[/youtube]

Daher hab ich jetzt eine Änderung in meiner Planung vorgenommen.
Weg von C++ und Ogre und hin zu Unity (der scharmante Vorteil ist dass ich einen höheren Wiederverwendungsfaktor meiner aktuellen C# Implementierungen habe).
Und ein neues Ziel:
Setting ähnlich wie bei Eve VR, d.h es soll eher ein Spiel werden mit Space-Fightern so wie dort mit Sicht aus einem Cockpit
Unterstützung der Oculus Rift (bedeutet leider Unity Pro), das DEV Kit will ich mir demnächst holen.
Ein Mix aus prozedural und vorgefergtigen Elementen.
Asteroiden und Cockpits und einiges weitere besteht aus fertigen Meshes.
Verteilung der Elemente wie Asteroiden oder Nebel-Effekte dann aber per Algorithmus (um z.B. zufällige Asteroidenfelder zu erzeugen, per Random und gleichverteilt ists langweilig habe ich bereits festgestellt. Ggf. mithilfe von Perlin Noise).
Ebenso will ich das Setting in der nähe eines oder zwei prozedural erzeugten Planeten stattfinden lassen, zu denen man hinunterfliegen können soll. Da kommt mir meine aktuelle Implementierung zugute, die aber noch stark aufgemotzt werden muss.

Im Moment finde ich mich erstmal in Unity 3D ein und experimentiere etwas, ebenso arbeite ich mich in Blender ein.
Aktuell habe ich erstmal eine Szene zusammengebaut in welcher ein normaler Planet mit Erdtextur zu sehen ist. Er hat einen Custom Shader bekommen um diesen leuchtenden Atmosphären-Look zu kriegen.
Einen Mond der die Erde umkreist sowie zwei Meshes von der NASA Webseite die die Erde umkreisen.

Vorbei fliegt mein erstes Asteroiden-Mesh aus Blender, mit Particle Effekt sowie einem ehrlicherweise unrealistischen Wind-Sound, aber ich finds cool ;-)
Den habe ich dann erstmal Random nochmals ein paar hundertmal in der Szene Verteilt.
Unterlegt mit Musik die ein Arbeitskollege dazu für mich gemacht hat.

[youtube]RRhjXfN4-Kk[/youtube]

Next Steps:
- Weiteres Experimentieren mit Unity 3D und Blender.
- Die Dimensionen festlegen auf Basis welcher ich arbeiten will, um ein oder zwei Planeten und eine Sonne in die Szene zu quetschen auf denen man landen kann und gleichzeitig irgendwie mit dem float Genauigkeitsproblem klar zu kommen. Man sehen wie genau ich unter diesen Umständen eine Planetenoberfläche abbilden kann.
- Erzeugung einer prozeduralen Cubesphere-Kugel analog meines ersten Versuchs, aber diesmal mit besserem Octree-Algorithmus für das LOD.
-Bau eines sehr simplen Spacefighter Cockpits und das Scripten der Steuerung. Das wird mein größter Horror, keine Ahnung ob und wie ich es schaffe ein simples Cockpit-Mesh zu bauen?! Mir schwebt sowas in der Art vor. Kennt jemand ein gutes Tutorial wo man sich ideen holen kann wie man dazu in Blender vorgeht??

Bild

Naja sobald dann eine Szene inklusive Cockpit und Steuerung steht kommt die Oculus Rift Bestellung dann als nächstes.

Bild

Bild
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Ob der wiederholte Technologie-Wechsel Dir was bringt, weiß ich nicht, aber Unity ist auf jeden Fall ein zugängliches Werkzeug für alle Arten von Experimenten. Die Bilder sehen schon ganz gut aus! Weiter so.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: [Projekt] Prozedurales Universum

Beitrag von Matthias Gubisch »

Die Bilder sehen gut aus :)
Was ich ein wenig störend fand in dem Video sind die Sterne vor der Erde, auf die Entfernung sollten da eigentlich keine Sterne mehr dazwischen sein, das trifft so nicht ganz die Dimensionen ;)

Ansonsten bin ich gespannt wie das Projekt weitergeht, sieht interessant aus.
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Matthias Gubisch hat geschrieben:Die Bilder sehen gut aus :)
Was ich ein wenig störend fand in dem Video sind die Sterne vor der Erde, auf die Entfernung sollten da eigentlich keine Sterne mehr dazwischen sein, das trifft so nicht ganz die Dimensionen ;)
Ansonsten bin ich gespannt wie das Projekt weitergeht, sieht interessant aus.
Ja ich geb zu das sieht im Video seltsam aus. Defakto sinds keine Sterne sondern Clone des Meteoriten, ca. 500 Stück, die ich Random in der Szene positioniert habe. Einfach um ein wenig mit der Random und Clone Funktion aus Unity zu spielen. Erkennt aber in der Tat nicht richtig, vor allem in dem Video, da siehts wirklich so aus als wären das Sterne vor der Erde.

Das soll nicht so bleiben, aber dient mir aktuell dazu nach einem guten Algorithmus oder Strategie zu suchen, um Asteroidenfelder zu erzeugen. Dabei geht es mir weniger um die welche eine Kreisbahn um einen Planeten bilden,
sondern solche die sich eher "willkürlich" im Weltraum befinden aber in Formationen/Feldern auftauchen, wo es Bereiche mit höherer und weniger höher Dichte an Asteroiden gibt (denke das wäre auch gut für ein Spielszenario).
hierzu suche ich noch nach dem besten Algorithmus, ggf. irgendwas in Richtung Random kombiniert mit 3D-Perlin Noise?! Oder ähnlich wie bei Nebeln Strange Attractors aus der Chasstheorie?! Keine Ahnung da bin ich noch am Suchen :-)
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: [Projekt] Prozedurales Universum

Beitrag von dronus »

Hallo,

ich habe sowas vor langer Zeit auchmal angegangen, leider ist es jetzt seit einer Weile eingeschlafen, rumort aber noch im Kopf rum... hier im Forum sind noch Relikte: http://zfx.info/viewtopic.php?f=10&t=54 ... eltenmotor

Für die Planeten habe ich keinerlei Texturen benutzt, sondern eine sich dynamisch erzeugende Baumstruktur. Der Planet beginnt als Tetraeder, und jedes Dreieck wird bei Bedarf (man ist nahe genug) in vier unterteilt. Dabei werden die ensprechenden Höhenwerte als Differenz zur Grundhöhe (also Mittelwert der Höhen der Ecken des großen Dreiecks) berechnet, abhängig von diversen geländeformenden Parametern. Das ganze passierte auf der CPU, da außer der Höhe und Farbe bei mir noch ein ganzer Sack Informationen verteilt wurde (Bevölkerung, Bewuchs, Wetter usw.). Durch diesen Aufwand ist die Auflösung erstmal ziemlich begrenzt. Aber: Ab einem bestimmten Detailgrad habe ich die Unterteilung als Geometry Program auf der GPU bearbeitet. Das hat aber nur wenige, visuelle Parameter (Geländehöhe und Farbstruktur) weiter unterteilt. Der Nachteil vom ganzen ist, das sehr kleine, aber bedeutsame Objekte (z.B. eine in der Nacht leuchtende Stadt) erst spät erscheinen, wenn das entsprechende Unterdreieck von der CPU übernommen wird. Außerdem muss man diverse Formeln doppelt implementieren, damit die CPU-Unterteilung ein zur GPU-Aufhübschung gleichwertige Geometrie leifert..

Eine weitere Besonderheit war, die Szene in zwei Richtungen zu rendern. Der Szenengraph wird praktisch umsortiert, so dass der Ort an dem man gerade ist, an der Wurzel liegt. Wenn man neben einem Planeten steht, wird dieser Planet als Wurzel genommen, kleinere Objekte wie Details auf dem Planeten und Monde klassisch rekursiv berechnet, aber ein 'Unterobjekt' ist nun das Sonnensystem in dem der Planet ist, mit all seinen Kindobjekten wie anderen Planeten und der Sonne. Das Sonnensystem hat wiederum die ganze Galaxis als Kindobjekt usw.
Der Vorteil vom ganzen: Die Kamera befindet sich immer nahe am Wurzelobjekt vom Baum. Wenn das sehr groß oder sehr klein ist, ist das egal, denn durch die Nähe zum Nullpunkt passt sich die Genauigkeit von float- oder double-Werten ideal an, so dass das Wurzelobjekt über einen großen Zahlenbereich hinweg immer präzise gerendert werden kann. So kann z.b. die Kamera beleibig fein um Objekte bewegt werden, egal ob sie Lichtjahre oder Mikrometer groß sind. Die übrigen dargestellten Objekte haben eine ebenfalls gut angepasste Genauigkeit, also entfernte Planeten können riesig sein usw. Schwierig ist nur das justieren des Z-Buffers, wenn man wirklich mit so großen Maßstabsbereichen arbeitet.

Ich hab mich damals aber weniger mit der Grafikgestaltung, als mit der plausiblen Berechnung des ganzen dynamischen Universums beschäftigt. Also wie man es hin bekommt, das die Planeten wenn man wo hingelangt an der richtigen Stelle stehen, und die Städte bevölkert werden. Besonders knifflig war, dass wenn man unsere bekannte Welt als Vorbild nimmt, sich zumindest wir Menschen sehr unlokal verhalten. Wenn ich eine Stadt, darin ein Haus und darin eine Person darstelle, kann es sein dass diese Person ein paar mal im Jahr in einer ganz anderen Stadt ist... wenn es Raumschiffe gibt, sogar auf anderen Planeten :-) wenn ich also eine Stadt rendere, hat sie ein paar Verknüpfungen zu weit entfernten Orten, z.B. Fahrzeuge, die von diesen anderen Orten kamen, Straßen die zu diesen Orten führen usw. mittlerweile hab ich ein relativ klares Konzept, wie das hinzubekommen ist, aber keine Zeit es zu tun.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Krishty »

dronus hat geschrieben:mittlerweile hab ich ein relativ klares Konzept, wie das hinzubekommen ist, aber keine Zeit es zu tun.
Schade! Ich hatte es mit großem Interesse verfolgt …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Leider hatte ich länger keine Zeit gehabt an Unity3D weiterzuarbeiten, aber zwischenzeitlich habe ich mal wieder ein paar Stunden gefunden.
In diesem Rahmen habe ich etwas an der dynamischen Planetengenerierung weitergemacht. Nix spektakuläres, ich muss erstmal das aufholen was von Ogre3D nach Unity zu portieren ist.
Im Moment ist aber wieder ein kleiner wirklich kleiner erfolgreicher Schritt getan, und zwar die dynamische Generierung der Planes in Unity sodaß am Ende ein Cubesphere dabei herauskommt. Das Grundgerüst sozuagen.
Diesmal habe ich die Plane-Generierung mit Berechnung der Triangles etwas flexibler gestaltet, sodaß es später im Quadtree leicher wird Planes, d.h. Teile der Planetenoberfläche nachzugenerieren.
Im Moment bin ich erstmal froh meinen Ogre3D Code mit den VertexDefintionArrays, TriangleIndicesLists und den Funktionen um die Sphere zu generieren usw. sauber nach Unity3D bekommen zu haben, der Rest, d.h. Noise für eine raue Oberfläche und den Planeten zu einem bestimmten Radius aufzublähen wird dann straightforward.

Nächste Schritte:
1) Organisieren der Planes in einem Quadtree - Meine jetzt größte Herausforderung und das worauf ich die ganze Zeit hinarbeite / mich einlese und schon echt gespannt bin wenns funktioniert.
2) Einen WorkerThread pro Planet, der bei ausreichender Distanz Kamera<->Planet das Update der Quadtrees übernehmen soll (d.h. im Endeffekt das Generieren und Löschen der Planes).
3) Laden von Materials/Texturen mittels Script/C# Code, hier will Unity noch nicht so ganz wie ich gerne hätte (die Planes nehmen die Materials im Unity3D Editor per Drag and Drop an, über den C# Code klappts aber noch nicht).

Bild
Zuletzt geändert von sushbone am 04.02.2014, 18:52, insgesamt 1-mal geändert.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

1) PENDING Organisieren der Planes in einem Quadtree - Meine jetzt größte Herausforderung und das worauf ich die ganze Zeit hinarbeite / mich einlese und schon echt gespannt bin wenns funktioniert.
2) DONE Einen WorkerThread pro Planet, der bei ausreichender Distanz Kamera<->Planet das Update der Quadtrees übernehmen soll (d.h. im Endeffekt das Generieren und Löschen der Planes).
3) DONE Laden von Materials/Texturen mittels Script/C# Code, hier will Unity noch nicht so ganz wie ich gerne hätte (die Planes nehmen die Materials im Unity3D Editor per Drag and Drop an, über den C# Code klappts aber noch nicht).


So es hilft nix, jetzt muss ich an den Quadtree ran :-)
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Die generische Quadtree Klasse ist schonmal erstellt, zumindest so wie ich denke wie sie sein müsste. ;) Ich habe die Planes noch nicht im Quadtree organisiert weil ich mir etwas unschlüssig bin wie ich den Quadtree ideal nutze. D.h. nicht nur für die Frage welche Planes ich rendern muss und welche nicht, denn dann würde es reichen die Planes nur in den Leafs des Quadtree zu packen, so wie es einige Tutorials ja auch beschreiben.
Sondern ich will ja auch LOD über den Quadtree umsetzen,d.h. in jeden Node des Quadtree muss ein Plane rein. Dabei haben alle Planes die gleiche Anzahl an vertices, aber die root node deckt ein größeres Gebiet ab, und mit jeder Ebene teifer im Quadtree werde ich durch Teilen der Nodes von einem in vier Childnodes immer genauer.


Soweit so gut, aber dann taucht die Frage auf wie ich den Quadtree am besten parse um in Abhängigkeit der Distanz Kamera zu jeder Plane die richtige Node-"tiefe" im Quadtree zu ermitteln um zu entscheiden, wann ich ein Plane rendere oder noch eine Ebene tiefer auf die Childs zugreife.

Ein Tutorial äußert sich dazu wie folgt:
The next step is to update which nodes should be enabled/rendered. This is determined by the camera's distance from a particular point. The formula (source) determining which nodes should be enabled is as follows:
length = distance between point and camera
d = width or depth of quad
C = constant
(length/d) < C
Wenn ich das richtig verstehe würde das bedeuten (würde ich C zum Beispiel auf 1 setzen):
Sobald die Entfernung zu der centralCoordinate einer Plane kleiner ist als dessen Durchmesser (beides lässt sich ja über den Quadtree ermitteln) wird gesplittet, d.h. ich gehe eine Ebende im Quadtree herab, ansonsten nutze ich das Plane. Das könnte eine Lösung sein, aber noch windet sich mein Kopf um die Frage wie ich mit dem Thema am besten umgehe. Denke aber ich werde es mit dieser Strategie einmal probieren.

Da ich aber offensichtlich jetzt langsam auf die echten WorldSpaceCoordinates eines Planeten zugreifen muss für diese Berechnungen habe ich jetzt zunächt noch das "Aufblähen" des Planeten auf seinen richtigen Radius sowie testhalber eine schnelle Noise-Implementierung umgesetzt.

Bild

Code: Alles auswählen

using UnityEngine;
using System.Collections;

// Author: Joerg Zdarsly
// This class is a generic quadtree implementation. In the case of the planetengine we use the quadtree to
// organize our planes. Lower levels within the quadtree means higher level of LOD (although the detail of the plane and number
// of vertices remains the same, the edges get more dense due to the splitting strategy).
public class Quadtree {
	
	// Quadtree 
	public Quadtree parentNode;
	public Quadtree childNode1;
	public Quadtree childNode2;
	public Quadtree childNode3;
	public Quadtree childNode4;
	public Vector3 centerCoordinate; 
	public Vector3 boundingEdgeCoordinate1;  // Edge structure:
	public Vector3 boundingEdgeCoordinate2;  // 1 - 2
	public Vector3 boundingEdgeCoordinate3;  // | c |
	public Vector3 boundingEdgeCoordinate4;  // 3 - 4
	public int level;
	// Engine specific
	public ProceduralPlane proceduralPlane;	// The proceduralplane object.
	public bool isActive = false;
		
	public Quadtree (int level) {
		this.parentNode = null;
		this.childNode1 = null;
		this.childNode2 = null;
		this.childNode3 = null;
		this.childNode4 = null;
		this.level = level;
		proceduralPlane = null;
	}
	
	// Creates the child nodes and sets the required parameters of the children (new bounding coordinates, level, parent node)
	public void createChildNodes()
	{
		// Quadtree actions
		childNode1 = new Quadtree(this.level+1);
		childNode1.parentNode = this;
		// Vector actions
		childNode1.boundingEdgeCoordinate1 = this.boundingEdgeCoordinate1;
		childNode1.boundingEdgeCoordinate2 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate2-this.boundingEdgeCoordinate1)/2;
		childNode1.boundingEdgeCoordinate3 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate3-this.boundingEdgeCoordinate1)/2;
		childNode1.boundingEdgeCoordinate4 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate1)/2;
		childNode1.centerCoordinate = childNode1.boundingEdgeCoordinate1+(childNode1.boundingEdgeCoordinate1-childNode1.boundingEdgeCoordinate1)/2;
		
		// Quadtree actions
		childNode2 = new Quadtree(this.level+1);
		childNode2.parentNode = this;
		// Vector actions
		childNode2.boundingEdgeCoordinate1 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate2-this.boundingEdgeCoordinate1)/2;
		childNode2.boundingEdgeCoordinate2 = this.boundingEdgeCoordinate2;
		childNode2.boundingEdgeCoordinate3 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate1)/2;
		childNode2.boundingEdgeCoordinate4 = this.boundingEdgeCoordinate2+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate2)/2;
		childNode2.centerCoordinate = childNode2.boundingEdgeCoordinate1+(childNode2.boundingEdgeCoordinate1-childNode2.boundingEdgeCoordinate1)/2;
		
		// Quadtree actions
		childNode3 = new Quadtree(this.level+1);
		childNode3.parentNode = this;
		// Vector actions
		childNode3.boundingEdgeCoordinate1 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate3-this.boundingEdgeCoordinate1)/2;
		childNode3.boundingEdgeCoordinate2 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate1)/2;
		childNode3.boundingEdgeCoordinate3 = this.boundingEdgeCoordinate3;
		childNode3.boundingEdgeCoordinate4 = this.boundingEdgeCoordinate3+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate3)/2;
		childNode3.centerCoordinate = childNode3.boundingEdgeCoordinate1+(childNode3.boundingEdgeCoordinate1-childNode3.boundingEdgeCoordinate1)/2;
		
		// Quadtree actions
		childNode4 = new Quadtree(this.level+1);
		childNode4.parentNode = this;
		// Vector actions
		childNode4.boundingEdgeCoordinate1 = this.boundingEdgeCoordinate1+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate1)/2;
		childNode4.boundingEdgeCoordinate2 = this.boundingEdgeCoordinate2+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate2)/2;
		childNode4.boundingEdgeCoordinate3 = this.boundingEdgeCoordinate3+(this.boundingEdgeCoordinate4-this.boundingEdgeCoordinate3)/2;
		childNode4.boundingEdgeCoordinate4 = this.boundingEdgeCoordinate4;
		childNode4.centerCoordinate = childNode4.boundingEdgeCoordinate1+(childNode4.boundingEdgeCoordinate1-childNode4.boundingEdgeCoordinate1)/2;
	}
	
	// Deletes the child nodes (simply sets them null)
	public void deleteChildNodes() {
		this.childNode1 = null;
		this.childNode2 = null;
		this.childNode3 = null;
		this.childNode4 = null;
	}
}
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

So, die Planes sind im Quadtree drinne. Und im Update() Thread für den Frameaufbau parse ich alle sechs Quadtree's für notwendige Updates in Abhängigkeit der Camera-Distance (nach dem oben beschriebenen Verfahren).

Und BÄM! Es funktioniert *froi*
Am Anfang wars etwas frickelig die richtige Methode zu finden beim Splitten eines Planes in 4 kleinere das alte große Plane zu löschen, ohne dass es Überblendungen oder Löcher gab. Aber jetzt funktionierts.

Bild

Als nächtses kommt dann folgendes:
- Optimieren der Updates mittels des separaten Threads
- Horizon Culling
- Optimieren der Noises für die Oberfläche. Im Moment sieht der Planet von weit weg noch unnatürlich aus, und nah an der Oberfläche finden sich dann keine Strukturen mehr da ist er nur noch glatt.
- Andere (unterschiedliche) Texturen.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Und weiter gehts:
- DONE Horizon Culling
- DONE Dynamische Texturen
- PENDING Optimierung des Noise (d.h. Nutzung von Frequency, Octaves, etc.)
- PENDING OPtimierung LOD (Berücksichtigung des PerlinNoise-Faktors)

An das Threading muss ich nochmal ran, das ist unter Unity3D der Horror. Bislang sperrt sich Unity noch dagegen die Generierung der Vertices in einen separaten Thread zu legen, obwohl ich keine Funktionen von Unity dort nutze soweit ich das sehe, bis auf die Instanzierung von Vector3 Objekten, selbst das scheint in einem separaten Thread nicht erlaubt zu sein *grrr*. Da war Ogre3D bzw. Axiom3D deutlich besser zu nutzen.

Egal. Als nächstes kommt erstmal das Perlin Noise unter die Lupe, und dann muss ich versuchen die Texturen zu optimieren (die Ränder der Texturen sind problematisch, sieht man ja auch, da habe ich aber schon eine Lösung gefunden da scheinbar kein unbekanntes Problem).

Bild

Bild
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Gepimptes Perlin Noise (d.h. nutze jetzt Frequency, Amplitude und Octaves).
Außerdem habe ich die Farbzuteilungen noch etwas angepasst...

Bild
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

So, so wie es aussieht werden ich demnächst meinen Code reengineeren. Es sind ein paar Probleme offensichtlich geworden, zwei davon unten in dem Video zu sehen, und mir gefällt die Organisation meiner Klassen nicht (mehr).
Nachdem jetzt mehr und mehr nach dem Implementieren mehrerer Features (prodedurale Planes, procedurale Texturen, der Quadtree, separate Threads) hinzugekommen sind bemerke ich eine gewissen Redundanz einiger Variablen in den Klassen (z.B. Worldspace Koordinaten als Quadtree-Node-Eigenschaft sowie in den Plane-Klassen, oder auch der Noise Parameter die ich an verschiedenen Stellen brauche), was das ganze zunehmend unhandlich macht.
Deswegen muss ich mir erstmal in Ruhe auf dem Papier bewusst machen wie ich das ganze organisieren will. Das gute ist, über viel Code redet man an der Stelle eigentlich gar nicht, die Basisklassen (VerticesDefinitions, SimplexNoise etc) werde ich übernehmen können, und der rest war mehr Brain in eine handvoll klassen zu stecken um zu checken wie das ganze grundsätzlich tickt.

Wichtig ist mir auch nochmal zu überlegen wie der Ablauf vom Frame-Update im Mainthread bis hin zum gerenderten Plane sein soll. Im Moment passiert mir noch zu viel im Main Thread. Weiterhin habe ich im Moment durchgängig das Problem dass das rendern neuer Planes und das löschen der alten Plane (bei einem Split) nicht zeitnah zueinander geschieht, deswegen weil die beiden Queues für das löschen und rendern von Objekte weitestgehend detached voneinander ist. Man kann zwar versuchen dass vorher abzufangen indem man eine Logik dahin pakt wo die Tasks in die Queue geschoben werden, aber letztlich fischt sich der Mainthread die Tasks während eines Frame-Updates gnadenlos alle Tasks aus den beiden Queues und und zieht sie durch. Was dann zu dem Effekt im Video führt.
Weiterhin parse ich die Quadtrees aus dem Main Thread heraus. Auch das würde ich gerne in einen separaten Thread packen. Im Idealfall sollte der Mainthread nur noch für das pushen der Vertices auf die GPU verantwortlich sein.

[youtube]Ce7H-HBwhJ0[/youtube]


Mal sehen. Da muss ich mir mal Gedanken machen. aber ich denke es ist fair für eine erste Implementierung wo ich mich zum ersten mal dem Quadtree sowie den dynamischen Texturen genähert habe. Folgende Punkte will ich gerne noch auf Basis der jetzigen Implementierung lösen, und dann organisiere ich den Code um:

- Im Moment lege ich für die Texture pro Pixel einfach eine feste Farbe fest je nach Noise-Ergebnis für den jeweiligen Pixel bzw. Koordinate innerhalb der Plane. Z.B. n<0.0f => blau, n<0.1f => gelb, n<0.2f = grün, n<0.6f = grau etc). Das führt natürlich zu einer eher flachen unstrukturierten Oberfläche. Daher würde ich gerne noch auf Basistexturen zurückgreifen wie zum Beispiel diese hier, um diese je nach Ergebnis des Noise auf meine Textur anzuwenden.
Denke ich hab das Grundprinzip (Cutting und Blending) verstanden, probiere ich als nächstes aus.
Bild

---------------

- Im Moment führt mein Horizon Culling dazu dass ich je nach festlegen des Threshold entweder bei niedrigem Treshhold, z.B. 10 Grad passend Culle (die nicht sichtbaren Bereiche werden nicht mehr gerendet/aktualisiert), aber komme ich nahe auf die Planetenoberfläche, die Planes nicht mehr gesplittet werden (da sie offensichtlich als außerhalb des Horizont interpretiert werden).
Setze ich den Treshhold hoch, z.B. 30 Grad, dann werden die nahen Planes zwar dann gesplittet, allerdings berechne ich dann zu viel des nicht sichtbaren Bereichs und die Performance geht in die Knie. Mir scheint ich vergleiche die falschen Winkel. Mein Hirn windet sich gerade ich habe zu lange auf den Code geschaut, ggf. sieht jemand den Fehler?

Horizon Methode:

Code: Alles auswählen

	// Checks the plane against the hozion and if its within the horizon
	// Returns true if vector is within horizon
	// Returns false if vector is outside horizon
	public static bool CheckVectorAgainstHorizon(float radius, Vector3 center, Vector3 cameraPosition, Vector3 planeCoordinate, int angleThreshhold) {
		// 1a) Calculate (with Distance Planet to Camera (h) and Planet Rarius (r) the Horizon Angle (t)
		float h = VectorServiceProvider.Distance(center,cameraPosition); // Distance from camera to planet center
                float r = (float)radius;
                float t = (float)(Math.Acos(r / h) * (180.0f / Math.PI));
		// 1b) Plane Angle
                // Get the camera position and plane position in space
                Vector3 C = cameraPosition;
                Vector3 P1 = planeCoordinate;
                // Normalize each vector
                C = C.normalized;
                P1 = P1.normalized;
                // Calculate the angle between the two vectors
                double PlaneAngle = ((float)Math.Acos(Vector3.Dot(C,P1)) * (180.0 / Math.PI));
		
		// 1c) Compare Angles. If true the plane is within the horizon
                if (PlaneAngle < t + angleThreshhold ) {
			return true;
		}
		return false;
	}
Aufruf:

Code: Alles auswählen

// Für jeden Quadtree / für jeden Plane pro Frameupdate prüfen
if (VectorServiceProvider.CheckVectorAgainstHorizon(this.planetRadius, this.planetCoordinates, this.cameraPosition, closestQuadtreeBoundingEdgeWorldCoordinate, 30) == true ) {
      // Distanz Plane zu Kamera prüfen und ggf. Splitten / neu rendern.....
}
------

Ich würde gerne die Grundprinzipien verstehen wie die Wasseroberfläche gerendert wird? In vielen Videos prozeduraler Planeten sieht man eine animierte Wasseroberfläche. Ich hab den Eindruck das wird durch eine separate Sphere gemacht die eine eigene Wassertextur enthält, und dann auf einen bestimmten Radius (Wasserhöhe) zu den prozeduralen Planes einfach additiv dazugerendert wird, mit gleicher Center-Koordinate.
Hab das Bute-Force-mäßig ausprobiert, und das schien sogar zu gehen, allerdings sieht man dann Z-Fighting wenn man sich weiter entfernt. Wäre das dennoch eine übliche Strategie aus eurer Sicht?
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Der Planet, jetzt texturiert. Optik hat enorm dadurch gewonnen, bin happy! Das Blending muss ich noch implementieren. Sowie am besten auch eine Art Scaling. Aber soweit erstmal der Zwischenstand:

Bild
Bild
Bild
Bild
Bild

Für alles weitere muss ich jetzt das Horizon Culling sauber zum fliegen bringen. Ansonsten hat die CPU/GPU keinen Spaß mehr auf Bodennähe ;)
Zuletzt geändert von sushbone am 26.02.2014, 11:39, insgesamt 2-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Das sieht schon ziemlich cool aus. Du hast allerdings noch Texturkanten durch das Filtering, wahrscheinlich an den Kanten der generierten Textursegmente.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Schrompf hat geschrieben:Das sieht schon ziemlich cool aus. Du hast allerdings noch Texturkanten durch das Filtering, wahrscheinlich an den Kanten der generierten Textursegmente.
Stimmt leider. Ich hab noch nicht herausgefunden wie ich die wegbekomme, bis auf den Umstand dass das wohl kein ungewöhnliches Problem ist wenn man mit mehreren separaten Planes arbeitet.
Im Momemt helfen sie mir noch weil ich an den Kanten ganz gut das Splitting der Planes sehe ;), aber an sich hätte ich die gerne weg. Warscheinlich auch noch eine Sache die ich vor dem Reengineeren angehen sollte,
wer weiss welche Klimmzüge dazu notwendig sind?!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Das ist schlicht die GPU, die beim Filtern der Textur bei jedem Samplen die Umgebung des Texels einberechnet. Je nach Texturfilter-Einstellungen kann das verdammt weit reichen. Entweder Du sorgst für einen farblich passenden Saum um jedes Textursegment, damit die GPU nur "gute" Farben von hinter dem Rand einbezieht. Oder Du rückst im Shader die Texturkoordinaten um so weit nach innen, dass der Texturzugriff nur gute Samples zu fassen kriegt. Also je nach MipMap-Stufe und Filterweite (anisotropische Filter greifen bis zu 8 Texel in jede Richtung) verschieden weit nach innen begrenzen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
sushbone
Beiträge: 78
Registriert: 02.06.2013, 15:31

Re: [Projekt] Prozedurales Universum

Beitrag von sushbone »

Hi Schrompf,

eine Frage zu diesem farblichen Saum (ich versuche mich lieber daran als im Shader zu arbeiten, das ist für mich noch fremdes Gebiet), ich versuche noch zu verstehen wie ich diesen am besten mache.
Wenn ich es noch ein wenig googlen richtig verstande geht es darum zu versuchen am Rand der Textur dafür zu sorgen dass die "innenliegende" Textur in den Pixelfarben nochmal wiederholt wird. Siehe Bild unten.
Geht es denn wirklich so dass ich in meiner Textur an jedem Rand nochmal eine Reihe Pixels anfühe und die Farbwerte wiederhole? Ich bin unsicher, weil letztlich landet diese Textur ja wieder auf meinem Plane,
und das Problem nach meinem naiven Verständnis nicht durch die auf dem Plane liegenden Farbwerte, sondern die Farben "daneben", also dort wo meine jeweilige Plane schon geendet hat?

Bild
Benutzeravatar
Schrompf
Moderator
Beiträge: 4854
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Prozedurales Universum

Beitrag von Schrompf »

Genau. Die Farbwerte stammen von außerhalb der unmittelbar sichtbaren Texturflächen. Stell Dir einfaches bilineares Texturfiltern vor. Die GPU nimmt dazu die beiden Texel links und rechts oberhalb der Sample-Position und die beiden Texel links und rechts unterhalb der Sample-Position und interpoliert zwischen denen. Das heißt, wenn die Sample-Position zum Rand des Dreiecks kommt, wird zumindest die nächste, eigentlich unsichtbare Texelreihe anteilig noch mit in die Farbwerte einberechnet und damit doch sichtbar.

Dann gibt es anisotropische Texturfilter. Die sind dazu gedacht, bei flachen Betrachtungswinkeln in eine Richtung sehr viel weiter zu sammeln als in die andere Richtung. Daher der Name "anisotrop". Je nach eingestelltem Anisotrop-Grad greift die Grafikkarte bis zu 8 Texel in jede Richtung weit, kann an so einer Kante also bis zu 8 Texel aus dem unsichtbaren Bereich mit einberechnen. Eine Reihe Texel außenrum wird also nicht reichen.

Und richtig übel wird es dann mit MipMapping. Die GPU holt ja kleinere MipMap-Level einer Textur raus, wenn die Fläche auf dem Bildschirm kleiner ist als die Fläche auf der Textur. In dem Fall gitl dann alles aus den vorherigen beiden Absätzen, multipliziert mit einer Zweierpotenz. Damit sollte dann endgültig klar sein, dass Du das nicht einfach so lassen kannst. Egal welchen Rand Du wählst, es wird immer Situationen geben, in denen doch wieder Texel von außerhalb des gültigen Texturbereiches sichtbar werden.

Wenn jede Textur wirklich eine eigene Textur ist, also kein Texturatlas verwendet wird, dann kannst Du einfach mal Texturkoordinaten-Spiegeln ausprobieren. Damit wird Deine Textur wiederholt, aber gespiegelt, wodurch im "unsichtbaren" Bereich zumindest farblich ähnliche Bereiche der selben Textur Verwendung finden. Falls die Texturen von einem Atlas stammen, würde ich stattdessen empfehlen, die MipMap-Stufe abzuschätzen und die Texturkoordinaten auf einem Sicherheitsbereich vom Rand weg zu beschränken.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten