Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Anonymous

unregistriert

1

07.06.2004, 15:38

Schwieriges Prob: Abhängigkeit eines Obj. von einem anderen

Hallo,

ich habe z.Z. ein (für mich) sehr schwieriges Problem. Es geht darum, ein Objekt so mit einem anderen zu Verknüpfen, dass Transformationen übernommen werden. Alle Modeling Programme z.B. bieten eine solche einfache Funktionalität: Man bindet Objekt A an Objekt B. Nun kann man Objekt B bewegen und es bewegt sich automatisch Objekt A mit - umgekehrt ist es jedoch nicht so. Man könnte dies auch als eine Art Hirarchie bezeichnen.

Am besten Vorstellen kann man sich das, wenn man mal Gelenke anschaut, ein Unterarm ist z.B. an den Oberarm gebunden. Bewegt man den Oberarm, so bewegt sich zwangläufig immer der Unterarm auch - man kann jedoch den Unterarm bewegen, ohne dass sich der Oberarm mitbewegt.

Mein Problem besteht nun darin, die beiden Transformationen der Objekte (rotation, translation...) richtig zu berechnen um eine entsprechende Matrix zu bekommen. Hier ist ein Code Ausschnitt, wie ich ihn z.Z. benutze, damit Objekt A (welches an Objekt B gebunden ist) die Rotation den anderen Objektes übernimmt:

Quellcode

1
2
3
4
5
6
7
8
9
10
// mMatrix   -> Die Matrix, die zur Transformation von Objekt A (welches an Objekt B gebunden ist) benutzt wird
// pBoundObj -> Zeiger auf das Objekt, an welches Obj. A gebunden ist, so hat man Zugriff
//              auf dessen Transformationsmatrix oder andere Dinge, wie Position, Rotationsvektoren etc...


mMatrix =   CMatrix::scale(vScale) *  // (1)
        CMatrix::axis(vXAxis, vYAxis, vZAxis) *  // (2)
        CMatrix::translation(CVector(-pBoundObj->vPosition.x, -pBoundObj->vPosition.y, -pBoundObj->vPosition.z)) *  // (3)
        CMatrix::axis(pBoundObj->vXAxis, pBoundObj->vYAxis, pBoundObj->vZAxis) *  // (4)
        CMatrix::translation(CVector(pBoundObj->vPosition.x, pBoundObj->vPosition.y, pBoundObj->vPosition.z));  // (5)


In (1) wird ganz normal das Objekt skaliert. In (2) wird das Obejekt auch normal rotiert.

(3), (4) und (5) sind nun meine Idee, wie ich das Objekt anhand der Rotation des 2. Objektes drehen kann. Ich verschiebe erst mein Objekt A um die negative Position des Objektes B (3), dann rotiere ich es, da ja jetzt der Mittelpunkt quasi bei 0 liegt (4) und schliesslich verschiebe ich es zurück, damit das Objekt A wieder richtig positioniert wird (5).

Mein Plan war, dass jedes Objekt eine Methode "bind()" besitzt, um es an ein anderes zu binden. Eine andere Methode "getMatrix" liefert dann die Matrix des gebundenen Objektes (oder die Transformationsvektoren einzelnd), falls jenes Objekt wieder gebunden ist, wird wieder getMatrix aufgerufen, so entsteht eine "quasi Rekursion", damit es halt mehrere Abhängigkeiten geben kann.

Im obigen Codeabschnitt ist die Translation des Objektes noch nicht berücksichtigt, das brachte mir leider noch viel mehr Probleme ein.

Führe ich den obigen Code aus, und lasse das Objekt B (Objekt A ist immer noch an B gebunden) bewegen, z.B. nach oben, so rotiert Objekt A zwar um Objekt B, doch wird der Abstand von A zu B merkwürdigerweise immer und immer größer, und ich verstehe einfach nicht warum?!?
Ganz zu schweigen davon, dass die eigene Tranlsation von Objekt A auch noch nicht funktioniert.


Hat jemand eine Idee, warum meine geplante Lösung vielleicht sehr dumm ist ;) bzw. vielleicht kennt jemand ja einen besseren Weg (oder überhaupt einen Weg :) ), solche eine Abhängigkeit von einem zum anderen Objekt möglich zu machen.

