PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : !! OpenGL, Selection Mode !!!


Phane01
26.04.2004, 12:04
Hallo zusammen,
ich schreibe an einem kleinem Programm in C# (.NET2003) mit einer OPENGL Bibliothek von Tao (http://www.randyridge.com/Tao/Default.aspx). Ich habe das Problem, das ich ein gezeichnetes Objekt nicht selektieren kann.
Ich habe das Programm mal hinzugefügt, vielleicht kann mir irgendjemand weiterhelfen.
Ablauf ist der folgende. Es soll ein Objekt erstellt und entsprechend positioniert werden. Dann ein neues Objekt und so weiter. Ich möchte dann irgendein breits erzeugtes Objekt seklektieren und dies dann wiederum verschieben etc. Ich bekomme aber immer irgendwelchen kryptischen Koordinaten aus dem SELECTION_MODE zurück, nur nicht die an der das Objekt tatsächlich liegt. Hat irgenwer eine Idee !!!!!

Danke Stephan


summer
01.05.2004, 12:25
Hallo,

ich habe noch nicht mit dem selection mode gearbeitet, weil ich zu faul war, mich damit auseinanderzusetzen, da mir folgende, recht einfache lösung auf der hand zu liegen schien:

zeichne all deine objekte nochmal in einen off screen buffer, aber OHNE texturen OHNE irgendwelche licht- oder sonstige effekte. ALLES AUS !!! die zahlenwerte dürfen nicht beeinflusst werden.
du musst 32bit farbmodus aktiviert haben.
dann nimmst du für jedes objekt eine "farbe" - einen 32-bit integer wert, der für jedes objekt einzigartig ist. das heisst, du kannst nur etwa 4 milliarden objekte haben, aber ichi denke, das reicht für's erste :D

so, und wenn du jetzt deine objekte mit ihrer jeweiligen ID-nummer als "farbe" gemalt hast, musst du nur (mit getPixels) schauen, welche "farbe" unter deinem mauscursor ist - dann weisst du auch, welches object unter deinem mauscursor ist.

achja, du solltest darauf achten, keinen index für dein objekt zu nehmen, welches mit der hintergrundfarbe deines off screen buffer übereinstimmt :D (den du jedes mal vorher natürlich "ausmalen" solltest)

kein wildes fehlberechnungsrumgefriemel in 3D, besser als das gehts gar nicht, finde ich, denn das basiert genau auf dem, was der user sieht, und darum geht es.
und komfortabler zu schreiben gehts wohl auch nicht :D

/me = faulpelz.







Hallo zusammen,
ich schreibe an einem kleinem Programm in C# (.NET2003) mit einer OPENGL Bibliothek von Tao (http://www.randyridge.com/Tao/Default.aspx). Ich habe das Problem, das ich ein gezeichnetes Objekt nicht selektieren kann.
Ich habe das Programm mal hinzugefügt, vielleicht kann mir irgendjemand weiterhelfen.
Ablauf ist der folgende. Es soll ein Objekt erstellt und entsprechend positioniert werden. Dann ein neues Objekt und so weiter. Ich möchte dann irgendein breits erzeugtes Objekt seklektieren und dies dann wiederum verschieben etc. Ich bekomme aber immer irgendwelchen kryptischen Koordinaten aus dem SELECTION_MODE zurück, nur nicht die an der das Objekt tatsächlich liegt. Hat irgenwer eine Idee !!!!!

Danke Stephan

DanDanger
01.05.2004, 15:22
Hi,

summer's Idee ist schon richtig (So wird's auch in 90% aller Anwendungen gemacht).

Ich hab' sowas mal für ein 3D-Simulationprogramm geschrieben,
vieleicht hilft Dir mein Picking-Code weiter :
(Hinweiss : PosX und PosY sind die Mauscoordinaten)


int GetObjectID(int PosX, int PosY, int Screen_Width, int Screen_Hight) {

int Sicht_Koordinaten[4] = {0} ;
int GeklickteObjekte = 0 ;
unsigned int SelectBuffer[32] = {0} ;

// Diese Function speichert ein Rechteck (4 Kanten).
// Das Rechteck entspricht dem, was die Camera sieht...
glSelectBuffer(32, SelectBuffer) ;
glGetIntegerv(GL_VIEWPORT, Sicht_Koordinaten) ;

glMatrixMode(GL_PROJECTION) ;
glPushMatrix() ;

glRenderMode(GL_SELECT) ;
glLoadIdentity() ;

gluPickMatrix(PosX, Sicht_Koordinaten[3] - PosY, 5, 5, Sicht_Koordinaten) ;

gluPerspective(45.0f,(float)Screen_Width/(float)Screen_Hight,0.1f,150.0f);

glMatrixMode(GL_MODELVIEW) ;

RenderScene() ;

GeklickteObjekte = glRenderMode(GL_RENDER) ;

glMatrixMode(GL_PROJECTION) ;

// 2D-Matrix vom Stack holen
glPopMatrix() ;

// Wieder alte 3D-Grafik und Ansicht wiederherstellen...
glMatrixMode(GL_MODELVIEW) ;


// Wenn auf mehr als ein Objekt geklickt wurde,
// soll das ausgewählt werden, welches am nächsten
// zur Camera steht => "Tiefeninformationen" aller
// angeklickten Objekte vergleichen...
// Das Objekt mit der "geringsten Tiefe" ist am
// nächsten zur Camera...
if(GeklickteObjekte > 0) {

unsigned int geringsteTiefe = SelectBuffer[1] ;

// Welches Object wurde angewählt ?
int GewaehltesObjekt = SelectBuffer[3] ;

// Alle gefundenen Objekte vergleichen
for(int i=1 ; i < GeklickteObjekte ; i++) {

// ist das i-te Objekt tiefer als das bisherige tiefste
// Objekt ???
if(SelectBuffer[(i * 4) + 1] < geringsteTiefe) {
// Wenn ja => geringsteTiefe = tiefe des i-ten Objektes
geringsteTiefe = SelectBuffer[(i * 4) + 1] ;

// "Tiefstes Objekt" = aktuelles (i-tes) Objekt
GeklickteObjekte = SelectBuffer[(i * 4) + 3] ;

} ; // Ende if(SelectBuffer...) Abfrage
} ; // Ende der for-Schleife
Global_Selected_ObjectID = SelectBuffer[3] ;
return SelectBuffer[3] ;

} ;
//Wurde ins leere geklickt => return 0 ;
return 0 ;

} ;

