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

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

1

06.05.2017, 21:00

Beliebigen Spawnpunkt auf einer Kugel berechnen

Hallo,
ich habe eine Kugel (Planet) mit einem Radius von 50. Ich möchte an der Stelle (X,Y,Z) ein Objekt spawnen lassen. Diese Stelle soll sich, vom Planetennittelpunkt aus gesehen, 2 Einheiten über der Oberfläche befinden. Dieses Objekt hat also eine Distanz von 52.

Nun möchte ich eine Formel dafür aufstellen, mir immer eine zufällig generierte gültige Position zurückzuliefern. Leider ist mein Mathe nach einigen Jahren dann doch sehr eingerostet und hoffe auf ein wenig Hilfe :)

Laut Google wäre die gesuchte Formel folgende:

"x² + y² + z² = r²

wobei r = 52"

Nun wäre ein Grundaufbau erst einmal folgender:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
private Vector3 GetSpawnPosition()
{
    float x;
    float y;
    float z;

    if(/* Koordinaten liegen innerhalb der Kugel */)
{
   // Koordinaten immer wieder neu auswürfeln
}

    return new Vector3(x, y, z);
}


Mindestens 1 Koordinate muss größer 51 sein, ansonsten würde sich das zu spawnende Objekt im Planeten befinden, so meine Überlegung. Da es aber auch negative Koordinaten gibt und das Objekt ja auch, gültig, bei (-51, 10, -20) liegen könnte, verkompliziert sich das Ganze nochmal.

Wäre super, wenn mir jemand dabei helfen könnte.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

2

06.05.2017, 21:34

Du könntest es einfach machen, indem du mit 2 zufälligen Winkeln arbeitest, anhand dieser Winkel einen Richtungsvektor vom Mittelpunkt zum Spawnpunkt erstellst und dann dessen Länge auf 52 setzt.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

06.05.2017, 21:36

Mit zufälligen Eulerwinkeln hat man allerdings eine höhere Wahrscheinlichkeit / Dichte nahe an den Polen. Ich würde einfach einen völlig zufälligen Vektor generieren, ihn normalisieren und dann eben mit 52 multiplizieren.
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]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

06.05.2017, 21:42

http://mathworld.wolfram.com/SpherePointPicking.html ;)

Ich würde einfach einen völlig zufälligen Vektor generieren, ihn normalisieren und dann eben mit 52 multiplizieren.

Das funktioniert ganz gut. Um dabei aber eine wirklich exakt gleichmäßige Verteilung auf der Kugelfläche zu erhalten, müssten die Koordinaten des Vektors gaußverteilt gewählt werden.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

5

06.05.2017, 21:45

Ist das so? Ich würde vermuten mit einer uniform_real_distribution zwischen 0 und 2Pi (zumindest in C++) würde man da ein ordentliches Ergebnis bekommen.

Edit: Ah ne, natürlich nicht. Da das ganze bei 2Pi ja wieder 0 ist, ist es natürlich wahrscheinlicher Winkel um 0° zu bekommen.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Nimelrian« (06.05.2017, 21:51)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

06.05.2017, 21:57

Ist das so? Ich würde vermuten mit einer uniform_real_distribution zwischen 0 und 2Pi (zumindest in C++) würde man da ein ordentliches Ergebnis bekommen.

Falls du das zufällige Wählen von sphärischen Koordinaten meinst: Das ist leider tatsächlich völlig unbrauchbar. Wie man z.B. hier schön sieht, fällt da selbst mit freiem Auge sofort auf, dass das nicht gleichverteilt sein kann. Der Grund dafür ist auch recht einfach zu verstehen: Du wählst einen zufälligen Längen- und Breitengrad. Wenn der Längengrad gleichverteilt ist, mappest du effektiv auf jeden Breitengrad die selbe Anzahl an Punkten. Der Umfang der Breitengrade nimmt aber zu den Polen hin ab (und zwar genau um den Kosinusfaktor). Wenn alle Breitengrade gleichwahrscheinlich sind, muss die Dichte der Punkte also zwangsweise zu den Polen hin zunehmen (und zwar genau um den Kosinusfaktor)...

Aus obiger Überlegung ergibt sich auch direkt die erste Variante aus dem von mir verlinkten Artikel: Anstatt jeden Breitengrad mit gleicher Wahrscheinlichkeit zu nehmen, nimmt man einen Breitengrad nur mit einer Wahrscheinlichkeit, die genau mit dem Kosinusfaktor abnimmt, um den die Punktdichte zu den Polen hin zunimmt. Beide Effekte heben sich gegenseitig exakt auf und man erhält eine gleichmäßige Verteilung auf der Kugel...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (06.05.2017, 22:07)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

06.05.2017, 21:59

Das Problem ist nicht die 0°, sondern dass an den Polen die Dichte einfach viel höher ist (10° Differenz sind am Äquator oder nahe am Pol unterschiedliche lange absolute Abstände).
Sieht man hier auch wunderbar:

(Link)

Quelle: http://mathworld.wolfram.com/Sphere.html

Bei meiner Random-Vector-Variante gibt es immer noch Häufungen in gewissen Arealen, allerdings weniger schlimm. Dot hatte aber den passenden Link für eine ideale Variante parat :)

Edit: :ninja:
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]

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

8

06.05.2017, 22:27

Ich habe hier mal einen Codefetzen ausgegraben, den ich gleich mal testen werde

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
private Vector3 GetSpawnPosition()
    {
        float pan = Random.Range(0, 2 * Mathf.PI);
        float tilt = Random.Range(0, 2 * Mathf.PI);

        float yr = Mathf.Cos(tilt) * (data.PlanetRadius);

        float x = Mathf.Sin(pan) * (yr);
        float y = Mathf.Sin(tilt) * (data.PlanetRadius);
        float z = Mathf.Cos(pan) * (yr);

        return new Vector3(x, y, z);
    }

Renegade

Alter Hase

Beiträge: 494

Wohnort: Berlin

Beruf: Certified Unity Developer

  • Private Nachricht senden

9

06.05.2017, 23:25

Captain here!

Ich nehme mal an, du nutzt Unity:
Vector3 position = Random.onUnitSphere * 52;

PS: Deine Methode über mir sollte korrekterweise CalculateSpawnPosition heißen.

*flies away*
Liebe Grüße,
René

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Renegade« (06.05.2017, 23:52)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

07.05.2017, 11:59

Ich habe hier mal einen Codefetzen ausgegraben, den ich gleich mal testen werde [...]

Das ist halt genau die naive Methode die, wie besprochen, eine relativ schlechte Verteilung gibt... ;)

Werbeanzeige