Jak pobrać współrzędne punktu w OpenGL

0

Witajcie,

Załóżmy najprostszą sytuację na świecie. Mam narysowane 3 punkty w OpenGL

glBegin(GL_POINTS);
  glColor3ub(255,0,0);
  glVertex3i(0,0,0);
  glColor3ub(0,255,0);
  glVertex3i(1,1,0);
  glColor3ub(0,0,255);
  glVertex3i(1,1,1);
glEnd;

To taki mega prosty przykład. Ponadto na obsłudze myszy mam zrobiony zoom:

gluLookAt(0,0,KameraZ, //polozenie oka
      0,0,0,
      0,1,0); //kierunek "do gory"

obrót:

glRotatef(Theta, 1.0, 0.0, 0.0); //wokol OX
glRotatef(Phi, 0.0, 1.0, 0.0); //wokol OY

oraz przesunięcie całości w prawo/lewo oraz góra dół:

glTranslated(MoveX,MoveY,0);

Teraz chciałbym zrobić taki myk, że jeśli kliknę myszą z wciśniętym shiftem w dowolny punkt i pod wskazanymi współrzędnymi znajduje się punkt to zwrócić X,Y,Z oraz R,G,B

Zrobiłem coś takiego:

procedure MouseClick(const X, Y: Integer);
var
  viewport : Array[0..3] of glUint;
  modelview, projection: Array[0..15] of GLdouble;
  WinX, WinY, WinZ: GLfloat;
  worldX, worldY, worldZ: Double;
  i: Integer;
begin
  glGetDoublev(GL_MODELVIEW_MATRIX, @modelview );
  glGetDoublev(GL_PROJECTION_MATRIX, @projection );
  glGetIntegerv(GL_VIEWPORT, @viewport );
  winX := X;
  winY :=viewport[3] - Y - 27;
  winZ := 0;

  gluUnProject( winX, winY, winZ, @modelview, @projection, @viewport, worldX,
        worldY, worldZ);
  for I := 0 to High(stars) do
      if (Round(stars[i].x) =  Round(WorldX)) and
         (Round(stars[i].y) = Round(WorldY)) then
      begin
        sbar.Panels[0].Text := 'R:'+FloatToStr(stars[i].R)+',G:'+FloatToStr(stars[i].G)+',B:'+FloatToStr(stars[i].B);
        Break;
      end;
end;

procedure pPaintMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
    if (ssShift in Shift) and (Button = mbLeft) then
       MouseClick(x,y);
end;

Niestety nie działa mi to za dobrze ... możecie podpowiedzieć o czym zapomniałem?

PS.
Zapomniałem dodać punkty mam w tablicy Stars

0

Porównuj raczej model kolizji point-circle, a nie point-point, abyś miał jakiś margines błędu.

0

Tzn tak sam margines już jest mocno okrojony za pomocą tego Round() jednak nijak się to ma do przesunięć i obrotów. Przykład: gdy nie ma żadnych obrotów, i przesunięć a jest tylko zoom to dla pierwszego punktu (gdy w niego klikam) mam współrzędne worldX = 270 co pokrywa się ze współrzędnymi punktu stars[0].x natomiast jak zrobię obórt o 90° (glRotatef) i kliknę w ten sam punkt wtedy worldX wywala mi już np 390. Stąd moje przypuszczenia, że coś zmaściłem.

Zmieniłem nieco funkcję na coś takiego:

type T3D_Point = array [1..3] of Double;

function GetOGLPos(const X, Y: Integer): T3D_Point;
  var
      viewport:   array [1..4]  of Integer;
      modelview:  array [1..16] of Double;
      projection: array [1..16] of Double;
      winZ: Single;
  begin
      glGetDoublev( GL_MODELVIEW_MATRIX, @modelview );
      glGetDoublev( GL_PROJECTION_MATRIX, @projection );
      glGetIntegerv( GL_VIEWPORT, @viewport );
      if( Y = 0 )then Y := 1;

      glReadPixels(X, -Y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @winZ );
      gluUnProject(X, viewport[4]-Y, winZ,
              @modelview, @projection, @viewport,
              Result[1], Result[2], Result[3]);
  end;

procedure MouseClick(const X, Y: Integer);
var
  i: integer;
  pt: T3D_Point;
begin
  pt := GetOGLPos(x,y);
  for I := 0 to High(stars) do
     if (CompareValue(stars[i].x, pt[1], 2) = EqualsValue)  and
        (CompareValue(stars[i].y, pt[2], 2) = EqualsValue) then
     begin
       sbar.Panels[0].Text := 'i:'+IntToStr(i)+ ',R:'+FloatToStr(Round(stars[i].R))+
                              ',G:'+FloatToStr(Round(stars[i].G))+
                              ',B:'+FloatToStr(Round(stars[i].B));
       Break;
     end;
end;

i mam taki efekt (bez przesuwania i obracania - tylko zoom), że bez względu na to, który punkt kliknę 0,0,0; 1,0,0 czy 2,0,0 to i tak zwraca mi punkt 0,0,0

1 użytkowników online, w tym zalogowanych: 0, gości: 1