klassendesign , oder Sinn und Unsinn



  • Alles was bisher kommt basiert auf jetzigen Überlegungen und es kann sein dass sich vieles noch ändern wird, aber:
    Ich möchte folgendes erreichen

    Es solle verschiedene Transformationen geben, für eine Trransformation ist eine 4*4 Matrix zuständig, repräsentiert durch ein float-array.

    Ich brauche später auch die Inverse einer Transformation.

    Abgesehen davon gibt es verschiedene Spezialfälle von Transformationen
    Translation, Skalierung und Rotation, für welche ich recht einfach eine Inverse herstellen kann.
    Es ist fraglich ob eine Transformation jemals so eingesetzt werden kann oder ob nur die Speizialfälle zulässig sind.

    Eine Translation soll einfach nur verschieben, eine Rotation soll um einen bestimmten Punkt rotieren können (an dieser Stelle glaube ich dass da einige Translationen neben einer Rotation nötig sind)

    Meine bisherigen Überlegungen:

    class XForm
    {
    protected:
        float array[16];
    public:
        XForm();
        virtual ~XForm(){};
    
        float* getArray();
        virtual XForm*  getInverse();
    };
    
    // cpp
    
    sg::XForm::XForm()
    {
        for(int i=0; i< 16; i++)
        {
            array[i] = 0;
            if(i % 5 == 0)
            {
                array[i] = 1;
            }
        }
    }
    
    float* sg::XForm::getArray()
    {
        return array;
    }
    
    sg::XForm* sg::XForm::getInverse()
    {
        return this;
    }
    
    class Translation : public XForm
    {
    protected:
        float xtrans, ytrans, ztrans;
    public:
        Translation();
        Translation(float x, float y, float z);
    };
    
    // cpp
    
    sg::Translation::Translation()
    {
    }
    
    sg::Translation::Translation(float x, float y, float z)
    {
        for(int i=0; i< 16; i++)
        {
            array[i] = 0;
            if(i % 5 == 0)
            {
                array[i] = 1;
            }
        }
    
        array[12] = x;
        array[13] = y;
        array[14] = z;
    }
    
    sg::XForm* sg::Translation::getInverse()
    {
    

    wie man gut sehen kann weiß ich noch nicht wie ich das mit der inversen angehen soll, bzw was ich da zurückgeben kann.

    Prinzipiell: wie köpnnte ich das oben halbwegs beschriebene aufbauen, oder anders gefragt ist mein bisheriger Weg plausibel oder ziemlich abwegig?



  • Wenn du von zusammengesetzen Rotationen/Translationen ausgehst, brauchst du keine inversen berechnen ... einfach Wert negieren und zurückrotieren. Eventuell könntest du Quaternionen statt Matrizen nutzen.

    Eventuell hilft dir diese Seite weiter:

    http://www.euclideanspace.com/maths/geometry/rotations/index.htm

    Abgesehen davon ist es mE fraglich ob in einem solchen Bereich jeder das Rad neu erfinden "muss", vielleicht schau dich nach einer guten 3D bib um?



  • shisha schrieb:

    Prinzipiell: wie köpnnte ich das oben halbwegs beschriebene aufbauen, oder anders gefragt ist mein bisheriger Weg plausibel oder ziemlich abwegig?

    Um zu beurteilen, ob ein Design taugt oder nicht, müßte man es gegen die Anforderungen prüfen, die an das System gestellt werden. Du sagst, dass Transformationen modelliert werden sollen. Du beschreibst aber nicht, wie Du diese Transformationen anwenden willst. Sollen diese z.B. miteinander verkbüpft werden? Wenn ja - wie sähe dann die gewünschte Operation aus?

    Was soll weiter mit den Transformationen geschehen? Wie sieht deren 'endgültiger' Output aus (OpenGL?)?

    Zu der Vererbung kann man zunächst sagen, dass eine Klasse von der alle anderen ableiten (hier XForm) selbst nicht instanziierbar sein sollte. Einer der Gründe liegt darin, dass so etwas

    Translation trafo1; 
        Xform trafo2 = trafo1; // ggf. unvollständige Kopie
    

    nicht möglich sein sollte. Das verhindert man, indem man die Basisklasse XForm abstrakt macht.

    class XForm
    {
    protected:
        float array[16];
    public:
        XForm();
        virtual ~XForm() =0{}; // pure abstract
        // usw....
    

    weiterhin stellt sich die Frage wozu XForm überhaupt gut ist? Wer ist der 'Kunde' von XForm - also wer benötigt sie im Gegensatz zu den abgeleiteten Klassen?

    Nächster Punkt ist die virtuelle Methode getArray(). Mit ihr werden die internen Daten der Klasse preisgegeben. Dies ohne Not zu tun, ist i.A. schlechtes Design. Eine Klasse dient ja gerade dazu derartige Internas zu kapseln. Was bringt diese Methode?

    Du beschreibst die Transformation Translation, Rotation und Skalierung, aber es sind 16 Parameter zur Beschreibung vorgesehen. I.A. benötigt man dazu aber nur 12. Sind 4 Parameter immer gleich?

    ( a[0] a[4] a[ 8] a[12] )
    ( a[1] a[5] a[ 9] a[13] )
    ( a[2] a[6] a[10] a[14] )
    (  0    0    0      1   )  // letzte Zeile ist konstant?
    

    Falls ja - könnte man sie einfach weglassen.

    Gruß
    Werner



  • Also zum Rad neu erfinden: Es ist meine Aufgabe genau das zu tun, die endgültige Ausgabe soll dann OpenGL sein.

    Ich denke auch daran XForm rein virtuell machen und dafür eine weitere Klasse
    IndividualTransformation oder was kürzeres ^^ einzuführen,
    ein besonderes Extra wäre meiner Meinung nach wenn ich eine beliebige Matrix angeben könnte, also einfach 12 (oder 16) floats, dann bräuchte ich aber eine Funktion die mir die Inverse berechnen kann und da scheitere ich bisher, ich dachte schon daran Python zu integrieren um dann mit numpy die Inverse zu berechnen, aber es sieht so aus als wenn das nicht so einfach wäre wie ichs mir vorstelle.

    Dass mir getArray eigentlich nichts kapselt stört mich im Moment am wenigsten, ich würde lieber das Teil mal im Kopf haben können, also es soll funktionieren.

    Zu den Quaternionen: ich habe bereits davon gelesen und die Teile sind wahrscheinlich echt gut, aber ich bezweifle dass ich mich da noch reinarbeiten kann.

    Die Anforderungen:

    Es soll ein Szenengraph entstehen, wobei jeder Knoten EINE Transformation (nicht unbedingt Transformationsmatrix) haben sollte.
    Es steht mir eigentlich alles frei, zB auch mehrere Matrizen die hintereinanderausgeführt werden sollen als XForm abzuspeichern, bisher habe ich das aber nicht im Sinn.

    Im Moment denke ich mir so etwas als Aufbau:

    Knoten hat XForm
    Traverser besucht Knoten und interpretiert Matrix und setzt das ganze in OpenGL um.

    Falls ihr ein par Vorschläge habt: immer her damit ^^



  • shisha schrieb:

    ein besonderes Extra wäre meiner Meinung nach wenn ich eine beliebige Matrix angeben könnte, also einfach 12 (oder 16) floats, dann bräuchte ich aber eine Funktion die mir die Inverse berechnen kann und da scheitere ich bisher, ich dachte schon daran Python zu integrieren um dann mit numpy die Inverse zu berechnen, aber es sieht so aus als wenn das nicht so einfach wäre wie ichs mir vorstelle.

    Bei dieser noch relativ kleinen matrix sollte es kein großes Problem sein das Gaußsche Eliminationsverfahren zu implementieren.

    shisha schrieb:

    Dass mir getArray eigentlich nichts kapselt stört mich im Moment am wenigsten, ich würde lieber das Teil mal im Kopf haben können, also es soll funktionieren.

    Ich verstehe den Sinn dieser Aussage nicht 😕

    shisha schrieb:

    Die Anforderungen:

    Es soll ein Szenengraph entstehen, wobei jeder Knoten EINE Transformation (nicht unbedingt Transformationsmatrix) haben sollte.
    Es steht mir eigentlich alles frei, zB auch mehrere Matrizen die hintereinanderausgeführt werden sollen als XForm abzuspeichern, bisher habe ich das aber nicht im Sinn.

    Im Moment denke ich mir so etwas als Aufbau:

    Knoten hat XForm
    Traverser besucht Knoten und interpretiert Matrix und setzt das ganze in OpenGL um.

    Falls ihr ein par Vorschläge habt: immer her damit ^^

    Wenn jeder Knoten nur eine Transformation hat, Du nicht im Sinn hast, diese zu verknüpfen und die Daten als getArray wieder ausgeliefert werden ... Dann könnte man fragen: wozu überhaupt eine Klasse - was ist der Zweck der Transformationsklassen? Du bräuchtest vielleicht nur einen Sack von Funktionen die aus einer Translation, Rotation bzw. Skalierung das 16-float-Array füllen - oder?
    Wie und in welcher Form kommt denn der Input in Dein System?

    Gruß
    Werner


Anmelden zum Antworten