Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
ich versuche gerade, mit libnoise ( http://libnoise.sourceforge.net/ ) eine Heightmap für ein Terrain zu erzeugen. Dabei habe ich momentan folgendes Problem:
Ich möchte gerne eine Möglichkeit, z. B. Wege zu bauen, hierfür sollte die Fläche also eben sein. Ich brauche also partiell die Möglichkeit, Ebene Flächen zu generieren, aber auch wieder Berge und Täler. Ein einfacher Weg wäre, einfach 2 Gradientpoints zu setzen und zu sagen:
von 0 bis x: Grauverlauf
von x bis y: einfarbig
von y bis Ende: Grauverlauf
Dann wäre aber die Ebene Fläche nur auf einer Höhe. Das wäre nicht optimal.
Ich dachte an etwas in dieser Richtung: http://lonesock.net/images/Heightmap_AO.jpg oder http://newbiz.developpez.com/tutoriels/opengl/heightmap/images/heightmap.png
Wenn die maximal höhe auf 1 ist und minimal 0 würde ich eine ebene erzeugen
in dem ich die felder neben an betrachte also x-1 x+1 y-1 y+1 und dann die neue höhe in einem wert wieder fluktuieren lasse nur das das rauschen in festen grenzen gesetzt wird die sich aus den
nachbar feldern ergeben.
Muss denn zwingend alles aus einer Funktion resultieren? Warum kombiniert man nicht verschiede Maps miteinander?
Eine Map enthält das Grund-Terrain, eine andere Map enthält die Wege (Wichtung w zwischen 0..1, reelle Zahlen), beide kombiniert (z.B. via Multiplikation) ergeben die finale Map.
Erstmal danke für die vielen Anregungen. Sorry, dass ich mich erst so spät melde.
@SeraFornax: Ich denke zu verstehen, was du meinst. Allerdings wüsste ich nicht, wie man das umsetzen sollte, es sei denn es gibt hierfür libs etc.
@Gluewurm: Ich benutze Perlin noise, soweit ich das sehe.
@XunnD: Nein, es muss nicht aus einer Funktion resultieren und das Kombinieren wäre eine gute Idee. Allerdings hängt es da wieder an der Umsetzung, die ich mir nicht ganz vorstellen kann.
Momentan generiere ich folgendes:
Dabei habe ich nach wie vor das Problem, dass ich a) alles auf einer Höhe habe (diesmal rot) und b) (was wichtiger ist), ich dennoch keine wirklich ebene Fläche habe.
Ich benutze libnoise das erste mal, daher kenne ich mich mit den Eigenheiten nicht so aus.
Hat jemand eine Idee, wie ich erreichen kann, dass ich ebene Flächen mit der Möglichkeit Wege zwischen diesen Flächen zu bauen, gleichzeitig müssen aber nach wie vor "Berge und Täler" vorhanden sein.
Ich glaube was den "Zufallsanteil" der Maps angeht hast du mit sowas wie mit deinem rot/schwarz Bild (lobnoise) schon ne Qualität erreicht, die auch von kommerziellen RTS Spielen nicht unbedingt erreicht wird. Sieht doch erstmal super aus als Gelände!
Da jetzt aber Basen einfügen ist sicher schwer, da dafür "das rauschen" analysiert werden müsste um Stellen zu finden, wo Wege/Basen sein könnten.
Ich würde daher andersrum anfangen, wie auch XunnD vorgeschlagen hatte. Maps getrennt generieren und kombinieren (multiplizieren)
Hierzu erst nochmal die Idee zwei Maps zu kombinieren als Bild:
1. Noise-Map (dein schöns Gelände)
2. Taktik-Map (Wege/Basen)
p1 und p2 sollen halt die StartPosis der Sieler sein und r1, r2 Ressourcen oder so.
Jetzt müsste man natürlich die Noise-Map "glatter" mit der anderen kombinieren indem du z.B. weichzeichnest oder ähnliches. Oder halt von der Taktik-Map ausgehend nur schwache Steigungen (zu Bergen/Tälern) erlaubst und diesen Filter selbst schreibst. Ein stupides Weichzeichnen würde evtl. Wege zerstören.
(Einschub: Oder man lässt das absichtlich zu und immer, wenn der Graph nicht passiert werden kann (Steigung zu groß/klein) fügt der Generator automatisch Tunnel und Brücken ein! Das wäre auch cool^^ Ist nur die Frage wo die herkommen sollen auf einem unbwohnten Weltraumplaneten)
Zusätzlich könnte man immer noch vorher rauschen auf die Taktik-Map bringen damit sie nicht so statisch/langweilig ist.
Also zB eine Noise-Map mit nur sehr schwaches Höhen-Rauschen(z-Koordinate) drauflegen, damit Fahrzeuge auch immer die Wege benutzen können (leicht hügelige Wege/Basen) oder auch Rauschen der Positionen der verschiedenen Knoten (x-/y-Koordinate).
Also nicht:
Noise erzeugen und nachträglich Wege /Basen /ressourcenpunkte einbauen, die die noise-map berücksichtigen
Sondern:
(Leicht variierte) Taktik-Maps generieren und mit starken zufalls-maps multiplizieren
Die offene Frage ist dann, wo die Taktik-Maps herkommen.. aber evtl kann man da wenige begrenzte "Arten" von Graphen von Hand vorgeben, die dann leicht Zufalls-Variiert mit den unterschiedlichsten Ergebnissen deiner libnoise-maps kombiniert werden.
edit:
ich wollt jetzt nochmal meine Rosa Wege zusätzlich durch dein noise (in abgeschwächter form) gefiltert darstellen, damit das resultat nicht so häßlich ist. Aber zum einen fehlt mir gerad sowas wie Photoshop hier aufm Laptop (Ebenen.....) und zum anderen frage ich mich gerade, wieso du 2 Dimensionen bei der Darstellung nutzt für die Höhe anstatt einer? (Rot-Intensität und Helligkeits-Intensität)
Height-Maps werden doch normalerweise dargestellt indem die Skala von weiß bis schwarz ausgenutzt wird. (Grauwertgebirge)
Was ist denn ein starker Rot-Wert bei dir, wenn das Bild dort hell ist und was ist dann der gleiche Rotwert, wenn das Bild dort dunkel ist?
Oder geht die Skala zB von Schwarz über Rot zu Weiß?
Schwarz könnten dann Täler sein, Weiß Gebirge und pures Rot wäre dann "Höhe des Meeresspiegels auf Normal-Null"^^
Hm... also die Wege haben nicht die Aufgabe Basen zu verbinden, dass ermöglicht es, das ganze wohl etwas einfacher zu generieren.
Es wäre natürlich auch interessant, wenn man sozusagen Teile "plattwalzt". Das stelle ich mir so vor: Ich gehe sozusagen einen Weg ab (mit meiner Walze ). Diese macht sozusagen eine lokale noise reduction. Damit könnte man z. B. auch Berg auf, Berg ab gehen (vorausgesetzt die Steigung ist nicht zu groß, dadurch hätte man auch schon ein Kriterium für die Route der Wege, denn da diese keine Basen verbinden müssen, könnte man die Streckenführung an diesem Merkmal festmachen).
Allerdings weiß ich momentan nicht ganz, wie ich das umsetzen kann, denn das würde bedeuten, das ich sozusagen "aktiv" in die Generierung eingreife.
Auf jeden Fall ein großes Danke an dich kuddlmuddl, für den Klasse Beitrag
Immer wieder gerne Hätte ich mehr Zeit würde ich gern mitmachen...
(Ich hab noch viel am vorigen Beitrag nachträglich verändert / hinzugefügt)
Zu deiner Walzen-Idee:
Guck dir mal Weichzeichnen an. Nicht die komplizierten Formeln sondern zB die resultierende Matrix.
Du könntest also zB entlang der Pfade der Taktikkarte mit so einer Matrix gehen und diese Zahlen der Matrix als Gewicht benutzen, wie stark an dieser Stelle die Noise-Map berücksichtigt wird!
Das ganze nennt sich mathematisch Faltung und sieht wie immer komplizierter aus als es ist.
Als Minimal-Beispiel wäre zB folgender "Faltungskern" denkbar, der die Pfade der Taktik-Map abläuft:
Code:
0,0 0,2 0,0
0,2 1,0 0,2
0,0 0,2 0,0
Das wäre dann ein Weichzeichner.
Erklärung:
Die Zahlen sind die als "Gewichtung" gemeint. Also die Berücksichtung der einen Karte im Gegensatz zu der anderen Karte.
1 bedeutet also, dass zu 100% die Taktik-Map (einheitliche Höhe) verwendet wird. 0,2 würde bedeuten, dass nur 20% der einheitlichen Höhe und 80% der libnoise-Rauschen-Map berücksichtigt wird.
Dieser Mini-Berg wandet nun entlang der Taktik-Map und rechnet eine resultierende Map "glatter" indem er beide mischt.
In der Bildverarbeitung wird sowas als Punktoperator bezeichnet, da Pixelweise eine Operation ausgeführt wird, die meist umliegende Pixel berücksichtigt.
Wenn du noch etwas mehr "Zufall" reinbringen willst lässt du dieses kleinen glättende Gebirge nicht direkt gerade laufen sondern lässt es "zufällig" seinen nächsten Pixel wählen wobei aber nicht alle umliegenden Pixel gleichwahrscheinlich sind sondern du jedesmal eine Art "Anziehung" an das Ziel berücksichtigst.
Von p1 zu p2 würde er zB mit 65% nach rechts gehen (Richtung p2), 15% nach oben, 15% nach unten und 5% vom Ziel weg. (Oder sowas wie bei Zufallsbewegung / Random-Walk
Wichtig für eine einfache Implementierung ist, dass du dann tatsächlich 3 Bilder gleichzeitig im Speicher hast, also die 2 Input-Bilder und noch ein Drittes wo das Ergebnis reingeschrieben wird.
Ansonsten besteht die Gefahr, dass du zB Pixel 100, 100 unter Berücksichtigung der umliegenden Modifizierst und beim nächsten Pixel 101, 100 schon die modifizierten berücksichtigst und nicht die Originale.
Btw gibts auch libs, die Faltung mit beliebigen Faltungskernen von Bildern miteinander erlauben. Die Frage ist nur, ob es sich lohnt sowas komplexes erstmal zum Laufen zu bringen, wenn man nur diese eine Funktion braucht, die man sicher schneller selbst programmiert hat: vigra
edit:
Die Summe solcher Glättungskerne / Matrizen muss 1 sein, damit die Karte nicht insgesamt angehoben/gesenkt wird. Häufig Gauss, aber jede Dichtefunktion erfüllt diese Eigenschaft.
Ergänzung ()
Und was mir gerade noch zu meinen rosa-Linien des resultierenden, gemischten Bildes einfällt:
Wenn du nicht Linien mit einer gewissen Breite verwendest, sondern sowas in der Art:
dann hätte man quasi automatisch einen "weichen" Übergang der Noise-Map in die "Taktik-Map
Die Helligkeit ist hier halt wieder das Gewicht
Je Heller, desto eher Taktik-Map und je Dunkler, desto eher Noise-Map
Wenn man jetzt Schwarz als 1 nimmt und weiß als 0 sind das direkt die Zahlen, die bei einer Multiplikation verwendet werden können um die Maps zu vereinen. In der Mitte der Wege ist dan garantiert, dass alles auf einer Höhe liegt und am Rand wird immer stärker das echte Rauschen der Gebirge berücksichtigt
Das war einfach dazu gedacht, dass man es gut sehen kann
Die Idee mit der dem Grauverlauf und der davon abhängigen Gewichtung erscheint mir als sehr gute Idee. Allerdings müsste man wohl die Höhe der Noise-Map mitberücksichtigen (z. B. den niedrigsten Punkt, gemessen an 40%igem Grau), da wenn man wirklich nur 100% Taktik-Map nehmen würde, man ja keine Höhe in dem Sinne hätte. Die Frage ist natürlich wie man das genau umsetzt.
Man müsste natürlich eine gewisse Steigung mitmachen, sonst hat man nur Wege auf einer Ebene. Aber was ist in diesem Zusammenhang unter "eben" zu verstehen. Wenn wir z. B. einen Weg haben, der einen Berg hinauf führt, so ändert sich i. d. R. die komplette Position (x, y, und z). Dies ist also relativ schwierig.
Wenn wir nun deine Idee oben aufgreifen (und die noise-map bei weiß gar nicht beücksichtigen), haben wir immer einen ebenen Weg, der auch durch Berge geht, allerdings mit einem glatten Übergang zum noise-Map, was auch jeden Fall ein Vorteil wäre.
Die Frage ist nur: Wie setzt man das um? Mit welcher lib ist es z. B. schonmal möglich einfach 2 Bilder übereinander zu legen? Interessant wäre z. B. zu sagen: weiß=100% und schwarz=0% Transparenz der Taktik Map, dann hätte man schonmal einen Anfang.
@Gluehwurm: Ok, ich würde das einfach mal ausprobieren mit einer primitiven "Taktik-Map". Kennst du zufällig eine Lib mit der man 2 Bilder kombinieren kann und darauf gleichzetig einen solchen Filter anwenden kann?
Im Primzip sind das alles Bildverarbeitungs-Algorithmen.
Die einzigen Bibs die ich kenne und mal ausprobiert hab in dem Bereich sind vigra, ImageJ und das wohl verbreitetste: OpenCV
Im Zusammenhang mit der vigra hab ich auch noch jede Menge selbst geschriebenen Filterkram, den ich dir geben könnte.. Einerseits stellt die Bib quasi alles zur Verfügung, so dass mans nur benutzen muss, andererseits kann man aber auch direkt auf den Pixeln operieren:
Code:
Lib (vigra) benutzen um Gauss-Glättung durchzuführen:
vigra::gaussianSmoothing(srcImageRange(meinInputBild), destImage(meinOutputBild), sigma);
Selbst implementierter Mittelwert-Filter mit konstantem Radius 1:
void meinMittelwertfilter(vigra::BImage &input, vigra::BImage &output) {
for (int y = 0; y < input.height(); ++y) {
for (int x = 0; x < input.width(); ++x) {
mittelPixel(input, output, x, y);
}
}
}
void mittelPixel(vigra::BImage &input, vigra::BImage &output, int x, int y) {
int summe = in(x-1, y-1) + in(x, y-1) + in(x+1, y-1) + // die oberen 3 der 8 nachbaren
in(x-1, y) + in(x, y) + in(x+1, y) + // der linke und rechte nachbar und der mittelpunkt selbst
in(x-1, y+1) + in(x, y+1) + in(x+1, y+1); // die unteren 3 der 8 nachbarn
output(x, y) = (summe + 0.5) /9;
} // TODO: Randberücksichtigung! Bei x=0, y=0 gibts beim Zugriff auf x-1, y-1 Pobleme ;-)
Ich würd mir irgendeine der Bibs nehmen (oder die, die dir schon diese Output-Bilder generiert, falls die das zulässt?) um auf den Pixels eines Bildes arbeiten zu können, aber die entsprechenden Filter dann selbst programmieren.
Es gibt auch minimalistischere Graphic-Bibs die in reinem C geschrieben sind und im Grunde nur Container zur Verfügung stellen um Speicher zu reservieren in dem ein Bild abgelegt wird.. ich hab nur den Namen gerad vergessen :/
In ITK sind ziemlich viele Filter enthalten, wird aber v.a. im medizinischen Sektor verwendet. Wie im vorigen Post aber schon gesagt, programmier die Filter selbst. Den Code findest du überall im Netz
Ich hab einfach mal nach "C library image processing" gegoogelt und der erste hit war: http://cimg.sourceforge.net/
Das war auch die, von der ich mal gehört hatte (*erinner*). Da's nur eine header-file ist, kann man die sicherlich relativ simpel einbauen und probieren.
Gibt aber noch mehr..
ne Liste zB auf http://www.mathtools.net/C_C__/Image_Processing/
Was ich mich gerad grundsätzlich frage - Angenommen du hast alles fertig und kombinierst wunderbar verschiedene Maps zu einer spielbaren fertigen spiele-map
Wie wird die in dem Spiel verwendet? Soweit ich das von Strategiespiel-Karteneditoren kenne arbeiten die meistens mit deutlich größeren "Feldern". Zwar können die Einheiten auch innerhalb der Felder unterschiedliche Positionen einnehmen, aber das Terrain ist nur so fein, weil pro Feld dann zum reinen Darstellungszweck Grafiken dafür verwendet werden, diese Felder nicht so sichtbar zu machen.
Oder anders formuliert: Wenn ne Einheit mehrere Pixel der Map belegt, wie wird dann entschieden ob die Steigung zu groß oder zu klein ist um ne Bewegung um 0,3 Pixel in irgendeine Rchtung durchzuführen?
Hm... cimg ist wohl lizenzmäßig nicht machbar, ich brauche etwas in die Richtung MIT oder auf LGPL.
Deine Frage
Wenn ne Einheit mehrere Pixel der Map belegt, wie wird dann entschieden ob die Steigung zu groß oder zu klein ist um ne Bewegung um 0,3 Pixel in irgendeine Rchtung durchzuführen?
Die vigra darf sogar auch in kommerziellen Projekten eingesetzt werden, hat aber leider einige Abhängigkeite an andere Libs wie zB libjpeg, libfftw etc. Für Bloodsheds DevCPP hätte ich ne schnellstart Anleitung mit der man in wenigen Minuten loslegen kann, falls du Interesse hast? Für Visual-Studio (2008) ist was auf der HP zu finden.
Ich meinte ganz einfach wie du aus den fertigen Bilder mit zB 500x500 Pixeln ne Map erstellst auf der die Einheiten sich dann bewegen. Also ob quasi bei der Einheitenbewegung entschieden wird, ob das Ziel erreicht werden kann oder ähnliches. (Wegfindung..) Oder ob das schon vorher irgendwie feststehen soll. Ich denke mal sowas jetzt schon zu berücksichtigen spart später Probleme.
Hm... also angenommen ich habe die Taktikmap, mithilfe der ich Wege, ebene, bebaubare Flächen erstelle, dann könnte ich einfach sagen: Darauf kann man sich bewegen und sonst nirgendwo.
Der Gedanke dahinter: Ich sehe auf der Taktik-Map: Oh, Weg beginnt, also fange ich langsam (jeweils max. Steierung von 0.07) mit meinem Grauton an. Allerdings passt da etwas nicht, wenn der weg sozusagen beginnt, da hier sofort mein Grauton da ist. Ich kann das irgendwie nicht nach vollziehen.
Hier mal das Resultat:
Ich werde das ganze natürlich noch verfeinern, aber es ist schonmal ein Ansatz, nur leider sitze ich gerade etwas auf dem Schlauf
Wie wärs, wenn du so´n Verlauf nimmst, der sich von außen nach innen immer mehr von dem Höhen/Tiefenton zu deinem Weg-Farbton nähert? Dadurch würden sich die Höhen im Detail ausgleichen und hättest damit nicht so´n komplett rechteckigen Weg (hier auf die Geraden bezogen), sondern hättest das an den Seiten immer terrainabhängig ausgefranzt.