(6) Polygon Clipping

Werbung
(6) Polygon Clipping
Vorlesung
„Computergraphik I“
S. Müller
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 1 -
Wiederholung I
Clipping
Berechnung eines Ausschnitts
Test der Gültigkeit der Parameter bei Putpixel zu teuer, daher
Clipping z.B. mit Bildschirmfenster
2-Stufiges Vorgehen:
• Schneller Test, ob Linie innerhalb/außerhalb des
Bildschirms liegt
• Berechnung des Schnittpunkts nur, wenn unbedingt nötig.
Cohen-Sutherland
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 2 -
Wiederholung II
1001
Durch einfache Bit-Operationen
(und, oder) lässt sich schnell
erkennen, ob eine Linie vollständig
innerhalb bzw. außerhalb des
Bereichs liegt.
1.
2.
3.
4.
5.
B
E
0001
0101
Linie vollständig außerhalb, fertig.
Linie vollständig innerhalb,
alles zeichnen.
Sonst: neue Punkte
bestimmen bis 3) erreicht ist
UNIVERSITÄT
KOBLENZ · LANDAU
1010
A
c1 & c2 ≠ 0
c1 | c2 == 0
1000
H
0000
C
F
D
G
0010
0110
0100
cA&cB
1000
cC&cD
0000
cC | cD
0100
cut
cE&cF
0000
cE | cF
0000
draw
cG&cH
0000
cG | cH
0110
cut
ignore
S. Müller - 3 -
Wiederholung III
{
c1 = outcode( a);
c2 = outcode( b);
A (Oben, Links)
A (Oben, Rechts)
while((c1 | c2) != 0)
{
if ((c1 & c2) != 0) return ;
n.x = a.y-b.y; n.y = b.x-a.x;
d = a.x*b.y-a.y*b.x;
A‘ (Oben)
A‘‘ (0000)
if (c1 == 0) c = c2;
else
c = c1;
A‘ (0000)
B (0000)
if ((c & C_LEFT) != 0)
{ p.x = xmin; p.y = -(n.x*p.x+d)/n.y;}
else if ((c & C_RIGHT) != 0)
{ p.x = xmax; p.y = -(n.x*p.x+d)/n.y;}
else if ((c & C_TOP) != 0)
{ p.y = ymax; p.x = -(n.y*p.y+d)/n.x;}
else if ((c & C_BOTTOM) != 0)
{ p.y = ymin; p.x = -(n.y*p.y+d)/n.x;}
B (0000)
B (Rechts)
A‘ (Rechts)
if (c == c1)
{ a = p; c1 = outcode( a);}
else
{ b = p; c2 = outcode( b);}
A (Unten)
}
draw_line( a, b);
}
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 4 -
Wiederholung IV: Cohen-Sutherland
Dieser Algorithmus arbeitet sehr effizient
Er findet vor allem für Clipping an Bildschirmkanten
Verwendung
Nachteil: er funktioniert nur für rechteckige Ausschnitte
für beliebige Ausschnittsfenster ist der Bereichscode so nicht
mehr einsetzbar;
das gleiche gilt für die einfache Berechnung der Schnittpunkte
zwischen den Kanten der Ausschnittsfenster und den Linien
Erweiterung für beliebige Ausschnittsfenster: CyrusBeck
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 5 -
Wiederholung V: Cyrus-Beck
Clipping von Linien, an
beliebigen, konvexen
Polygonzügen
Eckpunkte des Clip-Objekts
müssen gegen den
Uhrzeigersinn definiert werden
(„counterclockwise“)
Degenerierte Kanten (identische
Eckpunkte) müssen vorher
abgefangen werden
Berechnung der Normalen auf
die Kanten des Clip-Objekts,
wobei Normalen nach außen
zeigen
UNIVERSITÄT
KOBLENZ · LANDAU
Start- und Endpunkt der zu
zeichnenden Linie werden für
jede Kante mit Hilfe eines
In/Out-Tests klassifiziert
Skalarprodukt zwischen
Normale und Verbindung
Kante-Linienpunkt
Beiden innen: weitermachen
ohne SP Berechnung
Beide außen: aufhören.
Falls SP berechnet wird, wird
dieser ebenfalls als In/OutPunkt klassifiziert.
S. Müller - 6 -
Wiederholung VI: Cyrus-Beck
void clip_and_draw( glm::ivec2 a, glm::ivec2 b)
{
float t, t_in, t_out, c0, c1, nenner;
c0 = glm::dot( w0, n);
c1 = glm::dot( w1, n);
if (c0 > 0 && c1 > 0)
// alles außerhalb, fertig
return;
if (c0 <= 0 && c1 <= 0)
// innerhalb, weitertesten
continue;
nenner = glm::dot( v, n);
t = -c0/nenner;
glm::vec2 v;
glm::vec2 w0, w1, n;
v.x = b.x - a.x; v.y = b.y - a.y;
t_in = 0.0;
t_out = 1.0;
for (
{
int
n.x
n.y
int i = 0; i < 4; i++)
if (nenner < 0 && t > t_in)
t_in = t;
if (nenner > 0 && t < t_out)
t_out = t;
iNext = (i+1) % 4;
=
P[iNext].y-P[i].y;
= -(P[iNext].x-P[i].x);
}
if (t_in > t_out)
return;
w0 = a - P[i];
w1 = b - P[i];
b.x
b.y
a.x
a.y
04_Clipping.sln
UNIVERSITÄT
KOBLENZ · LANDAU
=
=
=
=
a.x
a.y
a.x
a.y
+
+
+
+
t_out
t_out
t_in
t_in
*
*
*
*
v.x;
v.y;
v.x;
v.y;
draw_line( a, b);
}
S. Müller - 7 -
Wiederholung VII: Cyrus-Beck
B
In
B
Out
Out
Out
A
In
A
In
Die klassifizierten Schnittpunkte (In/Out) werden entlang von t sortiert. Ist
t_in (t für äußersten In-Punkt) größer als t_out (t für innersten Out-Punkt),
dann liegt die Linie außerhalb und muss nicht gezeichnet werden.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 8 -
Polygon Clipping
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 9 -
Ausgangspunkt
Wir haben gesagt, dass die „Applikation“ sicherstellen
muss, dass put_pixel(x,y) nur für gültige Pixel
aufgerufen wird.
Bisher Clipping von Linien:
Cohen-Sutherland: Clippen von Linien an rechteckigen
Objekten mit Hilfe von Bereichscodes.
Cyrus-Beck: Clippen von Linien an beliebigen, konvexen
Polygonzügen
Clipping von Polygon gegen Polygon:
Sutherland-Hodgman
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 10 -
Sutherland-Hodgman
Clipping eines Polygonzugs gegen ein konvexes ClipPolygon (z.B. Bildschirm); der Polygonzug darf konkav
sein.
Polygonzug
(4 Punkte)
Ergebnis (9 Punkte)
Bildschirm
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 11 -
Vorgehen
Der Polygonzug wird der Reihe nach an den Clip-Kanten geschnitten.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 12 -
Vorgehen
Das Ergebnis muss wieder ein geschlossener
Polygonzug sein.
Als Eingabe dient die Liste der Eckpunkte in der
richtigen Reihenfolge (gegen den Uhrzeigersinn).
Die Routine gibt – nach dem Schnitt mit der jeweiligen
Clip-Kante - eine neue Liste von Eckpunkten zurück.
Wichtig: die Reihenfolge muss stimmen.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 13 -
4 Fälle
Annahme: der Startpunkt A wurde bereits behandelt
B
S
B
A
S
B
Beide Punkte
drinnen:
Output B
A
Linie „zeigt“ nach
außen:
Output S
B
A
A
Linie „zeigt“ nach
innen:
Output S, B
UNIVERSITÄT
KOBLENZ · LANDAU
Beide Punkte
draußen:
Output (nichts)
S. Müller - 14 -
D
Beispiel 1
S1
S2
A
Input:
Output:
C
A B C D
S1 A B C S 2
B
Man beginnt mit der Kante letzter Punkt (D) – erster Punkt (A)
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 15 -
Beispiel 2
S1
S3
S2
S6
A
C
S5
Input:
S1 A B C S 2
Output:
S3 S1 A S 4 S5 C S 6
UNIVERSITÄT
KOBLENZ · LANDAU
S4
B
S. Müller - 16 -
PseudoCode
Diese Routine wird der Reihe
nach für jede Clip-Kante
aufgerufen.
„Innerhalb/Außerhalb“: hier wird
wieder die Normale auf die
Kante berechnet und mit Hilfe
des Vorzeichens des
Skalarproduktes entschieden.
„Output“: stellt ein neues
Polygon zusammen, das am
Ende zurückgegeben wird.
„Schnittpunkt“ berechnet den
Schnittpunkt mit der Clipkante,
wobei nur Punkte zw. A und B
berechnet werden dürfen.
UNIVERSITÄT
KOBLENZ · LANDAU
Polygon SutherlandHodgman(Polygon poly,
Edge clipedge)
{
A ist letzter Punkt des Polygons;
Schleife über alle Ecken B des
Polygons
{
if B innerhalb von clipedge
if A innerhalb von clipedge
Output (B);
else
{
S = Schnittpunkt (A,B,edge);
Output(S), Output(B);
}
else
if A innerhalb von clipedge
{
S = Schnittpunkt (A,B,edge);
Output(S);
}
A = B;
}
Ergebnis von Output zurückgeben.
}
S. Müller - 17 -
Beispiel
D
A
C
B
Problem: unnötige Kanten mit Fläche Null…
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 18 -
Sutherland-Hodgman
Clipping eines Polygonzugs gegen ein konvexes ClipPolygon (z.B. Bildschirm); der Polygonzug darf konkav
sein.
Problem: unnötige Kanten können am Rand
entstehen, was nicht unbedingt zu Fehlern führt; aus
Effizienzgründen können diese nachträglich gelöscht
werden.
Lässt sich sehr gut als Pipeline in Hardware
umsetzen.
Erweiterung für konkave Clip-Polygone:
Weiler-Atherton
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 19 -
Clippen von Texten und Bildern
Schrift besteht aus Kurven für
Umrisse der Buchstaben
Diese werden in der Regel
einmal gezeichnet und in
verschiedenen Auflösungen
als Pixelmuster/Bitmap
gespeichert
Diese Bitmaps werden als
Rechtecke betrachtet und
gegen das Clip-Objekt
geschnitten und nur der
sichtbare Teil gezeichnet.
Das gleiche gilt auch für
Bilder.
UNIVERSITÄT
KOBLENZ · LANDAU
a
S. Müller - 20 -
GPU: Vertex Attribute
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 21 -
CPU vs. GPU
CPU: mehrere Recheneinheiten
GPU: tausende Recheneinheiten
„Stream“
Quasi jeder Computer hat
heute einen Grafikprozessor
(Graphics Processing Unit,
GPU)
Vorteil: Tasks können hoch
parallel bearbeitet werden
UNIVERSITÄT
KOBLENZ · LANDAU
Idee: möglichst gleiches
Programm auf vielen Daten
ausführen (single instruction
multiple data, SIMD)
S. Müller - 22 -
Vertices
Die Eingabedaten für das
Rendering sind Linienzüge
(Polygone, in der Regel
Dreiecke) als Liste von 3DEckpunkten (vertices).
Für jeden Vertex können
unterschiedliche Attribute
(Position, Farbe, Normale)
definiert werden mit 1-4 Werten
pro Eintrag
Die Liste der Attribute werden
als Arrays (ARRAY_BUFFER) in
einem Buffer-Objekt übergeben
(oft Vertex-Buffer-Objects
(VBOs) genannt)
UNIVERSITÄT
KOBLENZ · LANDAU
Diese Daten werden dann auf
die GPU geladen (oder liegen
dort schon vor).
Durch glDraw… werden dann
alle Polygone des Objekts
gerendert.
Hierfür gibt es 2 Buffer-Typen
Nicht indizierte Arrays
Indizierte Arrays
S. Müller - 23 -
2 Buffer-Typen
v
y
v
y
(1, 2)
2
(3, 2)
2
1
v3
v2
1
(0, 0)
0
0
(2, 0)
1
2
3
v
x
Nicht indiziert
Für jeden Eckpunkt (gegen den
Uhrzeigersinn) die Koordinaten
des Eckpunkt (x, y)
GLfloat vertices[] =
{0,0, 2,0, 1,2, 1,2, 2,0, 3,2};
v0
0
0
v1
1
2
3
v
x
Indiziert
Eine Liste der Koordinaten der
Eckpunkte
Eine Liste von Indizes (gegen den
Uhrzeigersinn)
GLfloat vertices[] = {0,0, 2,0, 1,2, 3,2};
Glint indices[] = {0,1,2, 2,1,3};
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 24 -
Mehrere Attribute
Pro Vertex können mehrere
Attribute angegeben werden.
Jedes Attribut kann
unterschiedliche Dimension
haben (z.B. Position (x, y)
und Farbe (r, g, b))
GLfloat vertices[] =
(6 Vertices ≈ 12 Einträge)
{0,0, 2,0, 1,2,
1,2, 2,0, 3,2};
GLfloat colors[] =
(6 Vertices ≈ 18 Einträge)
{1,0,0, 1,0,0, 1,0,0,
0,0,1, 0,0,1, 0,0,1};
Aber die Anzahl der Vertices
muss in allen Listen gleich
sein
UNIVERSITÄT
KOBLENZ · LANDAU
v
y
(1, 2 )
2
(3, 2)
1
(0, 0)
0
0
(2, 0)
1
2
3
v
x
Nicht indizierte Liste
Vorteil: verschiedene Werte
(z.B. Farben) pro Eckpunkt
Nachteil: braucht mehr
Speicher
S. Müller - 25 -
OpenGL Buffer Objekte
CPU
Viele Daten, wie hier die
Vertex-Arrays, werden in
Buffern angelegt.
Um einen Buffer anzulegen,
wird allerdings ein eigenes
„Objektmodell“ verwendet.
Z.B.
GPU
Lösung
Buffer allokieren und ID
(fortlaufende Nummer) holen
GLuint vbo;
glGenBuffers(1, &vbo);
Bufferid = new Buffer();
würde nicht funktionieren, da
es nur einen Pointer auf
einen Speicherbereich der
CPU liefern würde.
Ein Buffer braucht aber eine
eindeutige ID für CPU und
GPU
UNIVERSITÄT
KOBLENZ · LANDAU
Buffer binden (quasi eine glob.
Variable setzen), alle BufferKommandos beziehen sich auf
diesen „aktiven“ (gebundenen)
Buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
Indizierte Liste:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, …
S. Müller - 26 -
GLfloat vertices[] =
{-1.0,-1.0, 0.0,-1.0, -0.5,0.0,
-0.5, 0.0, 0.0,-1.0, 0.5,0.0};
Vertex Attribute zuordnen
Wir haben das Array (z.B. von Vertices) und ein „aktives“
Bufferobjekt.
Die Zuordnung der Daten geschieht mit
glBufferData(
GL_ARRAY_BUFFER,
sizeof(vertices),
vertices,
GL_STATIC_DRAW);
//Bei Index-Liste GL_ELEMENT_ARRAY_BUFFER
//Größe des Array in Bytes
//Pointer auf das Array
Das letzte Flag gibt dem Treiber einen Hinweis, wo er die Daten
ablegen soll
GL_STATIC_DRAW: Die Daten werden nicht verändert und können einmal auf
die Karte runtergeladen werden
GL_DYNAMIC_DRAW: Die Daten werden verändert und sollten auf der CPU
verbleiben
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 27 -
Vollständige Liste
(aus OpenGL SuperBible 6th ed.)
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 28 -
Letzer Schritt
Genaue Anweisung geben, wie der aktive (gebundene) Buffer zu
interpretieren ist
glVertexAttribPointer(
0,
// Eigene Location ID (z.B 0 für Position,
//
//
//
//
//
//
1 für Farbe (Details später…)
Anzahl der Elemente/Eintrag (x,y) oder (r,g,b)
Datentyp der Elemente
Normalized oder nicht
Schrittweite
Offset, wo in Array begonnen wird
2,
GL_FLOAT,
GL_FALSE,
0,
0);
Normalized ist relevant, wenn man als Datentypen int hat, die
automatisch nach float konvertiert werden. True: die Werte werden auf
[0,1] normalisert
Schrittweite: 0 gibt an, dass die Daten direkt aufeinander folgen.
Alternative: interleaved (Position, Farbe etc. werden nicht in eigenen
Arrays gespeichert, sondern hintereinander in einem).
UNIVERSITÄT
KOBLENZ · LANDAU
x1
y1
r1
g1
b1
Schrittweite (in Byte)
x2
y2
…
S. Müller - 29 -
Buffer rendern
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
In der Renderingschleife jedes Attribut explizit einschalten (der
Wert muss der location ID entsprechen, Details später…)
glEnableVertexAttribArray(0);
Gesamten Buffer Rendern
glDrawArrays(
GL_TRIANGLES,
0,
sizeof(vertices));
//Modus, wie gerendert wird
//Start-Index
//Anzahl der vertices
Alternative (indizierte Liste):
glDrawElements(
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
0);
//Modus, wie gerendert wird
//Anzahl der zu rendernden vertices
//Typ der Werte in der Indexliste
//Start-Index
Eventuell jedes Array wieder ausschalten
glDisableVertexAttribArray(0);
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 30 -
Beispiele mode
2.
2.
1.
3.
GL_POINTS
1.
3.
0.
4.
2.
0.
4.
1.
3.
0.
4.
GL_LINE_STRIP
GL_LINE_LOOP
Mehrfachprimitive
2.
1.
5.
4.
1.
3.
0.
0.
2.
4.
2.
4.
3.
4.
0.
GL_LINES
0.
5.
GL_TRIANGLES
UNIVERSITÄT
KOBLENZ · LANDAU
1.
3.
GL_TRIANGLE_STRIP
3.
1.
2.
GL_TRIANGLE_FAN
S. Müller - 31 -
Typischer Ablauf
GLfloat v[] =
{-1.0,-1.0, 0.0,-1.0, -0.5,0.0,
-0.5, 0.0, 0.0,-1.0, 0.5,0.0};
Ein VertexArray mit
Positionsdaten
Einmalig:
• Einen Buffer allockieren,
• diesen Buffer „aktiv“
schalten,
• Daten zuordnen
GLuint vertexbuffer;
…
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
while( !glfwWindowShouldClose( window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays( GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glfwSwapBuffers( window);
glfwPollEvents();
Pro Rendering
• Buffer „aktiv“ schalten,
• Traversierung bekannt geben
• An Shader Location 0 binden
und einschalten
}
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 32 -
CPU
GPU
0
Typischer Ablauf
GLfloat v[] = {…};
GLuint vertexbuffer;
…
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(v), &v, GL_STATIC_DRAW);
while( !glfwWindowShouldClose( window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays( GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glfwSwapBuffers( window);
glfwPollEvents();
05_Polygone.sln
}
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 33 -
Punkte und Linien in OpenGL
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 34 -
Punkte, Linien, Flächen
Alle bisher behandelten Algorithmen zum
Zeichnen von Punkten
Zeichnen von Linien (mit Clipping und linearer Interpolation
von Eckpunktwerten z.B. Farbe)
…
… sind in OpenGL sehr effizient implementiert und
auch entsprechend auf die Möglichkeiten der GraphikHardware abgebildet.
OpenGL bietet uns daher eine wichtige Bibliothek zur
Erstellung von graphischen Systemen (API:
application programming interface)
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 35 -
Namenstypisierung
Funktionen mit verschiedenen Parametern tragen Typ und
Dimension im Namen:
gl<FUNC>{1234}{b,ub,s,us,i,ui,f,d}[v](...)
1,2,3,4: Dimension der Argumente
b,ub,s,us,i,ui,f,d: Typ: GLbyte, GLubyte, etc. Sonderfall:
GLclampf, GLclampd
optional können Parameter auch als Vektor übergeben
werden, gekennzeichnet durch das abschließende v
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 36 -
Namenstypisierung
Beispiel: glColor{34}{b,ub,s,us,i,ui,f,d}[v](...)
GLfloat f[3] = { 0.0, 0.5, 1.0 };
GLubyte b[4] = { 0, 127, 255, 255 };
glColor3f( 0.0, 0.5, 1.0 );
glColor3fv( f );
glColor4ubv( b );
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 37 -
Primitivspezifische Einstellungen
Punkte: Größe mittels
glPointSize( GLfloat size );
nicht jede Größe unterstützt, über glGet() abzufragen
Wenn Antialiasing abgeschaltet ist (default), dann ist der
Punkt ein Quadrat von size*size Pixeln. Nicht-Integer Werte
werden gerundet.
glDisable(GL_POINT_SMOOTH);
Wenn Antialiasing eingeschaltet ist, dann wird ein Kreis
gezeichnet. Nicht-Integer Werte für size werden hier nicht
gerundet.
glEnable(GL_POINT_SMOOTH);
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 38 -
Aktivieren / Inaktivieren
Viele Features müssen explizit aktiviert werden
glEnable( GLenum feature );
zum Inaktivieren dient dann
glDisable( GLenum feature );
der Zustand kann abgefragt werden mittels
glIsEnabled( GLenum feature );
die Konstanten können nicht verodert werden
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 39 -
Linien
Linien: Breite mittels
glLineWidth( GLfloat width );
ähnlich wie Punkte nicht jede Größe möglich
Wenn Antialiasing abgeschaltet ist (default), dann ist width die
Breite der Linie in Pixeln (also unabhängig von
Fenstergröße…). Nicht-Integer Werte werden gerundet.
glDisable(GL_LINE_SMOOTH);
Wenn Antialiasing eingeschaltet ist, dann wird die Helligkeit
der Pixel abhängig vom Bedeckungsgrad berechnet. NichtInteger Werte werden hier nicht gerundet.
glEnable(GL_LINE_SMOOTH);
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 40 -
Beispiel
points_lines.c
points_lines.exe
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 41 -
GLFW: Input Manager
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 42 -
Events
Während der Renderer in einer Endlosschleife läuft,
wollen wir in der Regel auf Events (z.B. Taste
gedrückt, Maus bewegt, Maustaste gedrückt)
reagieren.
GLFW bietet zwei Modi an:
Callbacks: hier definieren wir eine Funktion, die
automatisch aufgerufen wird, wenn eine Event auftrifft
Polling: hier fragen wir explizit nach dem Zustand
(z.B. einer Taste)
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 43 -
Maus Callback
Callback Funktion definieren
int main()
{
…
glfwSetMouseButtonCallback(window, mouseCallback);
…
Callback Funktion
void mouseCallback(GLFWwindow* window, int button, int action, int mods)
window: The window that received the event.
button: The mouse button that was pressed or released.
action: GLFW_PRESS or GLFW_RELEASE.
mods: Bit field describing which modifier keys were held
down (GLFW_MOD_SHIFT, GLFW_MOD_CONTROL,
GLFW_MOD_ALT, GLFW_MOD_SUPER).
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 44 -
Beispiel
void mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
…
}
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
…;
}
}
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 45 -
Tastatur Callback
Callback Funktion definieren
int main()
{
…
glfwSetKeyCallback (window, keyCallback);
…
Callback Funktion
void keyCallback (GLFWwindow *window, int key, int code, int action, int mods)
window: The window that received the event.
key: The keyboard key that was pressed or released.
code: The system-specific scancode of the key.
action: GLFW_PRESS, GLFW_RELEASE, GLFW_REPEAT.
mods: Bit field describing which modifier keys were held
down.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 46 -
Beispiel
void keyCallback (GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_C && action == GLFW_PRESS)
…;
if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
…;
if (key == GLFW_KEY_F1 && action == GLFW_PRESS)
…;
}
05_Polygone.sln
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 47 -
Weitere Callbacks
GLFWkeyfun
glfwSetKeyCallback (GLFWwindow *window, GLFWkeyfun cbfun)
Sets the key callback.
GLFWcharfun
glfwSetCharCallback (GLFWwindow *window, GLFWcharfun cbfun)
Sets the Unicode character callback.
GLFWmousebuttonfun
glfwSetMouseButtonCallback (GLFWwindow *window, GLFWmousebuttonfun cbfun)
Sets the mouse button callback.
GLFWcursorposfun
glfwSetCursorPosCallback (GLFWwindow *window, GLFWcursorposfun cbfun)
Sets the cursor position callback.
GLFWcursorenterfun
glfwSetCursorEnterCallback (GLFWwindow *window, GLFWcursorenterfun cbfun)
Sets the cursor enter/exit callback.
GLFWscrollfun
glfwSetScrollCallback (GLFWwindow *window, GLFWscrollfun cbfun)
Sets the scroll callback.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 48 -
Alternative: direkt abfragen
int
glfwGetInputMode (GLFWwindow *window, int mode)
Returns the value of an input option for the specified window.
int
glfwGetKey (GLFWwindow *window, int key)
Returns the last reported state of a keyboard key for the specified window.
int
glfwGetMouseButton (GLFWwindow *window, int button)
Returns the last reported state of a mouse button for the specified window.
void
glfwGetCursorPos (GLFWwindow *window, double *xpos, double *ypos)
Retrieves the last reported cursor position, relative to the client area of the window.
void
glfwSetCursorPos (GLFWwindow *window, double xpos, double ypos)
Sets the position of the cursor, relative to the client area of the window.
int
const float *
const unsigned char *
const char *
glfwJoystickPresent (int joy)
Returns whether the specified joystick is present.
glfwGetJoystickAxes (int joy, int *count)
Returns the values of all axes of the specified joystick.
glfwGetJoystickButtons (int joy, int *count)
Returns the state of all buttons of the specified joystick.
glfwGetJoystickName (int joy)
Returns the name of the specified joystick.
UNIVERSITÄT
KOBLENZ · LANDAU
S. Müller - 49 -
Herunterladen