Wie kann ich ein Objekt in OpenGL biegen?

11

Gibt es eine Möglichkeit, ein Objekt wie einen Zylinder oder eine Ebene mit OpenGL zu biegen?

Ich bin ein OpenGL-Anfänger (ich verwende OpenGL ES 2.0, wenn das wichtig ist, obwohl ich vermute, dass Mathematik in diesem Fall am wichtigsten ist, also irgendwie versionunabhängig), verstehe ich die Grundlagen: Übersetzen, Drehen, Matrixtransformationen usw. Ich habe mich gefragt, ob es eine Technik gibt, mit der Sie die Geometrie Ihrer Objekte tatsächlich ändern können (in diesem Fall durch Biegen).

Alle Links, Tutorials oder andere Referenzen sind willkommen!

Valentin Radu
quelle

Antworten:

11

Um ein Objekt zu "biegen", müssen Sie eine geeignete Kombination aus Translation / Rotation / Skalierung nur auf eine Teilmenge der Eckpunkte des betreffenden Objekts anwenden und diese Transformation wahrscheinlich entsprechend gewichten.

Wenn Sie dies auf eine angenehm aussehende Weise tun, müssen Sie mehr Scheitelpunkte verwenden, als ansonsten zur Beschreibung des ursprünglichen Netzes unbedingt erforderlich wäre. Beispielsweise kann ein einfacher Zylinder nur an beiden Enden Scheitelpunkte haben. Wenn Sie jedoch möchten, dass sich dieser Zylinder in der Mitte biegt, benötigen Sie dort auch Scheitelpunkte.

Wenn Sie nur an sehr spezifischen, einmaligen Verformungen sehr einfacher Formen (wie Ihrer oben genannten Ebene) interessiert sind, können Sie dies wahrscheinlich einfach manuell tun. Entscheiden Sie sich beispielsweise für die "Biegeachse" für Ihre Ebene und berechnen Sie geeignete Transformationen für jede Reihe von Ebenenscheitelpunkten, um die entsprechende Drehung um diese Biegeachse in Abhängigkeit von ihrem Abstand zu dieser zu erzielen, und wenden Sie diese dann auf die Geometrie an (möglicherweise auf die CPU, da dies zumindest anfangs am einfachsten wäre). Aber eine solche Technik würde nicht gut skalieren und wäre sehr langweilig.

Da es so umständlich sein kann, richtig herauszufinden, wie eine Transformation auf jeden einzelnen Scheitelpunkt in einem Satz gewichtet werden muss, um die gewünschte Verformung zu erzielen (insbesondere für praktischere und kompliziertere Objekte), verwenden viele Spiele eine Technik, die als Skelettanimation bezeichnet wird . Auf hoher Ebene müssen Sie Ihrem Netz einen separaten Satz Geometrie (das "Skelett") zuordnen. Diese Geometrie stellt die Knochen Ihres Objekts dar und Sie definieren (häufig in Modellierungswerkzeugen) eine Zuordnung zwischen den Scheitelpunkten des realen Modells und den Knochen des Skeletts - welche Knochen mit jedem Scheitelpunkt verknüpft sind und wie stark dieser Knochen die Verformung beeinflusst dieses Scheitelpunktes. Dann wird das Skelett direkt animiert und die Animation wird über die Beziehung zwischen den Knochen und ihren Eckpunkten auf das reale Modell übertragen.

Typischerweise wird bei dieser Technik die Zuordnung zwischen Skelett und realem Netz zur Produktionszeit des Assets definiert. Die Animationen können dann auch erstellt werden oder sie können zur Laufzeit prozedural erstellt werden. Die Anwendung der Animationstransformationen auf das reale Netz erfolgt zur Laufzeit. Im Allgemeinen werden zur Laufzeit keine neuen Scheitelpunkte generiert. Dies bedeutet, dass der Bereich gut aussehender Verformungen implizit im Netz festgelegt ist, wenn es ursprünglich erstellt wird.

Theoretisch könnte man zur Laufzeit auch Tessellation und Unterteilung auf das Netz anwenden, basierend auf der Analyse der Transformationen in der Animation, und so die geeigneten Scheitelpunkte erzeugen, um eine Animation zu erstellen, die nicht unbedingt geplant war. Ich kenne keine Papiere zu diesem Thema.

Siehe auch:

Vaillancourt
quelle
9

Für die eigentliche Mathematik des Warpens kann dies sehr kompliziert werden. Warum fängst du nicht hier an? .

Ich werde jetzt darüber sprechen, wie Sie dies anwenden können, vorausgesetzt, Sie haben bereits die Mathematik, wie Sie Ihre Verformungen nach unten machen werden.

2 Wege:

1) Besuchen Sie bei jedem Frame jeden Scheitelpunkt im Zylindermodell und versetzen Sie ihn auf irgendeine Weise.

