Lösungsvorschlag zum dritten ¨Ubungsblatt

Werbung
Lösungsvorschlag zum dritten Übungsblatt
Aufgabe 1
Wie im Skript



x

 y !

z
benutzen wir auch hier die Korrespondenz

wx
wy 

wz 
w
zwischen gewöhnlichen 3D-Koordinaten und homogenen Koordinaten.
Für die Berechunung der Projektion eines Punktes XA = (xA , yA , zA ) auf eine
Ebene parallel zur yz-Ebene mit der x-Koordinate d stellt sich die Sachlage wie
folgt dar:
y
b
d
b
x
XA
yA
XP
yP
z
Man beachte, daß wegen der Rechtshändigkeit des Koordinatensystems die xAchse von der Bildebene aus nach hinten zeigt.
Um das Bild des Punktes XA zu bestimmen, verbinden wir ihn mit dem Projektionszentrum, dem Ursprung Ω, und geben dem Schnittpunkt dieser Verbindungsstrecke mit der Ebene x = d den Namen XP . Dieser Punkt XP = (xP , yP , zP )
ist der gesuchte Bildpunkt. Aufgrund des Strahlensatzes gilt (beachte xP = d!)
yP
yA
=
d
xA
und analog
zP
zA
=
d
xA
Insgesamt haben wir also

 
xp
 yp  = 
zp
d
dyA
xA
dzA
xA


In homogenen Koordinaten können wir diesen Punkt auch als
1


dxA
 dyA 


 dzA 
xA
schreiben und aus dem Punkt xA in homogenen Koordinaten mittels Matrizenmultiplikation berechnen:


 
 
dxA
xA
d 0 0 0
 dyA   0 d 0 0   yA 


 
 
 dzA  =  0 0 d 0  ·  zA 
xA
1
1 0 0 0
Da eine Skalierung aller Koordinaten um den gleichen Faktor in unserer neuen
Interpretation der homogenen Koordinaten keine Änderung in ihrem zugeordneten 3D-Punkt bewirkt, können wir die Transformationmatrix auch in der Form


1 0 0 0
 0 1 0 0 

Pd = 
 0 0 1 0 
1
0 0 0
d
schreiben.
Für d = 0 müssten wir hier durch Null dividieren; geometrisch macht so eine
Projektion wenig Sinn, da das Projektionszentrum in der Projektionsebene läge
und die Projektion nur zu einem einzigen Punkt entarten würde.
Aufgabe 2
Damit die Punkte A, B und C im Gegenuhrzeigersinn erscheinen, müssen die
−−→ −→
→
Vektoren AB, AC und der gesuchte Normalenvektor −
n (in dieser Reihenfolge)
→
ein Rechtssystem bilden. Für den (noch nicht normierten) Normalenvektor −
n
erhalten wir also

 


 

−2 − 2
6−2
−4
4
−
−
→
−
→
→
−
n = AB × AC =  4 − 5  ×  −1 − 5  =  −1  ×  −6  =
6−3
−1 − 3
3
−4

 

−1 · (−4) − 3 · (−6)
22
 3 · 4 − (−4) · (−4)  =  −4 
−4 · (−6) − (−1) · 4
28
und in seiner normierten Form lautet er




22
22
√ 2 1 2 2  −4  = √ 1  −4 
1284
22 +(−4) +28
28
28
Um zu entscheiden, ob der gegebene Vektor von der Vorder- oder Rückfläche
des Dreiecks wegzeigt, untersuchen wir, welchen Winkel er mit dem Normalen→
vektor −
n einschließt. Liegt dieser Winkel zwischen 0◦ und 90◦ , so zeigt er von
2
der Vorderseite des Dreiecks weg, andernfalls von der Rückseite. Der Winkel
→
zwischen −
n und dem gegebenen Vektor liegt genau dann zwischen 0◦ und 90◦ ,
falls das Skalarprodukt der beiden Vektoren positiv ist, wir berechnen also


