unit _OpenGL;

interface

uses
  Windows,
  Messages,
  _Geometry,
  OpenGl;

//function IntToStr(X:integer):string;                                                
procedure InitGL(var ghRC:HGLRC;var ghDC:HDC;var Hand:THandle;W,H:Integer);
procedure CloseGL(ghRC:HGLRC;ghDC:HDC;Hand:HWND);
procedure On_Resize(Width,Height:integer);
procedure Change_Resolution(x, y: word);
procedure Restore_Resolution;
function Point_To_Coord(Point:TPoint):TCoord;
function Coord_To_Point(Point:TCoord):TVector3f;
procedure Set_Ligth(X,Y,Z:Single);overload;
procedure Set_Ligth(Point:TPoint);overload;
procedure Set_Ligth(Point:TPlane);overload;

implementation

{$REGION '2d/3d'}
function Point_To_Coord(Point:TPoint):TCoord;
Var
X,Y,Z:GLdouble;
viewport:TVector4i;
projection,modelview:TMatrix4d;
begin
//  GLdouble vx,vy,vz;       // координаты курсора мыши в системе координат viewport-a.
//  GLdouble wx,wy,wz;       // возвращаемые мировые координаты.

 glGetIntegerv(GL_VIEWPORT,@viewport);           // узнаём параметры viewport-a.
 glGetDoublev(GL_PROJECTION_MATRIX,@projection); // узнаём матрицу проекции.
 glGetDoublev(GL_MODELVIEW_MATRIX,@modelview);   // узнаём видовую матрицу.
 gluProject(Point[0],Point[1],Point[2],modelview,projection,viewport,@X,@Y,@Z);
  Point_To_Coord[0]:=Round(X);
  Point_To_Coord[1]:=Round(Y);
end;

function Coord_To_Point(Point:TCoord):TVector3f;
Var
X,Y,Z:PGLdouble;
viewport:TVector4i;
projection,modelview:TMatrix4d;
begin
//  GLdouble vx,vy,vz;       // координаты курсора мыши в системе координат viewport-a.
//  GLdouble wx,wy,wz;       // возвращаемые мировые координаты.
 glGetIntegerv(GL_VIEWPORT,@viewport);           // узнаём параметры viewport-a.
 glGetDoublev(GL_PROJECTION_MATRIX,@projection); // узнаём матрицу проекции.
 glGetDoublev(GL_MODELVIEW_MATRIX,@modelview);   // узнаём видовую матрицу.
 gluUnProject(Point[0],Point[1],0,modelview,projection,viewport,Z,Y,X);
 Coord_To_Point[0]:=X^;
 Coord_To_Point[1]:=Y^;
 Coord_To_Point[2]:=Z^;
end;
{$ENDREGION}

{$REGION 'resolution'}
procedure Change_Resolution(x, y: word); {изменить разрешение}
var
  dm: TDEVMODE;
begin
  ZeroMemory(@dm, sizeof(TDEVMODE));
  dm.dmSize := sizeof(TDEVMODE);
  dm.dmPelsWidth := x;
  dm.dmPelsHeight := y;
  dm.dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  ChangeDisplaySettings(dm, 0);
end;

procedure Restore_Resolution;
begin
 ChangeDisplaySettings(devMode(nil^), 0);{возвращаем разрешение}
end;
{$ENDREGION}

{$REGION 'Resize'}
procedure On_Resize(Width,Height:integer); {перенастройка ЖЛ при изпменении разрешения}
begin
 glViewport(0,0,Width,Height);        
 glMatrixMode(GL_Projection);
 glLoadIdentity();
 gluPerspective(45.0, Width/Height, 0.05, 20.0);{параметры рабочего поля}
 glOrtho(-20,20,-20,20,1,50);
 gluLookAt(0,0,1, 0,0,0, 0,1,0);
 glMatrixMode(Gl_ModelView);
end;
{$ENDREGION}

