blog · git · desktop · images · contact & privacy · gopher


Art of Illusion: Helix-Script

Aus Spaß an der Freude hier das nächste Script für AoI, mit dem man endlich Ringelschwänzchen machen kann. ;)

Ringelschwänzchen

Ich werde die Benutzung hier nicht weiter erläutern, da sie in der im Archiv enthaltenen PDF relativ ausführlich beschrieben ist.

Download inklusive Dokumentation:

Was macht das Ding?

"Eigentlich simpel": Man zieht eine primitive Kurve in beliebiger Form in AoI auf und das Script legt (gemäß der angegebenen Parameter) eine Spirale entlang dieser sogenannten Richtkurve. Damit ist es dann möglich, Telefonkabel, Schläuche für LKW's oder eben ein Ringelschwänzchen für das Lieblingsschwein sehr leicht zu modellieren.

Wie gesagt, zur Benutzung steht einiges in der PDF.

Funktionsweise

Das Script arbeitet quasi direkt auf der Richtkurve. Ihre Punkte werden nacheinander paarweise durchlaufen, zu einem Punktepaar dann ein senkrechter Vektor bestimmt und dieser letztendlich spiralenförmig noch einmal um den lokalen Richtvektor gedreht.

Veranschaulichung der Vektoren

Man sieht zwei Punkte mit ihren Ortsvektoren 1 und 2. Vektor 1 wird von Vektor 2 abgezogen, so erhält man dann den lokalen Richtvektor Nummer 3. Durch diesen Richtvektor ist es dann möglich, die aktuelle Krümmung der Kurve in diesem Bereich zu bestimmen. Dazu wird erst einmal das Kreuzprodukt von Vektor 1 und 2 gebildet, um einen weiteren Vektor zu erhalten, welcher senkrecht auf 1 und 2 steht und damit auch senkrecht auf Vektor 3. Dreht man nun Vektor 3 um 90 Grad um diesen neuen Vektor, so hat man (bildlich gesprochen) die aktuelle Krümmung der Kurve nach "außen geklappt" - und erhält damit Vektor 4. Dieser ist in der Illustration lediglich etwas gestaucht worden, damit er besser ins Bild passt. ;)

Vektor 4 kann nun wieder um den lokalen Richtvektor 3 gedreht werden - der Winkel für diese Drehung steigt beim Durchschreiten der Kurve linear an, sodass die gedrehten Vektoren mit der Nummer 4 eine Spirale um die Kurve herum bilden. Den finalen Punkt für die neue Kurve erhält man dann, indem der gedrehte Vektor 4 zu Vektor 1 addiert wird.

Bei Bedarf wird der gedrehte Vektor 4 vorher noch normalisiert und hiernach auf die eingestellte Länge hochskaliert, sodass alle Radien der Spirale gleich sind.

Arbeitet man auf einer Richtkurve mit wenig Punkten, so kann diese vor der Verarbeitung noch um einen beliebigen Wert unterteilt werden. Glücklicherweise beachtet AoI hier das Smoothing, sodass die resultierende Kurve dieselbe Geometrie aufweist, bloß mit mehr Punkten.

Da sich das Script aber direkt an den Punkten der Richtkurve orientiert, folgt daraus, dass die Dichte der Spirale direkt von der Dichte der Punkte auf der Richtkurve abhängt - der Winkel für die Drehung von Vektor 4 wird nämlich pro Punkt auf der Richtkurve erhöht (und nicht im Bezug auf die Gesamtlänge der Kurve).

Auch ist jetzt leicht ersichtlich, dass sich so über die Dichte der Richtkurve der Radius der Spirale steuern lässt, wenn man die Normalisierung weglässt. Das kann man auch schön an der Illustration oben erkennen: Ohne Normalisierung wäre Vektor 4 genauso lang wie Vektor 3 und damit vom Abstand der Punkte abhängig.

Randbemerkung: Jetzt, da ich diese Erklärung schreibe, fällt mir auch auf, dass der grüne Vektor 4 überflüssig ist - das Kreuzprodukt von 1 und 2 würde bereits reichen. In der nächsten Version werde ich das Script dahingehend etwas entschlacken.

Vektoren in Art of Illusion drehen

An diesem Punkt saß ich einige Stunden, da ich nun nicht gerade der Top-Mathematiker/Physiker bin, mir aber scheinbar eine Methode selbst schreiben musste, um einen Vektor um einen anderen zu drehen - bis ich dann endlich geschnallt hatte, dass man Vektoren mittels spezieller Matrizen umeinander drehen kann.

Und siehe da: AoI bietet dafür fertige Funktionen, sodass man mit der AoI-API in einer Zeile einen Vektor um einen anderen drehen kann. Wenn man bereits zwei Vektoren, also Objekte vom Typ Vec3, hat, dann reicht folgendes, um a um 90 Grad um ein beliebiges b zu drehen:

Vec3 out = Mat4.axisRotation(b.normalize(), Math.PI / 2.0).times(a);

b wird dabei auch gleich normalisiert, wenn das noch nicht geschehen ist.

Ich erwähne das deshalb, weil das eine ziemlich mächtige Funktion ist, die man relativ oft braucht - da ist es gut zu wissen, dass es derart einfach geht. :)