2017-01-05 2 views
1

Ich schreibe meine eigene Inverse Kinematics und arbeite derzeit an gemeinsamen Einschränkungen. Es ist in Ordnung, aber ich möchte alle Diskontinuitäten aus der resultierenden Animation entfernen, und Einschränkungen sind das größte Problem.Klemmwinkel mit kontinuierlichem Ergebnis

Nehmen wir zum Beispiel an, Sie betrachten einen Ball, der sich um Ihren Kopf dreht. Es dreht sich nach rechts und Sie sehen nach rechts, bis zu Ihrem Hals Verdrehungsgrenze. Der Ball bewegt sich immer noch und wenn er an deinem Rücken vorbeikommt, wird dein Kopf plötzlich gegen das gegnerische Limit geklickt, nach links schauend. Das bekommen wir mit einer typischen Klemmung und es gibt mir eine Diskontinuität von Bild zu Bild.

Was ich brauche, ist, dass Ihr Kopf während weniger Frames von rechts nach links kommt. Meine erste Idee ist es, die Quellrichtung mit meiner X-Achse (zwischen den Schultern) zu reflektieren, und wenn die reflektierte Richtung Grenzbedingungen erfüllt - gebe sie zurück. Wenn die Grenzwerte nicht eingehalten werden, klemmen Sie die reflektierte Richtung statt der Quelle.

Das sollte mir die nette und kontinuierliche Bewegung geben und es ist keine Raketenwissenschaft, aber es gibt eine Menge von Details zu kümmern. Meine Grenzen können wie min < max sein, aber auch max < min, sie können den Schaltwinkelwert durchlaufen (wie 360->0 oder 180->-180) oder nicht. Wenn mein zulässiger Bereich größer als 180 Grad ist, sollte die Logik etwas anders sein.

Die Menge der verschiedenen Fälle baut sich sehr schnell auf, also frage ich mich, ob ich es irgendwo schon finden könnte?

BTW: Ich benutze Unreal-Engine, wenn es einen Unterschied macht.

EDIT:

Es tut mir Leid, wenn ich Sie mit meinem Kopf Beispiel verfehlt habe - es war nur eine Analogie meine Bedürfnisse zu visualisieren. Ich werde diesen Code nicht verwenden, um einen Kopfknochen (oder irgendeinen anderen) in einer letzten Animation zu orientieren. Ich plane, es als eine sehr grundlegende Operation zu verwenden, IK zu lösen. Es wird in jeder Iteration in jeder IK-Kette verwendet, für jeden Knochen viele Male. Also muss es so schnell wie möglich sein. Alle Konzepte auf höherer Ebene, wie Bewegungsplanung, Dynamik usw., werden bei Bedarf auf einer anderen Ebene hinzugefügt.

Vorerst Ich frage nur für eine Funktion wie:

float clampAngle(float angle, float min, float max) 

, die einen kontinuierlichen Wert für die Änderung Eingänge zurückkehren würde.

Ich arbeite gerade an verschiedenen Problemen, aber ich poste meinen Code, wenn ich auf diesen zurückkomme.

+0

Clipping an sich ist nicht ausreichend, müssen Sie eine Rotation von + Clip zu -clip über den Verlauf von mehreren Frames – Alnitak

+0

@Alnitak Ich möchte keine Planung hinzufügen, weil ich nicht die Zukunft kenne . Ich brauche es so einfach wie möglich, aber mit kontinuierlicher Ausgabe. Ich denke, dass meine Beschreibung das tun wird, ich muss es nur codieren :). – kolenda

+0

Ich würde wählen, Kopf Rotation auf eine maximale Änderung des Winkels für jedes Update zu beschränken. Wenn der Ball den mittleren Punkt hinter dem Kopf passiert, anstatt den Blick sofort von der rechten Begrenzung zur linken Begrenzung in einem großen Sprung zu bewegen, bewege dich in diese Richtung, aber niemals mehr als dein gewählter maximaler Winkel.Dies wird natürlicher und spiegelt auch realistische dynamische Einschränkungen wider. Was du beschreibst klingt seltsam, der Blick folgt einem Bild, das nicht wirklich existiert. –

Antwort

0

