unit Unit1;

interface
{$INCLUDE SGDXF.INC}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, OpenGL,
  sgGLOrbit3D, DXFImage, DXFConv, Menus, Buttons,
  sgConsts, ComCtrls, sgOpenGL, Math, ExtDlgs, sgDrawingNavigator;

type

  TsgGLOrbit3D = class(TsgOrbit3D)
  end;

  TsgGLControl = class(TsgCustomControl)
  end;

  TForm1 = class(TForm)
    pmMenu: TPopupMenu;
    pmiOpen: TMenuItem;
    pmiWireframe: TMenuItem;
    Panel1: TPanel;
    sbOpen: TSpeedButton;
    cbWireframe: TCheckBox;
    sbrStatusBar: TStatusBar;
    cbBlackBackground: TCheckBox;
    cbScale: TComboBox;
    sbGLOrbit3D: TSpeedButton;
    cbLighting: TCheckBox;
    cbNormalize: TCheckBox;
    OpenPictureDialog: TOpenPictureDialog;
    rbMat1: TRadioButton;
    rbMat2: TRadioButton;
    pmi3DOrbit: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure PanelMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure pmiOpenClick(Sender: TObject);
    procedure cbWireframeClick(Sender: TObject);
    procedure pmiWireframeClick(Sender: TObject);
    procedure cbBlackBackgroundClick(Sender: TObject);
    procedure sbGLOrbit3DClick(Sender: TObject);
    procedure cbScaleCloseUp(Sender: TObject);
    procedure PanelMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PanelMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure cbLightingClick(Sender: TObject);
    procedure cbNormalizeClick(Sender: TObject);
    procedure PanelMouseWheelDown(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure PanelMouseWheelUp(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    rc: HGLRC;    // Rendering Context
    dc: HDC;     // Device Context
    AppStart: DWord;  // Timing variables
    FOffs: TPoint;
    FPicture: TPicture;
    FPanelProc: TWndMethod;
    FOrbit: TsgGLOrbit3D;
    FPanel: TsgGLControl;
    procedure Idle(Sender: TObject; var Done: Boolean);
    procedure MaterialApply(Ambr: GLFloat; Ambg: GLFloat; Ambb: GLFloat;
              Difr: GLFloat; Difg: GLFloat; Difb: GLFloat;
              Specr: GLFloat; Specg: GLFloat; Specb: GLFloat; Shine: GLFloat);
    function GetImg: TsgDXFImage;
    procedure PanelProc(var Message: TMessage);
    procedure DoPanelFocus;
    procedure OrbitMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  public
    procedure glDraw;
    procedure glLoadEntities;
    property Img: TsgDXFImage read GetImg;
    property Panel: TsgGLControl read FPanel;
  end;

var
  Form1: TForm1;
  pos0: TArray4s = ((-800.0), (800.0), (-800.0), (0.0));
  _pos0: TArray4s;

  pos1: TArray4s = ((1), (-1), (-1), (0.0));
  _pos1: TArray4s;

  Amb0: TArray4s = ((0.5), (0.5), (0.5), (0.5));
  Diff0: TArray4s = ((0.5), (0.5), (0.5), (0.0));
  Spec0: TArray4s = ((0.1), (0.1), (0.1), (1.0));

  Diff1: TArray4s = ((0.3), (0.4), (0.8), (1.0));
  Spec1: TArray4s = ((0.5), (0.8), (0.3), (1.0));

  dir0: TArray4s = ((0.0), (0.0), (0.0), (0.0));
  _dir0: TArray4s;

  MatEmission: TArray4s = ((0.5), (0.5), (0.5), (1.0));

  MatAmbient: TArray4s = ((0.3), (0.3), (0.3), (1.0));
  MatDiffuse : Array [0..3] of GLfloat = (0.9, 0.9, 0.9, 1.0);
  MatSpecular: Array [0..3] of GLfloat = (0.8, 0.8, 0.8, 1.0);
  MatShine   : GLfloat = 50.0;

  Scale: TArray4s = (1.0, 1.0, 1.0, 0.0);
  DownPos, dPos: TPoint;
  qobj: GLUquadricObj;

  MaxVertex: GLFloat;

implementation

{$R *.DFM}

{------------------------------------------------------------------}
{  Function to load entities from dxf/dwg files                    }
{------------------------------------------------------------------}
procedure TForm1.glLoadEntities;
var
  I, J, K: Integer;
  pt, pt1, pt2, pt3: TFPoint;
  Red, Green, Blue: Double;
  dw, dh: Double;
  vEnt: TsgDXFEntity;

  function NormalVectorPlane(AMid, ALeft, ARight: TFPoint): TFPoint;
  const K = 1;
  var
    V1, V2: TFPoint;
    L: Double;
  begin
    V1.X := ALeft.X - AMid.X;
    V1.Y := ALeft.Y - AMid.Y;
    V1.Z := ALeft.Z - AMid.Z;
    V2.X := ARight.X - AMid.X;
    V2.Y := ARight.Y - AMid.Y;
    V2.Z := ARight.Z - AMid.Z;

    Result.X := (V1.Y * V2.Z - V1.Z * V2.Y) * K;
    Result.Y := (V1.Z * V2.X - V1.X * V2.Z) * K;
    Result.Z := (V1.X * V2.Y - V1.Y * V2.X) * K;

    L := Sqrt(Sqr(Result.X) + Sqr(Result.Y) + Sqr(Result.Z));
    Result.X := Result.X / L;
    Result.Y := Result.Y / L;
    Result.Z := Result.Z / L;
  end;

  procedure DrawQuadrangle(AEntity: TsgDXFEntity; p, p1, p2, p3: PFPoint; dz: Double);
  var
    mode: Cardinal;
    vColor: TColor;

    procedure ShiftPoint(pPt: PFPoint; dX, dY, dZ: Double);
    begin
      pPt^.X := pPt^.X + dX;
      pPt^.Y := pPt^.Y + dY;
      pPt^.Z := pPt^.Z + dZ;
    end;

    procedure PutVertex(PMid, PLeft, PRight: PFPoint);
    var
      n: TFPoint;
    begin
      CalcNormal(PMid, PLeft, PRight, @n);
      glNormal3d(n.X, n.Y, n.Z);
      glVertex3d(PMid^.X, PMid^.Y, PMid^.Z);
    end;

  begin
    vColor := EntColor(AEntity, nil);
    Blue := (vColor and $FF0000) shr 16;
    Green := (vColor and $FF00) shr 8;
    Red := vColor and $FF;

    Red := (Red+1)/256;
    Green := (Green+1)/256;
    Blue := (Blue+1)/256;

    dw := 0.0;
    dh := 0.0;
    dz := 0.0;

    ShiftPoint(p, -dw, dh, dz);
    ShiftPoint(p1, -dw, dh, dz);
    ShiftPoint(p2, -dw, dh, dz);
    ShiftPoint(p3, -dw, dh, dz);

    if pmiWireframe.Checked then
      mode := GL_LINE_LOOP
    else
      mode := GL_TRIANGLE_FAN;

    glBegin(mode);
      glColor3f(Red, Green, Blue);
      PutVertex(p, p2, p1);
      PutVertex(p1, p, p2);
      PutVertex(p2, p1, p);
      PutVertex(p3, p2, p);
    glEnd;
  end;

begin
  if Img <> nil then
  begin
    glDeleteLists(1, 1);

    glNewList(1, GL_COMPILE);
    for I := 0 to (Img.Converter.Counts[csEntities] - 1) do
    begin
      vEnt := Img.Converter.Sections[csEntities].Entities[I];
      if vEnt is TsgDXFSolid then
      begin
        pt := TsgDXFSolid(vEnt).Point;
        pt1 := TsgDXFSolid(vEnt).Point1;
        pt2 := TsgDXFSolid(vEnt).Point2;
        pt3 := TsgDXFSolid(vEnt).Point3;
        DrawQuadrangle(vEnt, @pt, @pt1, @pt2, @pt3, 0);
        pt := TsgDXFSolid(vEnt).Point;
        pt1 := TsgDXFSolid(vEnt).Point1;
        pt2 := TsgDXFSolid(vEnt).Point2;
        pt3 := TsgDXFSolid(vEnt).Point3;
        DrawQuadrangle(vEnt, @pt2, @pt1, @pt, @pt3, 0);
      end;
    end;
    glEndList;
  end;
end;

procedure TForm1.glDraw;
var
  dw, dh, coef: single;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
  glLoadIdentity;
  coef := 1.0;
  if Img <> nil then
    coef := (Panel.ClientWidth / Img.AbsWidth) / PixelsPerInch;
  dw := dPos.X * coef;
  dh := -dPos.Y * coef;
  glTranslatef(dw, dh, -10);
  glScaled(Scale[0] * coef, Scale[1] * coef, Scale[2] * coef);
  glLightfv(GL_LIGHT0, GL_POSITION, @pos0);
  //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, @pos0);

  glMultMatrixf(@glSwapMatrixes[bCurentMatrix][0, 0]);


  glFrontFace(GL_CW);
  glEnable(GL_CULL_FACE);
  //glPolygonMode(GL_FILL, GL_FRONT_AND_BACK);
  glPolygonMode(GL_FILL, GL_FRONT);
  //glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1);

  glMaterialfv(GL_FRONT, GL_AMBIENT, @MatAmbient);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, @MatDiffuse);
  glMaterialfv(GL_FRONT, GL_SPECULAR, @MatSpecular);
  //glColorMaterial(GL_FRONT, GL_DIFFUSE);
  MatShine := 0.8*128;
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MatShine);

  if (Img <> nil) and rbMat1.Checked then
    glCallList(1)
  else
    MaterialApply(0.7, 0.7, 0.7, 0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.01{0.078125});

  SwapBuffers(dc);