{$REGION 'pixel_format'}
function SetupPixelFormat(DC:HDC;g:byte):boolean;
var
pfd:PIXELFORMATDESCRIPTOR;
ppfd:PPIXELFORMATDESCRIPTOR;
pixelformat:integer;
begin
ppfd := @pfd;
ppfd.nSize := sizeof(PIXELFORMATDESCRIPTOR);
ppfd.nVersion := 1;
ppfd.dwFlags :=  PFD_DRAW_TO_WINDOW xor
                           PFD_SUPPORT_OPENGL xor
                           PFD_DOUBLEBUFFER;
ppfd.dwLayerMask := PFD_MAIN_PLANE;
ppfd.iPixelType := PFD_TYPE_RGBA;
ppfd.cColorBits := g;
ppfd.cDepthBits := g;
ppfd.cAccumBits := 0;
ppfd.cStencilBits := 0;
pixelformat := ChoosePixelFormat(dc, ppfd);
if pixelformat=0 then
begin
MessageBox(0, 'ChoosePixelFormat failed', 'Error', MB_OK);
SetupPixelFormat:=FALSE;
exit;
end;
{$ENDREGION}

if SetPixelFormat(dc, pixelformat, ppfd)=false then
begin
MessageBox(0, 'SetPixelFormat failed', 'Error', MB_OK);
SetupPixelFormat:=FALSE;
exit;
end;
SetupPixelFormat:=TRUE;
end;

{$REGION 'init/close GL'}
procedure InitGL(var ghRC:HGLRC;var ghDC:HDC;var Hand:THandle;W,H:Integer);
Var
 p:TVector4f;
 d:TVector3f;
begin   {OpenGL}
 ghDC:=GetDC(HAND);       {отлов хэндла}
 If SetupPixelFormat(ghDC,32)=False then
  Exit;
 ghRC:=wglCreateContext(ghDC);
 wglMakeCurrent(ghDC,ghRC);            {set handle}
 glClearColor(0.0,0.0,0.0,0.0);        {back color}
 On_Resize(W,H);                       {first resolution}
 glEnable(GL_Color_Material);
 glEnable(GL_Depth_Test);              {Z test}
 glEnable(GL_Lighting);                {enable ligthning}
 glEnable(GL_LIGHT0);                  {enable ligth 0}
 //glenable(GL_Point_Smooth);
 p[0]:=3; p[1]:=3; p[2]:=3; p[3]:=0;
 d[0]:=0; d[1]:=0; d[2]:=0;
 glLightFV(Gl_LIGHT0,Gl_Position,@p);          {ligth pozition}
 glLightFV(GL_LIGHT0,GL_Spot_Direction,@d);
 p[0]:=-0.2; p[1]:=-0.2; p[2]:=-0.2; p[3]:=1;
 glLightFV(Gl_LIGHT0,GL_AMBIENT,@p);          {set ligth ambient}

 {Settings}
 glDepthFunc(GL_LEQUAL);		           // Тип Z теста
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   //Перспектива
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);{режим наложения}
end;

procedure CloseGL(ghRC:HGLRC;ghDC:HDC;Hand:HWND);
begin
 If ghRC<>0 then             {закрытие хэндлов, убийство опенЖЛа}
  begin
  wglMakeCurrent(ghDc,0);
  wglDeleteContext(ghRC);
 end;
 If ghDC<>0 then
  ReleaseDC(Hand,ghDC);
end;
{$ENDREGION}

{$REGION 'Ligth'}
procedure Set_Ligth(X,Y,Z:Single);overload;
Var
 p:TVector4f;
begin
 p[0]:=X; p[1]:=Y; p[2]:=Z; p[3]:=1;
 glLightFV(Gl_LIGHT0,Gl_Position,@p);

end;

procedure Set_Ligth(Point:TPoint);overload; 
Var
 p:TVector4f;
begin
 p[0]:=Point[0]; p[1]:=Point[1]; p[2]:=Point[2]; p[3]:=1;
 glLightFV(Gl_LIGHT0,Gl_Position,@p);
end;

procedure Set_Ligth(Point:TPlane);overload;
begin
 glLightFV(Gl_LIGHT0,Gl_Position,@Point);
end;
{$ENDREGION}
end.
