Wir komplizieren Sci-Fi-Modelle prozedural: Was ist Greeble und wie wird es verwendet?

Bild

Lassen Sie mich zunĂ€chst beklagen, dass „greeble“ ein schreckliches Wort ist, das aus dem Wörterbuch verbannt werden muss.

Nun, indem wir den Stein von der Seele entfernen, wenden wir uns den ErklĂ€rungen zu. Greeble sind kleine, sich wiederholende Details, die einem Modell einen gewissen Maßstab und eine gewisse Ästhetik verleihen. Pilze sind populĂ€r geworden dank klassischer Science-Fiction-Filme, in denen die physische Skulptur oft das „Modell“ war:


Wenn Sie aus meinem Extrusions-Tutorial bereits wissen, wie Sie prozedurale Maschen extrudieren, wissen Sie, wie Sie Pilze hinzufĂŒgen. Das HinzufĂŒgen einfacher Pilze zum Netz kann durch Extrudieren aller Netzpolygone auf eine zufĂ€llige LĂ€nge erreicht werden .

Möglicherweise haben Sie jedoch bemerkt, dass im obigen Lernprogramm nur extrudierte Dreiecke betrachtet werden, wÀhrend das Bild am Anfang des Artikels quadratische Pilze darstellt. Ich musste das Netz so anpassen, dass es in Vierecke unterteilt war, und viele Netze bestanden oft aus Polygonen mit mehr als drei Indizes. In diesem Tutorial lernen wir daher, wie man ein Polygon mit n Indizes extrudiert und diesen Algorithmus auf das gesamte Netz anwendet, um Pilze zu erzeugen. Wir haben auch einige Möglichkeiten kennengelernt, wie Sie Variationen im Pilz-Algorithmus vornehmen können, um weniger einheitliche Ergebnisse zu erzielen.

OberflÀchennormal


Lassen Sie uns zunÀchst herausfinden, wie die Normalen eines Polygons mit beliebigen n Indizes berechnet werden. Wenn wir davon ausgehen können, dass dieses Polygon planar ist, dh alle seine Scheitelpunkte auf derselben Ebene liegen, unterscheidet sich der Prozess nicht von der Berechnung der Normalen eines Polygons mit drei Indizes.

Die OberflÀchennormale ist die Senkrechte zur FlÀche des Polygons, die berechnet werden kann, indem das Vektorprodukt von zwei Vektoren genommen wird, die entlang der Kante des Polygons zeigen .

Dann normalisieren wir diesen Vektor so, dass seine LÀnge 1 ist, da wir von der Normalen zur OberflÀche nur die Richtung brauchen, nicht die LÀnge.

  Funktion getFaceNormal (mesh, poly)
   Vec3 v1 = mesh: getVertex (poly [1])
   Vec3 v2 = mesh: getVertex (poly [2])
   Vec3 v3 = mesh: getVertex (poly [3])
   Vec3 e1 = v2 - v1
   Vec3 e2 = v3 - v2
   Vec3 normal = e1: kreuz (e2)
   RĂŒckkehr normal: normalize ()
 ende 

Wenn wir nicht sicher davon ausgehen können, dass das Polygon planar ist, bevorzugt der oben dargestellte Algorithmus die Ebene, auf der sich die ersten beiden Indizes befinden. FĂŒr eine genauere Darstellung der Richtung, in die das Polygon zeigt, können wir stattdessen den Durchschnitt aller Vektorprodukte der Kanten nehmen :

  Funktion getFaceNormal (mesh, poly)
   Vec3 n = Vec3 (0, 0, 0)
   fĂŒr i = 1 gilt #poly -2
     Vec3 v1 = mesh: getVertex (poly [1])
     Vec3 v2 = mesh: getVertex (poly [1+ i])
     Vec3 v3 = mesh: getVertex (poly [2+ i])
     n: addiere ((v2 - v1): kreuz (v3 - v1))
   ende
   return n: normalize ()
 ende 


Ein Beispiel fĂŒr die Extrusion eines planaren Vierecks.

Extrudieren


Nachdem wir nun Informationen ĂŒber die OberflĂ€chennormale haben, können wir das Polygon in normaler Richtung extrudieren. Einfach ausgedrĂŒckt, zum Extrudieren des Polygons erstellen wir neue Scheitelpunkte, indem wir die alten Scheitelpunkte in Richtung der OberflĂ€chennormalen verschieben.

