Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: So Dez 22, 2024 03:58

Foren-Übersicht » Programmierung » Mathematik-Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Sa Feb 02, 2013 20:05 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 16, 2008 20:26
Beiträge: 158
Wohnort: Berlin
Programmiersprache: c++,c#,java,ruby,php
Guten Abend,
Ich arbeite an einer kleinen Engine in WebGl.

Vorgeschichte:
Bisher funktionierte eine grobe Steuerung der Kamera ohne Probleme mit Matrizen.
Jetzt wollte ich jedoch eine umschaltbare Kamera haben von First zu Third Person oder auch gänzlich frei in der Bewegung haben.
Das klappte nach tagelangen Rumprobieren und Durchstöbern nicht. Irgendwie scheinen auch sehr viele Formeln/Beispiele die es im Internet gibt bei mir nicht direkt zu gehen, so wie sie sollten.

Die Spielfigur hatte ich mit Matrizen irgendwann im Griff und ich konnte sie auch korrekt steuern. Jedoch gelang es mir nicht dir Kamera auf den Spieler zu richten und gleichzeitig hinter ihm zu platzieren.
Eines von beiden funktionierte immer nur. Wollte ich dann die Kamera drehen lassen, drehte sie sich immer um den Szenenursprung. Inzwischen gab es auch viele Multiplikationen und Invertierungen, weshalb ich alles auf Quaternionen umgestellt habe, was über 20% schneller und eigentlich auch einfacher nachvollziehbar ist.

Jedoch bekomme ich es immer noch nicht hin.

Probleme:
1. Der Spieler kann sich nur noch auf den Weltkoordinatenachsen bewegen, bei den Matrizen wusste ich wie ich den Translationsvektor bearbeiten muss, damit er sich auf die lokalen Koordinatenachsen des Spielerobjektes auswirkt. Bei Quaternionen leider nicht, außer ich forme sie erst in eine Matrix um, aber dann ist der ganze Witz an der Sache weg wie ich finde.

2. Die Kamera rotiert immer um den Ursprung, das Problem hatte ich schon vorher oft. Aktuell ist das Cameraquaternion nur das invertierte Spielerqquaternion.
Bei den Matrizen war das Problem immer, dass die Kamera sich um eine Position etwas weiter vor sich rotierte und nicht genau um die eigene Y-Achse.

3. Wenn ich die Camera kippe um 45° um die X-Achse, dann bewegt sie sich auch nach oben oder unten weg beim bewegen, was ungewollt ist. Das liegt auch mit Problem 1 zusammen, dass ich nicht mehr weiß, wie ich an die korrekten Achsen komme. Ich hab einige Funktionen versucht die Vektoren mit den Quaternionen zu rotieren, aber dann wird alles nur noch merkwürdiger.

4. Seit ich Quaternionen einsetze scheint die Normalenmatrix nicht mehr zu stimmen, gut zu erkennen an dem einen Affenkopf, wenn das Licht auf der Z-Achse verschoben wird.
Muss da etwas spezielles beachtet werden anstatt das invertierte Quaternion zu nehmen und in eine 3x3 Matrix umzuformen?
Eventuell stimmen auch die Bi/Tangenten und Normalen nicht (Mit N aktivierbar).

Live-Beispiel: Damit sich das auch angeguckt werden kann, am besten in Chrome, dort sind Schieberegler vorhanden.
http://tunnistava.systemcloud.de/
oben/unten/links/rechts : Pfeiltasten zum steuern (Richtungen stimmen aber irgendwie nicht)
n: aktiviert die Normalen/Tagenten/Bitagenten-Ansicht
a: aktiviert Antialising mit Fxaa (was noch nicht korrekt geht)

Codeausschnitte:
Ich benutze Matrizen die so aufgebaut waren/sind:
Code:
  1.  x,  x,  x, x
  2.  y,  y,  y, y
  3.  z,  z,  z, z
  4. px,py,pz, w


