Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

1

29.12.2011, 08:47

Problem mit Spherical Texture Mapping [gelöst]

Hallo ihr lieben, ich bins mal wieder.

Für meinen Realtime Planet Renderer brauche ich jetzt die Möglichkeit Texturkoordinaten auf einer Kugel zu berechnen.
Ich habe schon ganz viele Formeln aus dem Internet ausprobiert, aber keine hat 100% funktioniert.
Vielleicht seht ihr, was ich übersehe.

Das einzige was bisher halbwegs funktioniert hat, war die Umkehrung dieser Funktion aus der libnoise.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
void noise::LatLonToXYZ (double lat, double lon, double& x, double& y,
  double& z)
{
  double r = cos (DEG_TO_RAD * lat);
  x = r * cos (DEG_TO_RAD * lon);
  y =     sin (DEG_TO_RAD * lat);
  z = r * sin (DEG_TO_RAD * lon);
}


Die Umkehrung sieht dann so aus:

C-/C++-Quelltext

1
2
3
4
5
6
void noise::XYZToLatLon(double x, double y, double z, double &lat, double &lon)
{
   lat = asin(y) * RAD_TO_DEG;
   double r = cos(DEG_TO_RAD * lat);
   lon = acos(x/r)*RAD_TO_DEG;
}


Auf der Hälfte der Kugel funktioniert es einwandfrei, doch nicht an den Grenzen.

C-/C++-Quelltext

1
2
v = lat/PI;
u = lon/PI;

Wenn sich einer der Werte seinen Grenzen nährt (u [0;PI], v [-PI/2;PI/2]), und die Grenze überschritten hat,
zählt er rückwärts. Das hat zur Folge, das bei einer sich regelmäßig drehender Kugel, es so aussieht als wenn sie sich erst in die eine Richtung und dann in die andere Richtung bewegen würde.
Die obige Formel gibt mir keine eindeutigen Koordinaten für die ganze Kugel, nur für die Hälfte.
Hat jemand eine Idee, wie ich herausfinden kann auf welcher Halbkugel ich mich nun befinde?
Wenn ich nur eine Richtung bräuchte, habe ich eine Lösung.

C-/C++-Quelltext

1
2
3
4
5
u = lon/(2*PI);
if(z < 0.0)
{
  u = 0.5f-u + 0.5f;
}

Wenn ich mich jetzt der Grenze nähre (um die y-Achse rotierend), rotiert die Textur sauber weiter.
Wenn ich aber um die x-Achse rotiere (nach oben und unten) und z minus wird, dann springt die Textur.
Ich habe mir schon das Gehirn zermatert um einen 2. Bedingung zu finden auf die ich prüfen könnte um das zu verhindern. Aber ich finde einfach nichts.

Was vielleicht auch noch wichtig ist. Ich verwende keine Kugel Geometrie sondern eine Ebene, deren neuberechnete Höhen-Werte eine gekrümmte Oberfläche ergeben,
abhängig von der aktuellen Kameraentfernung zum Planeten.
Wenn man sich auf einen Planeten zubewegt, und ihm immer näher kommt, sieht man ja nur einen Ausschnitt, der immer kleiner wird.
Ich versuche nun anstatt einen Quadtree zu benutzen, diesen Ausschnitt zu berechnen. Das klappt auch schon ganz gut, die Krümmung passt immer zur Höhe.
Die Texturkoordinaten werden im dann im Shader berechnet, basierend auf dem Schnittpunkt zwischen Kamera und Planetenmittelpunkt.
Dazu muss ich aber die Schnittpunktkoordinaten in die korrekten uv Koordinaten umrechnen.
Diese werden dann auf die lokalen uv-Koordinaten aufaddiert. Diese sind auch dynamisch, da sie wiederum von der Entfernung von der Kamera zum Planeten abhängen.

Hat sich einer von euch schon mit der Thematik des Spherical Texture Mappings beschäftigt und eine Idee, einen Hinweis für mich?
Liebe Grüße
Dario ;)
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DarioFrodo« (31.12.2011, 15:57)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

29.12.2011, 10:54

Ich stelle jetzt einfach mal die typischste Frage: Wozu brauchst Du es genau? Oft lässt sich ein Problem nämlich auch ganz anders lösen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

3

29.12.2011, 11:17

Wie ich eingangs schon erwähnt habe, benötige ich es für ein Realtime Planet Renderer.
Das heißt die Möglichkeit auf einen beliebig großen Planeten oder Sonne zuzufliegen und darauf zu landen.
Die Schwierigkeit dabei ist, der großen Größenunterschied.
Die größte bekannte Sonne die ich auch damit darstellen möchte, hat einen Radius von ca. 1066 AE, also ca. 160*10^9 km.