Ich hoffe ich habe es einigermaßen gut erklärt, falls noch Fragen sind, könnte ich auch ein Bild vorbereiten, welches mein Vorhaben genauer beschreibt. Über Hilfe würde ich mich sehr freuen, bin grad ein wenig am verzweifeln :crying:

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

07.06.2004, 15:44

Du musst eigentlich nur die beiden Matrizen miteinander multiplizieren, das reicht schon! Wenn Objekt B ein "Kindobjekt" von Objekt A sein soll, dann geht das so:

Absolute Matrix von Objekt B = Lokale Matrix von Objekt B * Absolute Matrix von Objekt A

Wenn Objekt A kein "Kindobjekt" eines anderen Objekts ist, dann gilt:
Absolute Matrix von Objekt A = Lokale Matrix von Objekt A

Anonymous

unregistriert

3

07.06.2004, 17:12

Danke für Deine Antwort, mir ist nur nicht ganz so klar, was Du mit "lokaler" und "absoluter" Matrix meinst?

Ich hatte schonmal probiert, einfach die Matrix von Objekt A mit B zu multiplizieren (und auch umgekehrt), die Ergebnisse waren aber nie ganz korrekt...

Till

Alter Hase

Beiträge: 378

Wohnort: Lincoln College, Oxford

Beruf: Student

  • Private Nachricht senden

4

07.06.2004, 19:51

Na, die lokale Matrix eines Objekts ist in diesem Fall die "normale" Transformationsmatrix (ohne Beeinflussung von parents), die absolute Matrix ist dann die Matrix, die (eben absolut) die entgültige Transformationsmatrix für das Objekt darstellt (und die ist eben das Produkt aus abs. Matrix des parents und eigener rel. Matrix)
DOMINVS ILLVMINATIO MEA
---
Es lebe unmanaged Code!
---
>> Meine Uni <<

Anonymous

unregistriert

5

07.06.2004, 20:29

Ok, also wenn ich alles richtig verstanden habe, dann müsste das ganze so aussehen:

Quellcode

1
2
3
4
5
6
7
mMatrix =   qCMatrix::scale(vScale) *
        qCMatrix::axis(vXAxis, vYAxis, vZAxis) *
        qCMatrix::translation(vPos) *

        qCMatrix::scale(pBoundObj->vScale) *
        qCMatrix::axis(pBoundObj->vXAxis, pBoundObj->vYAxis, pBoundObj->vZAxis) *
        qCMatrix::translation(pBoundObj->vPos);


Wobei pBoundObj ein Zeiger auf das Objekt, an welches dieses gebunden ist, darstellt. Dort sieht mal also, dass die ersten 3 Zeilen die "lokale" TRansformation ist und die letzten 3 Zeilen die Transformation des Parent-Objektes.

Falls ihr das genau so meint, dann ist da irgendwo ein Fehler, denn so funktioniert es nicht. Es ist zwar so, dass sich das Child Objekt nun abhängig vom Parent Objekt bewegt und rotiert, aber nehmen wir mal folgende Positionen für die Objekte an:

pObjectChild->vPosition = CVector(0.0f, 50.0f, 0.0f);
pObjectParent->vPosition = CVector(50.0f, 0.0f, 0.0f);

Das Child Objekt sitzt also etwas höher (y = 50) und das Parent weiter rechts (x = 50). Starte ich nun die Animation, und lasse das Parentobjekt mal ein wenig drehen oder sonstwas, so positioniert sich das Child Objekt -über- dem Parent Objekt. Eigentlich sollte es doch "links oben" von ihm sein (wenn man sich die Sicht einmal von vorne vorstellt).

Das Child Objekt ist ja 50 Einheiten nach oben gesetzt - es sieht so aus, als würde es durch die obige Matrix dann genau 50 Einheiten über dem Parent Objekt sitzen, und nicht über dem Nullpunkt. Es sitzt ausserdem dann an Position x = 50, also genauso weit rechts wie das Parent Objekt. Im ganzen sieht es so aus, als ob das Childobjekt das Parentobjekt als neuen Weltmittelpunkt ansieht - und das ist ja nicht richtig.