end;


{------------------------------------------------------------------}
{  Initialise OpenGL                                               }
{------------------------------------------------------------------}
procedure glInit;
begin
  glClearColor(0.5, 0.5, 0.5, 0.0); 	   // Black Background
  glShadeModel(GL_SMOOTH);                 // Enables Smooth Color Shading
  glClearDepth(2.0);                       // Depth Buffer Setup
  glEnable(GL_DEPTH_TEST);                 // Enable Depth Buffer
  glDepthFunc(GL_LESS);		           // The Type Of Depth Test To Do

  glEnable (GL_COLOR_MATERIAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   //Realy Nice perspective calculations
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_NORMALIZE);
  //glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 8);
end;


{------------------------------------------------------------------}
{  Create the form and initialist openGL                           }
{------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
var pfd : TPIXELFORMATDESCRIPTOR;
    pf  : Integer;
    Done: boolean;
begin
  FPicture := TPicture.Create;
  pmiWireframe.Checked := cbWireframe.Checked;
  cbScale.ItemIndex := 9;
  OpenPictureDialog.Filter := GraphicFilter(TGraphic);

  FPanel := TsgGLControl.Create(Self);
  FPanel.Parent := Self;
  FPanel.OnMouseWheelDown := PanelMouseWheelDown;
  FPanel.OnMouseWheelUp := PanelMouseWheelUp;
  FPanel.OnMouseMove := PanelMouseMove;
  FPanel.OnMouseDown := PanelMouseDown;
  FPanel.OnMouseUp := PanelMouseUp;
  FPanel.Align := alClient;
  // OpenGL initialisieren
  //InitOpenGL; // New call to initialize and bind the OpenGL dll
  IdentSwapMatrix;

  FOrbit := TsgGLOrbit3D.Create(Panel);
  FOrbit.Parent := Panel;
  FOrbit.Align := alClient;
  //Panel.DoubleBuffered := True;
  dc:=GetDC(Panel.Handle);
  FOrbit.Visible := True;
  FOrbit.Enabled := True;
  FOrbit.OpenGLDC := dc;
  FOrbit.OnMouseMove := OrbitMouseMove; 

  // PixelFormat
  pfd.nSize:=sizeof(pfd);
  pfd.nVersion:=1;
  pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;// or 0;
  pfd.iPixelType:=PFD_TYPE_RGBA;      // PFD_TYPE_RGBA or PFD_TYPEINDEX
  pfd.cColorBits:=128;

  pf := ChoosePixelFormat(dc, @pfd);   // Returns format that most closely matches above pixel format
  SetPixelFormat(dc, pf, @pfd);

  rc := wglCreateContext(dc);    // Rendering Context = window-glCreateContext
  wglMakeCurrent(dc,rc);        // Make the DC (Panel) the rendering Context

  //ReadExtensions;               // Read And Bind The Standard OpenGL Functions
  //ReadImplementationProperties; // Read And Bind All

  // Initialise GL environment variables
  glInit;
  FormResize(sender);    // sets up the perspective
  AppStart := GetTickCount;
  qobj := gluNewQuadric;

  // when the app has spare time, render the GL scene
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
  Idle(Sender, Done);
  Application.OnIdle := Idle;

  //glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 4);
  //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0);
  //glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);
  //glLightfv(GL_LIGHT0, GL_AMBIENT, @amb0[0]);
  //glLightfv(GL_LIGHT0, GL_DIFFUSE, @diff0[0]);
  //glLightfv(GL_LIGHT0, GL_SPECULAR, @spec0[0]);

  //glLightfv(GL_LIGHT0, GL_AMBIENT, @amb0[0]);
  //glLightfv(GL_LIGHT0, GL_DIFFUSE, @diff0[0]);
  //glLightfv(GL_LIGHT0, GL_SPECULAR, @spec0[0]);
  //glLightfv(GL_LIGHT0, GL_POSITION, @pos0);

  DownPos.X := 0;
  DownPos.Y := 0;
  dPos.X := 0;
  dPos.Y := 0;
  cbScaleCloseUp(Sender);
  cbBlackBackgroundClick(Sender);
  FPanelProc := Panel.WindowProc;
  Panel.WindowProc := PanelProc;
end;


{------------------------------------------------------------------}
{  Release rendering context when form gets detroyed               }
{------------------------------------------------------------------}
procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0,0);
  wglDeleteContext(rc);
  FPicture.Free;
  FOrbit.Free;
  ReleaseDC(Panel.Handle, dc);
