octoawesome
octoawesome copied to clipboard
Inkonsistente Block Koordinaten
Ich versuche mich gerade an einer alternativen Chunk Implementation, die die Daten anders abspeichert und theoretisch sehr viel RAM sparen sollte. Allerdings stoße ich auf das Problem, dass beim setzen und abrufen der Blocks ständig andere Koordinatensysteme benutz werden. Mal Global, mal Lokal.
Ich wäre dafür, das zu vereinheitlichen, entweder Global oder Lokal, aber nicht gemischt.
Das hat sehr gute Gründe, dass es Lokal und Global gibt. die Lokalen braucht man um Blöcke für Chunks abzurufen, die Globalen braucht man für alles Spieler und Generatorbezogenes. Und ich glaube die einzigsten Arten zur Komprimierung wären denke ich über etwas mit OctTrees oder sonstigen Komprimierungsalgorithmen. Ansonsten erklär doch vlt. einfach mal was du vorgehabt hättest.
Dass es Globale und Lokale Koordinaten gibt ist ja normal, wenn die aber dann wild durcheinander gewürfelt werden wird es unübersichtlich und ist eine potenzielle Fehlerquelle.
Zum einen mag man argumentieren, dass es ja praktisch ist, wenn man bei Chunk.GetBlock() und Chunk.SetBlock() beide Arten von Koordinaten benutzen kann, motiviert aber dazu, unsauberen Code zu schreiben.
Nach meiner Meinung sollte ein Chunk immer nur mit lokalen Koordinaten arbeiten, ({0,0,0} - {31,31,31})
Ich arbeite derzeit mit Octrees. Bin gerade dabei den von einem meiner experimentalen Unity Projekte zu portieren.
Dort hatte ich Eine statische World, den Chunk und den ChunkNode, (Entspricht bei OctoAwesome in etwa Planet, ChunkColumn, Chunk) und habe überall mit Globalen Koordinaten gearbeitet.
Mein Konzept des Chunks war aber ganz anders, hier ist ein Chunk nur ein Datenspeicher. Bei meinem Konzept hatten sich die Chunks (ChunkColumn) teils selbst "Verwaltet". Das war aber auch alles auf Unity zugeschnitten.
Chunk.SetBlock/GetBlock nehmen doch nur zum Chunk-Relative Koordinaten an?
Nein eben nicht, da kommen auch Globale Koordinaten an. Zumindest bei mir.
z.B in SceneControl Zeile 204 beim selektieren eines Blocks vom Spieler wird dem LocalChunkCache die Globale Koordinate übergeben und dort 1:1 dem Chunk übergeben.
Tatsache, aber dann guck dir doch mal an, was damit passiert, es ist einfach irrelevant, die Globale Position wird einfach abgeschnitten, schließlich haben wir ja Chunkgrößen von 2^N. Für die Positionierung interessieren uns nur die letzten 5 bits, warum dann nicht auf unterster Ebene abschneiden, ist sowieso schlauer als dann ne Exception zu schmeißen. Wir wollen schließlich Geschwindigkeit haben ;)
Bekomme ich da dann die lokale Koordinate raus? Mit dem Octree bin ich auf gleichbleibende Koordinaten angewiesen.
Wir haben folgendes Koordinaten-Konzept: Chunks müssen als Kantenlänge immer eine Zweierpotenz haben - in unserem Falle 32. Dadurch erlangt man die lokale Koordinate eines Blocks, indem man nur die letzten 5 Bit maskiert. Die nächstgrößere Einheit um eine Entität ist der LocalChunkCache. Der soll Chunks in unmittelbarer Nähe der Entität halten. Auch dessen Kantenlänge darf nur eine Zweierpotenz sein. Dieser hält für den schnellen Zugriff alle Chunks in einem 2d-Array - der entsprechende Index im Array ergibt sich aus der Maskierung der kommenden Bits der Koordinate. Nehmen wir auch hier eine Sichtweite von 32 an, dann sind das Bit 6 bis 10.
Octrees arbeiten ja naturgemäß mit Zweierpotenzen. Mir gefällt nur nicht, dass man nicht darauf vertrauen kann, ob man nun mit lokalen oder globalen Koordinaten gefüttert wird und selbst das Umrechnen erledigen muss. Am Ende hat man 20 Stellen pro Block, wo die Koordinaten maskiert werden.
warum sollte man sich darauf verlassen können, wenn es unnötig ist? Was hast du für einen Vorteil, wenn du es an 100 stellen außerhalb machen musst, anstelle von einer innerhalb? Und machen musst du es aufjedenfall. 1D Array ist auch sinnvoll für die Geschwindigkeit und auch einfachere Datenhaltung. Also eigt. ist es so wie es jetzt ist eine zentrale Stelle wo das gemacht wird und eben nicht 20 stellen :D
Man sollte sich darauf verlassen können was in der Dokumentation steht. Und für jemanden, der sich wie ich neu in den Code einarbeitet, bedeutet das durchaus Stunden an Frust, wenn das Teil nicht das macht was man erwartet ;)
Eigentlich braucht man das nicht extern an 200 Stellen machen, bei einer guten Architektur sollte eine globale Stelle reichen.
Die 1D Arrays sind zwar schnell , aber trotzdem Speicherfressend. Bei der aktuellen Standardeinstellungen werden 1800 Chunks im Speicher gehalten, das sieht dann in etwa so aus: Chunks.Blocks = 112,5 MB Chunks.MetaData = 225 MB Chunks.Resources = 450 MB
Mit allem drum und dran kommt man dann ca. auf 0,9-1,1 GB RAM Mit meinem Octree habe ich derzeit eine gesammt RAM verbrauch von 400 - 500MB
Das ist aber ein Anderes Thema.
Wie sieht es hiermit aus, ist das noch relevant?
Ich glaube für uns selbst war das nie relevant, das war eine Idee von runner78, um seine Octrees besser / überhaupt erst implementieren zu können. Das ist nie über einen WIP Pull Request herausgekommen, vgl. #172. Ich weiß nicht, ob @runner78 das hier überhaupt nocht braucht für seine neue Implementierung.
Ok #172 ist ja closed. Dann würde ich @runner78 bitten sich zu äußern ob er noch an diesem Issue weiter macht.
Ich bin immer noch der Meinung, dass es sich hier um einen schlechten Programmierstil handelt, auch weil das Verhalten schlecht dokumentiert ist. Ob das hier noch aktiv bleibt hängt davon ab, ob die derzeit aktiven Entwickler Interesse haben, was zu ändern.
Super! Wird Zeit, dass der Octtree endlich kommt!
OctoAwesome lebt von der Community wenn du was cooles hast dann immer gerne her damit @runner78
Ich arbeite derzeit an einem Octree basierten Blockterrain für ein eigenes Project in Unity, den ich danach für OctoAwesome portieren möchte.
Aber wie bereits an anderer Stelle mehrmals angebracht. OctTree schön und gut für Kollision/Speicher sparen etc. aber nichts fürs Rendering...
Wenn man nicht Block für Block sondern Node für Node rendert, dann spart man sich eine Menge Polygone. Und auch das iterieren geht schneller, da man leere Nodes direkt überspringen kann. Bei einem Blockarray musst du immer durch alle Blöcke durch. Es dürfte allerdings etwas komplizierter werden so einen Renderer zu programmieren.