Phane01
06.05.2004, 07:56
Servus,
vielen Dank für diese Info. Könnt Ihr mir bitte ein Stück aussagekräftigen Code Mailen, in welchem das erstellen, aber noch viel wichtiger in welchem das auslesen mittels der OpenGl Funktion getPixels aufgeführt ist. Habe schon einiges mit dieser Funktion probiert, aber irgendwie klappt's net !!!
Vieklen Dank Stephan


Hi,

summer's Idee ist schon richtig (So wird's auch in 90% aller Anwendungen gemacht).

Ich hab' sowas mal für ein 3D-Simulationprogramm geschrieben,
vieleicht hilft Dir mein Picking-Code weiter :
(Hinweiss : PosX und PosY sind die Mauscoordinaten)


int GetObjectID(int PosX, int PosY, int Screen_Width, int Screen_Hight) {

int Sicht_Koordinaten[4] = {0} ;
int GeklickteObjekte = 0 ;
unsigned int SelectBuffer[32] = {0} ;

// Diese Function speichert ein Rechteck (4 Kanten).
// Das Rechteck entspricht dem, was die Camera sieht...
glSelectBuffer(32, SelectBuffer) ;
glGetIntegerv(GL_VIEWPORT, Sicht_Koordinaten) ;

glMatrixMode(GL_PROJECTION) ;
glPushMatrix() ;

glRenderMode(GL_SELECT) ;
glLoadIdentity() ;

gluPickMatrix(PosX, Sicht_Koordinaten[3] - PosY, 5, 5, Sicht_Koordinaten) ;

gluPerspective(45.0f,(float)Screen_Width/(float)Screen_Hight,0.1f,150.0f);

glMatrixMode(GL_MODELVIEW) ;

RenderScene() ;

GeklickteObjekte = glRenderMode(GL_RENDER) ;

glMatrixMode(GL_PROJECTION) ;

// 2D-Matrix vom Stack holen
glPopMatrix() ;

// Wieder alte 3D-Grafik und Ansicht wiederherstellen...
glMatrixMode(GL_MODELVIEW) ;


// Wenn auf mehr als ein Objekt geklickt wurde,
// soll das ausgewählt werden, welches am nächsten
// zur Camera steht => "Tiefeninformationen" aller
// angeklickten Objekte vergleichen...
// Das Objekt mit der "geringsten Tiefe" ist am
// nächsten zur Camera...
if(GeklickteObjekte > 0) {

unsigned int geringsteTiefe = SelectBuffer[1] ;

// Welches Object wurde angewählt ?
int GewaehltesObjekt = SelectBuffer[3] ;

// Alle gefundenen Objekte vergleichen
for(int i=1 ; i < GeklickteObjekte ; i++) {

// ist das i-te Objekt tiefer als das bisherige tiefste
// Objekt ???
if(SelectBuffer[(i * 4) + 1] < geringsteTiefe) {
// Wenn ja => geringsteTiefe = tiefe des i-ten Objektes
geringsteTiefe = SelectBuffer[(i * 4) + 1] ;

// "Tiefstes Objekt" = aktuelles (i-tes) Objekt
GeklickteObjekte = SelectBuffer[(i * 4) + 3] ;

} ; // Ende if(SelectBuffer...) Abfrage
} ; // Ende der for-Schleife
Global_Selected_ObjectID = SelectBuffer[3] ;
return SelectBuffer[3] ;

} ;
//Wurde ins leere geklickt => return 0 ;
return 0 ;

} ;

DanDanger
06.05.2004, 11:04
Ich glaube nicht, dass Dir die diese "getPixels"-Funktion besonders viel weiterhilft.
Was passiert z.B. wenn 2 Objekte übereinanderliegen ???

Ausserdem ist "getPixels" KEINE OpenGL Funktion.
Die scheint wohl aus dieser Bibliothek zu stammen, die Du benutzt,
also kann Dir da wohl keiner weiterhelfen, der nicht auch diese Biblio. benutzt.
Ich würde da einfach mal an den Programmiere der Lib Mailen........

Du muss auf jeden Fall deine OpenGL-Scene in den Slection-Buffer Rendern,
Und dann schauen, was sich "unter" den Mauskoordinaten befindet.

Ansonsten : Auf www.OpenGL.org gibt's ne Menge Tutorials die sich damit
auseinandersetzen (such einfach mal nach "Picking").

Gruss
DanDanger