unit Mouse1;

interface

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

type
  TForm1 = class(TForm)
    OpenGL1: TOpenGL;
    Transform1: TTransform;
    Light1: TLight;
    Transform2: TTransform;
    Material1: TMaterial;
    Material2: TMaterial;
    Transform3: TTransform;
    Material3: TMaterial;
    Material4: TMaterial;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Transform1Paint(Sender: TObject);
    procedure Transform2Paint(Sender: TObject);
    procedure Transform3Paint(Sender: TObject);
  private
    startX,
    startY: integer;
    startShift: TShiftState;
    selTrans: TTransform;
    trnX,
    trnY: GLfloat;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Shapes;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  CylinderBase;
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
  glSelectBuffer(128,@PickBuffer);
  startX := -1;
end;

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

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

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
const
  countElement=1;
  nearElement=1;
  farElement=1;
var
  selno,
  place: integer;
  hit,
  hits: GLint;
  ahit: PHit;
  mx,
  nearer,
  nearest: double;
begin
  startX := -1; 
  if Button<>mbLeft then
    exit;
  Selection(x,y);
  with OpenGL1 do
    glFrustum(prxLeft,prxRight,prxBottom,prxTop,prxNear,prxFar);
  FormPaint(nil);
  hits := SelectionDone;
  if (hits<1) or (Button<>mbLeft) then
    exit;
  startX := X;
  startY := Y;
  startShift := Shift;
  place := 1;
  nearest := 9e33;
  mx := maxint;
  for hit := 1 to hits do
  begin
    ahit := @PickBuffer[place];
    with ahit^ do
    begin
      nearer := dnear;
      if nearer<0 then
      begin
        nearer := mx+nearer; {how much did it roll over?}
        nearer := mx+nearer; {add amount rolled over to maxint}
      end;
      if nearer<nearest then
      begin
        nearest := nearer;
        selno := names[1];
      end;
      place := place+countElement+nearElement+farElement+ncount;
    end; {with}
  end; {for}
  case selno of
    2: selTrans := Transform2;
    3: selTrans := Transform3;
  end; {case}
  with selTrans do
  begin
    trnX := TranX;
    trnY := TranY;
  end; {with}
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  deltaX,
  deltaY: integer;
  ratio,
  changeX,
  changeY: GLfloat;
begin
  if startX<0 then
    exit;
  deltaX := X-startX;
  deltaY := startY-Y;
  with selTrans,OpenGL1 do
  begin
    ratio := -tranZ/prxNear;
    changeX := deltaX*(prxRight-prxLeft)/ClientWidth;
    changeY := deltaY*(prxTop-prxBottom)/ClientHeight;
    tranX := trnX+changeX*ratio;
    tranY := trnY+changeY*ratio;
  end;
  FormPaint(nil);
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  startX := -1;
end;

procedure TForm1.Transform1Paint(Sender: TObject);
begin
  Light1.Apply;
end;

procedure TForm1.Transform2Paint(Sender: TObject);
begin
  Material1.Apply;
  Material2.Apply;
  glLoadName(2);
  Cylinder;
end;

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

end.