2) Versetzen Sie die Scheitelpunkte im Scheitelpunkt-Shader beim Rendern. OpenGL ES 2.0 unterstützt Vertex-Shader. In gewisser Weise haben Sie Glück.

Möchten Sie das Objekt nur so verziehen, wie es auf dem Bildschirm angezeigt wird , oder möchten Sie das Objekt verziehen, damit jedes Objekt im Spiel weiß, dass es deformiert wurde?

Wenn Sie das Objekt im Vertex-Shader verziehen , geschieht dies erst unmittelbar vor der Anzeige / Rasterung . Dies bedeutet, dass keines der Spielobjekte von der Verformung weiß . Dies ist in Ordnung, wenn Sie lediglich einen Bildschirmschoner erstellen oder wenn die Verformungen so gering sind, dass sie keinen Einfluss auf die kollidierbare Form des Objekts haben.

Wenn Sie die Geometrie im Scheitelpunkt-Shader verziehen, bewegen sich die ursprünglichen Scheitelpunkte des Modells tatsächlich nicht (sie scheinen sich nur zu bewegen ).

Verformung im Vertex-Shader

Undeformiert:

nicht deformiert

Deformiert

deformiert

Dies ist aus Kapitel 6 des CG-Tutorials (Programm Nr. 14).

Der Shader-Code, der diese Verformung erzeugt, ist ungefähr so

// choose a displacement amount
float displacement = scaleFactor * 0.5 * sin(position.y * frequency * time) + 1 ;

// displace it in the direction of the normal
float4 displacementDirection = float4(normal.x, normal.y, normal.z, 0) ;

// move the vertex
float4 newPosition = position + displacement * displacementDirection ;

// transform (as normal)
oPosition = mul(modelViewProj, newPosition) ;

Sie können also sehen, dass dies direkt vor der Anzeige geschieht (Vertex-Shader erfolgt auf der GPU), sodass der CPU-Code praktisch keine Möglichkeit hat, auf die transformierte Vertex-Position zuzugreifen (es gibt Möglichkeiten, Daten von der GPU an die CPU zu senden (hauptsächlich über Texturen), aber wir werde nicht dorthin gehen).

Bobobobo
quelle
8

Was Sie erreichen möchten, ist im Grunde eine Teilmenge des Themas Netzverformung. Aber da Sie ein Anfänger sind, befürchte ich, dass diese Art von Informationen für den Moment etwas zu seltsam sein könnte. Ich werde jedoch versuchen, die Grundbegriffe festzulegen.

Dazu benötigen Sie zwei Dinge:

  1. Ihr Netz muss genügend Eckpunkte haben, damit Sie es transformieren können. Wenn es sich beispielsweise um eine Ebene handelt, müssen Sie sicherstellen, dass sie tatsächlich als eine Art Gitter mit vielen Scheitelpunkten erstellt wird, die Sie verformen können. Gleiches gilt für einen Zylinder. Könnte zur Laufzeit mit Tessellation möglich sein, aber ich weiß nicht viel über das Thema.
  2. Sie müssen einen Scheitelpunkt-Shader verwenden, um die Scheitelpunkte zu verformen. Grundsätzlich kümmert sich der Vertex-Shader um die Berechnung der endgültigen transformierten Position jedes Vertex, sodass Sie die Möglichkeit nutzen können, eventuelle Verformungen auf sie anzuwenden.

Ich bin mir nicht sicher, wie hilfreich es sein wird, aber werfen Sie einen Blick auf diese OpenGL-Ressource, da sie genau das zu sein scheint, was Sie brauchen:

http://www.ozone3d.net/tutorials/mesh_deformer_p3.php#part_3

Screenshot von diesem Link:

Geben Sie hier die Bildbeschreibung ein

Bearbeiten

Ich habe gerade Joshs Antwort gesehen und ich stimme zu, dass Skelettanimationen auch eine sehr elegante Möglichkeit sind, dieses Problem zu erfassen, insbesondere wenn Ihre Deformationen komplexer und mathematisch schwieriger darzustellen sind.

Denken Sie jedoch daran, dass beide oben genannten Punkte immer noch zutreffen - Sie können nur Scheitelpunkte verformen, daher müssen sie offensichtlich an erster Stelle vorhanden sein, weshalb Ihr Netz eine angemessene Scheitelpunktdichte aufweisen muss. Und normalerweise ist es der Vertex-Shader, der die Skelettanimation steuert und Vertex-Blending und dergleichen ausführt.

Übrigens können Sie diese auch auf der CPU ausführen, aber heutzutage ist es normalerweise eine bessere Option, sie auf der GPU auszuführen. Deshalb lege ich Wert auf den Vertex-Shader, und Sie sollten sich damit befassen. Programmmäßig ist es sowieso nicht viel schwieriger als auf der CPU.

David Gouveia
quelle