Vector mittels (lokaler)Rotationsmatrix drehen
-
Was soll diese Spalte?
ist noch n verzweifelter test zur fehlersuche dieses fehlers. ändert aber nichts am ergebnis.
DIe Rotationsmatrix habe ich angegeben (konkret?? mit aktuellen werten?) aber die achsen sind auch OK.Ich habe nal das aktuelle programm raufgeladen http://www.tachyon-sound.de/temp/test.rar da kann man das gut sehen:
mit [einfg] und [pos1] rollt man. mit [strg] schiesst man eine rakete ab.
DIe Position die ich versuche zu berechnen soll die Startposition der Rakete(relativ zum raumschiff) sein (die rakete wird bereits korrekt ausgerichtet und startete _vorher_ von der raumschiff-mitte. Deswegen versuche ich den "turret-Psoitions-vektor" mittels zu rotieren.Hast du auch daran gedacht, hinterher den Offset wieder draufzurechnen?
Die Position rechne auch wieder drauf (Raumschiff-Position), aber z.zt ist es eh auf Pos 0,0,0
Man sieht dass die X-Psoition korrekt berechnet wird, aber die anderen beiden nicht so. DIe werte sind auch nicht einfach invertiert.
-
Tachyon76 schrieb:
DIe Rotationsmatrix habe ich angegeben (konkret?? mit aktuellen werten?) aber die achsen sind auch OK.
Und wie berechnen sich Right.X, usw.?
Ich habe nal das aktuelle programm raufgeladen http://www.tachyon-sound.de/temp/test.rar da kann man das gut sehen:
Es wird bestimmt niemand hier einfach so ein Programm runterladen und ausführen.
Kurz gesagt: Dein Ansatz, den Offsetvektor mit der Rotationsmatrix zu multiplizieren, ist richtig, also ist irgendwas bei der konkreten Umsetzung falsch. Aber die willst du ja anscheinend nicht herzeigen. Wie soll man dir dann helfen?
-
front ist der richtungsvektor(der ist korrekt),
right berechnet sich aus dem kreuzproduk von localAxisFront und localAxisTop
top = kreuzprodukt(localAxisRight, localAxisFront)
und immer normalisieren.Die Matrix-Vector-Multiplikation:
void Matrix::multVec(double &fX, double &fY, double &fZ, double &fL) { fX = matrixdata[0]*fX + matrixdata[4]*fY + matrixdata[8]*fZ; fY = matrixdata[1]*fX + matrixdata[5]*fY + matrixdata[9]*fZ; fZ = matrixdata[2]*fX + matrixdata[6]*fY + matrixdata[10]*fZ; } // Matrixdata = double[16] 4x4 matrix
und die matrix wird so befüllt:
RotationsMatrix:
Right.X | Top.X | Front.X | 0
Right.Y | Top.Y | Front.Y | 0
Right.Z | Top.Z | Front.Z | 0
0 | 0 | 0 | 1
-
Tachyon76 schrieb:
front ist der richtungsvektor(der ist korrekt),
right berechnet sich aus dem kreuzproduk von localAxisFront und localAxisTop
top = kreuzprodukt(localAxisRight, localAxisFront)
und immer normalisieren.Keine Ahnung, was das ist, aber eine Rotationsmatrix ist das bestimmt nicht. Es ist ein Gebilde, das zwar alle Informationen über die Drehung enthält, aber es ist halt nicht das was bei linksseitiger Multiplikation an einen Vektor einen gedrehten Vektor ergibt.
-
Keine Ahnung, was das ist, aber eine Rotationsmatrix ist das bestimmt nicht.
http://www.c-plusplus.net/forum/viewtopic-var-t-is-245737.html
die matrix nutze ich auch um die objekte mittels glMultMatrix() auszurichten.
schint also eine rotationsmatrix zu sein?
-
Ja, habe mich verrechnet, ich dachte zuerst, die Achsen wären verdreht. Verdreht waren aber meine Spalten in der Rechnung
Nun, dann müsste ich jetzt eigentlich weiter bohren, aber das könnte man auch alles abkürzen, indem du endlich mal den Sourcecode der zugehörigen Funktionen zeigst. Möglicherweise ist es nur ein Schreibfehler.
-
ok, ich poste mal was. ist aber mittlerweile in vielen dateien verstreut.
Lokale achse eines Objekts rotieren:
void GameObject::rotate(float degreeX, float degreeY, float degreeZ) { if (degreeX != 0 || degreeY != 0 || degreeZ != 0) { // Lokale Achse Rotieren (3 Richtungsvekttoren) Matrix matrix; matrix.createRotation(localAxisRight,degreeX); matrix.multVec(localAxisTop.x,localAxisTop.y, localAxisTop.z); matrix.multVec(localAxisFront.x,localAxisFront.y, localAxisFront.z); matrix.createRotation(localAxisTop, degreeY); matrix.multVec(localAxisFront.x,localAxisFront.y, localAxisFront.z); matrix.multVec(localAxisRight.x,localAxisRight.y, localAxisRight.z); matrix.createRotation(localAxisFront, degreeZ); matrix.multVec(localAxisRight.x,localAxisRight.y, localAxisRight.z); matrix.multVec(localAxisTop.x,localAxisTop.y, localAxisTop.z); // Achse wieder ausrichten (rundungsfehler aus rotation ausgleichen) localAxisFront.normalize(); localAxisRight=localAxisFront.crossProduct(localAxisTop); localAxisRight.normalize(); localAxisTop=localAxisRight.crossProduct(localAxisFront); localAxisTop.normalize(); } // Rotationsmatrix befülen updateMatrix(); }
Matrix befüllen:
void GameObject::updateMatrix() { translateMatrix.create(4,4); // bewegungs-matrix: translateMatrix.set(0,0,1); translateMatrix.set(1,1,1); translateMatrix.set(2,2,1); translateMatrix.set(3,3,1); translateMatrix.set(0,3,(float)position.x); translateMatrix.set(1,3,(float)position.y); translateMatrix.set(2,3,(float)position.z); localRotationMatrix.set(0,0, localAxisRight.x); localRotationMatrix.set(1,0, localAxisRight.y); localRotationMatrix.set(2,0, localAxisRight.z); localRotationMatrix.set(3,0, .0f); localRotationMatrix.set(0,1, localAxisTop.x); localRotationMatrix.set(1,1, localAxisTop.y); localRotationMatrix.set(2,1, localAxisTop.z); localRotationMatrix.set(3,1, .0f); localRotationMatrix.set(0,2, localAxisFront.x); localRotationMatrix.set(1,2, localAxisFront.y); localRotationMatrix.set(2,2, localAxisFront.z); localRotationMatrix.set(3,2, .0f); localRotationMatrix.set(0,3, .0f); localRotationMatrix.set(1,3, .0f); localRotationMatrix.set(2,3, .0f); localRotationMatrix.set(3,3, 1.0f); } void Matrix::createRotation(Vector axis, float degree) { Vector v=axis; v.normalize(); float radDegree = (3.1415926535897f/360.0f*1.155) *degree; double cosDegree = cos(radDegree); double sinDegree = sin(radDegree); create(4,4); set(0,0, (v.x * v.x) * (1.0f-cosDegree) + cosDegree); set(1,0, (v.x * v.y) * (1.0f-cosDegree) - (v.z*sinDegree)); set(2,0, (v.x * v.z) * (1.0f-cosDegree) + (v.y*sinDegree)); set(0,1, (v.y * v.x) * (1.0f-cosDegree) + (v.z*sinDegree)); set(1,1, (v.y * v.y) * (1.0f-cosDegree) + cosDegree); set(2,1, (v.y * v.z) * (1.0f-cosDegree) - (v.x*sinDegree)); set(0,2, (v.z * v.x) * (1.0f-cosDegree) - (v.y*sinDegree)); set(1,2, (v.z * v.y) * (1.0f-cosDegree) + (v.x*sinDegree)); set(2,2, (v.z * v.z) * (1.0f-cosDegree) + cosDegree); set(3,3,1); } void Matrix::multVec(double &fX, double &fY, double &fZ) { if (height = 4) { fX = matrixdata[0]*fX + matrixdata[4]*fY + matrixdata[8]*fZ; fY = matrixdata[1]*fX + matrixdata[5]*fY + matrixdata[9]*fZ; fZ = matrixdata[2]*fX + matrixdata[6]*fY + matrixdata[10]*fZ; } //.... } void Matrix::set(int x, int y, double value) { matrixdata[x + width * y] = value; }
diese Funktion funktionier nicht korrekt:
void SpaceShip::shootWeapon() { Projectile *newProjectile = (Projectile *)objectManager->createObject(2, gfxEngine); // Rocket Turret *turret = turrets.at(0); newProjectile->localAxisFront.x = this->localAxisFront.x; newProjectile->localAxisFront.y = this->localAxisFront.y; newProjectile->localAxisFront.z = this->localAxisFront.z; newProjectile->localAxisRight.x = this->localAxisRight.x; newProjectile->localAxisRight.y = this->localAxisRight.y; newProjectile->localAxisRight.z = this->localAxisRight.z; newProjectile->localAxisTop.x = this->localAxisTop.x; newProjectile->localAxisTop.y = this->localAxisTop.y; newProjectile->localAxisTop.z = this->localAxisTop.z; Vector turretPos = turret->turretPosition; this->localRotationMatrix.multVec(turretPos.x, turretPos.y, turretPos.z); Vector pos = getPos() newProjectile->setPos(pos + turretPos); newProjectile->updateMatrix(); newProjectile->speed = this->speed +1; }
edit:
genau die Zeile funktioniert nicht:
this->localRotationMatrix.multVec(turretPos.x, turretPos.y, turretPos.z);die Werte der achsen-ausrichtung (localAxisRight, localAxisFront, localAxisTop) habe ich kontrolliert; alle OK. die turretPosition ist auch OK.
nur das ergebnis der Vektor-Matrix-Muktiplikation "rotiert" nicht korrekt.
-
so, habs nun anders gelöst.
hab ja die richtungsvektoren der einzelnen achsen.
ich addiere nun einfach die turret-position anhand der achsen hinzu:Vector turretPos = position; turretPos.x += localAxisRight.x * turret->turretPosition.x; turretPos.y += localAxisRight.y * turret->turretPosition.x; turretPos.z += localAxisRight.z * turret->turretPosition.x; turretPos.x += localAxisTop.x * turret->turretPosition.y; turretPos.y += localAxisTop.y * turret->turretPosition.y; turretPos.z += localAxisTop.z * turret->turretPosition.y; turretPos.x += localAxisFront.x * turret->turretPosition.z; turretPos.y += localAxisFront.y * turret->turretPosition.z; turretPos.z += localAxisFront.z * turret->turretPosition.z;
Vector turretPos = position;
turretPos.x += localAxisRight.x * turret->turretPosition.x;
turretPos.y += localAxisRight.y * turret->turretPosition.x;
turretPos.z += localAxisRight.z * turret->turretPosition.x;turretPos.x += localAxisTop.x * turret->turretPosition.y;
turretPos.y += localAxisTop.y * turret->turretPosition.y;
turretPos.z += localAxisTop.z * turret->turretPosition.y;turretPos.x += localAxisFront.x * turret->turretPosition.z;
turretPos.y += localAxisFront.y * turret->turretPosition.z;
turretPos.z += localAxisFront.z * turret->turretPosition.z;
-
Vielleicht bei crossProduct ein Minuszeichen falsch? Da könnte ein Schlingern herkommen.
Außerdem kommt mir
float radDegree = (3.1415926535897f/360.0f*1.155) *degree;
komisch vor. Eigentlich sollte da radDegree = pi/180 * degree stehen. Aber das würde kein Schlingern erklären, dein Raumschiff dreht nur langsamer als gewollt.
Ansonsten sehe ich da jetzt keine Fehler, außer dass es meiner Meinung nach etwas umständlich ist, vier Rotationen anstatt einer (Stichwort Eulerwinkel) zu berechnen.
-
das ist so ein anderes Problem das ich nicht versteh:
irgendwie werden die winkel nicht korrekt berechnet. die komplette rotation arbeitet ja ansonsten nur mit (kleinen) relativen radien, deswegen ist mir das erst nichtaufgefallen. erst als ich ein objekt 90° drehen wollte.
grad wurde korrekt (mir der üblichen formel) in bogenmass umgerechnet. hab werte kontrolliert. nur rotation war mehr als 2* soviel.
hab alles kontrolliert, aber weiss auch nicth woher das kommt.
hängt vielleicht auch damit zusammen.
ich muss wohl nochmal alles (nun zum x-ten mal) durchgehen.danke dir für deine hilfe