Hat jemand einen Algorithmus zum Erzeugen einer Kugelprozedur mit einer la
Anzahl von Breitengradlinien, einer lo
Anzahl von Längengradlinien und einem Radius von r
? Ich brauche es, um mit Unity zu arbeiten, also müssen die Scheitelpunktpositionen definiert und dann die Dreiecke über Indizes definiert werden ( weitere Informationen ).
BEARBEITEN
Ich habe es geschafft, den Code in einer Einheit zum Laufen zu bringen. Aber ich glaube, ich hätte etwas falsch gemacht. Wenn ich das aufklappe detailLevel
, füge ich einfach mehr Eckpunkte und Polygone hinzu, ohne sie zu verschieben. Hab ich was vergessen
BEARBEITEN 2
Ich habe versucht, das Netz entlang seiner Normalen zu skalieren. Das habe ich bekommen. Ich glaube, ich vermisse etwas. Soll ich nur bestimmte Normalen skalieren?
quelle
vertices[i] = normalize(vertices[i])
. Übrigens gibt Ihnen dies auch Ihre neuen, korrekten Normalen, also sollten Sie diesnormals[i] = vertices[i]
später tun .Antworten:
Um so etwas zu bekommen:
Erstellen Sie ein Ikosaeder (20-seitiger regelmäßiger Körper) und unterteilen Sie die Flächen, um eine Kugel zu erhalten (siehe Code unten).
Die Idee ist im Grunde:
Unterteilen Sie jedes Gesicht in vier gleich große Gesichter. Jedes Mal, wenn Sie dies tun, wird die Anzahl der Flächen im Modell vervierfacht.
i0
,i1
Undi2
sind die Eckpunkte des ursprünglichen Dreiecks. (Eigentlich Indizes in den Vertex-Puffer, aber das ist ein anderes Thema).m01
ist der Mittelpunkt der Kante(i0,i1)
, m12 ist der Mittelpunkt der Kante(i1,12)
undm02
ist offensichtlich der Mittelpunkt der Kante(i0,i2)
.Wenn Sie eine Fläche unterteilen, stellen Sie sicher, dass Sie keine doppelten Scheitelpunkte erstellen. Jeder Mittelpunkt wird von einer anderen Quellfläche geteilt (da die Kanten von Flächen geteilt werden). Der folgende Code berücksichtigt dies, indem er ein Wörterbuch mit benannten Mittelpunkten verwaltet, die erstellt wurden, und den Index eines zuvor erstellten Mittelpunkts zurückgibt, wenn er verfügbar ist, anstatt einen neuen zu erstellen.
Wiederholen Sie diesen Vorgang, bis Sie die gewünschte Anzahl von Flächen für Ihren Würfel erreicht haben.
Wenn Sie fertig sind, normalisieren Sie alle Scheitelpunkte, um die Oberfläche zu glätten. Wenn Sie dies nicht tun, erhalten Sie statt einer Kugel nur ein Ikosaeder mit höherer Auflösung.
Voila! Sie sind fertig. Konvertieren Sie die resultierenden Vektor- und Indexpuffer in ein
VertexBuffer
undIndexBuffer
und zeichnen Sie mitDevice.DrawIndexedPrimitives()
.Folgendes würden Sie in Ihrer "Sphere" -Klasse verwenden, um das Modell zu erstellen (XNA-Datentypen und C #, aber es sollte ziemlich klar sein):
Und die
GeometryProvider
Klassequelle
int
Array? Und was macht der.Select(i => i + vertices.Count)
?.Select(i => i + vertices.Count)
funktioniert bei mir überhaupt nicht. Ist es nur eine XNA-Funktion?Betrachten wir die parametrische Definition einer Kugel:
wobei Theta und Phi zwei inkrementelle Winkel sind, die wir als
var t
und bezeichnen,var u
und Rx, Ry und Rz die unabhängigen Radien (Radien) in allen drei kartesischen Richtungen sind, die im Fall einer Kugel als eine einzige definiert werden Radiusvar rad
.Betrachten wir nun die Tatsache, dass das
...
Symbol eine Iteration anzeigt, die auf die Verwendung einer Schleife hindeutet. Das Konzept vonstacks
undrows
lautet "Wie oft werden Sie iterieren". Da jede Iteration den Wert von t oder u addiert, ist die Krümmung der Kugel umso genauer, je mehr Iterationen vorhanden sind.Die Voraussetzung der ‚Sphäre Zeichnung‘ Funktion ist es, die folgenden Parameter gegeben haben:
int latitudes, int longitudes, float radius
. Die Nachbedingung (Ausgabe) ist, die berechneten Eckpunkte zurückzugeben oder anzuwenden. Abhängig davon, wie Sie dies verwendenvector3
möchten , kann die Funktion ein Array von (dreidimensionalen) Vektoren zurückgeben. Wenn Sie vor Version 2.0 eine Art einfaches OpenGL verwenden, möchten Sie die Scheitelpunkte möglicherweise direkt auf den Kontext anwenden.NB Das Anwenden eines Scheitelpunkts in openGL ruft die folgende Funktion auf
glVertex3f(x, y, z)
. In dem Fall, in dem wir die Eckpunkte speichern würden, würden wirvector3(x, y, z)
zur einfachen Speicherung einen neuen hinzufügen .Auch die Art und Weise, wie Sie das Längen- und Breitengradsystem zum Arbeiten aufgefordert haben, erforderte eine Anpassung der Definition der Kugel (im Grunde genommen Umschalten von z und y), aber dies zeigt nur, dass die Definition sehr formbar ist und dass Sie frei umschalten können x-, y- und z-Parameter, um die Richtung zu ändern, in die die Kugel gezeichnet wird (wo die Breiten- und Längengrade liegen).
Nun schauen wir uns an, wie wir die Breiten- und Längengrade machen werden. Die Breiten werden durch die Variable dargestellt
u
, sie iterieren von 0 bis 2π Radianten (360 Grad). Wir können seine Iteration daher wie folgt codieren:Jetzt werden die Längengrade durch die Variable dargestellt
t
und für 0 bis π (180 Grad) iteriert. Daher sieht der folgende Code dem vorherigen ähnlich:(Beachten Sie, dass Schleifen die Endbedingung einschließen , da das Intervall für die parametrische Integration zwischen 0 und 2π liegt. Einschließlich . Sie erhalten eine Teilkugel, wenn Ihre Bedingungen nicht einschließen.)
Nach der einfachen Definition der Kugel können wir nun die Variablendefinition wie folgt ableiten (annehmen
float rad = radius;
):Noch eine wichtige Warnung! In den meisten Fällen verwenden Sie OpenGL in irgendeiner Form, und selbst wenn dies nicht der Fall ist, müssen Sie dies möglicherweise noch tun. Für ein dreidimensionales Objekt müssen mehrere Eckpunkte definiert werden. Dies wird im Allgemeinen erreicht, indem der nächste berechenbare Scheitelpunkt bereitgestellt wird.
Wie in der Abbildung oben die verschiedenen Koordinaten sind
x+∂
undy+∂
, können wir leicht drei weitere Eckpunkte für jede gewünschte Verwendung generieren. Die anderen Eckpunkte sind (angenommenfloat rad = radius;
):Schließlich ist hier eine funktionierende Vollfunktion, die alle Eckpunkte einer Kugel zurückgibt, und die zweite zeigt eine funktionierende OpenGL-Implementierung des Codes (dies ist eine C-Syntax und kein JavaScript, dies sollte mit allen C-Sprachen funktionieren, einschließlich C # bei Verwendung von Unity).
OpenGL-Code:
PS Möglicherweise haben Sie diese Aussage bemerkt
rad = radius;
. Auf diese Weise kann der Radius in der Schleife basierend auf der Position oder dem Winkel geändert werden. Dies bedeutet, dass Sie die Kugel rauschen können, um sie aufzurauen, sodass sie natürlicher aussieht, wenn der gewünschte Effekt einem Planeten ähnelt. Z.Bfloat rad = radius * noise[x][y][z];
Claude-Henry.
quelle
rad
. Jetzt machst du das eine Bein eines Dreiecks und implizierst, dass die Hypotenuse des Dreiecks auch istrad
. Dies gibt Ihnen effektiv einen Radius vonrad * sqrt(2)
.Ich habe so etwas vor einiger Zeit geschaffen, um aus Spaß und Wissenschaft eine Kugel aus Würfeln zu machen. Es ist nicht zu schwer. Im Grunde genommen nehmen Sie eine Funktion, die einen Kreis von Eckpunkten erzeugt, und gehen dann die Höheninkremente durch, bei denen Sie Kreise in jeder Höhe mit dem Radius erzeugen möchten, der zum Erzeugen einer Kugel erforderlich ist. Hier habe ich den Code geändert, damit er nicht für Cubes gilt:
Jetzt würde dieser Code nur noch Punkte für den Breitengrad erzeugen. Sie können jedoch fast den gleichen Code verwenden, um die Längengradlinien zu erstellen. Es sei denn, Sie müssen zwischen den einzelnen Iterationen rotieren und jeweils einen vollständigen Kreis bilden
degreeStep
.Entschuldigung, dies ist keine vollständige Antwort oder Unity-spezifisch, aber hoffentlich können Sie damit anfangen.
quelle
Könnte man nicht einfach mit einer einfachen Form beginnen, könnte es sich um ein Kästchen mit einem Abstand von der Mitte zur Ecke handeln. Um eine detailliertere Kugel zu erstellen, unterteilen Sie alle Polygone und verschieben Sie die Scheitelpunkte in einen Abstand von der Mitte, sodass der Vektor ihre aktuelle Position durchläuft.
Wiederholen Sie den Vorgang, bis er kugelförmig genug für Ihren Geschmack ist.
quelle
Benötigen Sie tatsächlich die 3D-Geometrie oder nur die Form?
Sie können eine gefälschte Kugel mit einem einzigen Quad erstellen. Setzen Sie einfach einen Kreis darauf und schattieren Sie es richtig. Dies hat den Vorteil, dass es unabhängig von der Entfernung zur Kamera oder der Auflösung genau die erforderliche Auflösung hat.
Hier gibt es ein Tutorial .
quelle
Hier ist ein Code für eine beliebige Anzahl von gleich beabstandeten Eckpunkten einer Kugel, der wie eine Orangenschale eine Linie von Punkten in einer Spirale um eine Kugel windet. Danach liegt es an Ihnen, wie Sie die Scheitelpunkte verbinden. Sie können Nachbarpunkte in der Schleife als 2 jedes Dreiecks verwenden und dann feststellen, dass der dritte Punkt eine proportionale Verdrehung um die Kugel ist, die höher oder tiefer liegt Kennen Sie einen besseren Weg?
};
quelle
Obwohl David in seiner Antwort absolut richtig ist, möchte ich eine andere Perspektive anbieten.
Für meine Aufgabe zur prozeduralen Inhaltsgenerierung habe ich unter anderem Ikosaeder im Vergleich zu traditionelleren unterteilten Sphären betrachtet. Schauen Sie sich diese prozedural erzeugten Bereiche an:
Beide sehen aus wie vollkommen gültige Kugeln, oder? Schauen wir uns die Drahtgitter an:
Wow, was ist da passiert? Die Drahtmodellversion der zweiten Kugel ist so dicht, dass sie texturiert aussieht! Ich werde Ihnen ein Geheimnis verraten: Die zweite Version ist ein Ikosaeder. Es ist eine fast perfekte Kugel, aber sie hat einen hohen Preis.
Kugel 1 verwendet 31 Unterteilungen auf der x-Achse und 31 Unterteilungen auf der z-Achse für insgesamt 3.844 Flächen.
Sphere 2 verwendet 5 rekursive Unterteilungen für insgesamt 109.220 Gesichter.
Aber okay, das ist nicht wirklich fair. Verringern wir die Qualität erheblich:
Kugel 1 verwendet 5 Unterteilungen auf der x-Achse und 5 Unterteilungen auf der z-Achse für insgesamt 100 Flächen.
Sphere 2 verwendet 0 rekursive Unterteilungen für insgesamt 100 Gesichter.
Sie verwenden die gleiche Anzahl von Gesichtern, aber meiner Meinung nach sieht die linke Kugel besser aus. Es sieht weniger klumpig und viel runder aus. Schauen wir uns an, wie viele Gesichter wir mit beiden Methoden erzeugen.
Ikosaeder:
Unterteilte Kugel:
Wie Sie sehen können, nimmt der Ikosaeder in Gesichtern exponentiell zu, um eine dritte Potenz! Das liegt daran, dass wir sie für jedes Dreieck in drei neue Dreiecke unterteilen müssen.
Die Wahrheit ist: Sie müssen nicht brauchen die Präzision ein Ikosaeder wird dir geben. Weil beide ein viel schwierigeres Problem verstecken: die Texturierung einer 2D-Ebene auf einer 3D-Kugel. So sieht die Oberseite aus:
Oben links sehen Sie die verwendete Textur. Zufällig wird es auch prozedural generiert. (Hey, es war ein Kurs zur prozeduralen Generierung, oder?)
Es sieht schrecklich aus, oder? Nun, das ist so gut wie es nur geht. Ich habe Bestnoten für mein Textur-Mapping bekommen, weil die meisten Leute es nicht einmal so richtig verstehen.
Überlegen Sie sich also, Cosinus und Sinus zu verwenden, um eine Kugel zu erzeugen. Bei gleicher Detailgenauigkeit werden deutlich weniger Gesichter generiert.
quelle
N
Teile verwenden, erhalten SieN*N
neue Dreiecke, die quadratisch sind, genau wie Sie es mit der UV-Kugel tun.Das folgende Skript erstellt ein Ikosaeder mit n Polygonen ... Basis 12. Es unterteilt die Polygone auch in separate Maschen und berechnet die Gesamtzahl der Vert-Duplikate und Polygone.
Ich konnte nichts Ähnliches finden, also habe ich das erstellt. Hängen Sie das Skript einfach an ein GameObject an und legen Sie die Unterteilungen im Editor fest. Als nächstes wird an der Modifikation des Rauschens gearbeitet.
quelle