Wie erzeugt man programmatisch eine Kugel?

25

Könnte jemand bitte erklären, wie es möglich wäre, Kugelscheitelpunkte, Indizes und Texturkoordinaten zu erstellen? Es gibt einen überraschenden Mangel an Dokumentation, und es ist etwas, das ich lernen möchte.

Ich habe das Offensichtliche ausprobiert, gegoogelt, auf gamedev.net nachgesehen usw. Allerdings deckt nichts die Generationen von sphärischen Punkten ab, indiziert sie und texturiert sie.

judeclarke
quelle
6
Ich werde nicht abstimmen oder abstimmen, um dies abzuschließen, aber sagen Sie mir wirklich, dass kein einziges Ergebnis von google.com/search?q=how+to+generate+a+sphere+vertices nützlich war? In diesem Fall müssen Sie das Problem genauer erläutern.
Suche nach icosphere. Viel schlauer als eine blöde "Polarkugel", die nutzlose Gesichter hervorbringt.
Notabene
3
Bemerkenswert ist, dass für einige einfache Zwecke eine perfekt feine "Kugel" ein Quad mit einer kreisförmigen Textur ist, die der Kamera zugewandt ist.
aaaaaaaaaaa 30.08.11
Hier ist, wie ich es für den Skydome in meinem Spiel implementiert habe.
Danijar

Antworten:

36

Es gibt zwei allgemeine Ansätze:

Bildbeschreibung hier eingeben

Die äußerste linke Sphäre wird als UV-Sphäre und die äußerste rechte als Icosphäre bezeichnet.

GLUT verwendet in der Regel den UV-Ansatz: Sehen Sie sich die Funktion glutSolidSphere()im Freeglut-Quellcode an .

Hier ist ein ausgezeichneter Artikel zum Erstellen einer Icosphere: http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html

Die UV-Kugel sieht aus wie ein Globus. Für viele Zwecke ist es vollkommen in Ordnung, aber für einige Anwendungsfälle, z. B. wenn Sie die Kugel verformen möchten, ist es nachteilig, dass die Dichte der Scheitelpunkte um die Pole herum größer ist. Hier ist die Icosphäre besser, ihre Scheitelpunkte sind gleichmäßig verteilt.

Das könnte Sie auch interessieren: http://kiwi.atmos.colostate.edu/BUGS/geodesic/text.html Es beschreibt einen Ansatz zum Organisieren der Gesichter in Zonen.

http://vterrain.org/Textures/spherical.html enthält eine hervorragende Beschreibung, wie Sie sie möglicherweise texturieren möchten.

Wille
quelle
2
Obwohl die allgemeine Idee gut ist, ist die Unterteilung eines Schläfli {3,5} -Polytops nicht die einzige Möglichkeit, dies zu tun. Im Allgemeinen bevorzuge ich die Arbeit mit der Schläfli {4, *} -Familie ({4,3} im Falle einer Kugel) für UV-Mapping-Zwecke.
Martin Sojka
Fein tessellierte ikosaedrische Kugeln sind etwas teurer zu erzeugen, da die Flächen rekursiv unterteilt werden müssen.
Bobobobo
9

Es gibt zwei Möglichkeiten:

  1. Wandeln Sie Theta und Phi in sphärischen Koordinaten, erzeugen Sie Gesichter und Tris

  2. Erstellen Sie ein Ikosaeder und unterteilen Sie die Flächen rekursiv, bis die gewünschte Tessellation erreicht ist.

Kugel mit sphärischen Koordinaten gehen

Für den ersten Weg benutzt man einfach ein doppeltes Nest, um Theta und Phi zu laufen. Während Sie Theta und Phi laufen, drehen Sie Dreiecke, um Ihre Kugel zu erzeugen.

Bildbeschreibung hier eingeben

Der Code dafür sieht ungefähr so ​​aus:

