PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : COLLADA skewing


Früchtemüsli
2013-08-10, 23:21:36
Hi :)

Könnte mir bitte wer das skewing lt. COLLADA-spec erklären bitte?

http://www.khronos.org/files/collada_spec_1_5.pdf
Seite 5-133

kloffy
2013-08-19, 16:50:44
Sorry, fuer eine richtige Erklaerung bin ich etwas zu muede. Es ist im Prinzip das gleiche Konzept wie bei einer 2D Scherung erweitert auf 3D:

http://www.scielo.br/img/revistas/lajss/v10n5/a03fig02.jpg

Vielleicht hilft dir Code (http://svn.xj3d.org/xj3d_code/trunk/apps/cadfilter/src/java/xj3d/filter/importer/collada/Skew.java) weiter, der diese Repraesentation in eine Matrix umwandelt.

Edit: Entweder liegt es an der Muedigkeit oder die Collada-Spezifikation ist missverstaenlich formuliert. Bei RenderMan (http://books.google.com.au/books?id=QB4AY1QI-HMC&q=skew&f=false) macht das deutlich mehr Sinn. Fuer das obige Beispiel wuerde das bedeuten: skew(α, y-achse, x-achse).

Früchtemüsli
2013-08-20, 10:25:15
Das Grundprinzip einer einfachen Scherung im 2D-Raum verstehe ich. Nur mit dieser speziellen Variante im 3D-Raum habe ich Probleme.

Ich schau mir mal den Code an. Danke :)

EDIT:

Nein, der Code hilft leider nicht weiter.


float angle = value[0];
// Normalize the two vectors, and construct a third perpendicular
Vector3f d1 = new Vector3f(value[1], value[2], value[3]);
d1.normalize();
Vector3f d2 = new Vector3f(value[4], value[5], value[6]);
d2.normalize();

Woher kommt die Variable value? Und welche Vektoren sind nun d1 und d2?

Früchtemüsli
2013-08-20, 12:24:58
Hier mal ein paar Vermutungen.

Koordinatensystem:
z|
|
|____ y
/
/x

Skew in y-Richtung, in Abhängigkeit von z:

float par = d1d2dot; // Amount of d1 parallel to d2
float perp = (float)Math.sqrt(1 - par * par); // Amount perpendicular
float s = (float)Math.tan(angle + Math.acos(perp)) * perp - par;
Matrix4f skew = new Matrix4f(
1, 0, 0, 0,
0, 1, s, 0,
0, 0, 1, 0,
0, 0, 0, 1);


z| z|
|----- | ----
| | => | / /
|____|__y |/___/__y
/ /
/x /x


Math.tan(angle + Math.acos(perp))


z|dy
|a ----
dz| / /
|/___/__y
/
/x


tan(alpha) = dy / dx => dy / dx = angle + Math.acos(perp)

cos(alpha) = Ankathete / Hypothenuse => alpha = acos(Ankathete / Hypothenuse)
acos(perp) => perp = dz / hypothenuse

Die hypothenuse liegt auf der yz-Ebene

z|
|a ----
dz| /*) / *) Hypothenuse
|/___/__y
/
/x

Es gibt also irgendeinen Punkt, der einen gewissen Winkel zur xz-Achse hat.
Dieser Punkt wird dann mittels angle gedreht.
Der Punkt verschiebt sich dann weiter in y-Richtung.

z| z| angle
| /---/ um angle gedreht | / /---/
| / / => | // /
|/___/__y |/___/___y
/ /
/x /x

perp ergibt sich aus par.

float perp = (float)Math.sqrt(1 - par * par); // Amount perpendicular

Das schaut mir irgendwie nach einem Satz von Pythagoras aus.
c^2 = a^2 + b^2 => b = sqrt(c^2 - a^2)
mit c = 1 => b = sqrt(1 - a^2)

par ist ein Sklalar:

float d1d2dot = d1.dot(d2);
float par = d1d2dot; // Amount of d1 parallel to d2

Hier wird scheinbar d1 auf d2 projiziert.

d1
/:
/ :
/__:__ d2
|..|
d1 dot d2

d1 ist ein Einheitsvektor und hat die Länge 1.
Mittels sqrt wird also die Höhe ausgerechnet:

d1
/:
/ : <- perp = sqrt(1 - (d1 dot d2)^2)
/__:__ d2
|..|
d1 dot d2

Was d1 und d2 sind, weiß ich nicht. Klar ist aber, dass de Winkel zwischen d1 und d2 zusammen mit alpha entscheidend dafür ist, wie stark geskewt wird.

Ich habe übrigens herausgefunden, dass value aus dem geerben http://svn.xj3d.org/xj3d_code/trunk/apps/cadfilter/src/java/xj3d/filter/importer/collada/TransformElement.java kommt. value sind float-Werte aus "CElement element".
Das wird der Klasse skeq im Konstruktor übergeben:

Skew(CElement skew_element) {
super("skew", skew_element);
}

value ist also skew_element.

CElement ist in http://svn.xj3d.org/xj3d_code/trunk/apps/cadfilter/src/java/xj3d/filter/importer/collada/CElement.java definiert.
Aber was das sein soll, weiß ich nicht.

Früchtemüsli
2013-08-20, 12:53:07
Jetzt zum Buch.

Die "source axis" wird in Richtung "target axis" gebäugt. Beides sind Vektoren. Lt. dem Programm jedoch scheinbar nicht zwangsläufig Einheitsvektoren.
Beispiel:

z| source axis
| /
| /
|/
------->--------- y
/ target axis
/x

Gedreht wird alles um alpha.
Lt. Programmierung würde ich vermuten, dass das alpha auf der Ebene liegt, die von source axis und target axis aufgespannt wird.
Ach würde ich jetzt einfach mal raten, dass sich die Programmierung an folgende Reihenfolge hält:

<distortion_angle> <source_axis> <target_axis>

Demnach würde gelten:

d1 = source_axis
d2 = target_axis

z| d1
| /
| /
|/
------->--------- y
/ d2
/x

Demnach würde d2 angeben, in welche Richtung geskewt wird, und d1 scheint lt. Programmierung irgendwie mitentscheidend dafür zu sein, wie stark geskewt wird.

Aber das ist alles nur geraten.

Was ich noch überhaupt nicht verstehe: wie spielen d1 und angle zusammen?
Und angenommen, ich habe in der letzten Grafik hier irgendwo einen Punkt, wo würde der dann geskewt landen?

Ich bräuchte also einfach mal nur irgendwie ein einfaches praktisches gezeichnetes Beispiel, damit ich verstehen kann, was hier eigentlich wirklich passiert :)

kloffy
2013-08-20, 13:26:28
Lt. Programmierung würde ich vermuten, dass das alpha auf der Ebene liegt, die von source axis und target axis aufgespannt wird.
Ach würde ich jetzt einfach mal raten, dass sich die Programmierung an folgende Reihenfolge hält:

<distortion_angle> <source_axis> <target_axis>

Soweit alles korrekt.


Demnach würde gelten:

d1 = source_axis
d2 = target_axis

z| d1
| /
| /
|/
------->--------- y
/ d2
/x

Demnach würde d2 angeben, in welche Richtung geskewt wird, und d1 scheint lt. Programmierung irgendwie mitentscheidend dafür zu sein, wie stark geskewt wird.

Aber das ist alles nur geraten.

Hier liegt der Denkfehler. Wie stark geskewt wird haengt alleine vom Winkel ab. Der Vektor d1 repraesentiert die Achse, die geskewt wird. Der Vektor d2 gibt an in welche Richtung geskewt wird. Das ASCII-Art sollte so aussehen:


z| d1'
d1 ^ /
|α/
|/
------->--------- y
/ d2
/x

Früchtemüsli
2013-08-20, 14:44:25
Das d1 muss aber nicht zwangsläufig im rechten Winkel auf d2 stehen, oder?
Was ist bei dir das d1´? Der Vektor auf einen geskewten Punkt?

z|
|
d1 ^
|
|geskewt
P o..>..o P'
| /
| /
| /
|α/
|/
------->----- y
/ d2
/x

Das alpha geht von d1 aus in Richtung d2, richtig?

kloffy
2013-08-20, 15:31:52
Das d1 muss aber nicht zwangsläufig im rechten Winkel auf d2 stehen, oder?
Richtig, deswegen die etwas kompliziertere Berechung von s:
Math.tan(angle + Math.acos(perp)) * perp - par;
Fuer den Sonderfall (perp=1, par=0) kann man einfach rechnen:
Math.tan(angle);

Was ist bei dir das d1´? Der Vektor auf einen geskewten Punkt?
Der Vektor d1' ist das Abbild von d1 nach der Scherung.



z|
|
d1 ^
|
|geskewt
P o..>..o P'
| /
| /
| /
|α/
|/
------->----- y
/ d2
/x

Das alpha geht von d1 aus in Richtung d2, richtig?
Jepp.

Früchtemüsli
2013-08-20, 18:21:40
Also das hat mir schon mal echt weitergeholfen. Das muss ich mir morgen mal in aller Ruhe nochmals durchlesen. Für heute fehlt mir leider schon die Energie dafür. Danke vorerst mal! :)

Früchtemüsli
2013-08-21, 12:54:33
Also die folgende Formel verwirrt mich noch etwas:

float s = (float)Math.tan(angle + Math.acos(perp)) * perp - par;

Wozu braucht man das "* perp - par"? Wieso kann man das nicht weglassen?

Ich habe den Winkel und ermittle davon den tan. Normalerweise reicht das doch zum Skewen, oder?

Hier z. B. eine Matrix für einen 2d-Skew in x-Richtung, in Abhängigkeit von y:

|1 tan(winkel) 0|
|0 1 0|
|0 0 1|


Hier eine Skizze, was ich mir bis jetzt zusammengereimt habe:

http://i41.tinypic.com/jb2wer.png

Alle Vektoren liegen auf der gleichen Ebene (ist ev. nicht die xy-Ebene) und sind Einheits-Vektoren.
d1' ist d1ortho.
Geskewt wird um angle + acos(perp)