Shadercodeauszug:
Code:
  1.     gl_Position = projektionsMatrix * modelviewMatrix * transformationsMatrix * vec4(vertexPosition, 1.0);

Projektionsmatrix ist klar.
modelviewmatrix ist meine Cameramatrix.
transformationsmatrix ist die Matrix des VBO-Objektes mit Drehungen und Verschiebungen, aus Performancegründen wird die Multiplikation im Shader gemacht.

Steuerungupdate pro Frame:
Code:
  1. this.update = function() {
  2.         this.camera.createViewport();
  3.         var fps = this.fpsCounter.getFPS();
  4.         var faktor = (fps > 0) ? fps : 1.0;
  5.  
  6.         var playerMatrix = this.player.getMatrix().duplizieren();
  7.         var speed = this.player.getPhysik().getSpeed();
  8.         var newX = new Vektor4();
  9.         var newZ = new Vektor4();
  10.         var playPo = playerMatrix.holePosition();
  11.  
  12.         if (this.accelerationSeitlich > 0 || this.accelerationSeitlich < 0) {
  13.             newX.z = 0; //playPo.x * ((this.accelerationSeitlich * speed * 25) / faktor);
  14.             newX.y = 0; //playPo.x * ((this.accelerationSeitlich * speed * 25) / faktor);
  15.             newX.x = ((this.accelerationSeitlich * speed * 25) / faktor);
  16.         }
  17.         if (this.accelerationBewegung > 0 || this.accelerationBewegung < 0) {
  18.             newZ.z = ((this.accelerationBewegung * speed * 25) / faktor);
  19.             newZ.y = 0;//playPo.z * ((this.accelerationBewegung * speed * 25) / faktor);
  20.             newZ.x = 0;//playPo.z * ((this.accelerationBewegung * speed * 25) / faktor);
  21.         }
  22.         var playerVektor = Math3D.addierenV4V4(newX, newZ);
  23.         playerVektor.invertieren();
  24.         playerVektor.x += playPo.x;
  25.         playerVektor.y += playPo.y;
  26.         playerVektor.z += playPo.z;
  27.         var rotQuatY = new Quaterion();
  28.         rotQuatY.identity();
  29. //Mausbewegung in X
  30.         if (this.deltaX) {
  31.             rotQuatY.rotationAchse(0.0, 1.0, 0.0, this.deltaX);
  32.         }
  33.         var rotMatrixX = new Quaterion();
  34.         rotMatrixX.identity();
  35. // Zwischengespeicherter Winkel, sollte am besten durch das Quaternion komplett abgebildet werden
  36.         winkelC += this.deltaY;
  37.         rotMatrixX.rotationAchse(1.0,0.0,0.0,winkelC);        
  38. //Mausbewegung in Y
  39.         if (this.deltaY) {
  40.             //  rotMatrixX = Math3D.createRotationsM(0.0, 1.0, 0.0, -this.deltaY / 1.0);
  41.         }
  42.         playerMatrix = QuaterionMath.multiplizierenQQ(rotQuatY,playerMatrix);
  43.         playerMatrix.setzePosition(playerVektor);
  44.         cameraMatrix = playerMatrix.duplizieren();
  45.         cameraMatrix.invertieren();
  46.         this.player.setMatrix(playerMatrix);
  47.         this.camera.setMatrix(cameraMatrix);
  48.     };


Hoffe einer hat eine clevere Idee, ich komme seit Wochen nicht wirklich voran. Nichts scheint zu helfen und ich rate mehr ins Blaue inzwischen, als dass ich mir noch etwas herleiten kann.

Grüße

