Perlin Noise -Eckdaten übergeben

    • GM 8

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Perlin Noise -Eckdaten übergeben

      Hallo Leute!
      Wieder mal ein Thread von mir wo es um die zufallsgeneration von Maps geht.
      Diesmal hätte ich eine Frage auf die ich im Internet keine Antwort bekommen habe.

      Viele kennen sicher "Perlin-Noise" mit dem man zufallsgenerierte Heightmaps erstellen kann.
      Nun, ich würde gerne wissen ob es schon irgendwelche Skripts/Pseudocodes gibt mit denen man die letzten "Pixelwerte" eines Perlin Noises an den generator übergeben kann um anhand von diesen einen 2ten Perlinnoise zu erstellen.

      Die Gedanke dahinter ist der dass die 2 unabhängig voneinander generierte Perlin-noise Hightmaps zueinander (vom übergang her) passen. (Also das der übergang zwischen den beiden sauber ist, als ob sie eine gemeinsame Hightmap wären.)

      Es tut mir wirklich leid dass ich euch damit belästige, jedoch finde ich dafür einfach keine Konkrete antwort. :(
      Die einzige Möglichkeit die ich für solch einen "sauberen" Übergang sehe ist Maps nicht anhand von Perlin-Noises zu generiere, sondern anhand von Zufallswerten, bei denen man die endposition an die startposition der neuen Generation übergibt. (Jedoch ergibt sich daraus kein so schönes terrain wie mit Perlin Noise.)

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von LEWA ()

    • Dazu muss man genau verstehen, wie Perlin noise geht, und du musst dir wohl alles von Grund auf selber schreiben. Ein weiteres Problem könnte irgendwann der Speicher werden, dazu aber später.

      Also, für Perlin noise benutzt lagen. 5 ist ein guter Wert. Diese lagen werden mit zufälligen Daten gefüllt. Jede dieser lagen ist verschieden groß.
      Dann werden alle lagen auf die selbe Größe skaliert. Die Daten werden dafür interpoliert. Danach werden alle lagen zusammen gelegt, und das Perlin ist fertig.

      Für die Erweiterung dieser Daten für ein benachbartes Perlin bedarf es, dass du die Werte vom Rand jeder Lage jedes Perlin speicherst. Dieser Rand ist nicht einfach die äußerste Reihe Werte, sondern, und das ist wichtig, die breite der äußersten Daten des kleinsten Layers hoch skaliert. Ich gebe mir Mühe, das verständlich zu machen, das ist aber gar nicht so leicht.

      Also, hier ein bisschen zur veranschaulichung. Dieses Perlin besteht aus 2 Lagen und nur aus boolischen Werten (X,O), welches normal nicht realistisch ist, aber nur zur Veranschaulichung dient.

      Quellcode

      1. Lage 1
      2. XOX
      3. XXO
      4. XOX
      5. Lage 2
      6. XOXXOX
      7. OOXOXO
      8. OXOXOO
      9. OXXXOX
      10. XXXOXO
      11. OXOXXO
      Alles anzeigen

      Wie gesagt, verschieden große Lagen. Danach werden ja alle auf eine Größe skaliert

      Quellcode

      1. Lage 1
      2. XXOOXX
      3. XXOOXX
      4. XXXXOO
      5. XXXXOO
      6. XXOOXX
      7. XXOOXX
      8. Lage 2 bleibt wie sie ist


      Jetzt sind beide lagen gleich groß. Ich sagte, dass der Rand so breit sein muss, wie die äußersten Daten des kleinsten Layer groß skaliert.
      XXOOXX
      XXOOXX

      XXXXOO
      XXXXOO
      XXOOXX
      XXOOXX


      Da die Größe des kleinen Layers sich verdoppelt hat, brauchen wir die Daten der äußersten beiden Reihen vom großen.

      So, besser kann ich nicht.


      Da wir jetzt diese Daten haben, und wir ein neues Perlin erstellen wollen, fischen wir uns die Randdaten des Nachbarn. Wenn wir jetzt ein neues Perlin erstellen, müssen wir dran denken, es größer zu machen. Genau den Wert, größer, wie die Breite der "Randdaten" des Nachbarns größten Layers. Also, das, was da oben so ausführlich beschrieben wurde.

      Bei der Erstellung des Perlin Setzten wir, wenn vorhanden, die Daten des Nachbarn an die Ränder der Layer ein, der Rest wird mit Zufälligkeiten gefüllt. Lagen zusammenlegen, und fertig ist das Perlin. Der Rand wird jetzt genau so aussehen, wie der des Nachbarn. Das kann man abschneiden, entfernen.

      Fertig!

      Ich übernehme natürlich keine Garantie dafür, dass das Funktioniert, das ist mir jetzt Spontan aus dem Kopf entsprungen. Ist aber mit meinem besten Wissen und Erfahrungen geschreiben. Falls es Probleme geben sollte, nur her damit. Du kannst ja Ausgangspunkt in meinem Perlin noise Script nehmen. Zu finden überall, aber auch hier.

      MfG SDX

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von SDX ()

    • So, nun melde ich mich mal wieder zu Wort.^^

      Ich habe mich ein wenig mit Perlin beschäftigt und versucht es so gut wie ur möglich z uverstehen.
      Dabei habe ich deinen Code analysiert, und verstehe grundsätzlich wass er macht, jedoch bin ich mit Perlin noise noch zu unerfahren um die gewünschten Ergebnisse zu erzielen.
      (Hab deinen Script auch um die längen/breitenangabe erweitert da man bei dir nur die Seitenlänge angeben konnte. War nicht sonderlich schwer. XD)

      Erstmal möchte ich dich zu den Argumenten die du deinem Perlin Skript übergibst was fragen:

      GML-Quellcode

      1. background_create_perlin(
      2. (real) size,
      3. (real) count,
      4. (real) octaves,
      5. (real) weight);


      - Size ist ja die Größe (ist ja klar.)
      - Count ist sozusagen die Interpoleration. (Vermischung der einzelnen Layer.)
      - Octaves ist der Detailgrad >(Wölbungen,etc...) sozusagen die "Rechentiefe"
      - Weight ist eine Variable die Angibt wie stark die einzelnen Layer einfluss auf das Ergebniss haben.

      > Stimmt so meine Analyse?
      ____

      Nun noch eine frage:
      Ich habe in etwa verstanden wie diese "fortschreitende" Perlin generation funktioniert, jedoch habe ich dir an einem Punkt nicht volgen können:

      Jetzt sind beide lagen gleich groß. Ich sagte, dass der Rand so breit sein muss, wie die äußersten Daten des kleinsten Layer groß skaliert.
      XXOOXX
      XXOOXX
      XXXXXX
      XXXXXX
      XXOOXX
      XXOOXX

      Da die Größe des kleinen Layers sich verdoppelt hat, brauchen wir die Daten der äußersten beiden Reihen vom großen.


      Also wir sollen die kleinste generierte Ebene nehmen, sie hochskalieren und die Differenz zwischen der Skalierten und Unskalierten Ebene an den neuen Perlin Skript übergeben.
      Blos bezieht sich die Aussage jetzt an die Anzahl der Pixel vom Rand oder an die Werte die die Pixel haben? (Dumme frage ich weiss. XD)


      Und wenn wir nun z.B: die Daten der Ränder haben (ich nehme an das sind die Pixelwerte) und sie in den "Grundlayer" einfügen, entsteht ja in der Mitte sozusagen Leere. Wenn wir da was "dazugenerieren" entstehen wieder diese "unebenheiten".
      Wird das durch die überlagerung der anderen Layer wieder wettgemacht? Oder verstehe ich hier von grund auf etwas komplett falsch?

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

    • Erst mal deine Analyse:

      Count ist die anzahl der Lagen. 5 Lagen ist ein Wert, der immer geht. Mehr wird selten bedarft, weniger sieht meistens bescheiden aus.
      Octaves ist wie "breit" die Wellen sind. Also, wie weit im Schnitt zwischen Berg und Tal liegt.
      Weight ist wie sehr die feinen Details gewichtet werden sollen. Also, wie stark die größeren Layer gegenüber den kleineren Layern im Endergebnis mitmischen dürfen.

      Zweitens: du sagst, dass wenn wir was dazu generieren, entstünde wieder diese "unebenheiten". Das ist schlichtweg falsch. Ich zeige mal das es zu machen gilt, an einem ganz realen Bespiel.
      Als erstes erstellen wir 5 Layer



      Wenn wir die alle auf die gleiche Größe (256) skalieren und zusammen mischen, erhalten wir das hier:




      Wenn ich jetzt sage, dass der kleinste Layer 7.1 mal kleiner ist als der größte, dann kann man mit der oben beschriebenen Theorie sagen, dass wir die äußersten 8 Pixel des größten mitnehmen müssen, in den neuen Perlin.

      Wie ich das berechnet habe? aktuellen_layer/kleinsten_layer. Durch teilen der Maße erhält man die breiten.

      Jetzt nimmst du die Daten der Kanten und speicherst sie in Grids oder Surfaces. Ich würde auch die ds_bin Struktur empfehlen. Ist ne DLL, gleichnamig und SAU schnell.

      Wenn du jetzt neue Layer für ein neues Perlin machst, das benachbart ist, nimmst du die Daten und klatscht diese an den Rand. Sieht dann so aus. Dieses Perlin hat Nachbarn rechts von sich. Außerdem einen Obenrechts und einen oben. Das grün markierte ist zufällig generiert. Rot, Gelb und Blau sind Daten der Nachbarn.



      Wenn man beim finalen Ergebnis des Perlin diese bereiche weg schneidet, umgeht man, dass an Kanten sich das Bild wiederholt, das nächste Abschnitt aber dennoch von den Nachbarn beeinflusst ist, und somit keine sichtliche Kante ensteht.

      Ich hoffe, dass es dieses Mal gut genug erklärt war, mit schönen Bildchen statt ASCII.

      MfG SDX
    • Ich weiss nicht ob ich mich jetzt trauen sollte dies zu sagen. XD

      Ich krieg das zum verrecken nicht hin. Geht es um solche Sachen wie Perlin Noise, schaltet mein Hirn einfach ab.

      Ich habe dein Example erweitert und versucht genau das zu implementieren was du mir da erklärt hast. Es funktioniert aber nicht.
      Ich habe sicher zig tausend denkfehler eingebaut die mir nicht wirklich bewusst sind... (oder gar rechenfehler.)

      Falls du evtl Zeit haben wirst: Schaus dir bei gelegenheit mal an. Würde diesen "fortschreitenden" Perlin gerade recht gut gebrauchen.
      (Ein Terrain Generator der auf Zufallswerten basiert ist nicht so das wahre...)
      Dateien
    • Ich glaube ich habe dich jetzt lange genug zappeln lassen. Die präsentierte Methode ist zwar die korrekteste, die Mustergültigste und die vllt sogar die schnellste. Aber, du ahnst es schon, es gibt noch eine weitere, eine schlampigere, eine improvisiertere aber dennoch mit dem (fast) gleichen Ergebnis kommende Art der Lösung dieses Problemes.

      Dazu brauchst du ein Teil des Wissens aus den obigen Posts.

      Also, wir fangen wir wieder an mit "die breite der äußersten Daten des kleinsten Layers hoch skaliert" - wenn du vergessen hast, ließ noch mal. Dieser Wert, also eine Breite, gilt es mit dem Nachbarn zu vermischen - immer noch das Alte. Dies mal machen wir das Mischen allerdings mit den bereits fertigen Perlins. Einfach dessen kanten "ausfaden" - also immer transparenter werden lassen. Das machst du mit 2 der Seiten, sagen wir oben und rechts. Wenn du jetzt dein Perlin erweitern willst, setzt du einfach ein neues Perlin (also eine Surface oder Background) auf dessen Kante, und schwubs, du hast ein neues, größeres, in alle Richtungen erweiterbares, perfektes Perlin.


      Und wo ist da jetzt dieser magische hochskalierte kleinste Daten dingsbums Wert? Nun, an zwei stellen. Erst mal da, wo du anfängst "auszufaden" ist von der Kante des Perlin entfernt. Außerdem wird der neue Perlin unter das alte geschoben bzw. rüber gesetzt (je nach Seite) (um den Übergang zu machen).


      Schau dir mal an, das sollte gut machbar sein. Und wenn nicht, konnte ich es nicht gut genug Beschreiben ^^


      MfG SDX
    • Das ist schon irgendwie eine Folter. XD Du ennst dich in dem Bereich super aus, erklärst das grundsätzlich auch ausführlich, ich jedoch bin dermaßen unfähig um das Vorhaben in die tat umzusetzen. Glaub mir, nach deinem letzten Post (wo alles ausführlich erklärt wurde) habe ich ca einen Monat lang versucht dies im GM umzusetzen.


      Ging aber nicht. XD
      Das was du da erzählst hört sich zwar wesentlich einfacher an, aber es ist dennoch schwer sich die umsetzung so leicht aus den fingern zu saugen.
      Ich kann zwar den Vorgang theoretisch nachvollziehen, Aber bei der Praxis stellen sich meine Haare zu berge. X(
      Dieser ganze Perlinnoise Schnickschnack ist für mich ziemlich komplex. ^^
      (Mich plagen u.a. Denk und Rechenfehler. XD)

      Nunja, dann bis einen Monat! :D
    • Benutzer online 1

      1 Besucher