Registriert: Fr Mai 29, 2009 19:44 Beiträge: 12 Wohnort: Saarland
Hallo,
ich hoffe ihr könnt mir weiterhelfen
Wie kann ich berechnen welches Polygon ich angeklickt habe? Also wenn ich auf das Render-Fenster klicke und die Maus zeigt auf ein Polygon, dann soll sich das Polygon um z.B um 1 nach oben verschieben.
Hoffe meine Zeichnungen helfen das Problem zu verstehn:
und nach den klick:
Bin auch für stichworte dankbar, nach welchen ich googeln könnte. Habe schon nach "Polygon anklicken" gesucht, aber leider nix gefunden T.T
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Registriert: Fr Jan 04, 2008 21:29 Beiträge: 419 Wohnort: Lübeck
ganz einfach ist das nicht. Eine Idee wäre Colorselection. bei dem verfahren renderst du deine Szene einmal so wie sie aussehen soll und einmal jedes quad in einer einzigartigen Farbe (kein Polygon, darf die gleiche farbe wie ein anderes besitzen). mittels glReadPixels, kannst du dann herrausfinden welche farbe du angeklickt hat und kannst dadurch ermitteln, welches Polygon du erwischt hast.
Eine andere Methode ist Raycasting. Dabei ermittelst du einen Strahl, der von der Position deiner Maus auf dem Bildschirm entlang der Blickrichtung in die Szene geht. danach prüft man jedes Polygon/Objekt, ob es von dem Strahl geschnitten wird. das Objekt mit der kürzesten Distanz vom Betrachter ist dann dein Opfer.
Wie die beiden verfahren genau funktionieren kann ich nicht bechreiben, weil ich sie selbst (noch) nicht umgesetzt habe. Einziges was ich weiß ist, dass das raycasting auch für andere Dinge missbraucht werden kann, das Colorpicking dafür aber schneller und genauer ist, da du auch komplexe Objekte damit pixel genau selektieren kannst.
Einzige Schwachstelle des Colorpickings ist das Antialiasing, bei dem die Farbe an der Kante eines Objektes in die darunter liegende Farbe schmiert und man manchmal evtl. ein ganz anderes Objekt selektiert, weil die geschmierte Farbe womöglich zu einem ganz anderen Objekt gehört. Eine Möglichkeit das zu ändern wäre ein Epsilon, das als Toleranz wert dient, damit verringerst du aber den nutzbaren Farbraum.
Kann man beim Render der Color-Picking-Szene Anti-Aliasing nicht eh ausschalten? Nimmt ja im Zweifel nur Performance, von der man eh "nichts sieht". Diese Methode ist mir aber auch am geläufigsten. Was es noch gibt, was aber imho irgendwelche Nachteile hat, weshalb es praktisch kaum noch genutzt wird, ist "OpenGL Selection", hier wäre dazu ein passendes Tutorial: http://wiki.delphigl.com/index.php/Tutorial_Selection
Es gibt offensichtlich ein Problem mit den nVidia-Treibern, das dafür sorgt, dass die Selektion die Darstellung massiv verlangsamt. Wenn es also darum geht, die Anwendung portabel zu machen, sollte man auf andere Methoden und nicht auf die OpenGL-Eigene Selektion zurückgreifen.
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
Um den Strahl zu berechnen der vom Cursor in den Bildschirm zeigt kannst du die Funktion "MouseTo3d" aus meiner functions_coolcat.pas benutzen.
=> http://www.delphidev.de/forum/viewtopic.php?id=69
Dann einfach alle Polygone mit dem Strahl schneiden (Funktionen dafür müssten in der Datei auch drin sein) und das Polygon mit der kürzesten Distanz nehmen. (was ja Sellmann auch schon gesagt hat)
Ist die Strahlmethode nicht die aufwendigste und komplizierteste?
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
@Ziz: Wenn es nur wenige Polygone sind ist das auch schnell implementiert. Bei vielen Polygonen muss man natürlich mit einem BSP- oder Octtree optimieren.
Die Color-Methode ist nicht so einfach, wenn man mit Vertexbuffer-Objekten arbeitet. Wie willst du da die Polygone eindeutig einfärben? Selbst wenn du das Color-Attribut für Vertices nutzt kannst du dann keine Indices oder TriangleStrips verwenden. Die Farben würden sonst interpoliert. Dadurch wird also dein Vertexbuffer mal eben 6 mal so groß. In jedem Fall brauchst du ein zweites Mesh, wenn du mit dem Overhead nicht ständig leben willst.
Oder gibt es da irgendeinen Trick der mir gerade nicht einfällt?
Ab Shader Model 4.0 (?) gibt es allerdings im Shader eine Variable (gl_PrimitiveID) aus der man im Fragmentshader auf das Dreieck schließen kann und eine entsprechende Farbe berechnen kann. Damit wäre das dann wirklich eine Option.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Wenn ich mich recht entsinne gibt es in OpenGL3.1(Shader Model 4) kein Colorpicking mehr und gl_PrimitiveID ist meines wissens für das ab da fest Implementierte Occlusion Culling und Instancing gedacht.
In diesem Fall, kannst du ja noch die Scissorbox auf den bereich des zu prüfenden Punktes beschränken und somit viel Zeit in diesem Pass sparen.
edit:
Die Raycast Intersection hat durchaus seine Vorteile, z.B. genauigkeit, sowie platform-,software- und Hardware-unabhängigkeit.
Beim Colorpicking muss die Grafikkarte entsprechend verfügbar sein und OpenGL auf dem Gerät laufen.
Ein weiterer Nachteil kann eventuell entstehen, wenn man nicht nur das vorderste Objekt an diesem punkt, sondern alle haben möchte(z.B. bei Modelierungssoftware, durchschlagende objekte).
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Coolcat hat geschrieben:
Um den Strahl zu berechnen der vom Cursor in den Bildschirm zeigt kannst du die Funktion "MouseTo3d" aus meiner functions_coolcat.pas benutzen.
Grundsätzlich finde ich das eine gute Sache, was Du hier machst. Folgendes finde ich aber nicht so gut, da wir uns hier in einem Anfängerforum befinden: die Typen "TD3DXVector3" und "TD3DXMatrix" sind in der besagten Unit nicht definiert. Einem Profi macht so etwas kein Problem. Für einen Anfänger kann das ein großes Problem sein.
Und die Benennung der Typen finde ich - angesichts der Tatsache, dass wir uns hier in einem OpenGL-Forum befinden - etwas seltsam, denn man kauft damit die Katze im Sack, nicht wahr? Außen steht OpenGL drauf und innen ist D3D drin.
Da Du mich jetzt gleich darauf hinweisen wirst, dass das keinen Unterschied macht, sage ich Dir schon mal vorneweg: doch es macht einen Unterschied, - einen großen sogar.
Zwiespältige Grüße
Traude
Dies ist nicht das "Einsteiger"-Forum, sondern das "Allgemein"-Forum. Trotzdem hast du recht
Zitat:
Und die Benennung der Typen finde ich - angesichts der Tatsache, dass wir uns hier in einem OpenGL-Forum befinden - etwas seltsam, denn man kauft damit die Katze im Sack, nicht wahr? Außen steht OpenGL drauf und innen ist D3D drin.
DelphiDev.de ist ein DirectX-Forum...aber ich denke die Typen sind weniger das Problem, eher die Funktion D3DXMatrixInverse. Ich könnte das ganze jetzt unter Verwendung meiner C++-MatheLibrary für OpenGL umbasteln, aber damit wäre wohl auch nicht geholfen. Da es sich nur um die View-Matrix handelt, kann man die aber relativ leicht invertieren.
x,y sind die Cursor-Koordinaten
die beiden Matrizen holst du dir mit glGetFloatv(GL_PROJECTION_MATRIX, ...) bzw. glGetFloatv(GL_MODELVIEW_MATRIX, ...). Bei der ModelVIew-Matrix musst du aufpassen das du auch wirklich die View-Matrix nimmst und nicht das Produkt von Model und View Matrix. Am besten einfach direkt nach der Benutzung von gluLookAt auslesen.
Dein Ergebnis erhälst du dann mit den beiden Vektoren Origin und Dir.
Ich habe den obigen Code nicht getestet, vielleicht kann das mal jemand der ein Delphi zur Hand hat ausprobieren.
Wenn ich mich recht entsinne gibt es in OpenGL3.1(Shader Model 4) kein Colorpicking mehr
Mit entsprechenden Extensions kannst du auch mit OpenGL 2.x schon Shader Model 4 nutzen. Zudem meinte ich das so wie es jemand oben irgendwo geschrieben hat: Also wirklich die Dreiecke rendern und Pixelfarbe auslesen. Das geht sicher auch noch mit OpenGL 3.x, nur halt auf andere Weise. Was nicht mehr funktioniert ist Selektion. So wie ich das verstehe funktioniert Selektion aber sowieso nicht pro Polygon? Allersdings habe ich diesen Selektions-Puffer noch nie verwendet.
Zitat:
gl_PrimitiveID ist meines wissens für das ab da fest Implementierte Occlusion Culling und Instancing gedacht.
Fest implementiertes Occlusion Culling, wie soll das gehen? Meinst du vielleicht Occlusion Queries? Dafür benötigt man kein gl_PrimitiveID, vor allem weil das mit dem Shader nichts zu tun hat. Das ist lediglich ein Zähler für gerenderte Pixel. Diesen kann man natürlich dann für Occlusion Culling verwenden.
gl_PrimitiveID ist nichts weiter als ein Zähler der von der Grafikkarte bei jedem Dreieck inkrementiert wird. Beim Instancing kann dieser nützlich sein, aber primär wird man da sicher gl_InstanceID verwenden wollen.
[/offtopic]
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Selectiongibt es definitiv nicht mehr in OpenGL3.1 aber du kannst noch ein Pixel aus dem FrameBuffer lesen, indem du die gute alte gl_ReadPixel Funktion verwendest(die die so zum brechen lahm ist).
Ja ich meinte Occlusion Query und nicht Occlusion Culling, dafür wird auch kein gl_PrimitiveID benötigt.
In OpenGL3.1 gibt es nun Conditional Rendering, dabei wird ein Occlusion Query gestartet und an die rückgabe eine condition gebunden(die ausgelöst wird oder nicht aber halt alles in der renderpipeline auf der gpu), damit wird Occlusion Culling ohne hinzutuen realisiert.
Beim Instancing werden 2 IDs oft genutzt, zum einen gl_InstanceID und gl_VertexID.
gl_VertexID, wird z.B. genutzt, wenn man über Instancing tesselierung realisiert wird.
Ich hab allerdings an gl_InstanceID gedacht, als ich gl_PrimitiveID zu Instancing stecken wollte ^^.
Mit OpenGL3.1 muss man nun auch die Matrizen selber verwalten, damit wird die Raycast intersection Variante wieder interessanter, da man ein großen Teil des Mathematischen Code ja sowieso implementieren muss.
Für ein Einsteiger denke ich daher, ist das alte Colorpicking noch die bessere Lösung aber wer über diesen Stand hinaus ist sollte sich schon mit Raycast Intersection anfreunden.
Dieses ist übrigens unter umständen schneller. In diesem Fall ist ein Quadtree mit RayPlaneIntersection recht fix(eine einzige intersection Berechnung gibt das kleinste Node im Quadtree schon zurück).
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Fr Mai 29, 2009 19:44 Beiträge: 12 Wohnort: Saarland
Hi,
also wenn ich die Polygone mit einer Textur nutze, dann ist die Color Methode eigl. nicht mehr zu gebrauchen, oder (mit Textur hab ich es noch nicht getestet ^^ )? Was bleibt, ist dann die Raycast Methode. Ich denke mal mit etwas Vektor rechnung klappt das schon
@ Coolcat:
Danke für die Unit, aber ich würde gern selber mal so was in der Art schreiben
Registriert: Fr Jan 04, 2008 21:29 Beiträge: 419 Wohnort: Lübeck
texturierte objekte ist auch kein Problem, denn du renderst das Bild sozusagen 2x. Das erste mal mit den Farbwerten und prüfst dann as du angeklickt hast. danach löscht du den Inhalt vom Buffer und zeichnest die gesamte Szene noch einmal mit den texturen. Dann siehst du von den Farben nichts und hast deine Texturen trotzdem auf den Objekten.
Mitglieder in diesem Forum: 0 Mitglieder und 6 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.