Registriert: Sa Feb 03, 2007 11:10 Beiträge: 26 Wohnort: Dingolfing
Hallo.
Ich versuche gerade, eine Selektion zu implementieren. Ich hab mir folgendes gebastelt:
Code:
function TMCEngine.GetClickedObject(X, Y:Integer): TMCObject;
var Buffer:array[0..255]ofCardinal;
view: TGLVectori4;
I, hitcount, id:Integer;
z:Cardinal;
begin
glGetIntegerv(GL_VIEWPORT,@view);
glSelectBuffer(256,@Buffer);
glMatrixMode(GL_PROJECTION);
glRenderMode(GL_SELECT);
glPushMatrix;
glLoadIdentity;
gluPickMatrix(X, view[3]-Y,1.0,1.0, view);
gluPerspective(45, view[2]/view[3],1,256);
//Ab hier wird gerendert
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glInitNames;
glPushName(0);
World.Camera.Apply;
for I:=0to World.Objects.Count-1do
if World.Objects[I]is TMCVisibleObject then
begin
glPushName(I+1);
glLoadName(I+1);
(World.Objects[I]as TMCVisibleObject).Render;
end;
SDL_GL_SwapBuffers;
//Fertig gerendert
glMatrixMode(GL_PROJECTION);
glPopMatrix;
hitcount:=glRenderMode(GL_RENDER);
id:=0;
z:=high(Cardinal);
for I:=0to hitcount-1do
if Buffer[(i*4)+1]<z then
begin
id:=Buffer[(I*4)+3];
z:=Buffer[(I*4)+1];
end;
if id=0then
Result:=nil
else
Result:=World.Objects[id-1];
glMatrixMode(GL_MODELVIEW);
end;
TVisibleObject.Render sieht so aus:
Code:
procedure TMCVisibleObject.Render;
begin
glPushMatrix;
glTranslatef(FX, FY, FZ);
glMultMatrixf(@FRotMatrix[0,0]);
ifassigned(FTexture)then
begin
glEnable(GL_TEXTURE_2D);
glColor3f(1,1,1);
FTexture.Apply;
endelse
begin
glDisable(GL_TEXTURE_2D);
SetColor(FColor);
end;
DoRender;
glPopMatrix;
end;
Das konkrete Rendern eines Objektes, z.B. eines Würfels, sieht so aus:
Code:
procedure TMCCube.DoRender;
var ss, st:Single;
begin
inherited DoRender;
ifassigned(FTexture)then//Texturenstreckung, unwichtig in dem Fall
begin
ss:=FTexture.ScaleS;
st:=FTexture.ScaleT;
endelse
begin
ss:=1;
st:=1;
end;
glBegin(GL_QUADS);
ifassigned(FTexture)then glTexCoord2f(0,0);
glVertex3f(-Width/2,-Height/2,-Depth/2);
ifassigned(FTexture)then glTexCoord2f(0,1/st);
glVertex3f(-Width/2,+Height/2,-Depth/2);
ifassigned(FTexture)then glTexCoord2f(1/ss,1/st);
glVertex3f(+Width/2,+Height/2,-Depth/2);
ifassigned(FTexture)then glTexCoord2f(1/ss,0);
glVertex3f(+Width/2,-Height/2,-Depth/2);
//Und jetzt noch 5 andere Seiten, das lasse ich mal weg
glEnd;
end;
Bei GetClickedObject ist teilweise schon hitcount falsch, es wird ein Klick auf ein Objekt mit hitcount=0 gesehen, wenn ich weiter unten auf das gleiche Objekt klicke, kriege ich jedoch hitcount=1. Wenn ich dann mal einen richtig hitcount bekomme, ist jedoch der gefundene Name vollkommen falsch.
Ich habe mir jede der Methoden mehrmals durchgeschaut aber nirgendswo einen Fehler gefunden...
1. Du hast zuviele Namen im Namestack. Es reicht einmal am Anfang ein glPushName und vor dem Anfang eines jeden Objektes ein glLoadName.
2. Du kannst zur Selektion Deine normale Renderprozedur benutzen, da man glPushName und glLoadName immer rufen kann, auch wenn man nicht im Selection-Modus ist. Wenn Du dann selektieren willst, initialisierst Du Deine selektion(mit dem RenderMode) und rufst dann die normale Renderprozedur. Auf die Weise kannst Du sicherstellen, dass beim Darstellen und Selektieren genau das selbe gerendert wird. Dies ist eine wichtige Vorraussetzung, dass die Selektierung funktioniert. Nachdem er alles gerendert hat, wird eben kein SwapBuffers gerufen, sondern der RenderMode wieder auf Normal gesetzt und dann kannst Du Deinen Puffer auslesen.
_________________ Manchmal sehen Dinge, die wie Dinge aussehen wollen, mehr wie Dinge aus, als Dinge.
<Esmerelda Wetterwax>
Es kann vorkommen, dass die Nachkommen trotz Abkommen mit ihrem Einkommen nicht auskommen und umkommen.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Wenn das dann funktioniert, solltest du trotzdem im Selection-Mode deine Renderprozedur etwas tunen, und alles ausschalten was man nicht unbedingt brauch. Also kein Licht, Blending, Texturen, .... Damits bisl flotter geht.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Ich sträubte mich anfangs auch gegen den Umstieg der OGL-Selektion auf einen eigenen Pick-Mechanismus. Als ich jedoch feststellte dass meine recht einfache Szene (im Projekt "Memorix") auf einer Nvidia 6600 GT ruckelte, während es auf einer Radeon 9250 flockig lief, wars mir dann auch zuviel. Letztlich ist ein eigener Mechanismus mit ~ 10 Zeilen und 30 Minuten Einbauzeit fertiggestellt und funktioniert prima und schnell auf allen Grafikkarten. Falls es Dir mit GL_SELECT zu nervig wird, dann kann ich Dir eine kurze Anleitung geben.
Grüße, DNA
_________________ Heute code ich, morgen debug ich, und übermorgen caste ich die Königin auf int.
http://www.2ndmoon.de
Zuletzt geändert von DNA am Mi Jan 30, 2008 22:47, insgesamt 1-mal geändert.
Registriert: Sa Feb 03, 2007 11:10 Beiträge: 26 Wohnort: Dingolfing
OK, mal schaun.
Dass ich nicht die normale Renderprozedur verwende, liegt daran, dass ich keine Rechenzeit mit dem Aktualisieren der Matrix in der Physikengine verschwenden will.
Mitglieder in diesem Forum: 0 Mitglieder und 2 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.