_________________
System: Phenom XII X4 955 3,21Ghz , GTX 560 TI, 4GB-Ram, Windows 7 64x


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Feb 03, 2013 15:15 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
bei den Matrizen wusste ich wie ich den Translationsvektor bearbeiten muss, damit er sich auf die lokalen Koordinatenachsen des Spielerobjektes auswirkt. Bei Quaternionen leider nicht, außer ich forme sie erst in eine Matrix um, aber dann ist der ganze Witz an der Sache weg wie ich finde.

Quaternionen alleine können ausschließlich Rotationen darstellen. Keine Translation und keine Skalierung.
ABER, du kannst Quaternionen mit einem Translationsvektor kombinieren und das ganze in eine Klasse verpacken, so dass der Translationsvektor immer korrekt aktualisiert wird.Bei Coolmath gibt es die "Frame"-Klasse die genau das macht.

Für deine Kamera brauchst du aber eigentlich keine Quaternionen. Es sollte ausreichen dir eine LookAt-Funktion zu bauen. Dort gibt du einfach die gewünschte Kameraposition und den Punkt auf den sie blicken soll an. Außerdem noch einen Up-Vektor um anzugeben wo oben im Bild sein soll. Siehe auch http://wiki.delphigl.com/index.php/gluLookAt

In CoolMath sieht die Funktion so aus:
Code:
  1. template<typename T, int N, int M>
  2. Matrix<T,4,4> Matrix<T,N,M>::lookAt(const Vector<T,3>& eye, const Vector<T,3>& center, const Vector<T,3>& up)
  3. {
  4.     STATIC_ASSERT(N==4 && M==4, "Operation only allowed for 4x4 matrices.");
  5.     Vector<T,3> f = center - eye;
  6.     f.normalize();
  7.     Vector<T,3> s = cross(f, up);
  8.     s.normalize();
  9.     Vector<T,3> u = cross(s, f);
  10.     return Matrix<T,4,4>(   s.x,              u.x,       -f.x, 0,
  11.                             s.y,              u.y,       -f.y, 0,
  12.                             s.z,              u.z,       -f.z, 0,
  13.                          -dot(s,eye), -dot(u,eye), dot(f,eye), 1);
  14. }


Edit:
Zitat:
Muss da etwas spezielles beachtet werden anstatt das invertierte Quaternion zu nehmen und in eine 3x3 Matrix umzuformen?

Die Normalmatrix ist die invertierte und transponierte WorldView-Matrix. Also nicht vergessen zu transponieren. Da du aber dank Quaternionen nur Rotation und ggf. Translation hast (und keine Skalierung oder Scherungen) heben sich das invertieren und transponieren gegenseitig auf. Du kannst also einfach den 3x3-Teil der resultierenden Matrix benutzen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Feb 03, 2013 19:10 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 16, 2008 20:26
Beiträge: 158
Wohnort: Berlin
Programmiersprache: c++,c#,java,ruby,php
Edit:
Ich glaube die Mathematik wird an sich stimmen, aber meine Vorgehensweise wohl nicht.
Vielleicht muss ich nur irgendetwas normalisieren bzw. invertieren.
Diese Mathematik ist nichts für mich.

1. Auf einen Tastendruck reagieren und einen Vektor erstellen z.B. 1,0,0 für eine Bewegung in X-Richtung
2. Spielerquaterion rotieren bei Mausbewegung

Variante1
3. Auf den neuen Vektor die alten Positionen dazuaddieren
4. Die Position dem Spielerobjekt zuordnen
5. Beim Zeichnen des VBOs die Rotationsmatrix aus dem Quaterion erzeugen
6. Die Felder [12], [13], [14] auf die Vektorkoordinaten X, Y, Z setzen

Variante2
3. Den Vektor mit einer der Methoden unten drehen
4. Dann zur alten Position dazuaddieren
5. Beim Zeichnen des VBOs die Rotationsmatrix aus dem Quaterion erzeugen
6. Die Felder [12], [13], [14] auf die Vektorkoordinaten X, Y, Z setzen

