Ist hier dynamic_cast ok?



  • Die Erfahrung lehrt mich dass es nicht wirklich sinnvoll ist eine 3D API auf dieser Ebene zu kapseln auf der dus gerade versuchst. Bau lieber einen Renderer der ein Interface bietet für das was du eigentlich damit anstellen willst und implementier dann dieses Interface jeweils mit D3D bzw. OpenGL. Ein downcast ist ein Symptom für sehr kaputtes Design und selbst abgesehen davon willst du hier schon um der Performance willen keinen dynamic_cast. Einen OOP Wrapper für OpenGL schreiben willst du nicht, glaub mir. Mit dem komischen Objektmodell von OpenGL endet das nur in Trauer und Schmerz...



  • dot schrieb:

    Die Erfahrung lehrt mich dass es nicht wirklich sinnvoll ist eine 3D API auf dieser Ebene zu kapseln auf der dus gerade versuchst. Bau lieber einen Renderer der ein Interface bietet für das was du eigentlich damit anstellen willst und implementier dann dieses Interface jeweils mit D3D bzw. OpenGL. Einen OOP Wrapper für OpenGL schreiben willst du nicht, glaub mir. Mit dem komischen Objektmodell von OpenGL endet das nur in Trauer und Schmerz...

    RenderSystem IST mein Interface zu den Render APIs....



  • caster2 schrieb:

    RenderSystem IST mein Interface zu den Render APIs....

    Ist mir klar. Was ich damit sagen wollte ist: Dein Interface ist imo zu low-level. Du versuchst einfach nur D3D bzw. OpenGL hinter einen Layer zu stellen der exakt den gleichen Abstraktionsgrad hat wie die APIs selbst. Und genau das ist meiner Erfahrung nach absolut nicht sinnvoll. Glaub mir, ich hab schon oft genug solche Wrapper geschrieben. Vor allem OpenGL in C++ zu wrappen ist einfach nur pita 😉



  • caster2 schrieb:

    Ich verletze nirgends das LSP. Ein D3D9RenderWindow HAT alle Methoden eines RenderWindow und fuellt diese auch sinnvoll aus!

    Du verletzt das LSP z.B. an dieser Stelle:

    D3D9RenderSystem::swapBuffers(RenderWindow* win)
    

    LSP schrieb:

    Preconditions cannot be strengthened in a subtype

    RenderSystem::swapBuffers hat zur Bedingung, dass *win ein gültiger Zeiger auf irgendeine RenderWindow Instanz ist.
    D3D9RenderSystem::swapBuffers hat die Bedingung dass *win ein Zeiger auf ein D3D9RenderWindow ist. Du kannst also D3D9RenderSystem nicht durch ein andereres substituieren. Das ist nun wirklich eine eindeutige Verletzung.

    D3D9RenderSystem kann nicht jedes RenderWindow behandeln, daher ist diese Abstraktion an dieser Stelle einfach sinnlos.



  • brotbernd schrieb:

    D3D9RenderSystem kann nicht jedes RenderWindow behandeln, daher ist diese Abstraktion an dieser Stelle einfach sinnlos.

    Stimmt, aber da es nur D3D9RenderWindows kriegen kann, sehe ich damit kein Problem. Vor allem faellt mir nichts eleganteres ein.

    @Dot: Ich weiss. Das abstrahieren von Render APIs ist immer ein Schmerz im Hintern und OpenGL ganz besonders. Ich wage zu behaupten, dass ein 100% elegantes Wrappen beider APIs ohne kleinere Hacks unmoeglich ist. Dazu sind sie teilweise einfach zu unterschiedlich. Ich sag nur Contexts vs Swap Chains, Lost Devices etc.



  • caster2 schrieb:

    Stimmt, aber da es nur D3D9RenderWindows kriegen kann, sehe ich damit kein Problem. Vor allem faellt mir nichts eleganteres ein.

    Und was war mit diesem Vorschlag

    class RenderSystem
    {
    public:
        virtual void MachWas() const = 0;
    };
    
    class RenderTarget
    {
    public:
        void TuWas()
        {
            GetRenderSystem()->MachWas();
            Schwipp();
        }
    private:
        virtual void Schwipp() = 0;
        virtual const RenderSystem* GetRenderSystem() const = 0;
    };
    
    class D3RenderWindow;
    class D3RenderSystem : public RenderSystem
    {
    public:
        void MachWas() const { std::cout << "D3RenderSystem macht was\n"; }
        void Schwapp(D3RenderWindow& window){}
    
    };
    
    class D3RenderWindow : public RenderTarget
    {
    public:
        D3RenderSystem mRenderSystem;
        void Schwipp()
        {
            mRenderSystem.Schwapp(*this);
        }
        const RenderSystem* GetRenderSystem() const
        {
            return &mRenderSystem;
        }
    };
    


  • caster2 schrieb:

    Ich wage zu behaupten, dass ein 100% elegantes Wrappen beider APIs ohne kleinere Hacks unmoeglich ist.

    Ja definitiv.



  • dot schrieb:

    caster2 schrieb:

    Ich wage zu behaupten, dass ein 100% elegantes Wrappen beider APIs ohne kleinere Hacks unmoeglich ist.

    Ja definitiv.

    Im Grunde gehts mir nur darum die Anzahl Hacks zu minimieren. 😃 Ganz vermeiden ist unmoeglich.

    @brotbernd: Danke! Hab leider im Moment keinen Zugriff auf meinen echten Code und kann deshalb gerade nicht sagen, ob das an irgend einer Stelle Probleme geben koennte. Aber sieht sehr interessant aus! 🙂



  • caster2 schrieb:

    Ganz vermeiden ist unmoeglich.

    Man könnte es vermeiden sinnlose Wrapper zu schreiben, dann braucht man auch keine Hacks und spart unnötigen Overhead 😉



  • dot schrieb:

    caster2 schrieb:

    Ganz vermeiden ist unmoeglich.

    Man könnte es vermeiden sinnlose Wrapper zu schreiben, dann braucht man auch keine Hacks und spart unnötigen Overhead 😉

    Geht nicht. Die Engine soll mit beiden APIs laufen und das erfordert nun mal Abstraktion. Klappt ja bis jetzt auch. Nicht immer schoen, aber es klappt. Schonheitspreise fuer Code gibts eh nicht. Entscheidend ist nur die Qualitaet des Spiels, das man mit dem Code macht.



  • caster2 schrieb:

    Die Engine soll mit beiden APIs laufen und das erfordert nun mal Abstraktion.

    Ich seh grad nicht wo das Problem liegt, implementier den Renderer der Engine eben einmal mit D3D und einmal mit OpenGL!?



  • dot schrieb:

    caster2 schrieb:

    Die Engine soll mit beiden APIs laufen und das erfordert nun mal Abstraktion.

    Ich seh grad nicht wo das Problem liegt, implementier den Renderer der Engine eben einmal mit D3D und einmal mit OpenGL!?

    Wir drehen uns im Kreis. Lass gut sein.



  • caster2 schrieb:

    dot schrieb:

    caster2 schrieb:

    Die Engine soll mit beiden APIs laufen und das erfordert nun mal Abstraktion.

    Ich seh grad nicht wo das Problem liegt, implementier den Renderer der Engine eben einmal mit D3D und einmal mit OpenGL!?

    Wir drehen uns im Kreis. Lass gut sein.

    Er hat schon recht. Baue jeden Renderer für sich auf, und packe dann Fassaden vor jeden Rendertypen, welche das zusammenfassen, was die unterschiedlichen Renderer wirklich gemein haben.



  • Und genau diese Fassade ist RenderSystem.



  • Wie gesagt: Dann ist der Abstraktionsgrad dieser Fassade zu niedrig...



  • caster2 schrieb:

    Und genau diese Fassade ist RenderSystem.

    RenderSystem * rs = RenderSystem3d(...);
    
    //...
    
    RenderWindow rw = AnyAvailableRenderWindowCanBeHere();
    rs->method(rw); //wie wird sicher gestellt, dass es ein RenderWindow3D ist bzw. woher weißt Du, dass rs auf ein RenderSystem3d zeigt?
    


  • Tachyon schrieb:

    RenderWindow rw = AnyAvailableRenderWindowCanBeHere();
    rs->method(rw); //wie wird sicher gestellt, dass es ein RenderWindow3D ist bzw. woher weißt Du, dass rs auf ein RenderSystem3d zeigt?

    [/cpp]

    Garnicht, denn sowas wie AnyAvailableRenderWindowCanBeHere(); habe ich nicht. Wenn das RenderSystem D3D9 ist, gibt es nur D3D9 Render Windows. Ich baue mit Sicherheit nicht einen Wrapper um eine API und darueber dann nochmal einen Wrapper. Halte ich fuer unglaublich haesslich und habe ich bis jetzt auch in noch keiner einzigen Engine gesehen.



  • caster2 schrieb:

    Tachyon schrieb:

    RenderWindow rw = AnyAvailableRenderWindowCanBeHere();
    rs->method(rw); //wie wird sicher gestellt, dass es ein RenderWindow3D ist bzw. woher weißt Du, dass rs auf ein RenderSystem3d zeigt?

    [/cpp]

    Garnicht, denn sowas wie AnyAvailableRenderWindowCanBeHere(); habe ich nicht. Wenn das RenderSystem D3D9 ist, gibt es nur D3D9 Render Windows. Ich baue mit Sicherheit nicht einen Wrapper um eine API und darueber dann nochmal einen Wrapper. Halte ich fuer unglaublich haesslich und habe ich bis jetzt auch in noch keiner einzigen Engine gesehen.

    Dann leuchtet mir mal gar nicht ein, warum RenderSystem eine virtuelle Methode haben muss, welche RenderWindow -Basisklassen bekommt. RenderWindow-Basisklassenzeiger zu übergeben, wenn eigentlich konkrete RenderWindow-Instanzen erwartet werden halte ich fuer unglaublich haesslich und habe ich bis jetzt auch in noch keiner einzigen Engine gesehen. :p
    Btw. hast Du gefragt, ob dynamic_cast okay ist. So ziemlich alle meinten nein. Eine Antwort hast Du. Wenn Du es trotzdem so machst, dann war die Frage eigentlich überflüssig.

    Da die mögliche Gesamtmenge an Rendersystemen vermutlich begrenzt sein dürfte, werfe ich jetzt zur Behandlung Deiner konkreteten RenderWindows einfach mal das Visitor-Pattern in den Raum.



  • Tachyon schrieb:

    caster2 schrieb:

    Tachyon schrieb:

    RenderWindow rw = AnyAvailableRenderWindowCanBeHere();
    rs->method(rw); //wie wird sicher gestellt, dass es ein RenderWindow3D ist bzw. woher weißt Du, dass rs auf ein RenderSystem3d zeigt?

    [/cpp]

    Garnicht, denn sowas wie AnyAvailableRenderWindowCanBeHere(); habe ich nicht. Wenn das RenderSystem D3D9 ist, gibt es nur D3D9 Render Windows. Ich baue mit Sicherheit nicht einen Wrapper um eine API und darueber dann nochmal einen Wrapper. Halte ich fuer unglaublich haesslich und habe ich bis jetzt auch in noch keiner einzigen Engine gesehen.

    Dann leuchtet mir mal gar nicht ein, warum RenderSystem eine virtuelle Methode haben muss, welche RenderWindow -Basisklassen bekommt. RenderWindow-Basisklassenzeiger zu übergeben, wenn eigentlich konkrete RenderWindow-Instanzen erwartet werden halte ich fuer unglaublich haesslich und habe ich bis jetzt auch in noch keiner einzigen Engine gesehen. :p
    Btw. hast Du gefragt, ob dynamic_cast okay ist. So ziemlich alle meinten nein. Eine Antwort hast Du. Wenn Du es trotzdem so machst, dann war die Frage eigentlich überflüssig.

    Da die mögliche Gesamtmenge an Rendersystemen vermutlich begrenzt sein dürfte, werfe ich jetzt zur Behandlung Deiner konkreteten RenderWindows einfach mal das Visitor-Pattern in den Raum.

    Na 3mal darfst du raten wieso ich diesen Thread erstellt hab;)



  • caster2 schrieb:

    Na 3mal darfst du raten wieso ich diesen Thread erstellt hab;)

    Trollversuch?


Anmelden zum Antworten