end;


{------------------------------------------------------------------}
{  Application onIdle event                                        }
{------------------------------------------------------------------}
procedure TForm1.Idle(Sender: TObject; var Done: Boolean);
begin
  glDraw;
  //if FOrbit.Visible then FOrbit.Repaint;
end;


{------------------------------------------------------------------}
{  If the panel resizes, reset the GL scene                        }
{------------------------------------------------------------------}
procedure TForm1.FormResize(Sender: TObject);
begin
  //if not (ExtensionsRead and ImplementationRead) then // Only call the resize if the OpenGL dll was bound to the functions
    //exit;

  glViewport(0, 0, Panel.Width, Panel.Height);    // Set the viewport for the OpenGL window
  glMatrixMode(GL_PROJECTION);        // Change Matrix Mode to Projection
  glLoadIdentity;                   // Reset View
  gluPerspective(45.0, Panel.Width/Panel.Height, 1.0, 300.0);  // Do the perspective calculations. Last value = max clipping depth

  glMatrixMode(GL_MODELVIEW);         // Return to the modelview matrix
end;


{------------------------------------------------------------------}
{  Monitors all keypress events for the app                        }
{------------------------------------------------------------------}
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #27 then
    Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Done: boolean;
begin
  Idle(Sender, Done);
end;

procedure TForm1.pmiOpenClick(Sender: TObject);
var
  R: TFRect;
