Thermonologie
Ich nenne Ihr "linker / rechter Drehpunkt des Revolvers" Gelenk "horizontales Gelenk" und Ihren "Auf / Ab-Drehpunkt des Laufs" Gelenk "vertikales Gelenk".
Berechnen Sie mit Vorwärtskinematik (Transformationen, die zu (bisher unbekannter) Ausrichtung / Position führen) die Position und den Upvektor und den Vorwärtsvektor (dieser Vektor zeigt vom horizontalen Gelenk nach vorne).
Inverser Teil Verwenden Sie danach die Position und den Upvektor und den Vorwärtsvektor, um die vertikalen und horizontalen Zielrotationen zu berechnen.
Formeln für den umgekehrten Teil des Falls, wenn sich die horizontale Verbindung direkt auf der vertikalen Verbindung befindet
(Pseudocode - ungetestet)
// input
Vector3f UpVector; // upvector (normalized)
Vector3f ForwardVector; // (normalized)
Vector3f TargetPosition; // (absolute target position
Vector3f FKPosition; // forward kinematic Position of the turret
// is the absolute position in worldspace of the turret head
// temp
Vector3f SideVector; (normalized)
Vector3f TargetDiffUnnormalized; // difference to the target
Vector3f TargetDiff; // (normalized)
// output
float HorizontalRotationRawRad;
float VerticalRotationRawRad;
// calculation
// first we calculate the sidevector which is perpendicular to the up and ForwardVector
SideVector = UpVector.Cross(ForwardVector).normalized();
TargetDiffUnnormalized = TargetPosition - FKPosition;
TargetDiff = TargetDiffUnnormalized.normalize();
// we "project" the TargetDiff vector to the Plane which is described by the ForwardVector and SideVector
float ProjectedForward = ForwardVector.dot(TargetDiff)
float ProjectedSide = SideVector.dot(TargetDiff)
// now we need to normalize the 2d Vector which is described by ProjectedForward and ProjectedSide because the length of it is not 1.0 and we would get wrong results
Vector2f ProjectedHorizontal = new Vector2f(ProjectedForward, ProjectedSide);
ProjectedHorizontal = ProjectedHorizontal.normalized();
// NOTE< here the components _could_ be wrong and the multiplication _could_ be wrong, depending on the direction of rotation and so on >
HorizontalRotationRawRad = acos(ProjectedHorizontal.Y);
if( ProjectedHorizontal.X < 0.0f )
{
HorizontalRotationRawRad *= -1.0f;
}
//-----
Vector3f HorizontalDirection = ForwardVector.scale(ProjectedHorizontal.X) + SideVector.scale(ProjectedHorizontal.Y)
// NOTE< HorizontalDirection should be normalized, check if wanted with assertion to make sure >
VerticalRotationRawRad = acos(HorizontalDirection.dot(TargetDiff));
Bearbeiten 1
Die Mathematik und der Code sowie die Beschreibung für den Fall, dass sich die horizontale Verbindung nicht auf der vertikalen Verbindung befindet (der allgemeinere Fall), folgen hier.
Wenn Sie den 2D-Fall von oben betrachten (sozusagen auf der Ebene des horizontalen Gelenks in der 3D-Welt), stellen Sie fest, dass sich das vertikale Gelenk beim Drehen des horizontalen Gelenks auf einem Kreis dreht.
Jetzt suchen wir den Rotationsversatz, da Sie die Rotation zur HorizontalRotationRawRad
Variablen hinzufügen müssen , um die tatsächliche Rotation zu erhalten.
Um dies zu archivieren, müssen Sie den Zielpunkt im 3D-Raum auf die horizontale Gelenkebene projizieren (Sie können dies mit der Berechnung des Schnittpunkts zwischen der Ebene und einem Strahl archivieren, der am Zielpunkt beginnt und in Richtung der Normalen zeigt des Flugzeugs).
Ich nenne diesen Punkt, den Sie als Ergebnis der Kreuzung erhalten PlaneTarget
.
Jetzt können Sie die Entfernung von FKPosition
bis berechnen PlaneTarget
und ich nenne esc
.
Für die folgende Berechnung müssen Sie nur einmal beim Gameloading oder bei der Bauzeit des Panzers oder immer dann berechnen, wenn nur der Abstand von der horizontalen Verbindung zur vertikalen Verbindung und der Winkel der beiden (von 90 bis 180 Grad) und die Seite von die vertikale Verbindung.
Um den Versatzwinkel zu berechnen, verwenden wir das Kosinusgesetz:
Wir kennen c und b und Gamma und suchen Alpha.
nach einigem rechnen ...
c² = a² +b² - 2ab cos(gamma)
rearanging->
c² = a² + b² - a * 2b cos(gamma)
this is a quadratic equation, solve it with some math or a solver which you wrote to get c
Wir wissen, dass wir die Fälle abfangen müssen, wenn sich das Ziel innerhalb des Kreises befindet (c <b), weil es nicht viel Sinn macht.
Jetzt müssen wir den Winkel Alpha mit etwas mehr Mathematik berechnen ...
a² = b² + c² - 2bc cos(alpha) | + 2bc cos(alpha) | - a²
2bc cos(alpha) = b² + c² - a²
alpha = acos(b² + c² - a² / 2bc)
Jetzt können wir Alpha von / zu VerticalRotationRawRad addieren / subtrahieren, um den richtigen Winkel für das horizontale Gelenk zu erhalten.
Die Berechnung der vertikalen Verbindung ist etwas einfacher. Verwenden Sie den Winkel der horizontalen Verbindung, um den Punkt der vertikalen Verbindung im Weltraum zu drehen.
Dann machen Sie einfach ein Punktprodukt zwischen der normalisierten Richtung des Zylinders und der Differenz zur Zielposition (natürlich hat das Ergebnis kein Vorzeichen, wenn es eines haben sollte, verwenden Sie einfach die horizontale Ebene und schauen Sie, ob die Zielposition darüber liegt oder darunter).