Einen Ansatz:

  • den Bereich definieren, wo die Einschränkung nicht (Kegel hinter dem Kopf) erfüllt werden kann
  • Maß dafür, wie weit in diese Region Ziel (Winkel zwischen dem Ziel und in der Mitte des Kegels ist aufgeteilt um einen halben kegel~~POS=TRUNC)
  • uns diese Skalarwert glatt mische Ihr beschränktes Objekt zurück bis zu einem gewissen vordefinierten Neutralstellung (dh Drehkopf zurück zur Mitte/Ruheposition reibungslos Ziel bewegt hinter dem Kopf)
1

Wenn Sie dies als eine Simulation betrachten, wird es viel klarer. Sie benötigen keine Planung wie in Ihrem Kommentar, da der nächste Frame nur mit Informationen berechnet wird, die im aktuellen Frame verfügbar sind.

Richten Sie ein Gelenk für den Hals wie in den ersten beiden Absätzen beschrieben ein. Es wird von links nach rechts in einem Rahmen umdrehen, wenn der Ball herumkommt.

Dann richten Sie ein zweites identisches Gelenk ein und schreiben Sie eine Winkelfeder, die es im Laufe der Zeit in Richtung des ersten Gelenks dreht. Durch Einstellen der Federkoeffizienten - Stärke, Dämpfung usw. - haben Sie die Kontrolle über die Art und Weise, wie sich der Kopf dreht.

Wie schreibe ich eine eckige Feder?

Dies kann nicht den besten Weg, aber der Code ist ziemlich kurz und einfach, so geht hier ...

Läßt das 2 Gelenke Master und einen Slave nennen. Sie müssen die Drehung phi und die Winkelgeschwindigkeit omega auf dem Slave-Gelenk speichern.

phi und omega sind axis-angle vectors - ein 3D-Vektor, dessen Größe ist die Anzahl der Radianten um die durch den Vektor definierte Achse zu drehen. Es macht Simulationen sehr einfach. Ob Ihre Gelenkdrehungen als Euler-Winkel oder Matrizen oder Quaternionen gespeichert werden, Sie werden wahrscheinlich einige Klassen un UE-API haben, um die Achsen-/Winkelvektoren zu extrahieren.

Wenn sich das Hauptgelenk ändert, wandeln Sie seine Drehung in den Achsenwinkel um. Lass uns das phi_m nennen.

Im Startrahmen sollte die Slave-Rotation phi auf denselben Wert wie der Master eingestellt werden. phi = phi_m. Es hat keine Winkelgeschwindigkeit, daher wird omega auf den Nullvektor (0,0,0) gesetzt.

Dann gehen Sie einen Frame vorwärts. Eine Rahmenlänge dt ist vielleicht 1/60 sec oder was auch immer.

Während der Simulation simulieren Sie zunächst einen neuen Wert für phi_m. Dann stellt die Differenz zwischen Master und Slave (der Vektor phi_m - phi) das auf das Slave-Gelenk einwirkende Drehmoment dar. The bigger the angle the stronger the torque. Nehmen wir an, die Masse ist 1,0, dann wird mit F = ma die Winkelbeschleunigung alpha dem Drehmoment gleichgesetzt. Das bedeutet, dass die Änderung der Winkelgeschwindigkeit für die Slave-Verbindung über diesen Rahmen alpha*dt ist. Jetzt können wir neue Winkelgeschwindigkeit berechnen: omega = omega + (alpha*dt). In ähnlicher Weise ist die neue Drehung die alte Drehung plus die Änderung der Drehung über die Zeit (Winkelgeschwindigkeit). phi = phi + (omega * dt)

setzen sie alle zusammen und das Hinzufügen in einem Koeffizienten für das Frühjahr strength und damping kann ein Simulationsschritt in etwa so gehen:

damping = 0.01 // between 0 and 1 
strength = 0.2 // ..experiment 
dt = currentTime-lastTimeEvaluated 

phi_m = eulerToAxisAngle(master.rotate) 
if (currentTime <= startTime || dt < 0) { 
    slave.phi = phi_m 
    slave.omega = (0,0,0) 
} else { 
    alpha = (phi_m - slave.phi)*strength 
    slave.omega = (slave.omega * (1.0 - damping)) + (alpha*dt) 
    slave.phi = slave.phi + slave.omega*dt 
} 
slave.rotate = axisAngleToEuler(slave.phi) 
lastTimeEvaluated = currentTime 

Beachten Sie, dass nur Dämpfung ein wenig von der gespeicherten Geschwindigkeit tötet. Wenn die Dämpfung sehr niedrig ist, wird die Verbindung überschwingen und in Position schwingen !!