Modulare 3D-Engines
-
Du hast recht, die If..-Lösung wäre tausendmal aufwändiger, um trotzdem nur zum selben Ziel zu kommen. Die Wrapper-Lösung scheint die Ideallösung zu sein. Ich werde mich einmal daran versuchen, wenn ich Probs habe weiss ich ja wo ich Hilfe finde.
Danke für die Entscheidungshilfe.
-
wir helfen gerne. meißten erkennt man die beste lösung daran, was sich im Darwin'schen system durchgesetzt hat
... und die allermeißten machen das so.
<tip>
ich würde dir trotzdem vorschlagen, dass du dir anregungen für die art und weise wie man es realisieren kann, in ein paar engines anzuschaust, denn es gibt viele kleine stolpersteine, die man vielleicht in den wrappern anderer engines findet, von denen man noch nicht wuste, dass es sie überhaupt gibt
</tip>rapso->greets();
-
vampalive schrieb:
Eigentlich müsste ja nur die zu ladende DLL verändert werden, die Funktionen heissen ja eh alle gleich.
Eine Funktion reicht: die nämlich, welche den Zeiger auf die Klasse liefert, die von der DLL bereitgestellt wird. Siehe mein Beispiel.
-
@raspo
Verstehst du unter Wrapper eine Schnittstelle (interface Klasse)? Und die vererbten Klassen sind dann in den DLLs gespeichert?
-
Zum Thema modulare Engine... Schau dir mal das Konzept von Half-Life an. Die benutzen zwar nur eine engine.dll und eine game.dll, verbunden mit einer hl.exe, aber das Konzept kann man trotzdem einwandfrei auch adaptieren um mehrere Module zu benutzen. Was die Problematik der richtigen DLL für die richtige Konfiguration betrifft, würde ich z.B. das liblist.gam - Konzept aus HL verwenden (oder wie das file dort heisst...) da wird einfach der Name der zu ladenden DLL für das game in das File gekritzelt und dann beim Laden ausgelesen...
-junix
-
AJ schrieb:
@raspo
Verstehst du unter Wrapper eine Schnittstelle (interface Klasse)? Und die vererbten Klassen sind dann in den DLLs gespeichert?eine interfaceklasse ist eine abstrakte klasse die also nur virtuelle funktionen deklariert ohne sie zu definieren, weil sich die definition woandes befinden und man auf sie zugreifen möchte.
die vererbten klassen können in dlls sein, wenn du eine Engine(.dll) benutzt, dann kannst du auch in deiner exe von einem interface ableiten um es der engine quasi als "user erweiterung zu geben", z.B. wenn du ein partikelsystem hast und für jeden partikel eine berechnung durchführen möchtest, wie sie die engine standardmässig nicht macht, dann kannst vom (class I)ParticleAnimator ableiten und der engine dann deine klasse als Animator für alle partikel geben. natürlich ist es nur ein beispiel
man kann auch ganz neue dinge einbauen, je nachdem wie abtract das interface ist, z.B. wenn die engine garkeine particle unterstützt, könntest du von einer objektklasse ableiten, einmal für einen particle-collector und einmal für die partikel selbst. dann würde die engine immer noch das culling und sonstiges für dich machen, aber die particle selbst würden sich nicht rendern, sondern bei Particle-collector "anmelden" und wenn der sich dann rendern soll, zeichnet er alle "angemeldeten" particle... je nachdem wie flexible eine engine ist, natürlich verliert man für die flexibilität einiges an performance.rapso->greets();
-
@raspo
Aja, danke.
Aber leider bin ich jetzt nicht schlauer als vorher. Was eine Interfaceklasse ist, wusste ich schon. Ich weiß nur nicht was du mit Wrapper meinst. Mir ist der Begriff nicht geläufig. Wie ich es aus dem ganzen Zusammenhang verstanden habe, wäre ein Wrapper genau so eine Interfaceklasse bzw. die vererbten Klassen davon, oder??
-
ganz genau gesagt ist ein wrapper nur die ummantelung einer anderen API. anstatt also direkt z.B. auf die festplatte zuzugreifen, sagst du sowas wie pWrapper->Open(...); und der wrapper macht intern dann das API bedingte zeug.
das gute an sowas ist, dass du ein fest definiertes Interface hast, mit dem du auf die daten zugreifen willst. möchtest du nun z.B. über das internet daten laden, mußt du in dein programm nichts neues implementieren, du schreibst dir einen wrapper, der die selben interfaces anbietet wie der gerade und tauscht ihn mit dem vorherigen aus. nun lädt dein programm alles aus dem netz ohne geändert worden zu sein.
der vorteil ist nicht nur dass du ohne programmeingriff neue "features" unterstützen kannst, du kannst dabei auch den selben Wrapper für viele programme nutzen, und programmierst du einmal eine neue variation davon für deinen wrapper, können alle applikationen soeinen nutzen.
ich hab z.b. schon lange einen wrapper für das öffnen von bildern, schaut in etwa so aus
class IImage { public: virtual bool Open(const char* pFileName)=NULL; virtual bool Save(const char* pFileName)=NULL; virtual bool Create(const int SizeX,const int SizeY)=NULL; virtual unsigned int Pixel(const int SizeX,const int SizeY)=NULL; virtual void Pixel(const int SizeX,const int SizeY,unsigned int Color)=NULL; virtual unsigned int Pixel(const int SizeX,const int SizeY)=NULL; virtual unsigned int SizeX()=NULL; virtual unsigned int SizeX()=NULL; }
ok, das ist nur ganz grob hier mal reingetippt, aber mit diesem interface greife ich auf eine "Image.dll", diese lädt bei initialisierung alle plugins aus dem verzeichniss "ImagePlugins/" und dort füge ich ab und zu ein neues dateiformat ein, ab da können alle meine programme damit arbeiten, sowas ist wirklich sehr nützlich, weil ich nicht jedes programm, dass ich mal wieder nutzen möchte, dann neu compilieren muss. außerdem kann ich das programm nach außen freigeben und jeder der es nutz, kann sein format einbinden, ohne dass er dafür den source vom hauptprogramm haben muss.
sowas ist wirklich angenehm.
rapso->greets();
ps. vielleicht release ich das ja mal
-
@rapso
Ok, danke. Dann ist es genau so wie ich es mir gedacht habe und wie ich es auch gemacht hätte *ggg*.Wie sieht dann das in den DLLs eigentlich aus? Hast du da drin dann nur die Klassendefinition? Wie greifst du richtig auf das Objekt zu? Du hast zwar das Interface, aber wie sagst du dem Interface, dass es sich jetzt um die Klasse für BMP handelt und nicht um die Klasse für GIF?
-
in dem konkreten fall, kann es ja sein dass es mehrere klassen für die selbe dateiendung gibt, deswegen versucht die imager.dll jedes plugin durch bis entweder eines das bild geöffnet hat oder keines mehr vorhanden ist in der list.
beim speichern gibst du ja die datei dann an blabla.bmp und dann wird auch einfach gespeichert... vielleicht müßte man da ne möglichkeit für einen setup dialog einbauen oder so, das war ja auch schon vor langem als ich das gemacht hab, deswegen weiß ich das interface auch nicht mehr 100%ig auswendig.auf das objekt greift man beispielweise folgend zu:
//irgendwo in nem header: class CImageBMP : public IImage { public: //funktionen überladen } //irgendwo in nem cpp dann die definition . . . //in der maindll.cpp #inlclude "image.hpp" CImage g_Image; IImage* ImageInterface() { return g_Image; }
dabei kann man in diesem fall CImage auch schön als singleton aufbauen.
rapso->greetS();