Variante3
3. Auf den neuen Vektor die alten Positionen dazuaddieren
4. Die Position dem Spielerobjekt zuordnen
5. Beim Zeichnen des VBOs die Rotationsmatrix aus dem Quaterion erzeugen
6. Die Felder [12], [13], [14] auf die Vektorkoordinaten X, Y, Z setzen, welche vorher mit einer der Methoden unten gedreht werden

-------------
Ich hab auch eine eigene Klasse, die beides kapselt und anpasst, jedoch klappt die Vektoranpassung einfach noch nicht.
Code:
  1.  
  2. v' = q * v * (q^-1)
  3. q*/(magnitude(q))^2 (q* is the conjugate)
  4. implementiert in this.rotationsVektor2
  5.  

Ist die Formel die ich oft dazu finde.
Hier sind alle Varianten die ich durchprobiert habe. Setze ich dann die Werte in die Matrix ein passiert oft nichts, als dass sich die Figur weiterhin auf den Weltachsen bewegt.
Ich bin durch das wochenlange Ausprobieren und durchlesen einfach nur total verwirrt, dabei wird es ganz einfach sein.
Wenn ich Zuerst eine Matrix erstelle aus dem Quaterion und mit einer Translationsmatrix multipliziere dann geht es.
Ich hatte auch schon einige LookAt-Funktionen probiert, aber die wollten auch nicht so wirklich funktionieren. Diese scheint bisher besser zu gehen, solange die Vektoren stimmen.
Danke dafür schon mal (:

Code:
  1.    
  2. this.rotationsVektor = function(vektor) {
  3.          var vec = new Vektor4();   // any constructor will do
  4.          vec.x = 2.0*(this.x*vektor.z*this.z + this.y*vektor.z*this.w - this.x*vektor.y*this.w + this.y*vektor.y*this.z) + vektor.x*(this.x*this.x + this.y*this.y - this.z*this.z - this.w*this.w);
  5.          vec.y = 2.0*(this.x*vektor.x*this.w + this.y*vektor.x*this.z - this.x*vektor.z*this.y + this.z*vektor.z*this.w) + vektor.y*(this.x*this.x - this.y*this.y + this.z*this.z - this.w*this.w);
  6.          vec.z = 2.0*(this.x*vektor.y*this.y - this.x*vektor.x*this.z + this.y*vektor.x*this.w + this.z*vektor.y*this.w) + vektor.z*(this.x*this.x - this.y*this.y - this.z*this.z + this.w*this.w);
  7.          return vec;
  8. }
  9. this.rotationsVektor2 = function(vektor) {
  10.         var tmp = this.duplizieren();
  11.         tmp.konjugante();
  12.         var tmp2 = new Quaterion();
  13.         tmp2.setzeX(vektor.x);
  14.         tmp2.setzeY(vektor.y);
  15.         tmp2.setzeZ(vektor.z);
  16.         tmp2.setzeW(0.0);
  17.  
  18.         var tmp3 = QuaterionMath.multiplizierenQQ(this, tmp2);
  19.         var tmp4 = QuaterionMath.multiplizierenQQ(tmp3, tmp);
  20.         return (new Vektor4(tmp4.holeX(), tmp4.holeY(), tmp4.holeZ(), 0.0));
  21.     }
  22.     this.rotationsVektor3 = function(vektor) {
  23.         var k0 = this.w * this.w - 0.5;
  24.         var k1;
  25.         var rx;
  26.         var ry;
  27.         var rz;
  28.         // k1 = Q.V
  29.         k1 = vektor.x * this.x;
  30.         k1 += vektor.y * this.y;
  31.         k1 += vektor.z * this.z;
  32.         // (qq-1/2)V+(Q.V)Q
  33.         rx = vektor.x * k0 + this.x * k1;
  34.         ry = vektor.y * k0 + this.y * k1;
  35.         rz = vektor.z * k0 + this.z * k1;
  36.         // (Q.V)Q+(qq-1/2)V+q(QxV)
  37.         rx += this.w * (this.y * vektor.z - this.z * vektor.y);
  38.         ry += this.w * (this.z * vektor.x - this.x * vektor.z);
  39.         rz += this.w * (this.x * vektor.y - this.y * vektor.x);
  40.         //  2((Q.V)Q+(qq-1/2)V+q(QxV))
  41.         rx += rx;
  42.         ry += ry;
  43.         rz += rz;
  44.         return new Vektor4(rx, ry, rz, 0.0);
  45.     };
  46.     this.rotationsVektor4 = function(vektor) {
  47.         var result = new Vektor4();
  48.         var a00 = this.x * this.x;
  49.         var a01 = this.x * this.y;
  50.         var a02 = this.x * this.z;
  51.         var a03 = this.x * this.w;
  52.         var a11 = this.y * this.y;
  53.         var a12 = this.y * this.z;
  54.         var a13 = this.y * this.w;
  55.         var a22 = this.z * this.z;
  56.         var a23 = this.z * this.w;
  57.         var a33 = this.w * this.w;
  58.         result.x = vektor.x * (+a00 + a11 - a22 - a33)
  59.                 + 2 * (a12 * vektor.y + a13 * vektor.z + a02 * vektor.z - a03 * vektor.y);
  60.         result.y = vektor.y * (+a00 - a11 + a22 - a33)
  61.                 + 2 * (a12 * vektor.x + a23 * vektor.z + a03 * vektor.x - a01 * vektor.z);
  62.         result.z = vektor.z * (+a00 - a11 - a22 + a33)
  63.                 + 2 * (a13 * vektor.x + a23 * vektor.y - a02 * vektor.x + a01 * vektor.y);
  64.         return result;
  65.     };
  66.     this.rotationsVektor5 = function(vektor) {
  67.         var vektorRotiert = vektor.duplizieren();
  68.         vektorRotiert.normalisieren();
  69.         var vecQuat = new Quaterion();
  70.         var resQuat = this.duplizieren();
  71.         resQuat.invertieren();
  72.         vecQuat.setzeX(vektorRotiert.x);
  73.         vecQuat.setzeY(vektorRotiert.y);
  74.         vecQuat.setzeZ(vektorRotiert.z);
  75.         vecQuat.setzeW(0.0);
  76.         resQuat = QuaterionMath.multiplizierenQQ(vecQuat, resQuat);
  77.         resQuat = QuaterionMath.multiplizierenQQ(this, resQuat);
  78.         return (new Vektor4(resQuat.x, resQuat.y, resQuat.z, 0.0));
  79.     };

_________________
System: Phenom XII X4 955 3,21Ghz , GTX 560 TI, 4GB-Ram, Windows 7 64x


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Feb 13, 2013 09:08 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 16, 2008 20:26
Beiträge: 158
Wohnort: Berlin
Programmiersprache: c++,c#,java,ruby,php
Hallo,
ich hab es teilweise hinbekommen mit Quaternionen, nur die Kamera will noch nicht ganz so wie sie sollte.

1. Also mit der lookAt Funktion kann ich zwar den Charakter oder in beliebiges Objekt im Fokus halten, jedoch sind die Eye-Koordinaten falsch. Selbst wenn ich etwas einsetze bewegt sich die Kamera komisch. Der Eye-Vektor wird als Abstand zum Koordinaten Ursprung genommen, so dass sie um den Ursprung dreht.
1.1 Deshalb habe ich das jetzt mit Quaternionen gemacht.
Das einzige Problem was jetzt besteht, ist, dass die Kamera zwar korrekt um den Charakter kreisen kann, allerdings nicht auf ihn blickt. sondern immer in eine feste Richtung.
Nach der Invertierung kann ich zwar weitere Drehungen anwenden, die sich nur auf die Kamera beziehen, jedoch werden dann auch wieder die Koordinaten beeinflusst.
Code:
  1.  
  2.         var pV = playerQuat.holePositionE(10.0);
  3. /*
  4.     this.holePositionE = function(faktor) {
  5.         var localVor = this.holeVorwaerts(); // Hole den aktuellen Vektor für die Lokale Z-Achse
  6.         localVor.x *= faktor; // Vektor skalieren für den Abstand
  7.         localVor.y *= faktor;
  8.         localVor.z *= faktor;
  9.         var gesamt = Math3D.addierenV4V4(localVor, this.vektor); // Verschiebung addieren
  10.         return gesamt;
  11.     };
  12. */
  13.         pV.x = pV.x*-1; // Die Invertierung wird später mal woanders gemacht werden, wenn alles klappt
  14.         pV.y = 2*-1;
  15.         pV.z = pV.z*-1;
  16. var cameraQuat = new Quaterion();  //neues Quaternion
  17. cameraQuat.identity(); // x,y,z =0, w =1
  18. cameraQuat.invertieren();
  19. cameraQuat.setzePosition(pV); // Position setzen
  20.  


2.
Der Charakter kann jetzt korrekt bewegt und gedreht werden. Mein Problem war, dass die falschen Achsen benutzt wurden und nicht die korrekten lokalen Y- und X-Achsen. Für alle, die das auch brauchen:
Code:
  1.         var rotQuatY = new Quaternion(); //neues Quaternion
  2.         rotQuatY.identity(); // x,y,z =0, w =1
  3.         if (this.deltaX) { //wenn Mausdrehung links/rechts
  4.             rotQuatY.rotationAchse(0.0, 1.0, 0.0, this.deltaX / -1.0);       // Rotations Quaternion erstellen
  5.         }
  6.         var playPos = playerQuat.holePosition(); // Position speichern
  7.         playerQuat = QuaternionMath.multiplizierenQQ(rotQuatY, playerMatrix); // Rotation auf das vorhandene Spielerquaternion anwenden
  8.         playerQuat.setzePosition(playPos); // Position wieder setzen
  9.         var speed = this.player.getPhysik().getSpeed(); // Geschwindigkeit ermitteln
  10.         if (this.accelerationSeitlich > 0 || this.accelerationSeitlich < 0) { //wenn seitlich bewegt
  11.             playerQuat.bewegeX(((this.accelerationSeitlich * speed * 25.0) / faktor));
  12. /*
  13.     this.bewegeX = function(faktor) {
  14.         this.vektor.x += (1.0 - (2.0 * ((this.y * this.y) + (this.z * this.z)))) * faktor;
  15.         this.vektor.y += (2.0 * ((this.x * this.y) - (this.z * this.w))) * faktor;
  16.         this.vektor.z += (2.0 * ((this.x * this.z) + (this.y * this.w))) * faktor;
  17.     };
  18. */
  19.         }
  20.         if (this.accelerationBewegung > 0 || this.accelerationBewegung < 0) { // wenn vorwärts bewegt
  21.             playerQuat.bewegeZ(((this.accelerationBewegung * speed * 25.0) / faktor));
  22. /*
  23.     this.bewegeZ = function(faktor) {
  24.         this.vektor.x += (2.0 * ((this.x * this.z) - (this.y * this.w))) * faktor;
  25.         this.vektor.y += (2.0 * ((this.y * this.z) + (this.x * this.w))) * faktor;
  26.         this.vektor.z += (1.0 - (2.0 * ((this.x * this.x) + (this.y * this.y)))) * faktor;
  27.     };
  28. */
  29.         }
  30.  

Damit kann der Charakter wunderbar bewegt werden.

Grüße

_________________
System: Phenom XII X4 955 3,21Ghz , GTX 560 TI, 4GB-Ram, Windows 7 64x


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Foren-Übersicht » Programmierung » Mathematik-Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.018s | 16 Queries | GZIP : On ]