4
→
h−
n ,  −1 i = 22 · 4 + (−4) · (−1) + 28 · (−4) = −20
−4
Der Vektor (4, −1, −4) zeigt also von der Rückseite des Dreiecks weg. Um den
Winkel zwischen der Dreiecksfläche und dem Vektor zu bestimmen, berechnen
→
wir zunächst den Winkel zwischen dem Normalenvektor −
n und dem Vektor
(4, −1, −4) und erhalten:
−
h→
n ,(4,−1,−4)i
→
−20√
∢(−
n , (4, −1, −4)) = arccos k→
= arccos √1284·
≈ 95, 576◦
−
n k·k(4,−1,−4)k
33
Der Winkel zwischen der Dreiecksfläche und dem Vektor (4, −1, −4) beträgt also ungefähr 5, 576◦.
Aufgabe 3
Für diese Aufgabe haben wir mehrere Lösungsmöglichkeiten:
1.Ansatz:
Ein Punkt P liegt genau dann im Inneren des von den Punkten A, B und C
−→
aufgespannten Dreieckes, wenn sich der Vektor AP als Konvexkombination der
−−→
−→
Vektoren AB und AC darstellen lässt, d.h., falls es λ1 und λ2 gibt mit λ1 , λ2 ≥ 0,
−−→
−→
−→
λ1 + λ2 ≤ 1 und λ1 · AB + λ2 · AC = AP . Dies führt uns auf folgendes Gleichungssystem:
xAB · λ1 + xAC · λ2 = xAP
yAB · λ1 + yAC · λ2 = yAP
Mit den
Abkürzungen
xAB xAC = xAB · yAC − yAB · xAC ,
det := yAB yAC xAP xAC = xAP · yAC − yAP · xAC
det1 := yAP yAC x
xAP = xAB · yAP − yAB · xAP
det2 := AB
yAB yAP und
haben wir
λ1 =
λ2 =
det1
det
det2
det
und
Diese Werte dürfen wir aber nicht direkt berechnen, da sie im allgemeinen keine
3
ganzen Zahlen sind. Dafür untescheiden wir zwei Fälle:
1. Fall:
det > 0: Damit λ1 , λ2 ≥ 0 gilt, muß hier det1 , det2 ≥ 0 gelten. Damit λ1 +λ2 ≤ 1
erfüllt ist, müssen det1 und det2 die Bedingung det1 + det2 ≤ det erfüllen.
2. Fall:
det < 0: Hier müssen wir wegen der Division durch eine negative Zahl die Ungleichheitszeichen umdrehen; es muß hier det1 , det2 ≤ 0 und det1 + det2 ≥ det
gelten.
Im Falle von det = 0 entartet das Dreieck zu einer Strecke; hier erklären wir
den Aufrufer zum Schuldigen und garantieren für nichts. Unsere Überlegungen
können wir in folgender Funktion zusammenfassen:
boolean liegt_innerhalb (int x1, int y1, int x2, int y2,
int x3, int y3, int p_x, int p_y){
int det = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);
int det_1 = (p_x-x1)*(y3-y1)-(p_y-y1)*(x3-x1);
int det_2 = (x2-x1)*(y_p-y1)-(y2-y1)*(x_p-x1);
if (det>0){
return ((det_1>=0) & (det_2>=0) & ((det_1+det_2)<=det));
}
else{
return ((det_1<=0) & (det_2<=0) & ((det_1+det_2)>=det));
}
}
2. Ansatz:
Hier beobachten wir, daß ein Punkt P genau dann im Inneren des von den Punkten A, B und C aufgespannten Dreiecks liegt, wenn beim Ablaufen der Kanten
−−→ −−→
−→
AB, BC und CA der Punkt P immer auf der gleichen Seite des Beobachters
liegt. Um hier rechts und links in Zahlen ausdrücken zu können, betrachten wir
−−→ −−→ −→ −→ −−→
−−→
die Vektoren AB, BC, CA, AP , BP und CP als Vektoren im R3 , indem wir ih−−→ −→
nen einfach noch die z-Komponente 0 geben. In den Kreuzprodukten AB × AP ,
−→ −−→
−−→ −−→
BA× BP und CA× CP sind dann die x- und y-Koordinate Null, und wir können
links und rechts einfach mit dem Vorzeichen der z-Koordinate identifizieren. Was
genau links und rechts ist, braucht uns hier nicht zu interessieren; wichtig ist
nur, ob das Vorzeichen immer gleich ist oder nicht. Falls die z-Komponente Null
ergibt, so kann der Punkt auf einer Kante liegen, und wir behandeln diesen Fall
dementsprechend:
boolean liegt_innerhalb (int x1, int y1, int x2, int y2,
4
int x3, int y3, int p_x, int p_y){
int det_1 = (x2-x1)*(y_p-y1)-(x_p-x1)*(y2-y1);
int det_2 = (x3-x2)*(y_p-y2)-(x_p-x2)*(y3-y2);
int det_3 = (x1-x3)*(y_p-y3)-(x_p-x3)*(y1-y3);
return (((det_1>=0) & (det_2>=0) & (det_3>=0)) ||
((det_2<=0) & (det_2<=0) & (det_3<=0)));
}
3. Ansatz: Ein dritter Ansatz führt uns über Flächenbetrachtungen: Der Punkt
P liegt genau dann in Inneren des Dreieckes ∆ABC, wenn die Summe der
Flächen der Dreiecke ∆ABP , ∆BCP und ∆ACP die Fläche des Dreiecks
∆ABC ergibt. Da der Betrag des Kreuzproduktes zweier Vektoren der Fläche
des von ihnen augespannten Parallelogramms entspricht, können wir die Fläche
des von ihnen aufgespannten Dreiecks als die Hälfte des Betrages ihres Kreuzproduktes berechnen. Wenn wir die Vektoren wie im vorigen Ansatz in der R3
einbetten, so ist der Betrag eines Kreuzproduktes durch den Betrag seiner zKomponente gegeben, und als Bedingung dafür, daß P im Inneren des Dreiecks
∆ABC liegt, erhalten wir
1
2
−−→ −→
· |(AB × AC)z | =
1
2
−−→ −→
· |(AB × AP )z | +
1
2
−−→ −−→
· |(BC × BP )z | +
1
2
−→ −−→
· |(AC × CP )z |
oder äquivalent dazu in ganzen Zahlen:
−−
→ −→
−−→ −→
−−→ −−→
−→ −−→
|(AB × AC)z | = |(AB × AP )z | + |(BC × BP )z | + |(AC × CP )z |
Als Code:
boolean liegt_innerhalb (int x1, int y1, int x2, int y2,
int x3, int y3, int p_x, int p_y){
return (abs((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)) ==
(abs((x2-x1)*(y_p-y1)-(y2-y1)*(x_p-x1))+
abs((x3-x2)*(y_p-y2)-(y3-y2)*(x_p-x2))+
abs((x1-x3)*(y_p-y3)-(y1-y3)*(x_p-x3))));
}
abs(int x) ist hierbei eine Funktion, die den Absolutwert eines int-Wertes x
zurückgibt. Je nach Geschmack kann man sie selbst implementieren oder
Math.abs(int x) verwenden.
5
Aufgabe 4
Zuerst sehen wir uns einmal die Situation an:
view-up
up
right
eye
point of interest
Die Kamera (hier mit eye bezeichnet) liegt wegen der Bedingung near = 0 in der
vorderen Clippingebene. Die vordere Clippingebene ist dadurch gekennzeichnet,
daß sie den Vektor von der Kamera zum point of interest (also die Blickrichtung)
als Normalenvektor hat. Der Vektor up ist eine geeignet skalierte Projektion des
view-up-Vektors auf diese Ebene, während der Vektor right in dieser Ebene liegt
und senkrecht auf dem up-Vektor steht. Am leichtesten ist die Richtung des
right-Vektors zu bestimmen: er muß senkrecht auf dem view-up-Vektor und der
Blickrichtung stehen. Somit können wir ein Vielfaches des right-Vektors mittels
des Kreuzproduktes aus der Blickrichtung und dem view-up-Vektor ermitteln:

 
 

