Sollen sich Objekte selber zeichnen oder nicht?
-
@Marc++us
Damit wird zwar IMHO die Trennun gzwischen Grafik und Logik erreicht, jedoch wären wir doch wieder bei dem "selber rendern" Prinzip?Ich kann mir einfach nicht so genau vorstellen, wie das mit dem "globalen Renderer" hinsichtlich der Architektur funktionieren soll...
-
Ich hab zwar keine Erfahrung, aber was ich machen würde ist:
-mehrere Klassen schreiben die die jeweiligen "Rendertypen" abdecken.
-jedes Objekt weiß, wieviele passes es hat und welche Rendertypen mit welcher Konfiguration dabei verwendet werden.
-Der SceneGraph sortiert dann alle passes von allen Objekten so, dass gleiche Rendertypen hintereinander durchgerendert werden können und ruft sie dann auch in dieser Reihenfolge auf.Das ist also eine Kombination von beiden Möglichkeiten. Jedes Objekt weiß wie es gerendert werden will und bringt direkt das Kochrezept mit, der SceneGraph als Koch sortiert dann aber die Rezepte so, dass er möglichst wenig Arbeit bei der Zubereitung hat. Gleichzeitig hast du den Vorteil, dass deine Objekte selbst mit den Direct3D/OpenGL calls gar nichts mehr am Hut haben, denn die werden extern geregelt. Auch der Scenegraph der eigentlich ein ziemliches high-level Konzept ist, wird so von den Feinheiten des Renderns verschont.
-
wie das mit dem "globalen Renderer" hinsichtlich der Architektur funktionieren soll...
Loesungen gibt es immer viele...
Bei mir ist das einfach nur eine Liste unterschiedlicher Materialien.
Jedes Mesh wird anhand einer ID einem Material zugewiesen.
Das Material erzeugt dann aus den "Mesh-Roh-Daten" Vertex- & Index-Buffer mit sinnvollem Aufbau fuer die benoetigten Render-Passes.
Da zum Rendern einfach die Material-Liste abgearbeitet wird, sind fast keine Sortierungen nach Render-State notwendig.
Fuer einen Depth-First-Pass steckt beispielsweise einfach ein zusaetzliches Material am Anfang der Liste in das alle Meshes mit reinkommen.
-
Ich bin strikt dagegen, dass die Objekte selbst auch nur irgend etwas selbst machen dürfen, wenn es ums rendern geht. Mein SceneGraph und die enthaltenen Elemente sind darstellungsunabhängig designt (sprich die Objekte wissen nicht, ob sie per Software Rasterizer, Raytracer oder OpenGL dargestellt oder im Extremfall sogar als Text auf Papier gedruckt werden
). Wenn man das durchzieht, erreicht man einen viel höheren Grad an Flexibilität (ob das gewünscht ist, ist natürlich wieder eine ganz andere Frage), was allerdings auch etwas an Performance kostet. Ich bin mir aber auch noch nicht ganz sicher, inwiefern ich mich mit meinem System wirklich tief in den Bereich Echtzeitgrafik bewegen soll
Btw, wie nennt ihr die Kombination aus Vertex- und Indexbuffer? Irgendwie muss man dafür doch einen originellen Namen haben, und bisher habe ich es
vib_entity_test
(ich habe bisher meine Geometry komplett mathematisch definiert, also mit Formeln; Vertexbuffer usw. gibt es erst provisorisch ;)) genannt und will es nun umbenennenMfG
-
Wenn man konsequent sein möchte, müsste man dann aber auch sagen, ein solches Objekt darf auch keine Sounds auslösen und auch keine Benutzereingaben verarbeiten... (Wenn es nur ums Prinzip geht)
-
Ishildur schrieb:
Wenn man konsequent sein möchte, müsste man dann aber auch sagen, ein solches Objekt darf auch keine Sounds auslösen und auch keine Benutzereingaben verarbeiten... (Wenn es nur ums Prinzip geht)
Sehr richtig. Diese Dinge müssen komplett entkoppelt sein bei meinem Designansatz. Ich versuche natürlich auch ein wenig auszuloten, wie weit man damit gehen kann. Die Einschränkungen im Systems sind derzeit milde ausgedrückt massiv.
Ein Material ist z.B. weitegehend darstellungsunabhängig gehalten, enthält allgemeine Angaben wie Dichte und andere physikalische Eigenschaften, sowie eine Schnittstelle, über welche prozedurale Texturen ermöglicht werden (jedoch geht es hierbei nicht um Farben, sondern um diverse Werte) - diese wiederum werden so bereitgestellt, dass sie an eine allfällige Engine ausgelagert werden können (sprich via Shader/GPU oder mittels CPU berechnet werden können). In Sachen Eye Candy ist dieses System recht gut, wenn man die Inhalte maschinell generieren lässt
Dinge wie Sound hingegen bekommt man mit diesem Ansatz nicht mehr so toll hin. Wie man im übrigen Benutzereingaben über die Objekte regeln sollte, verstehe ich überhaupt nicht
-
/rant/ schrieb:
Ishildur schrieb:
Wenn man konsequent sein möchte, müsste man dann aber auch sagen, ein solches Objekt darf auch keine Sounds auslösen und auch keine Benutzereingaben verarbeiten... (Wenn es nur ums Prinzip geht)
Sehr richtig. Diese Dinge müssen komplett entkoppelt sein bei meinem Designansatz. Ich versuche natürlich auch ein wenig auszuloten, wie weit man damit gehen kann. Die Einschränkungen im Systems sind derzeit milde ausgedrückt massiv.
Ein Material ist z.B. weitegehend darstellungsunabhängig gehalten, enthält allgemeine Angaben wie Dichte und andere physikalische Eigenschaften, sowie eine Schnittstelle, über welche prozedurale Texturen ermöglicht werden (jedoch geht es hierbei nicht um Farben, sondern um diverse Werte) - diese wiederum werden so bereitgestellt, dass sie an eine allfällige Engine ausgelagert werden können (sprich via Shader/GPU oder mittels CPU berechnet werden können). In Sachen Eye Candy ist dieses System recht gut, wenn man die Inhalte maschinell generieren lässt
Dinge wie Sound hingegen bekommt man mit diesem Ansatz nicht mehr so toll hin. Wie man im übrigen Benutzereingaben über die Objekte regeln sollte, verstehe ich überhaupt nicht
-
@volkard: Danke, habe ich schon mal gelesen. Trifft sehr gut auf mein Projekt zu; es ist der Versuch, wirklich alles mit einem grossen einheitlichen System zu lösen, indem man alles auf möglichst wenige, portierbare Einzelteile zerlegt, welche ebenso flexibel wie unverständlich sind (der Aufwand um eine simple Textur auf ein Dreieck zu mappen steigt beinahe ins unermessliche
). Vorher hatte ich mit einem viel einfacheren System, welches die jetzige Quellcodebasis bildet, recht viel Erfolg. Aber schlussendlich will ich sowieso nur sehen, wie weit ich damit gehen kann. Dass der Weg für ein Ein-Mann-Projekt nicht geeignet ist, ist mir schon sehr lange bewusst
MfG & gute nacht
-
Ishildur schrieb:
@Marc++us
Damit wird zwar IMHO die Trennun gzwischen Grafik und Logik erreicht, jedoch wären wir doch wieder bei dem "selber rendern" Prinzip?Ja, und?
Es geht doch nicht um's Prinzip, sondern um die Vermeidung von irgendwo gesehenen Nachteilen... was sind die Nachteile des Selbsrenderns, was die Vorteile? Welche Nachteile kann ich durch die Auftrennung in Objekt und ObjektView vermeiden unter Beibehaltung von Vorteilen?
-
@Marc++us
Völlig deiner Meinung! In 2 Monaten ist Abgabetermin und wenn das Ding bis dahin nicht steht kann ich meinen Abschluss vergessen und mein Partner ebenfalls! Nein ich suche nach pragmatischen Lösungen und nicht nach irgendwelchen theoretisch perfekt anmutenden Konzepte, die jedoch in der Praxis kaum umsetzbar sind.Ich bin absolut offen für die Ideen des "globalen Renderes", denn bezüglich der "lokalen Renderer" innerhalb der Objekte sehe ich grosse Probleme in Bezug mit Shadowmapping sowie einigen anderen Dingen.
Auf der anderen Seite kann ich mir einfach nicht so recht vorstellen, wie der globale Renderer genau funktionieren soll
Ich meine eine Liste von Meshes auf das Viewing Frustum hin zu überprüfen und die verbleibenden Mehses nach Material zu sortieren und dann zu rendern ist ja nicht so schwierig. Was aber, wenn Teile von Meshes einen anderen Vertex- bzw. PixelShader benötigen? Bspw. eine reflektierende (Environment Mapping) Glasscheibe des Cockpits eines Raumschiffes oder ähnliches. Ich meine, dieser Shader verlangt dann andere Parameter, als solche, die kein ReflectionMapping machen.
Das würde ja dann in sowas ähnliches ausarten:
while(NextObjectInList) if(dynamic_cast<MeinObjektA*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektB*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektC*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektD*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektE*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektF*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektG*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektH*>(Object)){ // objektspeziefiesches rendern } }
Hääääsliiich......
Ein weiteres Problem sind sicher die Partikelsysteme. Ein Raumschiff zieht einen Schweif nach sich. Da dieser Schweif allerdings ein reines grafisches Feature ist, darf es nicht in der "World" gespeichert sein, sondern ist nur dem globalen Renderer bekannt. Ein Partikelemitter ist allerdings ein statefull Object, woher weis der Renderer dann, wann das Teil erlöschen muss usw... Frage über Fragen...
Mfg Samuel
-
/rant/ schrieb:
Ich bin strikt dagegen, dass die Objekte selbst auch nur irgend etwas selbst machen dürfen, wenn es ums rendern geht. Mein SceneGraph und die enthaltenen Elemente sind darstellungsunabhängig designt (sprich die Objekte wissen nicht, ob sie per Software Rasterizer, Raytracer oder OpenGL dargestellt oder im Extremfall sogar als Text auf Papier gedruckt werden
). Wenn man das durchzieht, erreicht man einen viel höheren Grad an Flexibilität (ob das gewünscht ist, ist natürlich wieder eine ganz andere Frage), was allerdings auch etwas an Performance kostet. Ich bin mir aber auch noch nicht ganz sicher, inwiefern ich mich mit meinem System wirklich tief in den Bereich Echtzeitgrafik bewegen soll
Ich habe spasseshalber auch mal soeine abstraktion erstellt, war an sich sogar performanter. Ein objekt bestand an sich nur aus einer ID (typedef size_t GID).
das system laeuft wie folgt.-beim initialisieren hat ein kleiner "mini loader" alle DLLs im plugin verzeichnis geladen (was ein wenig tricky war, da der momory manager ebenfalls nur ein plugin ist und das ganze somit ohne allokation durch den source ablaufen musste).
-danach hat der loader alle plugins entsprechend ihrer dependancies initialisiert
-jedes plugin hat dabei factories regestriert (nenne ich so, gibt vielleicht einen besseren namen, es waren auch listener fuer life-time-events von objekten usw.)-beim erstellen eines objects wird dann ein xml uebergeben (ich habe nen recht fixen parser geschrieben der ein paar hunder MB/s verarbeitet, tinyxml usw. waren leider vorher das bottleneck gewesen).
-jede factory sucht sich dann raus, ob fuer sie relevante daten enthalten sind und legt lokale strukturen fuer die ID des objects ab.so hat dann die sound engine nur soundquellen und obstacles (meist simple ebenen aus 4 vertices), diese liegen in einem vector der der laengsten achse sortiert ist (kann man ueber eigenvectors rausfinden). das culling system hat nur bounding boxen die in einem AABB oder OctTree liegen (hatte beides mit der zeit implementiert). Physic hat ein 2D sweep&prune system mit einzelnen polys, die werden entweder aus dem mittleren LOD oder einem dedizierten physic proxy mesh erstellt. usw.
Das system funktioniert erstaunlich schnell, ich denke die optimalen daten pro system sind ausschlaggebend. wenn man z.b. nur einen scenegraph hat, der culling, physics, rendering verwalten soll, blaeht das sehr auf und mit jedem system das man einbaut wird es schwerer den baum so zu verbiegen, dass er noch representiert was man braucht. Dazu kommen viele viele verschwenderische dinge.
Wie z.B. bringt man die 20 lichtquellen oder 20 soundquellen die gerade aktiv sind, dass sie ihr werk tun wenn man mehrere tausend nodes hat die man dafuer traversieren muss? in den systemen die ich sah fingen die leute an
- nodes zu taggen mit flags z.b. dass alles drunter staisch ist und nicht durchtransformiert werden muss, oder dass keine sound, lichtquellen oder actoren drunter sind
- caching einzubauen, pro frame wurde nur eines oder nur ein teil vom cache geupdated, (z.b. die aktuell zu verwendeten lichtquellen).
- "manager" wurden geschrieben, an sich quasi die verewaltungsstruktur die man mit einem abstrakten system eh macht, nur das es im nachinein sehr aufwendig war.
- nodes wurden von ueberliegenden systemen sammt aller childs abgeschaltet um cpu zeit und speicher zu sparen, was sehr error prone war.Zum aufbauen und fehlerfreien lauf brauchte mein system ca 3 monate, es ist sicherlich viel aufwand, aber es hat im nachinein sehr sehr nette eigenschaften.
1. da alles sehr entkoppelt ist, kann man nicht nur schnell systeme austauschen, man kann sie auch sehr sehr leicht komplett weglassen.
was z.b. wenn man von seinem spiel nur eine server-stand-alone version haben will? einfach die plugins fuer sound, rendering, culling weglassen.
2. das debuging geht sehr gut, zwar hat man durch die abstraktion ein wenig den verlust direkt irgendwas ablesen zu koennen, aber auf der anderen seite kann man z.b. dadurch dass man fast jedes modul weglassen kann schnell evaluieren wo das problem liegen koennte und da es nur wenige kernstellen gibt, kann man an denen sehr einfach ein logging einbauen und dann nochmal abspielen. So hab ich 2 input manager, der eine gibt daten wieder (z.b. maus position), der zweite loggt diese wenn der erste existiert, startet man aber ohne diesen, wird das log wiedergegeben und man kann quasi zusehen wie alles reproduziert wird und das ist bei vielen bugs gold wert.
3. nicht nur das ersetzen, sondern auch das erweitern ist sehr sehr simple. z.B. einbauen von streaming:
das streaming plugin regestriert sich als resource manager mit groesseren prioritaet als der normale (die regel ist, dass es quasi ne linked list ist und wie ein filter stack die nicht verarbeiteten requests weitergeleitet werden).
Leitet aber erstmal alle requests an den normalen weiter, kann der ein objekt anhand der GID nicht resolven, kommt der streaming manager dran, der gibt entweder das default objekt zurueck oder ein kleineres lod von der geforderten resource wieder, streamt im hintergrund weiter und regestriert das objekt beim normalen.
es ist quasi wie eine riesige composing machine mit vererbungs support.aber das ist nur mein home research und man muss es nicht so machen
mein momentaner reserach geht noch ein wenig weiter und abstrachiert zwischen daten und code, es gibt also nicht die ID die daten in einem plugin representieren die (zumeist) nur das plugin verarbeitet. Daten liegen nur noch als resourcen rum (binary blobs), wie bei opencl, d3d, ogl, kann eine resource nur als quelle oder ziel dienen (jedenfalls meistens), intern werden dabei die resourcen transparent fuer den user, vom backend verwaltet, dabei kann eine resource geclont werden (z.b. wenn ein task sie noch als source nutzt, ein zweiter diese schon als quelle haben will, oder wenn diese auf mehreren rechnern oder speicherbereichen z.b. systemmemory und opencl verarbeitet wird).
Daneben gibt es tasks, die werden in temporaer erstellte resource-blobs gesteckt. Damit die mit dem gleichen system verarbeitet werden koennen. usw. usw. (will hier niemanden zutode langweile).das system ist krank, wie kann man sich sowas ausdenken, niemand wuerde/wird sowas verwenden?
nah, nicht ganz, eine kleine version davon ist wie windows ab vista sein driver model aufgebaut hat. Alle komponenten sind "worker" z.b. netzwerkkarte, video karte, HDD etc. und alle daten die zu verarbeiten sind werden ueber resourcen verschoben (keine direkten software->driver->hardware aufrufe moeglich).Btw, wie nennt ihr die Kombination aus Vertex- und Indexbuffer? Irgendwie muss man dafür doch einen originellen Namen haben, und bisher habe ich es
vib_entity_test
(ich habe bisher meine Geometry komplett mathematisch definiert, also mit Formeln; Vertexbuffer usw. gibt es erst provisorisch ;)) genannt und will es nun umbenennen
MfGein verbund aus vertex und indexdaten nennt man normalerweise "Mesh".
-
Ishildur schrieb:
@Marc++us
Völlig deiner Meinung! In 2 Monaten ist Abgabetermin und wenn das Ding bis dahin nicht steht kann ich meinen Abschluss vergessen und mein Partner ebenfalls! Nein ich suche nach pragmatischen Lösungen und nicht nach irgendwelchen theoretisch perfekt anmutenden Konzepte, die jedoch in der Praxis kaum umsetzbar sind.wenn du sowenig zeit hast, wundert mich dass du so knapp davor mit diskusionen ueber grundlagen deiner software anfaengst.
Was aber, wenn Teile von Meshes einen anderen Vertex- bzw. PixelShader benötigen? Bspw. eine reflektierende (Environment Mapping) Glasscheibe des Cockpits eines Raumschiffes oder ähnliches. Ich meine, dieser Shader verlangt dann andere Parameter, als solche, die kein ReflectionMapping machen.
Du kannst z.B. ueber die reflection vom shader sehr einfach rausfinden was der braucht.
quasifor_each(parameterliste)
device->SetParam(param->index,constantlist[param->constindex]);die die constants setzen, analog dazu texturen, buffer etc.
Das würde ja dann in sowas ähnliches ausarten:
while(NextObjectInList) if(dynamic_cast<MeinObjektA*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektB*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektC*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektD*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektE*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektF*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektG*>(Object)){ // objektspeziefiesches rendern } else if(dynamic_cast<MeinObjektH*>(Object)){ // objektspeziefiesches rendern } }
Hääääsliiich......
ja, das tut schon weh das zu sehen, c design mit c++ maechtigkeit. sowas hab ich mal mit try-catch und dynamic cast gesehen, als ich das umgebaut hatte lief das ganze spiel 49mal schneller. dagegen ist deine version noch "nur" haesslich
Ein weiteres Problem sind sicher die Partikelsysteme. Ein Raumschiff zieht einen Schweif nach sich. Da dieser Schweif allerdings ein reines grafisches Feature ist, darf es nicht in der "World" gespeichert sein, sondern ist nur dem globalen Renderer bekannt. Ein Partikelemitter ist allerdings ein statefull Object, woher weis der Renderer dann, wann das Teil erlöschen muss usw... Frage über Fragen...
"World" "scenegraph" deine eierlegenden wollmilchsaeue werden dir mehr kopfschmerzen bereiten als nutzen bringen ;).
natuerlich kannst du einen emiter bzw spawner vom particlesystem in den scenegraph stecken der diese dann in einen particle pool wirft. problem geloest, naechstes bitte.Der trick ist wohl viele individuelle systeme zu haben, deren design aber so gut zu machen, dass sie dir keine kopfschmerzen bereiten und diese dann auch moeglichst minimal zu halten.
Z.B. dein scenegraph, den brauchst du eigentlich nur dafuer um verbundene dinge zu transformieren, brauchst du eine root? brachen alle objekte einen parent? nein? dann mach einen simplen container mit deinen entities
std::...<entity*> Transforms.
und neben dem globalen container, steck auch in jedes entity einen. so kannst du deine hierarchy haben, obwohl alle objekte noch als einzeleintrag im globalen container sind.
Du willst culling betreiben? regestriere einfach jedes der sichtbaren bei
std::...<entity*> renderable.
Das culling laeuft langsam weil du schon 10k objekte hast? dann schreib die regestrierung um und nutze z.b. einen octree.
Objekte koennen mehrfach gezeichnet werden (z.b. schatten und normal?) dazu kann ein objekt mehrrere abschnitte haben?
dann regestriert der culler jeden dieser abschnitte beim renderer
std::...<draw_job> renderertodoliste. und jeder drawjob enthaelt die individuellen resourcen, position, shader, textur (natuerlch nur als ptr).wozu brauchte man nochmal den scenegraph so dringend?
-
@rapso
Ich bin über deinen Eintrag ein wenig verwirrt...
Wenn es nur ums Rendern geht OK, dann pflichte ich deinem Eintrag bei, aber wir haben ja auch noch ein KI System, ein Collision Detection System, ein Missions System sowie ein Scripting System, welche allesamt auf den Scenegraphen zugreifen müssen. Wir hatten uns das so gedacht, dass die "logische Welt" in einem SceneGraphen abgebildet wird.Würdest du denn vorschlagen, dass all diese Systeme einen eigenen Scenegraphen oder was auch immer benutzen sollten?
std::...<entity*> renderable.
Ich finde ja auch, dass mit einer solchen Liste Spiellogik und Rendering auch nicht mehr getrennt ist...
P.S.
wenn du sowenig zeit hast, wundert mich dass du so knapp davor mit diskusionen ueber grundlagen deiner software anfaengst.
Ja dumm ich weiss...
-
Ishildur schrieb:
@rapso
Ich bin über deinen Eintrag ein wenig verwirrt...
Wenn es nur ums Rendern geht OK, dann pflichte ich deinem Eintrag bei, aber wir haben ja auch noch ein KI System, ein Collision Detection System, ein Missions System sowie ein Scripting System, welche allesamt auf den Scenegraphen zugreifen müssen. Wir hatten uns das so gedacht, dass die "logische Welt" in einem SceneGraphen abgebildet wird.ich hatte dir das fuer transforms, culling, rendering geschildern, ich kann es weitertreiben fuer sound, collision, scripting etc.
alles was scriptable ist, wird beim scriptingsystem regestriert. natuerlich nicht jeder stein und jede wand, wieso auch? trigger boxen, ai-areas usw. schon, die braucht auch nur das scripting system. natuerlich darf das scriptingsystem auch mal selbst in dem container der entities nach "goldschatz" suchen duerfen um den dann bei sich zu regestrieren. aber wozu sollte das scriptingsystem jeden einzelnes objekt in der welt, nur weil du einen einzigen scenegraph hast, durchtraversieren? oder sollten die objekte selbst sogar scripte haben? was wenn es mehrere gibt, fuer sound, on-click etc. scripte? jedes objekt mit eigener scripting logik?
Collision detection? da regestrierst du am besten nur die meshes+transformation. also auch die die nicht geraendert werden (invisible walls anyone?), dabei kannst du statische objekte sehr optimiert orginisieren und die dynamischen darin testen.
Mission system? dem kann 99.9% von dem im transformation graph egal sein.Würdest du denn vorschlagen, dass all diese Systeme einen eigenen Scenegraphen oder was auch immer benutzen sollten?
ich schlug vor einen simplen container zu nutzen falls es fuer das system ausreicht. und falls nicht, etwas optimales fuer das system.
std::...<entity*> renderable.
Ich finde ja auch, dass mit einer solchen Liste Spiellogik und Rendering auch nicht mehr getrennt ist...
das entity als datencontainer ist natuerlich shared.
beim trennen spricht man allgemein vom programcode, nicht so strikt von den daten, denn die daten kann man abstrakt halten sofern es nicht spezialisierten code gibt.
als beispiel kann dein entity ein material haben das "dachpappe" heisst. was bedeutet dachpappe? Fuers soundsystem ist es vielleicht dachpappe.wav, fuer physics bedeutet es dass soein objekt zerbrechen kann. fuers rendering dass es den dachpappe.pixelshader und dachpappe.bmp nutzt. was bedeutet es fuer das entity? garnichts, des es gibt keinen spezialisierten dachpappe code im entity.das ist _meine_ sicht was trennung bedeutet.
wenn du sowenig zeit hast, wundert mich dass du so knapp davor mit diskusionen ueber grundlagen deiner software anfaengst.
Ja dumm ich weiss...
das sollte eher ein arschtritt sein dass du jetzt wie ein wilder fleissig loscodest
Am ende wirst du eh unzufrieden sein und "beim naechsten mal mach ich alles besser" sagen. programmierer krankheit.
-
OK, ich sehe, dass ist ein ganz anderer sehr interessanter Ansatz. Ich hatte mehr eine Art MVC Pattern im Auge, sprich der SceneGraph sollte das Model sein, die verschiedenen System (Collision, Mission, Scripts) die Controls und der Renderer das View.
Sehe ich dass aber dann richtig, dass sich bspw. jedes abgefeuerte Projektil (100erte) sich dann beim Rendergraphen, sowie beim AudioGraphen und dem Physikgraphen registrieren müssen?
Ich hatte eben mehr so eine Art Layersytem im Kopf. Bei deiner Architektur erscheint mir das mehr so wie eine Art Client-/Server System, (Projektil ist ein Client, der sich bei mehreren Servern registriert, die dann die Daten verarbeiten). Oder habe ich das komplett falsch verstanden?
wenn du sowenig zeit hast, wundert mich dass du so knapp davor mit diskusionen ueber grundlagen deiner software anfaengst.
Hehe, nein die Frage ist natürlich schon berechtig. Ja wir hatten einfach mal angefangen mit sehr allgemeinen Dingen wie Errorhandling, Logging, Datenstrukturen, Mathlibrary und dem Resourcenmanagement (Laden von Texturen, Meshes, Fonts usw). Natürlich hatten wir uns bereits ganz am Anfang wochenlang den Kopf darüber zerbrochen, wie wir alles machen wollen, aber irgendwann hatten wir gesagt, "Wir müssen jtzt einfach mal anfangen, sonst sind wir in 4 Monaten immer noch am überlegen, wie wirs genau machen wollen und haben einfach nichts"
-
Ishildur schrieb:
OK, ich sehe, dass ist ein ganz anderer sehr interessanter Ansatz. Ich hatte mehr eine Art MVC Pattern im Auge, sprich der SceneGraph sollte das Model sein, die verschiedenen System (Collision, Mission, Scripts) die Controls und der Renderer das View.
Es ist im gewissen sinne noch ein MVC (sogar staerker als wenn du das objekt sich selbst rendern, abspielen usw. lassen wuerdest).
Du hast aber dedizierte container in denen objekte organisiert sind, dadurch sparst du dir quasi beim visitor einen filter zu haben. ein visitor, z.b. "frustum" in einem "culling system container" wird vom container gegen die objekte evaluiert. das kann jedes einzelne entity sein oder die hierarchy eines octrees, das resultat von dem "visitor" (ich glaube das heisst, anders, visitor ist ein aktiver part, das einhaengsel hatte noch nen anderen namen auf den ich nicht komme) ist eine verfeinerte liste von objekten. (eventuel auch transformiert, z.b. in drawjobs).
Sehe ich dass aber dann richtig, dass sich bspw. jedes abgefeuerte Projektil (100erte) sich dann beim Rendergraphen, sowie beim AudioGraphen und dem Physikgraphen registrieren müssen?
jap, du wirst auch schnell sehen "100erte" sound kann kein system ertragen, behalte nur die 16 nahesten bzw lautesten. waehrend "100erte" particle locker gehen.
Ich hatte eben mehr so eine Art Layersytem im Kopf. Bei deiner Architektur erscheint mir das mehr so wie eine Art Client-/Server System, (Projektil ist ein Client, der sich bei mehreren Servern registriert, die dann die Daten verarbeiten). Oder habe ich das komplett falsch verstanden?
das stimmt schon, deines ist wie eine datenbank mit einer zentralen table in der alles pro entry vorhanden ist. Ich schlage quasi mehrere tables vor die auf einzelne eintraege mit spezialisierten keys indizieren. das "ubersystem" waere dann natuerlich das mit der ID und jede table hat fuer sich die daten, das waere vermutlich aus datenbanksicht eine saubere normalisierung.
leg dich nur nicht zu extrem auf ein system fest, nichts ist pefekt fuer alle bereiche ;).
-
Nun bleibt die Frage, wer registriert diese Entitäten?
Ich habe mal ein Spiel gemacht, da lief das folgendermassen. Jede Entität hatte einen Zeiger auf die Welt, in der es sich befindet. bspw...
void PlayerShip::Update(float32 Time){ if(Services::GetService<InputService>("Input")->IsKeyDown(DIK_SPACE)){ this->wpnAct->Fire(); } } void LaserWeapon::Fire(void){ if(this->heat < MAX_HEAT){ this->GetWorld()->Add(new LaserBeam()); Servies::GetService<AudioService>("Audio")->Play(this->snLaser); } }
Der Vorteil von sowas ist halt, dass ich jederzeit neue Objekttypen hinzufügen kann, ohne dass ich an der Engine was rumbasteln muss, da diese Entitäten selbständig mit den verfügbaren Services kommunizieren und die Welt manipulieren.
Wie würde sowas nun mit der von dir vorgeschlagenen Architekur aussehen? Eben bspw. ein Ship will in seiner "Update" methode einen Schuss abfeuern (Die Spielengine hat keine Ahnung, was das Teil tut, sondern ruft eifach einmal pro Frame die "Update" Methode auf) Oder ist das auch bereits der falsche Ansatz?
-
Ich verstehe von der Diskussion wenig bis gar nichts, aber ein Leerzeichen für die Einrückung von Code tut meinen Augen wehe. Aus dem Code wird nix
-
Aus dem Code wird nix
Noch so ein Ding... Augenring...