Ich habe vor kurzem mal angefangen, mich etwas mit 2D-OpenGL zu beschäftigen (mit dem 2D-Tutorial aus der Wiki). Prompt sind mir dabei aber auch zwei Fragen untergekommen, die eigentlich gar nichts mit der Grafikausgabe zu tun haben :
1. Kann man feststellen, welches Objekt an einer Stelle auf der Ausgabefläche sichtbar ist? Wenn es also von transparenten Texturen überlagert wird, der Nutzer aber dennoch dieses (der Anordnung nach) hintere Objekt sieht, kann man das dann herausfinden und identifizieren? Ich denke dabei daran, Einheiten (oder irgendwas anderes) auszuwählen, die teilweise - z.B. von einem Ast - verdeckt werden.
2. Kann man überprüfen, ob sich zwei Objekte schneiden? Dabei will ich ebenfalls den transparenten Teil nicht zum Objekt zählen. (Diese Frage hat schonmal mein GDI-Asteroids Spiel zum Scheitern verurteilt. Das schmale, dreieckige Schiff wurde immer schon getroffen, obwohl es noch meilenweit von dem Asteroiden entfernt war, wenn der rechteckige Umriss-Bereich, in dem das Schiff gezeichnet wurde, kolidierte)
Wie gesagt will ich mich erstmal auf 2D beschränken. Die Fragen beziehen sich daher auch nur auf 2D-Objekte, die wie in dem Tutorial gezeigt hintereinander angeordnet sind.
Registriert: Sa Mai 04, 2002 19:48 Beiträge: 3830 Wohnort: Tespe (nahe Hamburg)
Versuche mal zu 1 genau zu beschreiben, was Du damit erreichen willst. Zu 2: Nun ob ein Objekt transparent ist und mit etwas kollidiert wird Dir OpenGL nicht sagen können. Immerhin ist dies ein Logik-Problem und damit nicht im Sorgenfeld einer Grafik-API. Sowohl in 2D als auch 3D läßt sich dies sehr leicht mit einer sogenannten BoundingTest prüfen. Du stellst Dir um dein Objekt ein Rechteck vor und brauchst nun nur noch zu prüfen, ob ein mögliches Kollisionsobjekt in dieses Rechteck eingedrungen ist. Genauso leicht ist dies auch mit einer Kugel. Mit diesen beiden Gebilden kann man in 95% aller Fälle eine absolut ausreichende Kollision erzeugen. Die Aufgabe ob Du diese Prüfung mit einem "transparenten" Objekt durchführst bleibt der Logik deines Programmes überlassen.
Man stelle sich eine prächtige Winterlandschaft vor (sollte atm nicht das Problem sein ). Im Vordergrund rankt sich ein riesiger Baum mit immer weiter verästelten Ästen und Ästchen. Davor steht jetzt (aus welchen Gründen auch immer) ein Jäger, der mit hauchfeiner Munition schießt, so dass sie auch an dem kleinsten Ästchen abprallt. Das heißt, wenn er schießt, muss man anhand der Position auf die er geschossen hat ermitteln können, ob er jetzt ein Ästchen in der überlagerten Textur oder eine Schneeflocke in der hinterlegten Winterlandschaft getroffen hat.
Anderes Szenario: Wir befinden uns jetzt in einer uralten ägyptischen Grabkammer. An der (Hintergrund-)Wand befinden sich (Vordergrund-)Hyroglyphen. Nur wenn man exakt auf die Hyroglyphen drückt, öffnet sich die Schatzkammer und damit unendlicher Reichtum.
In beiden Fällen ist es sehr schwierig, die Objekte geometrisch exakt zu beschreiben. Gleichzeitig ist es aber einfach, sie als Textur mit einem Großteil an Transparenz zu betrachten. Die Frage ist jetzt nur: Woher weiß ich, ob mein Objekt an einer bestimmten Stelle durchsichtig ist?
Wenn man das dann noch etwas verallgemeinert und von beliebig vielen Schichten mit beliebiger Transparenzverteilung ausgeht, ergibt sich natürlich auch die Frage: >Welche< Schicht "sieht" man denn jetzt an einem Punkt. Das kann man aber im Zweifelsfall durchprobieren, imdem man alle Schichten von vorne nach hinten abklappert.
zu 2:
Um das nochmal etwas "bildlicher" zu beschreiben :
Das ist ein Ausschnitt aus dem (urmelalten) Asteroids-Projekt. Das blaue Dreieck (das Schiff) und der rote Kreis (der Asteroid) berühren sich zwar noch nicht einmal, die rechteckigen Objekte (mit den nachgezeichneten weißen Umrandungen) überschneiden sich aber schon längst. Da ich dieses vorne relativ schmale Schiffsmodell gewählt habe fällt der Effekt ziemlich extrem auf.
Ich gehe mal davon aus, dass man mit vernünftigen Grafiken schon einigermaßen gute Ergebnisse mit den Näherungen erzielen kann. Aber dennoch verstehe ich nicht, dass man das nicht eindeutig ermitteln kann. Im Prinzip müsste man doch nur die Alphawerte in jedem Punkt vergleichen und feststellen, ob beide nicht transparent (bzw. größer als ...) sind.
Naja, vielleicht mache ich mir auch einfach nur zu viele Gedanken... Die beiden Probleme sind mir jedenfalls schon untergekommen und deshalb wollte ich jetzt gleich mal im Vorhinein abklären, wie man damit umgehen kann.
Registriert: So Feb 06, 2005 17:29 Beiträge: 187
Programmiersprache: C, C++
Mein Beitrag zu Problem 2:
Deine Idee mit den Alphawerten hört sich interessant an, auch wenn ich nicht weiss, ob sie funktionieren könnte. Ich bin jetzt zu faul um mir Gedanken dazu zu machen.
Ansonsten würde ich sagen, dass PerPixel-Kollision bei einem Asteroids vielleicht noch möglich ist, aber bei anderen Sachen zu rechenaufwendig wird.
Mit Boundingboxen kannst du übrigens fast alle Objekte sehr genau beschreiben, indem du, wie Phobeus schon sagte, Boxen und Kugeln benutzt. Ich mach mal ein Beispiel für eine Bauer-Schachfigur:
Der untere Teil der Figur wird als Box beschrieben und der "Kopf" als Kugel. Eine Pseudoabfrage könnte dann so aussehen:
Mir fällt gerade noch eine Möglichkeit ein: Erst sortierst du mit Boundingboxern grob aus und die die sich überschneiden überprüfst du dann nochmal Pixelgenau. Immerhin besser als alles Pixelgenau zu testen
Allerdings weiss ich immer noch nicht, ob das für deine Anwendung nützt. Besonders dein erstes Beispiel mit der Winterlandschaft hat mich *schluck* ...
Registriert: Di Nov 26, 2002 22:12 Beiträge: 259 Wohnort: Dresden
Normalerweise nutzt man in solchen Szenen sowieso ein eigenes Materialsystem und damit ist es auch völlig egal ob ein Objekt durchsichtig ist oder nicht. Anhand der Materials kannst du dann nicht nur Grafikeigenschaften festlegen, sondern auch Kollisionseigenschaften. Dazu zählt dann z.B. auch welcher Sound abgespielt werden soll, wenn du den Ast triffst. Die Schneeflocken würde man wohl normalerweise gar nicht erst ins Kollisionssystem mit einbeziehen. Weitere Vorteile hiervon sind, dass man auch sichtbare Objekte erstellen kann, durch die eine Kugel hindurchfliegen kann. Stell dir vor du befindest dich umgeben von Papierwänden, kannst aber nicht durchschießen, weil diese sichtbar sind.
Für das Beispiel einer Kugel reicht es einfach eine Gerade zu erstellen und diese gegen die Polygone selbst, Brushes oder Bounding Volumes zu prüfen (was auch immer du verwendest). Der Schnittpunkt der dabei dem „Ursprungspunkt“ der Geraden am nächsten ist „gewinnt“ die Kollision. Für komplexere Objekte musst du entsprechend mehr Geraden erstellen, bis du sicher sein kannst, dass wirklich eine Kollision existiert. Je nach dem wie komplex du das Ganze machen willst solltest du dir evtl. entsprechende Artikel im Internet ansehen.
Arbeitest du ausschließlich mit Bounding Voumes, was häufig ausreicht kannst du auch Zusatzeigenschaften an deine Bounding Volumes anhängen. Beispielsweise „durchlässig“ für Geschosse aber „undurchlässig“ für den Spieler selbst. Der Kreativität sind hier keine Grenzen gesetzt, man sollte das ganze aber auch strikt von OpenGL trennen.
Ich habe vor einiger Zeit auch den Quellcode zu meinem Asteroids-Clone veröffentlicht. Das Kollisionssystem dort ist sehr simpel aber für den konkreten Fall absolut ausreichend. Für eine 3D-Szene wie du sie beschrieben hast wäre das System aber absolut inakzeptabel. Es hängt also alles davon ab, was du genau machen willst. Du kannst ja mal einen Blick darauf werfen, wenn es dich interessiert und vielleicht die eine oder andere Idee übernehmen.
Du kannst auch mehrere Bounding Volumes für ein Objekt nutzen um es besser beschreiben zu können. Sei kreativ!
_________________ Nichts auf der Welt ist so gerecht verteilt wie der Verstand. Denn jederman ist überzeugt, dass er genug davon habe.
Rene Descartes, frz. Mathematiker u. Philosoph, 1596-1650
Um das gleich vorweg zu nehmen: Es geht mir atm ausschließlich um 2D Operationen. In den Beispielen habe ich übereinandergelegte Quads gemeint, keine ausgetüfftelte 3D-Umgebung. Es sind auch nur Beispiele, mit denen man meiner Meinung nach das Problem ganz gut rüberbringen kann. Konkret geht es mir um gestapelte Objekte und die Frage ist, auf welches ein Nutzer geklickt hat.
Zitat:
Für das Beispiel einer Kugel reicht es einfach eine Gerade zu erstellen und diese gegen die Polygone selbst, Brushes oder Bounding Volumes zu prüfen"
Da der Nutzer ja immer von vorne schaut, ist die Gerade auch entsprechend x=x, y=y, z=beliebig. Das Problem ist aber, dass sie mehrere Quads schneiden kann, aber die meisten sind eben an dieser Stelle unsichtbar. Ich frage mich jetzt, ob man durch die GL die Bildpunkte ausgeben kann, die die Objekte an diesem Ort haben, oder ob man praktisch zusätzlich zu der Grafikausgabe die ganzen Objekte nochmal im Speicher halten und verwalten muss, um dann die Position des Mauszeigers auf die Position auf den Objekten umzurechnen. Das klingt für mich einfach sehr aufwendig, wenn man bedenkt, dass die GL diese Daten ohnehin besitzt.
Zitat:
Ansonsten würde ich sagen, dass PerPixel-Kollision bei einem Asteroids vielleicht noch möglich ist, aber bei anderen Sachen zu rechenaufwendig wird.
Versteh ich aber eigentlich nicht. Wenn man bedenkt, welche Anforderungen im 3D-Bereich gestellt werden, dann sollte das doch eigentlich ein Klax sein. Wenn ich eine transparente Textur in einer 3D-Anwendung habe, muss der Rechner doch auch dauernd prüfen, ob sie an Stelle xy transparent ist und ob demnach die Objekte dahinter angezeigt werden. Da geht das eventuell sogar über mehrere Schichten. Im Verhältnis zu diesen Anforderungen sollte es doch kein Problem sein, zwei Alphakanäle von zwei festgelegten Objekten zu vergleichen?
Zitat:
Ich habe vor einiger Zeit auch den Quellcode zu meinem Asteroids-Clone veröffentlicht. Das Kollisionssystem dort ist sehr simpel aber für den konkreten Fall absolut ausreichend.
Würde mich mal interessieren, kannste mal nen Link dazu posten?
Registriert: Di Nov 26, 2002 22:12 Beiträge: 259 Wohnort: Dresden
Du musst dir das ganze etwas anders vorstellen. OpenGL ist eine Grafik-API. D.h. Sie verwaltet keinerleich Informationen zu deinen Objekten. Im Prinzip kannst du es dir vereinfacht so vorstellen:
Renderst du ein Primitiv, dann wird dieses in Fragmente zerlegt (vorzustellen als Bildpunkte mit Zusatzeigenschaften). Darin sind Informationen wie z.B. Farbinformationen und Tiefeninformationen enthalten. Renderst du nun ein zweites Primitiv, wird lediglich geprüft ob die neuen Fragmente davor oder dahinter liegen (Setzt Tiefentest vorraus). Liegen die neuen Fragmente dahinter wird gar nichts getan und OpenGL vergisst quasi das neue Primitiv. Liegt es näher beim Betrachter „vergisst“ OpenGL einfach die alten Fragmentinformationen und erstezt die Farbinformationen und Tiefeninformationen an den neuen Bildpunkten durch die neuen Informationen.
Entsprechend liegen keine Informationen zu den Primitiven vor und du hast auch keine Chance die Informationen vernünftig auf die entsprechenden Objekte zurückzuführen. Der Vorteil dieser Methode ist, dass die neuen Informationen unheimlich schnell in den Framebuffer geschrieben werden können.
Aus diesem Grund empfiehlt es sich die Objekte einfach durch einfache geometrische Objekte zu umschreiben um möglichst zeitsparend mit etwas Mathematik prüfen zu können ob sich die Objekte schneiden usw.. Je nachdem was du willst.
Pixelgenaue Kollision ist daher auch sehr aufwändig und in den meisten Fällen auch unnötig und vor allem langsam.
_________________ Nichts auf der Welt ist so gerecht verteilt wie der Verstand. Denn jederman ist überzeugt, dass er genug davon habe.
Rene Descartes, frz. Mathematiker u. Philosoph, 1596-1650
Ich denke, ich habe jetzt alle Informationen, die ich wollte, und weiß vor allem, wieso eine Grafikengine eine >Grafik<engine ist und keine interaktive Objektverwaltung . Das Projekt werd ich mir bei Gelegenheit mal ansehen, aber wahrscheinlich werd ich ohnehin ein Weilchen brauchen, um den Quellcode zu verstehen .
Auf jeden Fall nochmal: Vielen Dank für die schnelle Hilfe!
Mitglieder in diesem Forum: 0 Mitglieder und 7 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.