unit Pick1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  OpenGL, cOpenGL, Transfrm, Material, light;

type
  TForm1 = class(TForm)
    OpenGL1: TOpenGL;
    Transform1: TTransform;
    Material1: TMaterial;
    Transform2: TTransform;
    Material2: TMaterial;
    Transform3: TTransform;
    Material3: TMaterial;
    Light1: TLight;
    procedure Transform1Paint(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure Transform2Paint(Sender: TObject);
    procedure Transform3Paint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    Buffer: array[1..64] of GLuint;
    procedure Cube;       
    procedure Selection(px,py:GLdouble);
    procedure SelectionDone;
  public
    { Public declarations }
  end;
  
  PHit=^THit;
  THit=packed record
    ncount,
    dnear,
    dfar: GLuint;
    names: array[1..32] of GLuint;
  end; {THit}

var
  Form1: TForm1;

implementation

uses Pick2;

{$R *.DFM}

procedure TForm1.Transform1Paint(Sender: TObject);
begin
  Material1.Apply; 
  glLoadName(1);
  Cube;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  Transform3.Apply;
  Transform1.Apply;
  Transform2.Apply;
  glFlush;
  OpenGL1.ErrorCheck('FormPaint');
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  if OpenGL1.Smaller then
    FormPaint(Sender);
end;

procedure TForm1.Cube;
begin
  glBegin(GL_POLYGON); {near face}
    glVertex3f(-0.4,-0.4,+0.4);
    glVertex3f(+0.4,-0.4,+0.4);
    glVertex3f(+0.4,+0.4,+0.4);
    glVertex3f(-0.4,+0.4,+0.4);
  glEnd;

  glBegin(GL_POLYGON); {right face}
    glVertex3f(+0.4,-0.4,+0.4);
    glVertex3f(+0.4,-0.4,-0.4);
    glVertex3f(+0.4,+0.4,-0.4);
    glVertex3f(+0.4,+0.4,+0.4);
  glEnd;

  glBegin(GL_POLYGON); {left face}
    glVertex3f(-0.4,-0.4,-0.4);
    glVertex3f(-0.4,-0.4,+0.4);
    glVertex3f(-0.4,+0.4,+0.4);
    glVertex3f(-0.4,+0.4,-0.4);
  glEnd;

  glBegin(GL_POLYGON); {back face}
    glVertex3f(+0.4,-0.4,-0.4);
    glVertex3f(-0.4,-0.4,-0.4);
    glVertex3f(-0.4,+0.4,-0.4);
    glVertex3f(+0.4,+0.4,-0.4);
  glEnd;

  glBegin(GL_POLYGON); {bottom face}
    glVertex3f(-0.4,-0.4,+0.4);
    glVertex3f(-0.4,-0.4,-0.4);
    glVertex3f(+0.4,-0.4,-0.4);
    glVertex3f(+0.4,-0.4,+0.4);
  glEnd;

  glBegin(GL_POLYGON); {top face}
    glVertex3f(-0.4,+0.4,+0.4);
    glVertex3f(+0.4,+0.4,+0.4);
    glVertex3f(+0.4,+0.4,-0.4);
    glVertex3f(-0.4,+0.4,-0.4);
  glEnd;
end;

procedure TForm1.Transform2Paint(Sender: TObject);
begin
  Material2.Apply;; 
  glLoadName(2);
  glPushMatrix;
    glTranslatef(0.5,0.0,0.0);
    glScalef(0.3,0.3,0.3);
    glPushName(4);
    Cube;
    glPopName;
  glPopMatrix;
  Cube;
end;

procedure TForm1.Transform3Paint(Sender: TObject);
begin
  Light1.Apply;
  Material3.Apply;; 
  glLoadName(3);
  Cube;
end;

procedure TForm1.Selection(px,py:GLdouble);
type
  TViewPort=packed record
    left,bottom,width,height: GLint;
  end;
var
  viewport: TViewPort;
begin
  glRenderMode(GL_SELECT);
  glInitNames;
  glPushName(0); 
  glMatrixMode(GL_PROJECTION);
  glPushMatrix; 
  glLoadIdentity;; 
  glGetIntegerv(GL_VIEWPORT,@viewport); 
  py := viewport.height-py;
  gluPickMatrix(px,py,2.0,2.0,@viewport);
  with OpenGL1 do
    glFrustum(prxLeft,prxRight,prxBottom,prxTop,prxNear,prxFar);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  glSelectBuffer(64,@Buffer);
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Selection(x,y);
  FormPaint(nil);
  SelectionDone;
end;

procedure TForm1.SelectionDone;
const
  countElement=1;
  nearElement=1;
  farElement=1;
var
  place,
  nm,
  hit,
  hits: GLint;
  ahit: PHit;
  nameList: string;
begin
  glMatrixMode(GL_PROJECTION);
  glPopMatrix;
  hits := glRenderMode(GL_RENDER);
  place := 1;             
  with Form2,ListBox1,Items do
  begin
    Clear;
    Add(Format('Hits = %d',[hits]));
    for hit := 1 to hits do
    begin
      ahit := @Buffer[place];
      with ahit^ do
      begin
        place := place+countElement+nearElement+farElement+ncount;
        Add(Format('  hit#%d  count=%d  near=%d  far=%d', 
          [hit,ncount,dnear,dfar])); 
        nameList := '    names:';
        for nm := 1 to ncount do
          nameList := nameList+' '+IntToStr(names[nm]);
        Add(nameList);
      end; {with}
    end; {for}
  end; {with}
  Form2.Show;
end; 

end.
 