−4 − 3
7
22
−−−→
right1 =  2 − 1  ×  5  =  −56 
−1 − 4
−3
−42
Gründliches Betrachten der rechten Hand zeigt auch, daß dieser Vektor tatsächlich
von der Blickrichtung aus nach rechts zeigt, wenn der view-up-Vektor als oben
gewählt ist. Zur späteren Verwendung normieren wir diesen Vektor und erhalten:


22
−−−→
1
 −56 
rightn = √5384
−42
Der right-Vektor ist dann identisch zum normierten
(da der right right-Vektors

22
−−−→
1
 −56 
Parameter 1 ist); somit haben wir right = √5384
−42
Die Richtung des up-Vektors können wir dann durch das Kreuzprodukt eines
6
positiven Vielfachen des right-Vektors und der Blickrichtung bestimmen:

 
 

11
−7
161
−
→ =  −28  ×  1  =  202 
up
1
−21
−5
−185
Auch diesen Vektor normieren wir vor der weiteren Verwendung:


161
−
→ = √ 1
 202 
up
n
100950
−185
Der up-Vektor ist dann das Doppelte dieses Vektors (da der Wert von top 2 ist):


322
−
→= √ 1
 404 
up
100950
−370
Den rechten oberen Punkt Fvor der Vorderseite des Frustums können wir nun
leicht berechnen, indem wir zur Kameraposition die Summe aus up- und rightVektor addieren:
 


3
4, 31
−
−
−
→
→ + right ≈  1, 51 
Fvor =  1  + −
up
4
2, 26
Analog berechnen wir den linken oberen Punkt Fvol , den linken unteren Punkt
Fvul und den rechten unteren Punkt Fvur der vorderen Frustumsebene:




3
3, 71
−
−
−
→
−
→
Fvol =  1  − up + right ≈  3, 03 
4
3, 41
 


3
1, 69
−
−
−
→
→ − right ≈  0, 49 
Fvul =  1  − −
up
4
5, 74
 


3
2, 29
−
−
−
→
→ − right ≈  −1, 03 
Fvur =  1  + −
up
4
4, 59
Um die hinteren Punkte des Frustums zu bestimmen, müssen wir die so erhaltenen Punkte noch um eine Längeneinheit (far = 1!) in die Blickrichtung verschieben. Mathematisch gesprochen normieren wir die Blickrichtung zum Vektor
→
−
b n:


−7
→
−
b n = √175  1 
−5
7
und addieren diesen Vektor zu den bisher erhaltene Punkten und bekommen so
die Punkte Fhor , Fhol , Fhul und Fhur :


3, 50
Fhor ≈  1, 62 
1, 69


2, 91
Fhol ≈  3, 15 
2, 83


0, 88
Fhul ≈  0, 61 
5, 16


1, 48
Fhur ≈  −0, 92 
4, 01
8
Herunterladen