Ich habe mir das oben genannte System überlegt, also keine Kugel zu nehmen, da ich die Höhenunterschiede exakt darstellen möchte.
Man könnte zum Beispiel auch einen Würfel mit normalisierten Vektoren nehmen.
Die Erde hat einen Radius von 6.378 km. Wenn ich das mit normalisierten Vektoren mache,
bekomme ich für die Berge nur noch eine Genauigkeit von einigen Metern.
Wenn ich zum Beispiel einen Berg von einem Meter habe, würde auf den normalisierten Vektor 1,56788962057071E-007 aufaddiert = 1,0000001568.
float hat aber nur eine Genauigkeit von ca. 7-8 Nachkommastellen und double wird intern in der Grafikkarte nicht verwendet.
Und die Erde ist noch ein sehr kleiner Planet.
Unsere Sonne hat einen Radius von ca. 695.999 km, das sind 2 Stellen mehr und damit nur noch eine Genauigkeit von ca. 100 Metern.

Ich habe nun also eine adaptive Geometrie geschaffen, mit der ich einen beliebig großen Planeten sowohl aus der ferne anzeigen kann, aber auch aus einer Entfernung von wenigen Metern. Dabei wird die gekrümmte Ebene immer mit rotiert wenn sich die Kamera bewegt. Das heißt nicht der ganze Planet wird modelliert, sondern nur der Teil der sichtbar ist.
Die Grundgeometrie unterscheidet sich ja nicht, wenn ich den Planeten von vorne oder von hinten betrachte, aber die Texturedaten und die Höhendaten.

Wenn du eine andere Idee hast, immer her damit :)
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

29.12.2011, 12:01

Das Ganze mag ja schön und gut sein, leider ist mir nicht ganz klar, wieso Du da jetzt Spherical Texture Mapping brauchst, bzw. wo genau das in's Spiel kommt.
Die Informationen über die Geometrie des Planeten entnimmst Du einer rechteckigen Heightmap? Die Farbinformationen aus normalen rechteckigen Texturen? Werden diese generiert oder statisch geladen? Denn bei Ersterem bietet sich für Dich eventuell ein Algorithmus deutlicher mehr an, der aus den Positionsdaten Geometrie erzeugt, die dann sogar beliebig skalierbar wäre - Perlin Noise sei hier nur ein mögliches und simples Beispiel. Ähnlich ließe es sich mit den Farb-Informationen handhaben (bzw. generierten Textur-Verteilungs-Maps). Aber ob das anwendbar wäre, hängt wie gesagt davon ab, woher Du Deine Daten für die Oberflächen beziehst.

PS:
Zu viel "Spore" gespielt? ;)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

5

29.12.2011, 12:26

Die Höhendaten und die Farbdaten werden mithilfe von Perlin Noise generiert, das ist richtig.
Der Perlin Noise Algorithmus benötigt x,y,z Koordinaten. Aber er ist sehr langsam, daher würde ich den gerne innerhalb eines Shaders berechnen lassen
und ihn dann in eine 2D Textur speichern.
Mein Algorithmus erzeugt aus Positionsdaten die Höhendaten und damit auch die Farbdaten, das ist richtig.
Aber der Algorithmus ist für Echtzeit auf dem PC zu langsam, er benötigt ca. 5 sekunden (auf einem 2.3 GHz Kern) für 65.536 Höhendaten (256x256).
Im Shader schafft er es in einer Sekunde eine wesentlich größere Menge an Werten zu berechnen.
Die Frage ist also im wesentlichen wie bekomme ich die Daten in 2D gespeichert um sie dann wieder in 3D zu extrahieren (idealerweise wieder im Shader).
Das wollte ich mit Spherical Texture Mapping machen. Aber wenn du eine bessere Idee hast wäre natürlich super.

Eher zu viel Minecraft und zu viele Sci Fiction Filme gesehen :)
Aber Spore war ja in der Hinsicht nicht sehr realistisch, die Planeten waren ja winzig.
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

29.12.2011, 12:40

Wozu in 2D speichern? Du brauchst doch nie alle Daten auf einmal und selbst 5-stufiges Perlin-Noise in einer 512*512 Textur ließe sich flüssig mit weiß der Geier wie viel FPS berechnen. Aber wie gesagt, Du brauchst ja nie alle auf einmal, kannst somit also massiv an Performance einsparen und es direkt im Shader machen. Wenn Du es unbedingt zwischenspeichern willst, wäre natürlich die nächste Überlegung die der Datenstruktur und des Aufbaus deiner Welten. Sind die nach dem Prinzip eines Globus aufgebaut oder eher als platonische Körper oder als Polygonmengen mit nahezu gleich großen Polygonen? Je nachdem brauchst Du eine andere Art des Mappings und es bieten sich Dir mehr oder weniger gute Möglichkeiten. Persönlich würde ich ja zu platonischen Körpern greifen und die Polygone je nach Detailstufe tesselieren.

Die Planeten bei Spore mögen winzig gewesen sein, aber nur in diesem Maßstab ist so etwas für Spieler vermutlich überhaupt noch handhabbar.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

7

29.12.2011, 12:53

