unit Un_3D;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, GLU, GL, MathComponent{, BMP};

type
  TGraph3D = class(TForm)
    MathControl1: TMathControl;
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
    DC:HDC;
    hrc:HGLRC;
    bitmap: TBitmap;
    bits: Array [0..63, 0..63, 0..3] of GLubyte;
    procedure PixelFormat;
    procedure DrawScene;
  public
    { Public declarations }
  end;

var
  Graph3D: TGraph3D;

implementation

uses Un_numbers, Un_main, Un_param, Un_graph2, Un_param3D;

{$R *.DFM}

const
  // массив свойств материала
  MaterialColor: Array [0..3] of GLfloat = (0.2, 0.0, 0.8, 1.0);

var angle,acc:glFloat;
    WaterTexture : glUint;

procedure TGraph3D.DrawScene;
 var x,y,xm,ym,z,dx,dy,U,F,xn,yn,zn,t,dt:real;
     i1,code,i,im,j1:integer;
     a:array[1..2,1..100] of real;
     b1,b2:array[1..1000] of real;
     s1,s2,s:string;
begin
 // очистка буфера цвета и буфера глубины
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 // трехмерность
 glLoadIdentity;
 gluLookAt(2.0, 3.0, 1.0, 1.0, 1.0, -2.0+acc, 0, 1, -0.3);
 glTranslatef(0.0, 0.0, -5.0);
 glRotatef(70.0, 1.0, 0.0, 0.0);
 glRotatef(angle, 0.0, 0.0, 1.0); // поворот на угол
 glRotatef(0.0, 0.0, 1.0, 0.0); // поворот на угол

 y:=-8;x:=-3.5;
 ym:=3;xm:=3.5;
 dy:=0.05;dx:=0.05;
 code:=0;s:=Main.FuncEd.Text;
 for i1:=1 to strtoint(Main.ParamEd.Text) do
  begin
   s1:=s;
   j1:=1;
   val(Numbers.Parameters.Cells[2,i1], a[1,i1], code);
   while j1<=length(s) do
    begin
     if s1[j1]='x' then
      begin
       str(a[1,i1]:0:0,s2);
       s1:=copy(s1,1,j1-1)+s2+copy(s1,j1+1,length(s1)-j1);
      end;
     inc(j1);
    end;
   MathControl1.MathExpression:=s1;
   a[2,i1]:=MathControl1.MathResult;
  end;
 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// glBindTexture(GL_TEXTURE_2D, WaterTexture);
 glColor3f (1, 1, 1);
 glBegin(GL_LINES);
  glVertex3f(3.8,3.3,0);
  glVertex3f(-3.8,3.3,0);
  glVertex3f(3.8,3.3,0);
  glVertex3f(3.8,-8.3,0);
  glVertex3f(3.8,3.3,0);
  glVertex3f(3.8,3.3,-3);
 glEnd;                        
 t:=0;dt:=strtoint(Param3D.Edit1.Text)/10;
 while x<=xm do
  begin
   glBegin(GL_TRIANGLE_STRIP{GL_POLYGON});
   i:=1;y:=-8;
   while y<=ym do     {x - время, у - х-овая коордиеата}
    begin
     z:=0;
     for i1:=1 to strtoint(Main.ParamEd.Text) do
      begin
       val(Numbers.Parameters.Cells[1,i1],U,code);
       val(Numbers.Parameters.Cells[3,i1],F,code);
       z:=z+(cos(a[1,i1]*t-a[2,i1]*(y+2)+F))*U/(10*(strtoint(Param3D.Edit2.Text)));
      end;
     b1[i]:=z;inc(i);y:=y+dy;
    end;
   im:=i;i:=1;y:=-8;
   while y<=ym do     {x - время, у - х-овая коордиеата}
    begin
     z:=0;
     for i1:=1 to strtoint(Main.ParamEd.Text) do
      begin
       val(Numbers.Parameters.Cells[1,i1],U,code);
       val(Numbers.Parameters.Cells[3,i1],F,code);
       z:=z+(cos(a[1,i1]*(t+dt)-a[2,i1]*(y+2)+F))*U/(10*(strtoint(Param3D.Edit2.Text)));
      end;
     b2[i]:=z;inc(i);y:=y+dy;
    end;
   y:=-8;i:=1;
   glVertex3f(x,-8,b1[1]);
   glVertex3f(x+dx,-8,b2[1]);
   i:=2;
   while y<ym-dy do
    begin
     xn:=(y-dy)*b1[i+1]-(y-dy)*b1[i-1]-(y-dy)*b1[i+1]-(y+dy)*b2[i-1]+(y+dy)*b1[i-1]+(y-dy)*b2[i-1];
     yn:=b2[i-1]*x-b2[i-1]*x-b1[i-1]*x-b1[i+1]*(x+dx)+b1[i+1]*x+b1[i-1]*(x+dx);
     zn:=(x+dx)*(y+dy)-(x+dx)*(y-dy)-x*(y+dy)-(y-dy)*x+(y-dy)*x+(y-dy)*x;