for( int t = 0 ; t < stacks ; t++ ) // stacks are ELEVATION so they count theta
{
  real theta1 = ( (real)(t)/stacks )*PI ;
  real theta2 = ( (real)(t+1)/stacks )*PI ;

  for( int p = 0 ; p < slices ; p++ ) // slices are ORANGE SLICES so the count azimuth
  {
    real phi1 = ( (real)(p)/slices )*2*PI ; // azimuth goes around 0 .. 2*PI
    real phi2 = ( (real)(p+1)/slices )*2*PI ;

    //phi2   phi1
    // |      |
    // 2------1 -- theta1
    // |\ _   |
    // |    \ |
    // 3------4 -- theta2
    //

    //vertex1 = vertex on a sphere of radius r at spherical coords theta1, phi1
    //vertex2 = vertex on a sphere of radius r at spherical coords theta1, phi2
    //vertex3 = vertex on a sphere of radius r at spherical coords theta2, phi2
    //vertex4 = vertex on a sphere of radius r at spherical coords theta2, phi1

    // facing out
    if( t == 0 ) // top cap
      mesh->addTri( vertex1, vertex3, vertex4 ) ; //t1p1, t2p2, t2p1
    else if( t + 1 == stacks ) //end cap
      mesh->addTri( vertex3, vertex1, vertex2 ) ; //t2p2, t1p1, t1p2
    else
    {
      // body, facing OUT:
      mesh->addTri( vertex1, vertex2, vertex4 ) ;
      mesh->addTri( vertex2, vertex3, vertex4 ) ;
    }
  }
}

Beachten Sie daher, dass es wichtig ist, die obere und die untere Kappe nur mit Tris und nicht mit Quads zu wickeln.

Ikosaedrische Kugel

Um ein Ikosaeder zu verwenden, erzeugen Sie einfach die Punkte des Ikosaeders und wickeln dann Dreiecke daraus auf. Die Eckpunkte eines Ikosaeders, das am Ursprung sitzt, sind:

(0, ±1, ±φ)
1, ±φ, 0)
(±φ, 0, ±1)
where φ = (1 + 5) / 2 

Sie müssen dann nur ein Diagramm eines Ikosaeders und Windflächen von diesen Vert betrachten. Ich habe bereits Code, der das hier macht .

Bobobobo
quelle
Irgendwelche Ideen, wie man den halben Körper wie von Theta = pi / 4 zu Theta = 3pi * 4 bekommt? Dieses Bild gefällt mir: i.stack.imgur.com/Jjx2c.jpg Ich habe Tage damit verbracht, dieses Problem zu lösen.
Tina J
3

Wenn die Punkte müssen nicht lokal einheitlich sein, sollte aber global einheitlich sein, und haben keine festen Muster zu folgen, können Sie eine Variante des Dart-Wurf - Algorithmus verwenden zu verteilen n Punkte auf einer Kugel mit dem Radius r , im Durchschnitt dist Punkte auseinander. Diese Werte sind dann ungefähr:

  1. Wenn Sie eine bestimmte Anzahl von Scheitelpunkten haben möchten:
    • n = (gewünschte Anzahl von Eckpunkten)
    • dist = 2 × r × √ ( π / n )
  2. Wenn Sie einen bestimmten durchschnittlichen Abstand zwischen den Eckpunkten haben möchten:
    • n = 4 × π × ( r / dist ) 2
    • dist = (gewünschte durchschnittliche Entfernung)

Im einfachsten Fall können Sie dann Punkte gleichmäßig zufällig auswählen, indem Sie aus (0, 1) zwei gleichmäßig verteilte Variablen u und v auswählen und daraus die Polarkoordinaten nach den Formeln θ = 2 × π × u und ϕ = Bogen berechnen cos (2 × v - 1); Anschließend werden alle Punkte verworfen, die zu nahe an den bereits ausgewählten Punkten liegen. Für einen etwas komplexeren und wesentlich leistungsfähigeren Algorithmus siehe " Dart Throwing on Surfaces " von Cline, Jeschke, White, Razdan und Wonka.

Nachdem Sie Ihre ersten vier Punkte ausgewählt haben (vorausgesetzt, keine drei davon sind degeneriert , das heißt, sie liegen nicht auf demselben großen Kreis, aber das ist höchst unwahrscheinlich), können Sie vier Gesichter zwischen ihnen erstellen und jedes Mal ein neues hinzufügen Neuer Punkt, Sie können das Gesicht, zu dem es gehört, entsprechend in drei Untergesichter aufteilen.

Zu Texturierungszwecken können Sie die Punkte dann einer Würfelkarte zuordnen.

Martin Sojka
quelle