An dem Zeitpunkt, wo ich quasi die "bind" Methode aufrufe, muss man sich vorstellen, dass ein Brett zwischen den beiden Objekten genagelt wird, sodass sich das Parent Objekt nicht unabhängig vom Child Objekt bewegen kann (aber umgekehrt schon).

Ich hoffe Ihr versteht nun, was ich meine - vielleicht mache ich da auch irgendwo nen groben Fehler und hab Euch gar nicht verstanden :)


Über weitere Idee würde ich mich sehr freuen!

6

07.06.2004, 21:19

Was du machen möchtest fällt unter den Begriff "Kinematik". Such einmal danach. Dann wirst du auch eine Lösung für dein Problem finden und du kannst vieleicht auch gleich die "Inverse Kinematik" Implementieren :)
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Anonymous

unregistriert

7

07.06.2004, 22:12

Ohne jetzt komisch zu klingen, aber ich hab ganz ehrlich wirklich länger gesucht, und leider keine guten Informationen darüber gefunden, die mir halt auch programmiertechnisch was bringen.

Das mit dem Code da oben... es ist ja schon fast perfekt. Nur das Objekt wird merkwürdigerweise so komisch verschoben, sodass es an der falschen Position ist, was ich leider nicht verstehe.

Kennt vielleicht jemand noch ne Lösung oder hat eine Idee, wie dies funktionieren könnte? Oder hat jemand nen Link parat, auf dem man etwas darüber (eben für 3D Programmierer) lernen kann?

Irgendwie glaube ich langsam daran, dass es nie klappen wird :crying:

Vielen Dank

8

07.06.2004, 22:35

Doch doch das wird schon. Ich hab hier in einem Buch alles drin stehen.

Werd dir später etwas dazu schreiben. Kannst aber auch selber nachschauen wenn du es hast.

Spieleprogrammierung Gems 1
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

07.06.2004, 22:35

Also dein Beispiel: der torso ist bei CVector(50.0f, 0.0f, 0.0f); und das Armchen(zum torso) CVector(0.0f, 50.0f, 0.0f); , aber relavtiv da es sich auf den NULLPunkt des Torsos bezieht.
Also ist der Pos-vektor des Armes (absolut) CVector(50.0f, 50.0f, 0.0f); und das hat seine Richtigkeit, denn wenn sich der Torso um 11 einheiten nach oben verschiebt sähe es so aus:

Torso: CVector(50.0f, 11.0f, 0.0f); , Arm(rel): CVector(0.0f, 50.0f, 0.0f); , Arm (abs) CVector(50.0f, 66.0f, 0.0f); .

Anonymous

unregistriert

10

07.06.2004, 23:17

Hm, ich glaube ich habe es gelöst, hier ist meine aktuelle Berechnung der entgültigen Matrix des Child - Objektes:

Quellcode

1
2
3
4
5
6
7
8
9
mMatrix =   CMatrix::scale(vScale) *
        CMatrix::axis(vXAxis, vYAxis, vZAxis) *
        CMatrix::translation(vPos) *

        CMatrix::translation(-vBoundPos) *

        CMatrix::scale(pBoundObj->vScale) *
        CMatrix::axis(pBoundObj->vXAxis, pBoundObj->vYAxis, pBoundObj->vZAxis) *
        CMatrix::translation(pBoundObj->vPos)


Entscheident ist hier die mittlere Zeile. Der Vektor "vBoundPos" ist die Position des Parent-Objektes zum Zeitpunkt des Bindens, welche ich beim Binden speichere.

Ich habe einige Fälle durchgespielt, und die Animation sieht bisher immer gut aus. Ich hoffe auch dass es für Objekte stimmt, deren Mittelpunkt nicht genau in der Mitte des Objektes liegen, mal sehen...

@DragonMaster: Bin gespannt was in dem Buch steht, oder ob ich tatsächlich ins Schwarze getroffen habe mit meiner Berechnung :)

Werbeanzeige