//     glNormal3f(xn, yn, zn);
     glVertex3f(x,y+dy,b1[i]);
     glVertex3f(x+dx,y+dy,b2[i]);
     y:=y+dy;inc(i);
    end;
   x:=x+dx;
   t:=t+dt;
   glEnd;
  end;
end;

procedure TGraph3D.FormPaint(Sender: TObject);
 var
 ps:TPaintStruct;

begin
 BeginPaint(Handle, ps);
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 glPushMatrix;
 DrawScene;
 glPopMatrix;
 swapBuffers(dc);
 EndPaint(Handle, ps);
end;

procedure TGraph3D.FormResize(Sender: TObject);
begin
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity;
 if width <= height then
  glOrtho (-2, 2, -2*height/width, 2*height/width, -10.0, 10.0)
 else
  glOrtho (-3.5*width/height, 5.5*width/height, -4, 4, -200.0, 200.0);
 // gluPerspective(30.0, Width / Height, 0.0, 10.0);
 glViewport(0, 0, Width, Height);
 glMatrixMode(GL_MODELVIEW);
 InvalidateRect(Handle, nil, False);
end;

procedure TGraph3D.FormDestroy(Sender: TObject);
begin
 wglMakeCurrent(0,0);
 wglDeleteContext(hrc);
 ReleaseDC(handle,DC);
end;

procedure TGraph3D.PixelFormat;
var
 nPixelFormat:Integer;
 pfd:TPixelFormatDescriptor;
begin
 FillChar(pfd,Sizeof(pfd),0);
 pfd.nSize:=sizeof(pfd);
 pfd.nVersion:=1;
 pfd.dwFlags:=PFD_DOUBLEBUFFER+PFD_SUPPORT_OPENGL+PFD_DRAW_TO_WINDOW;
 pfd.iPixelType:=PFD_TYPE_RGBA;
 pfd.cColorBits:=24;
 pfd.cAlphaBits:=64;
 pfd.cAccumBits:=64;
 pfd.cDepthBits:=32;
 pfd.cStencilBits:=64;
 pfd.iLayerType:=PFD_MAIN_PLANE;
 nPixelFormat:=ChoosePixelFormat(DC,@pfd);
 if nPixelFormat<>0 then
  SetPixelFormat(DC,nPixelFormat,@pfd);
end;

procedure TGraph3D.FormCreate(Sender: TObject);
 const LightModelAmbient : Array[0..3] of GLFloat = (0.75, 0.75, 2.70, 1.0);
       glfLightDiffuse : Array[0..3] of GLfloat = (1.0, 1.7, 6.7, 0.0);
       glfLightSpecular: Array[0..3] of GLfloat = (1.1, 2.1, 0.1, 0.0);
 var LightPos: Array [0..3] of GLFloat;
begin
 angle:=20;
 LightPos [0] := -2.0;
 LightPos [1] := -1.3;
 LightPos [2] := 2.0;
 LightPos [3] := 1.0;
 DC:=GetDC(Handle);
 PixelFormat;
 hrc:=wglCreateContext(DC);
 wglMakeCurrent(DC,hrc);
 glShadeModel(GL_SMOOTH);
 glEnable(GL_DEPTH_TEST); // разрешаем тест глубины
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   //Realy Nice perspective calculations
 glEnable(GL_LIGHTING);   // разрешаем работу с освещенностью
 glEnable(GL_LIGHT0);     // включаем источник света 0
 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LightModelAmbient);
 glLightfv(GL_LIGHT0, GL_DIFFUSE, @glfLightDiffuse);//Диффузные свойства источника света
// glLightfv(GL_LIGHT0, GL_SPECULAR,@glfLightSpecular);//Зеркальные свойства источника света
 glLightfv(GL_LIGHT0, GL_POSITION, @LightPos);
 glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, @MaterialColor);
 // glEnable(GL_TEXTURE_2D);               // Enable Texture Mapping
 // LoadTexture('reflection.bmp', WaterTexture);    // Load the Texture
 // enable spherical environment maping
 // glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
 // glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
end;

procedure TGraph3D.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 Case Key of
  VK_LEFT :   begin
               angle := angle + 1;
	             If angle >= 360 then angle := 0;
              end;
  VK_RIGHT:   begin
               angle := angle - 1;
	             If angle <= -360 then angle := 0;
              end;
 VK_UP :     begin
    	        acc := acc + 0.1;
	            If acc > 10 then acc := 10;
             end;
 VK_DOWN :   begin
    	        acc := acc-0.1;
              If acc < 0 then acc := 0;
             end;
 end; {case}
 InvalidateRect(Handle, nil, False);
end;

end.