begin
  if OpenPictureDialog.Execute then
  begin
    FPicture.LoadFromFile(OpenPictureDialog.FileName);
    if Img <> nil then
    begin
      glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
      glLoadIdentity;
      IdentMatGL(@glSwapMatrixes[False]);
      IdentMatGL(@glSwapMatrixes[True]);
      Img.CurrentLayout := Img.Layouts[0];
      dPos.X := 0;
      dPos.Y := 0;
      FOffs.X := 0;
      FOffs.Y := 0;
      R := Img.Extents;
      MaxVertex := Max(Max(Max(Max(Max(R.Left, R.Top), R.Right), R.Bottom), R.Z1), R.Z2);

      pos0[0] := -MaxVertex*1000;
      pos0[1] := MaxVertex*1000;
      pos0[2] := MaxVertex*1000;
      cbScaleCloseUp(nil);
      glLightfv(GL_LIGHT0, GL_POSITION, @pos0);

      sbrStatusBar.Panels[0].Text := OpenPictureDialog.FileName;
      glLoadEntities;
      glDraw;
    end;
  end;
end;

procedure TForm1.cbWireframeClick(Sender: TObject);
begin
  pmiWireframe.Checked := cbWireframe.Checked;
  glLoadEntities;
end;

procedure TForm1.pmiWireframeClick(Sender: TObject);
begin
  pmiWireframe.Checked := not pmiWireframe.Checked; 
  cbWireframe.Checked := pmiWireframe.Checked;
end;

procedure TForm1.cbBlackBackgroundClick(Sender: TObject);
begin
  if cbBlackBackground.Checked then
    glClearColor(0.0, 0.0, 0.0, 0.0)   	   // Black Background
  else
    glClearColor(0.5, 0.5, 0.5, 1.0); 	   // White Background
end;

procedure TForm1.sbGLOrbit3DClick(Sender: TObject);
begin
  if FOrbit <> nil then
  begin
    if Sender is TMenuItem then
    begin
      pmi3DOrbit.Checked := not pmi3DOrbit.Checked;
      sbGLOrbit3D.Down := pmi3DOrbit.Checked;
    end
    else
      if Sender is TSpeedButton then
        pmi3DOrbit.Checked := sbGLOrbit3D.Down;
    FOrbit.Visible := sbGLOrbit3D.Down;
  end
end;

procedure TForm1.cbScaleCloseUp(Sender: TObject);
var
  S: string;
  ie: TIdleEvent;