Nein, das ist richtig, man könnte sowieso nicht alle Daten auf irgendeinem PC der Welt speichern :)
Es ist kein einfaches Perlin Noise. Ich habe das complexplanetBeispiel der libnoise in einen Shader umgesetzt. Das sind insgesamt 1536 Zeilen Code. In einem anderem Forumsbeitrag hatte ich das auch schon vorgestellt.
Auf meinem PC habe ich ca. 6 FPS gehabt.
Vielleicht erinnerst du dich ja an den Beitrag, denn du hast den auch kommentiert. Findest du hier.

Meine Welt ist im Prinzip grob gesehen in Hierarchische Sektoren gespeichert.
Der größte Sektor ist das Universum, in ihm befinden sich Super Galaxie Haufen. Jeder dieser Super Galaxie Haufen ist wieder ein Sektor, mit eigenem Koordinatensystem.
Darin befinden sich Galaxienhaufen und Einzelgalaxien. Jeder wieder ein Sektor mit eigenem Koordinatensystem und so weiter:
Root -> Super Galaxienhaufen -> Galaxienhaufen -> Galaxien -> Sternenhaufen -> Sonnensysteme -> Planeten -> Teil Planet -> noch keine Name -> Blöcke (ähnlich wie bei Minecraft)
Alles wird generiert, jedoch wird jede Änderung die der Spieler macht (in Minecraft-manier Blöcke verändern) gespeichert.
Wozu tesselieren? Die Anzahl der sichtbaren Flächen bleibt doch gleich. Nur haben sie eine andere Bedeutung, desto näher ich dem Planetengrund komme, und eine andere Textur!
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

8

29.12.2011, 13:22

Der Planet hat im Augenblick 3 verschiedene Stadien. Aus großer Entfernung wird er als Kugel behandelt,
näher dran wird nur eine gekrümmte Oberfläche verwendet, die zur Kamera hin rotiert wird und noch näher dran,
wird nur noch eine glatte Ebene benutzt, da eine Krümmung in der Nähe nicht mehr wahrnehmbar ist.
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

29.12.2011, 13:26

Wozu? :) Mit einer Ebene kannst Du doch nie "um die Welt laufen" ;)

Wozu tesselieren? Die Anzahl der sichtbaren Flächen bleibt doch gleich. Nur haben sie eine andere Bedeutung, desto näher ich dem Planetengrund komme, und eine andere Textur!

Du hast die Frage schon selbst beantwortet. Du brauchst verschiedene Detailstufen für verschiedene Entfernungen. Platonische Körper lassen sich perfekt tesselieren, die benötigen Infos für die Height bekommst Du aus Deinem Algo. Wenn er zu langsam ist zur Echtzeit-Berechnung, dann brauchst Du abhängig von der verwendeten Polygon-Struktur noch immer verschiedene Detail-Stufen in Deinen Maps, bzw. deutlich mehr Maps als nur eine. Aber Spherical Texture Mapping brauchst Du so richtig eigentlich nie, meiner Meinung nach. Hängt wie gesagt allerdings davon ab, wie Du Deine Kugeln aufbaust.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (29.12.2011, 13:31)


DarioFrodo

Treue Seele

  • »DarioFrodo« ist der Autor dieses Themas

Beiträge: 349

Wohnort: Kerkau, 100km nördlich von Magdeburg

Beruf: Selbstständig

  • Private Nachricht senden

10

29.12.2011, 14:00

Doch kann ich, denn die Ebene wird basierend auf dem Schnittpunkt zwischen Kamera und Planet ausgerichtet.
So wie eine Tangente an einem Graphen.
Wenn du also immer in eine Richtung läufst, ändert sich die Geometrie nicht. Aber die Textur und die Ausrichtung der Geometrie.
Ich brauche Maps in verschiedenen Detailstufen ja, aber sie werden erst generiert wenn sie benötigt werden.
Die alten kann ich dann löschen. Oder mal sehen ob es schneller geht sie erstmal im Speicher zu lassen, falls der Spieler in Naher Zukunft auf diese Detailstufe zurückkehrt.

Ich habe immer die gleiche Detailstufe für alle Entfernungen. Nur berechnet sich die Detailstufe der Geometrie in Abhängigkeit von der Entfernung der Geometrie zur Near-Plane.
Das heißt ob ich mich nun 100 km entfernt befinde, oder 10 km.., es wird dasselbe Vertex-Gitter angezeigt. Jedoch werden die Höhen und Farbdaten im Shader basierend, auf der vorberechneten Textur und der aktuellen Position und Entfernung, angepasst.

Vielleicht verstehst du ja so besser was ich meine, das habe ich grade aufgenommen (livestream-video)
edit: nicht mehr funktionierenden Link entfernt
Erst wenn der letzte Fluss vergiftet,
der letzte Baum gefällt,
der letzte Fisch gefangen,
dann werdet ihr merken, dass man Geld nicht essen kann

Man verkauft die Erde nicht, auf der die Menschen wandeln.

- Indianerweisheiten

Ich bin auch ein einhornimmond ;)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DarioFrodo« (29.07.2019, 18:14)


Werbeanzeige