AusfĂŒhrlicher:

  1. Erstellen Sie neue Peaks "ĂŒber" den alten in der normalen Richtung.

    Neue Eckpunkte können wie folgt berechnet werden:

      (Position des alten Peaks) + (normale Richtung) 

    Dadurch wird die alte Position in Richtung der OberflÀchennormalen verschoben.

    Schauen Sie sich zum Beispiel das Bild oben an, auf dem sich v1 in der normalen Richtung zu v5 bewegt.
  2. Erstellen Sie Vierecke , um die neuen und alten Eckpunkte zu verbinden.

    Es ist zu beachten, dass fĂŒr jeden Index im neuen Polygon ein neues Viereck erstellt wird.

    Sehen Sie sich zum Beispiel ein Quad an, das aus v8, v7, v3 und v4 erstellt wurde .
  3. Ersetzen Sie das alte Polygon durch ein neues Polygon, das durch neue Scheitelpunkte erstellt wurde. Sehen Sie sich zum Beispiel ein Quad an, das aus v5, v6, v7 und v8 erstellt wurde.


  Funktion extrudePoly (Mesh, PolyIndex, LĂ€nge)
   int [] poly = mesh.polys [polyIndex]
   int [] newPoly = []
   Vec3 n = getFaceNormal (mesh, poly)

   - (1) Erstellen Sie extrudierte Verts
   fĂŒr j = 1 #poly do
     lokales p = mesh: getVertex (poly [j])
     newPoly [#newPoly + 1] = # mesh.verts
     - LĂ€nge bestimmt die LĂ€nge der Extrusion
     mesh: addVertex (p + (n * LĂ€nge))
   ende

   - (2) Extrusionsseiten mit Quads nÀhen
   fĂŒr j0 = 1 #poly do
     lokal j1 = j0% #poly + 1
     mesh: addQuad (
       poly [j0],
       poly [j1],
       newPoly [j1],
       newPoly [j0]
     )
   ende

   - (3) Verschieben Sie das vorhandene Gesicht in extrudierte Verticies
   fĂŒr j = 1 #poly do
     mesh.polys [pi] [j] = newPoly [j]
   ende
 ende 


GleichmĂ€ĂŸiges Pilzen.

Alle Maschen pilzen


Jetzt, da wir die Funktion getSurfaceNormal () und die Funktion extrude () haben, ist das Pilzesammeln sehr einfach! Wir wenden einfach die extrude () -Funktion auf jedes Polygon an . Wir verwenden Extrudieren mit einer zufĂ€lligen LĂ€nge, sodass jedes extrudierte Polygon eine leicht unterschiedliche GrĂ¶ĂŸe hat, wodurch ein GefĂŒhl der Textur entsteht. Der unten gezeigte Algorithmus wird auf den oben dargestellten WĂŒrfel angewendet, der vollstĂ€ndig aus Vierecken besteht.

  Funktion greeble (mesh)
   fĂŒr i = 1 gilt # mesh.polys
     - Diese Zufallswerte sind beliebig: p
     float length = random: getUniformRange (0.1, 1.0)
     extrudePoly (mesh, i, length)
   ende
   Netz zurĂŒckgeben
 ende 

Herzlichen GlĂŒckwunsch, unser Pilzesammeln hat verdient. Aber wir können noch mehr! Jetzt ist das Pilzen ziemlich einheitlich. Hier sind zwei Beispiele fĂŒr Modifikationen, um es interessanter zu machen.


Änderung 1: Das Vorhandensein von Pilzen hĂ€ngt vom Zufall ab


Es ist ganz einfach: Wirf einfach den WĂŒrfel, um festzustellen, ob die Pilze auf jedes Polygon angewendet werden sollen. Dadurch wird das Pilzen weniger gleichmĂ€ĂŸig. Der unten gezeigte Algorithmus wird auf den obigen WĂŒrfel angewendet.

  fĂŒr i = 1 gilt # mesh.polys
    <strong> Wenn zufÀllig: Chance (0,33), dann </ strong>
      float length = random (0,1, 1,0)
      extrudePoly (mesh, i, length)
    ende
  ende
  Netz zurĂŒckgeben
 ende 


Änderung 2: Extrusionsskala hinzufĂŒgen


Dies erfordert eine Änderung des Extrusionsalgorithmus. Wenn wir die Eckpunkte eines extrudierten Polygons erstellen, können wir sie zur Mitte des Polygons hin um einen zufĂ€lligen Betrag reduzieren , damit das Objekt interessanter aussieht.

ZunĂ€chst muss unsere extrude () -Funktion einen zusĂ€tzlichen Parameter erhalten, der den Grad der Verengung des neuen Polygons bestimmt. Wir werden es als Vec3 mit dem Namen scale . Um einen Scheitelpunkt in Richtung der Mitte zu verschieben, interpolieren wir die Position des Scheitelpunkts zwischen seiner ursprĂŒnglichen Position und der Mitte des Polygons mit dem scale .

(Wenn Sie den Algorithmus zum Ermitteln des Mittelpunkts eines Polygons kennen mĂŒssen, empfehle ich, schnell zum Lernprogramm zur Triangulation zu springen und die Triangulation des Mittelpunkts (Schwerpunkttriangulation) zu lesen.)

  - Finden Sie die Mitte der Poly
 Vec3 c = mesh: getFaceCentroid (poly)
 fĂŒr j = 1 #poly do
   lokales p = mesh: getVertex (poly [j])
   newPoly [#newPoly + 1] = # mesh.verts
   self: addVertex (
     math.lerp (cx, px, scale.x) + nx * LĂ€nge
     math.lerp (cy, py, scale.y) + ny * LĂ€nge
     math.lerp (cz, pz, scale.z) + nz * LĂ€nge
   )
   mesh: addVertex (p + (n * LĂ€nge))
 ende 

Jetzt können Sie es im Pilz-Algorithmus verwenden, indem Sie fĂŒr jedes Polygon einen zufĂ€lligen Wert verwenden. So erhalten wir das oben gezeigte Bild.

  Funktion greeble (mesh)
   fĂŒr i = 1 gilt # mesh.polys
     float length = random: getUniformRange (0.1, 1.0)
     Vec3 scale = (zufÀllig: getUniformRange (0.1, 1.0),
                   zufÀllig: getUniformRange (0.1, 1.0),
                   zufÀllig: getUniformRange (0.1, 1.0))
     extrudePoly (mesh, i, lÀnge, skala)
   ende
   Netz zurĂŒckgeben
 ende 

Das Ende


Super, wir sind am Ende angelangt! Ich hoffe, dieses Tutorial hat Ihnen geholfen.

Source: https://habr.com/ru/post/de482316/


All Articles