begin
  ie := Application.OnIdle;
  Application.OnIdle := nil;
  S := copy(cbScale.Text, 1, length(cbScale.Text)-1);
  Scale[0] := strtofloat(S)/100.0;
  Scale[1] := strtofloat(S)/100.0;
  Scale[2] := strtofloat(S)/100.0;
  Application.OnIdle := ie;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
end;

procedure TForm1.OrbitMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  DoPanelFocus;
end;

procedure TForm1.PanelMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Assigned(FOrbit) and not FOrbit.Visible then
    if ssRight in Shift then
    begin
      dPos.X := FOffs.X + X - DownPos.X;
      dPos.Y := FOffs.Y + Y - DownPos.Y;
    end
    else
      DoPanelFocus
  else
    DoPanelFocus
end;

procedure TForm1.DoPanelFocus;
begin
  if Panel.Visible and Panel.Enabled and
     not Panel.Focused and Panel.CanFocus then
    Panel.SetFocus;
end;

procedure TForm1.PanelMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  DownPos := Point(X, Y);
  if Assigned(FOrbit) and not FOrbit.Visible and (Button = mbRight) then
  begin
    Panel.Cursor := crHandPoint;
    SetCapture(Panel.Handle);
  end;
end;

procedure TForm1.PanelMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  P: TPoint;
begin
  if (Button = mbRight) then
  begin
    if (DownPos.X = X) and (DownPos.Y = Y) then
    begin
      P := Panel.ClientToScreen(Point(X, Y));
      pmMenu.Popup(P.X, P.Y);
    end
    else
      if Assigned(FOrbit) and not FOrbit.Visible then
      begin
        Panel.Cursor := crDefault;
        FOffs.X := dPos.X;
        FOffs.Y := dPos.Y;
        ReleaseCapture;
      end;
  end;
end;

procedure TForm1.cbNormalizeClick(Sender: TObject);
begin
  if cbNormalize.Checked then
    glEnable(GL_NORMALIZE)
  else
    glDisable(GL_NORMALIZE);
end;

procedure TForm1.cbLightingClick(Sender: TObject);
begin
  if cbLighting.Checked then
    glEnable(GL_LIGHTING)
  else
    glDisable(GL_LIGHTING);
end;


procedure TForm1.MaterialApply(Ambr, Ambg, Ambb, Difr, Difg, Difb, Specr,
  Specg, Specb, Shine: GLFloat);
var
  Mat: array [0..3] of Single;
begin
  glPushMatrix;
  Mat[0] := Ambr;
  Mat[1] := Ambg;
  Mat[2] := Ambb;
  Mat[3] := 1.0;//0.3;
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, @mat);
  //glMaterialfv(GL_BACK, GL_AMBIENT, @mat);
  Mat[0] := Difr;
  Mat[1] := Difg;
  Mat[2] := Difb;
  Mat[3] := 1.0;//0.3;
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, @mat);
  //glMaterialfv(GL_BACK, GL_DIFFUSE, @mat);
  Mat[0] := Specr;
  Mat[1] := Specg;
  Mat[2] := Specb;
  Mat[3] := 1.0;//0.3;
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, @mat);
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, Shine * 128.0);
  //glMaterialfv(GL_BACK, GL_SPECULAR, @mat);
  //glMaterialf(GL_BACK, GL_SHININESS, Shine * 128.0);
  glCallList(1);
  glPopMatrix;
end;

procedure TForm1.PanelMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  ie: TIdleEvent;
begin
  if not cbScale.DroppedDown then
  begin
    ie := Application.OnIdle;
    Application.OnIdle := nil;
    Scale[0] := Scale[0]*0.8;
    Scale[1] := Scale[1]*0.8;
    Scale[2] := Scale[2]*0.8;
    Application.OnIdle := ie;
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
  end;
end;
       
procedure TForm1.PanelMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  ie: TIdleEvent;
begin
  if not cbScale.DroppedDown then
  begin
    ie := Application.OnIdle;
    Application.OnIdle := nil;
    Scale[0] := Scale[0]*1.2;
    Scale[1] := Scale[1]*1.2;
    Scale[2] := Scale[2]*1.2;
    Application.OnIdle := ie;
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
  end;
end;

function TForm1.GetImg: TsgDXFImage;
begin
  Result := nil;
  if FPicture.Graphic is TsgDXFImage then
    Result := TsgDXFImage(FPicture.Graphic);
end;

procedure TForm1.PanelProc(var Message: TMessage);
begin
  FPanelProc(Message);
  if Message.Msg = WM_PAINT then
    glDraw;
end;

end.
