Ich möchte eine Schieberegler-Beschränkung instanziieren, die es einem Körper ermöglicht, zwischen Punkt A und Punkt B zu gleiten. Zur Instanzierung der Zwangsbedingung weise ich die beiden Körper zu, die gebunden werden sollen, in diesem Fall einen dynamischen Körper, der an die statische Welt gebunden ist, z. B. eine Schiebetür. Der dritte und vierte Parameter sind Transformationen, Bezugsrahmen A y Bezugsrahmen B . Zur Erstellung und Bearbeitung von Transformationen unterstützt die Bibliothek Quaternionen, Matrizen und Euler-Winkel.
Die Standard-Schieberegler-Beschränkung verschiebt den Körper entlang der X-Achse. Meine Frage ist: Wie stelle ich die beiden Transformationen so ein, dass Körper B entlang einer Achse gleitet, die durch seinen eigenen Ursprung und einen zusätzlichen Punkt im Raum gegeben ist?
Ich habe es ganz naiv versucht:
frameA.setOrigin(origin_of_point); //since the world itself has origin (0,0,0)
frameA.setRotation(Quaternion(directionToB, 0 rotation));
frameB.setOrigin(0,0,0); //axis goes through origin of object
frameB.setRotation(Quaternion(directionToPoint,0))
Allerdings scheinen die Quaternionen nicht so zu funktionieren, wie ich es erwartet habe. Meine mathematischen Kenntnisse sind nicht sehr gut, wenn mich also jemand aufklären könnte, warum das nicht funktioniert, wäre ich sehr dankbar. Was passiert, ist, dass der Körper entlang einer Achse gleitet, die orthogonal zur Richtung ist. Wenn ich den Rotationsteil im Quaternion-Konstruktor variiere, wird der Körper um diese Gleitrichtung gedreht.
Bearbeiten: Der Rahmen ist die Geschossphysik. Die beiden Transformationen sind die Art und Weise, wie das Schiebergelenk an jedem Körper in Bezug auf das lokale Koordinatensystem des jeweiligen Körpers befestigt ist.
Bearbeiten2 Ich könnte auch die Rotationsanteile der Transformationen durch eine orthogonale Basis festlegen, aber dann müsste ich eine orthogonale Basis zuverlässig aus einem einzigen Vektor konstruieren. Ich hoffte, dass Quaternionen dies verhindern würden.
Bearbeiten3 Ich habe mit dem folgenden Verfahren einen begrenzten Erfolg:
btTransform trafoA, trafoB;
trafoA.setIdentity();
trafoB.setIdentity();
vec3 bodyorigin(entA->getTrafo().col_t);
vec3 thisorigin(trafo.col_t);
vec3 dir=bodyorigin-thisorigin;
dir.Normalize();
mat4x4 dg=dgGrammSchmidt(dir);
mat4x4 dg2=dgGrammSchmidt(-dir);
btMatrix3x3 m(
dg.col_x.x, dg.col_y.x, dg.col_z.x,
dg.col_x.y, dg.col_y.y, dg.col_z.y,
dg.col_x.z, dg.col_y.z, dg.col_z.z);
btMatrix3x3 m2(
dg2.col_x.x, dg2.col_y.x, dg2.col_z.x,
dg2.col_x.y, dg2.col_y.y, dg2.col_z.y,
dg2.col_x.z, dg2.col_y.z, dg2.col_z.z);
trafoA.setBasis(m);
trafoB.setBasis(m2);
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
btSliderConstraint* sc=new btSliderConstraint(*game.worldBody, *entA->getBody(), trafoA, trafoB, true);
GramSchmidt spiegelt jedoch immer einige Achsen der TrafoB-Matrix und die Tür erscheint auf dem Kopf stehend oder von rechts nach links. Ich hatte gehofft, dies auf elegantere Weise lösen zu können. Bearbeiten4 Ich habe eine Lösung gefunden, aber ich bin mir nicht sicher, ob dies zu einer Singularität im Constraint Solver führt, wenn der obere Vektor mit der Gleitrichtung übereinstimmt:
btTransform rbat = rba->getCenterOfMassTransform();
btVector3 up(rbat.getBasis()[0][0], rbat.getBasis()[1][0], rbat.getBasis()[2][0]);
btVector3 direction = (rbb->getWorldTransform().getOrigin() - btVector3(trafo.col_t.x, trafo.col_t.y, trafo.col_t.z)).normalize();
btScalar angle = acos(up.dot(direction));
btVector3 axis = up.cross(direction);
trafoA.setRotation(btQuaternion(axis, angle));
trafoB.setRotation(btQuaternion(axis, angle));
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));