1{
2 ***************************************************************************
3 *                                                                         *
4 *   This source is free software; you can redistribute it and/or modify   *
5 *   it under the terms of the GNU General Public License as published by  *
6 *   the Free Software Foundation; either version 2 of the License, or     *
7 *   (at your option) any later version.                                   *
8 *                                                                         *
9 *   This code is distributed in the hope that it will be useful, but      *
10 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12 *   General Public License for more details.                              *
13 *                                                                         *
14 *   A copy of the GNU General Public License is available on the World    *
15 *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16 *   obtain it by writing to the Free Software Foundation,                 *
17 *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18 *                                                                         *
19 ***************************************************************************
20
21written 2001 by Satan
22
23}
24unit ExampleForm;
25
26{$mode objfpc}{$H+}
27
28interface
29
30uses
31  Classes, SysUtils, LazFileUtils, LazUTF8, LCLProc, Forms, LResources, Buttons,
32  StdCtrls, Dialogs, Graphics, IntfGraphics, GL, FPimage, OpenGLContext;
33
34const
35  GL_CLAMP_TO_EDGE = $812F;
36
37type
38  TglTexture = class
39  public
40    Width,Height: longint;
41    Data        : pointer;
42    destructor Destroy; override;
43  end;
44
45type
46
47  { TExampleForm }
48
49  TExampleForm = class(TForm)
50    OpenGLControl1: TOpenGLControl;
51    ExitButton1: TButton;
52    LightingButton1: TButton;
53    BlendButton1: TButton;
54    MoveCubeButton1: TButton;
55    MoveBackgroundButton1: TButton;
56    RotateZButton1: TButton;
57    RotateZButton2: TButton;
58    HintLabel1: TLabel;
59    procedure IdleFunc(Sender: TObject; var Done: Boolean);
60    procedure FormResize(Sender: TObject);
61    procedure ExitButton1Click(Sender: TObject);
62    procedure LightingButton1Click(Sender: TObject);
63    procedure BlendButton1Click(Sender: TObject);
64    procedure MoveCubeButton1Click(Sender: TObject);
65    procedure MoveBackgroundButton1Click(Sender: TObject);
66    procedure RotateZButton1Click(Sender: TObject);
67    procedure RotateZButton2Click(Sender: TObject);
68    procedure OpenGLControl1Paint(Sender: TObject);
69    procedure OpenGLControl1Resize(Sender: TObject);
70  public
71    constructor Create(TheOwner: TComponent); override;
72    destructor Destroy; override;
73    procedure LoadTextures;
74  private
75    AreaInitialized: boolean;
76    FrameCount: integer;
77    LastFrameTicks: integer;
78  end;
79
80  TParticle = class
81    x, y, z: GLfloat;
82    vx, vy, vz: GLfloat;
83    life: single;
84  end;
85
86  TParticleEngine = class
87    xspawn: GLfloat;
88    Particle: array [1..2001] of TParticle;
89    procedure MoveParticles;
90    procedure DrawParticles;
91    procedure Start;
92  public
93    constructor Create;
94    destructor Destroy; override;
95  private
96    procedure RespawnParticle(i: integer);
97  end;
98
99var AnExampleForm: TExampleForm;
100    front, left1: GLuint;
101    rx, ry, rz, rrx, rry, rrz: single;
102    LightAmbient : array [0..3] of GLfloat;
103    checked, blended, lighted, ParticleBlended, MoveCube, MoveBackground: boolean;
104    textures       : array [0..2] of GLuint;    // Storage For 3 Textures
105    MyglTextures   : array [0..2] of TglTexture;
106    lightamb, lightdif, lightpos, light2pos, light2dif,
107    light3pos, light3dif, light4pos, light4dif, fogcolor: array [0..3] of GLfloat;
108    ParticleEngine: TParticleEngine;
109    ParticleList, CubeList, BackList: GLuint;
110
111var direction: boolean;
112    timer: single;
113    LastMsecs: integer;
114
115function LoadFileToMemStream(const Filename: string): TMemoryStream;
116function LoadglTexImage2DFromPNG(PNGFilename:string;
117  Image: TglTexture): boolean;
118
119implementation
120
121
122function LoadFileToMemStream(const Filename: string): TMemoryStream;
123var FileStream: TFileStream;
124begin
125  Result:=TMemoryStream.Create;
126  try
127    FileStream:=TFileStream.Create(UTF8ToSys(Filename), fmOpenRead);
128    try
129      Result.CopyFrom(FileStream,FileStream.Size);
130      Result.Position:=0;
131    finally
132      FileStream.Free;
133    end;
134  except
135    Result.Free;
136    Result:=nil;
137  end;
138end;
139
140function LoadglTexImage2DFromPNG(PNGFilename: string; Image: TglTexture
141  ): boolean;
142var
143  png: TPortableNetworkGraphic;
144  IntfImg: TLazIntfImage;
145  y: Integer;
146  x: Integer;
147  c: TFPColor;
148  p: PByte;
149begin
150  Result:=false;
151  png:=TPortableNetworkGraphic.Create;
152  IntfImg:=nil;
153  try
154    png.LoadFromFile(PNGFilename);
155    IntfImg:=png.CreateIntfImage;
156    Image.Width:=IntfImg.Width;
157    Image.Height:=IntfImg.Height;
158    GetMem(Image.Data,Image.Width*Image.Height * 3);
159    p:=PByte(Image.Data);
160    for y:=0 to IntfImg.Height-1 do begin
161      for x:=0 to IntfImg.Width-1 do begin
162        c:=IntfImg.Colors[x,y];
163        p^:=c.red shr 8;
164        inc(p);
165        p^:=c.green shr 8;
166        inc(p);
167        p^:=c.blue shr 8;
168        inc(p);
169      end;
170    end;
171  finally
172    png.Free;
173    IntfImg.Free;
174  end;
175  Result:=true;
176end;
177
178{ TExampleForm }
179
180constructor TExampleForm.Create(TheOwner: TComponent);
181begin
182  inherited CreateNew(TheOwner);
183  if LazarusResources.Find(ClassName)=nil then begin
184    SetBounds((Screen.Width-800) div 2,(Screen.Height-600) div 2,800,600);
185    Caption:='LCL example for the TOpenGLControl';
186
187    Application.OnIdle:=@IdleFunc;
188    OnResize:=@FormResize;
189    blended:=false;
190    lighted:=false;
191    ParticleEngine:=TParticleEngine.Create;
192
193    ExitButton1:=TButton.Create(Self);
194    with ExitButton1 do begin
195      Name:='ExitButton1';
196      Parent:=Self;
197      SetBounds(320,10,80,25);
198      Caption:='Exit';
199      OnClick:=@ExitButton1Click;
200    end;
201
202    LightingButton1:=TButton.Create(Self);
203    with LightingButton1 do begin
204      Name:='LightingButton1';
205      Parent:=Self;
206      SetBounds(220,0,80,25);
207      Caption:='Lighting';
208      OnClick:=@LightingButton1Click;
209    end;
210
211    BlendButton1:=TButton.Create(Self);
212    with BlendButton1 do begin
213      Name:='BlendButton1';
214      Parent:=Self;
215      SetBounds(220,0,80,25);
216      Caption:='Blending';
217      OnClick:=@BlendButton1Click;
218    end;
219
220    MoveCubeButton1:=TButton.Create(Self);
221    with MoveCubeButton1 do begin
222      Name:='MoveCubeButton1';
223      Parent:=Self;
224      SetBounds(320,10,80,25);
225      Caption:='Move Cube';
226      Checked:=false;
227      OnClick:=@MoveCubeButton1Click;
228    end;
229
230    MoveBackgroundButton1:=TButton.Create(Self);
231    with MoveBackgroundButton1 do begin
232      Name:='MoveBackgroundButton1';
233      Parent:=Self;
234      SetBounds(320,10,80,25);
235      Caption:='Move Back';
236      Checked:=false;
237      OnClick:=@MoveBackgroundButton1Click;
238    end;
239
240    RotateZButton1:=TButton.Create(Self);
241    with RotateZButton1 do begin
242      Name:='RotateZButton1';
243      Parent:=Self;
244      SetBounds(320,10,80,25);
245      Caption:='P. Respawn';
246      Checked:=false;
247      OnClick:=@RotateZButton1Click;
248    end;
249
250    RotateZButton2:=TButton.Create(Self);
251    with RotateZButton2 do begin
252      Name:='RotateZButton2';
253      Parent:=Self;
254      SetBounds(320,10,80,25);
255      Caption:='P. Blending';
256      Checked:=false;
257      OnClick:=@RotateZButton2Click;
258    end;
259
260    HintLabel1:=TLabel.Create(Self);
261    with HintLabel1 do begin
262      Name:='HintLabel1';
263      Parent:=Self;
264      SetBounds(0,0,280,50);
265      Caption:='Demo';
266    end;
267
268    // resize the components first, because the opengl context needs some time to setup
269    FormResize(Self);
270
271    OpenGLControl1:=TOpenGLControl.Create(Self);
272    with OpenGLControl1 do begin
273      Name:='OpenGLControl1';
274      Parent:=Self;
275      SetBounds(10,90,380,200);
276      OnPaint:=@OpenGLControl1Paint;
277      OnResize:=@OpenGLControl1Resize;
278    end;
279
280  end;
281
282  LoadTextures;
283
284  // now resize
285  FormResize(Self);
286end;
287
288destructor TExampleForm.Destroy;
289var i: integer;
290begin
291  for i:=0 to 2 do begin
292    Textures[i]:=0;
293    FreeAndNil(MyglTextures[i]);
294  end;
295  FreeAndNil(ParticleEngine);
296
297  inherited Destroy;
298end;
299
300procedure TExampleForm.LoadTextures;
301
302  procedure LoadglTexture(Filename:string; Image:TglTexture);
303  begin
304    Filename:=ExpandFileNameUTF8(Filename);
305    if not LoadglTexImage2DFromPNG(Filename,Image) then begin
306      MessageDlg('File not found',
307        'Image file not found: '+Filename,
308        mtError,[mbOk],0);
309      raise Exception.Create('Image file not found: '+Filename);
310    end;
311  end;
312
313var
314  i: Integer;
315begin
316  for i:=0 to 2 do begin
317    Textures[i]:=0;
318    MyglTextures[i]:=TglTexture.Create;
319  end;
320  {loading the texture and setting its parameters}
321
322  LoadglTexture('data/particle.png',MyglTextures[0]);
323  LoadglTexture('data/texture2.png',MyglTextures[1]);
324  LoadglTexture('data/texture3.png',MyglTextures[2]);
325end;
326
327// --------------------------------------------------------------------------
328//                              Particle Engine
329// --------------------------------------------------------------------------
330
331constructor TParticleEngine.Create;
332var i: integer;
333begin
334  for i:=1 to 2001 do Particle[i]:=TParticle.Create;
335  xspawn:=0;
336end;
337
338destructor TParticleEngine.Destroy;
339var i: integer;
340begin
341  for i:=1 to 2001 do FreeAndNil(Particle[i]);
342  inherited Destroy;
343end;
344
345procedure TParticleEngine.DrawParticles;
346var i: integer;
347begin
348  for i:=1 to 2001 do begin
349    glPushMatrix;
350    glTranslatef(Particle[i].x, Particle[i].y, Particle[i].z);
351    glCallList(ParticleList);
352    glPopMatrix;
353  end;
354end;
355
356procedure TParticleEngine.RespawnParticle(i: integer);
357begin
358  if (xspawn>2) and (direction=true) then direction:=false;
359  if (xspawn<-2) and (direction=false) then direction:=true;
360  if direction then
361    xspawn:=xspawn+0.0002*(timer/10)
362  else
363    xspawn:=xspawn-0.0002*(timer/10);
364  Particle[i].x:=xspawn;
365  Particle[i].y:=-0.5;
366  Particle[i].z:=0;
367  Particle[i].vx:=-0.005+GLFloat(random(2000))/200000;
368  Particle[i].vy:=0.035+GLFloat(random(750))/100000;
369  Particle[i].vz:=-0.005+GLFloat(random(2000))/200000;
370  Particle[i].life:=GLFloat(random(1250))/1000+1;
371end;
372
373procedure TParticleEngine.MoveParticles;
374var i: integer;
375begin
376  for i:=1 to 2001 do begin
377    if Particle[i].life>0 then begin
378      Particle[i].life:=Particle[i].life-0.01*(timer/10);
379      Particle[i].x:=Particle[i].x+Particle[i].vx*(timer/10);
380
381      Particle[i].vy:=Particle[i].vy-0.00035*(timer/10); // gravity
382      Particle[i].y:=Particle[i].y+Particle[i].vy*(timer/10);
383
384      Particle[i].z:=Particle[i].z+Particle[i].vz*(timer/10);
385    end else begin
386      RespawnParticle(i);
387    end;
388  end;
389end;
390
391procedure TParticleEngine.Start;
392var i: integer;
393begin
394  for i:=1 to 2001 do begin
395    RespawnParticle(i);
396  end;
397end;
398
399// ---------------------------------------------------------------------------
400// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
401// ---------------------------------------------------------------------------
402
403procedure TExampleForm.IdleFunc(Sender: TObject; var Done: Boolean);
404begin
405  OpenGLControl1.Invalidate;
406  //OpenGLControl1Paint(Self);
407  Done:=false; // tell lcl to handle messages and return immediatly
408end;
409
410// --------------------------------------------------------------------------
411//                                 Buttons
412// --------------------------------------------------------------------------
413
414procedure TExampleForm.LightingButton1Click(Sender: TObject);
415begin
416  if lighted then glDisable(GL_LIGHTING) else glEnable(GL_LIGHTING);
417  lighted:=not lighted;
418  OpenGLControl1.Invalidate;// not need
419end;
420
421procedure TExampleForm.BlendButton1Click(Sender: TObject);
422begin
423  blended:=not blended;
424  OpenGLControl1.Invalidate;
425end;
426
427procedure TExampleForm.MoveCubeButton1Click(Sender: TObject);
428begin
429  MoveCube:=not MoveCube;
430  OpenGLControl1.Invalidate;
431end;
432
433procedure TExampleForm.MoveBackgroundButton1Click(Sender: TObject);
434begin
435  MoveBackground:=not MoveBackground;
436  OpenGLControl1.Invalidate;
437end;
438
439procedure TExampleForm.RotateZButton1Click(Sender: TObject);
440begin
441  ParticleEngine.Start;
442  OpenGLControl1.Invalidate;
443end;
444
445procedure TExampleForm.RotateZButton2Click(Sender: TObject);
446begin
447  ParticleBlended:=not ParticleBlended;
448  OpenGLControl1.Invalidate;
449end;
450
451// ---------------------------------------------------------------------------
452// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
453// ---------------------------------------------------------------------------
454
455procedure TExampleForm.FormResize(Sender: TObject);
456begin
457  if OpenGLControl1<>nil then
458    OpenGLControl1.SetBounds(10, 30, Width-120, Height-40);
459  ExitButton1.SetBounds(Width-90, 5, 80, 25);
460  LightingButton1.SetBounds(Width-90, 180, 80, 25);
461  BlendButton1.SetBounds(Width-90, 210, 80, 25);
462  MoveCubeButton1.SetBounds(Width-90, 50, 80, 25);
463  MoveBackgroundButton1.SetBounds(Width-90, 80, 80, 25);
464  RotateZButton1.SetBounds(Width-90, 115, 80, 25);
465  RotateZButton2.SetBounds(Width-90, 145, 80, 25);
466  HintLabel1.SetBounds(10, 0, 80, 25);
467end;
468
469procedure TExampleForm.ExitButton1Click(Sender: TObject);
470begin
471  Close;
472end;
473
474procedure TExampleForm.OpenGLControl1Paint(Sender: TObject);
475
476  procedure myInit;
477  begin
478    {init lighting variables}
479    {ambient color}
480    lightamb[0]:=0.5;
481    lightamb[1]:=0.5;
482    lightamb[2]:=0.5;
483    lightamb[3]:=1.0;
484    {diffuse color}
485    lightdif[0]:=0.8;
486    lightdif[1]:=0.0;
487    lightdif[2]:=0.0;
488    lightdif[3]:=1.0;
489    {diffuse position}
490    lightpos[0]:=0.0;
491    lightpos[1]:=0.0;
492    lightpos[2]:=3.0;
493    lightpos[3]:=1.0;
494    {diffuse 2 color}
495    light2dif[0]:=0.0;
496    light2dif[1]:=0.8;
497    light2dif[2]:=0.0;
498    light2dif[3]:=1.0;
499    {diffuse 2 position}
500    light2pos[0]:=3.0;
501    light2pos[1]:=0.0;
502    light2pos[2]:=3.0;
503    light2pos[3]:=1.0;
504    {diffuse 3 color}
505    light3dif[0]:=0.0;
506    light3dif[1]:=0.0;
507    light3dif[2]:=0.8;
508    light3dif[3]:=1.0;
509    {diffuse 3 position}
510    light3pos[0]:=-3.0;
511    light3pos[1]:=0.0;
512    light3pos[2]:=0.0;
513    light3pos[3]:=1.0;
514    {fog color}
515
516    fogcolor[0]:=0.5;
517    fogcolor[1]:=0.5;
518    fogcolor[2]:=0.5;
519    fogcolor[3]:=1.0;
520
521  end;
522
523const GLInitialized: boolean = false;
524
525procedure InitGL;
526var
527  i: Integer;
528begin
529  if GLInitialized then exit;
530  GLInitialized:=true;
531  {setting lighting conditions}
532  glLightfv(GL_LIGHT0,GL_AMBIENT,lightamb);
533  glLightfv(GL_LIGHT1,GL_AMBIENT,lightamb);
534  glLightfv(GL_LIGHT2,GL_DIFFUSE,lightdif);
535  glLightfv(GL_LIGHT2,GL_POSITION,lightpos);
536  glLightfv(GL_LIGHT3,GL_DIFFUSE,light2dif);
537  glLightfv(GL_LIGHT3,GL_POSITION,light2pos);
538  glLightfv(GL_LIGHT4,GL_POSITION,light3pos);
539  glLightfv(GL_LIGHT4,GL_DIFFUSE,light3dif);
540  glEnable(GL_LIGHT0);
541  glEnable(GL_LIGHT1);
542  glEnable(GL_LIGHT2);
543  glEnable(GL_LIGHT3);
544  glEnable(GL_LIGHT4);
545
546  glGenTextures(3, @textures[0]);
547  for i:=0 to 2 do begin
548    glBindTexture(GL_TEXTURE_2D, Textures[i]);
549    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
550    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
551    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
552    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
553    glTexImage2D(GL_TEXTURE_2D,0,3,MyglTextures[i].Width,MyglTextures[i].Height,0
554        ,GL_RGB,GL_UNSIGNED_BYTE,MyglTextures[i].Data);
555  end;
556  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
557  {instead of GL_MODULATE you can try GL_DECAL or GL_BLEND}
558  glEnable(GL_TEXTURE_2D);          // enables 2d textures
559  glClearColor(0.0,0.0,0.0,1.0);    // sets background color
560  glClearDepth(1.0);
561  glDepthFunc(GL_LEQUAL);           // the type of depth test to do
562  glEnable(GL_DEPTH_TEST);          // enables depth testing
563  glShadeModel(GL_SMOOTH);          // enables smooth color shading
564  {blending}
565  glColor4f(1.0,1.0,1.0,0.5);       // Full Brightness, 50% Alpha ( NEW )
566  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
567  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
568  {}
569  glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
570  glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
571  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
572
573  // creating display lists
574
575  ParticleList:=glGenLists(1);
576  glNewList(ParticleList, GL_COMPILE);
577    glBindTexture(GL_TEXTURE_2D, textures[0]);
578    glBegin(GL_TRIANGLE_STRIP);
579      glNormal3f( 0.0, 0.0, 1.0);
580      glTexCoord2f( 1.0, 1.0);     glVertex3f(+0.025, +0.025, 0);
581      glTexCoord2f( 0.0, 1.0);     glVertex3f(-0.025, +0.025, 0);
582      glTexCoord2f( 1.0, 0.0);     glVertex3f(+0.025, -0.025, 0);
583      glTexCoord2f( 0.0, 0.0);     glVertex3f(-0.025, -0.025, 0);
584    glEnd;
585  glEndList;
586
587  BackList:=ParticleList+1;
588  glNewList(BackList, GL_COMPILE);
589    glBindTexture(GL_TEXTURE_2D, textures[2]);
590    glBegin(GL_QUADS);
591      {Front Face}
592      glNormal3f( 0.0, 0.0, 1.0);
593      glTexCoord2f( 1.0, 1.0);     glVertex3f( 2.5, 2.5, 2.5);
594      glTexCoord2f( 0.0, 1.0);     glVertex3f(-2.5, 2.5, 2.5);
595      glTexCoord2f( 0.0, 0.0);     glVertex3f(-2.5,-2.5, 2.5);
596      glTexCoord2f( 1.0, 0.0);     glVertex3f( 2.5,-2.5, 2.5);
597      {Back Face}
598      glNormal3f( 0.0, 0.0,-1.0);
599      glTexCoord2f( 0.0, 1.0);     glVertex3f( 2.5, 2.5,-2.5);
600      glTexCoord2f( 0.0, 0.0);     glVertex3f( 2.5,-2.5,-2.5);
601      glTexCoord2f( 1.0, 0.0);     glVertex3f(-2.5,-2.5,-2.5);
602      glTexCoord2f( 1.0, 1.0);     glVertex3f(-2.5, 2.5,-2.5);
603      {Left Face}
604      glNormal3f(-1.0, 0.0, 0.0);
605      glTexCoord2f( 1.0, 1.0);     glVertex3f(-2.5, 2.5, 2.5);
606      glTexCoord2f( 0.0, 1.0);     glVertex3f(-2.5, 2.5,-2.5);
607      glTexCoord2f( 0.0, 0.0);     glVertex3f(-2.5,-2.5,-2.5);
608      glTexCoord2f( 1.0, 0.0);     glVertex3f(-2.5,-2.5, 2.5);
609      {Right Face}
610      glNormal3f( 1.0, 0.0, 0.0);
611      glTexCoord2f( 1.0, 1.0);     glVertex3f( 2.5, 2.5,-2.5);
612      glTexCoord2f( 0.0, 1.0);     glVertex3f( 2.5, 2.5, 2.5);
613      glTexCoord2f( 0.0, 0.0);     glVertex3f( 2.5,-2.5, 2.5);
614      glTexCoord2f( 1.0, 0.0);     glVertex3f( 2.5,-2.5,-2.5);
615      {Top Face}
616      glNormal3f( 0.0, 1.0, 0.0);
617      glTexCoord2f( 1.0, 1.0);     glVertex3f( 2.5, 2.5,-2.5);
618      glTexCoord2f( 0.0, 1.0);     glVertex3f(-2.5, 2.5,-2.5);
619      glTexCoord2f( 0.0, 0.0);     glVertex3f(-2.5, 2.5, 2.5);
620      glTexCoord2f( 1.0, 0.0);     glVertex3f( 2.5, 2.5, 2.5);
621      {Bottom Face}
622      glNormal3f( 0.0,-1.0, 0.0);
623      glTexCoord2f( 1.0, 1.0);     glVertex3f(-2.5,-2.5,-2.5);
624      glTexCoord2f( 0.0, 1.0);     glVertex3f( 2.5,-2.5,-2.5);
625      glTexCoord2f( 0.0, 0.0);     glVertex3f( 2.5,-2.5, 2.5);
626      glTexCoord2f( 1.0, 0.0);     glVertex3f(-2.5,-2.5, 2.5);
627
628    glEnd;
629  glEndList;
630
631  CubeList:=BackList+1;
632  glNewList(CubeList, GL_COMPILE);
633    glBindTexture(GL_TEXTURE_2D, textures[1]);
634    glBegin(GL_QUADS);
635      {Front Face}
636      glNormal3f( 0.0, 0.0, 1.0);
637      glTexCoord2f( 1.0, 1.0);     glVertex3f( 0.5, 0.5, 0.5);
638      glTexCoord2f( 0.0, 1.0);     glVertex3f(-0.5, 0.5, 0.5);
639      glTexCoord2f( 0.0, 0.0);     glVertex3f(-0.5,-0.5, 0.5);
640      glTexCoord2f( 1.0, 0.0);     glVertex3f( 0.5,-0.5, 0.5);
641      {Back Face}
642      glNormal3f( 0.0, 0.0,-1.0);
643      glTexCoord2f( 0.0, 1.0);     glVertex3f( 0.5, 0.5,-0.5);
644      glTexCoord2f( 0.0, 0.0);     glVertex3f( 0.5,-0.5,-0.5);
645      glTexCoord2f( 1.0, 0.0);     glVertex3f(-0.5,-0.5,-0.5);
646      glTexCoord2f( 1.0, 1.0);     glVertex3f(-0.5, 0.5,-0.5);
647    glEnd;
648    glBindTexture(GL_TEXTURE_2D, textures[1]);
649    glBegin(GL_QUADS);
650      {Left Face}
651      glNormal3f(-1.0, 0.0, 0.0);
652      glTexCoord2f( 1.0, 1.0);     glVertex3f(-0.5, 0.5, 0.5);
653      glTexCoord2f( 0.0, 1.0);     glVertex3f(-0.5, 0.5,-0.5);
654      glTexCoord2f( 0.0, 0.0);     glVertex3f(-0.5,-0.5,-0.5);
655      glTexCoord2f( 1.0, 0.0);     glVertex3f(-0.5,-0.5, 0.5);
656      {Right Face}
657      glNormal3f( 1.0, 0.0, 0.0);
658      glTexCoord2f( 1.0, 1.0);     glVertex3f( 0.5, 0.5,-0.5);
659      glTexCoord2f( 0.0, 1.0);     glVertex3f( 0.5, 0.5, 0.5);
660      glTexCoord2f( 0.0, 0.0);     glVertex3f( 0.5,-0.5, 0.5);
661      glTexCoord2f( 1.0, 0.0);     glVertex3f( 0.5,-0.5,-0.5);
662    glEnd;
663    glBindTexture(GL_TEXTURE_2D, textures[2]);
664    glBegin(GL_QUADS);
665      {Top Face}
666      glNormal3f( 0.0, 1.0, 0.0);
667      glTexCoord2f( 1.0, 1.0);     glVertex3f( 0.5, 0.5,-0.5);
668      glTexCoord2f( 0.0, 1.0);     glVertex3f(-0.5, 0.5,-0.5);
669      glTexCoord2f( 0.0, 0.0);     glVertex3f(-0.5, 0.5, 0.5);
670      glTexCoord2f( 1.0, 0.0);     glVertex3f( 0.5, 0.5, 0.5);
671      {Bottom Face}
672      glNormal3f( 0.0,-1.0, 0.0);
673      glTexCoord2f( 1.0, 1.0);     glVertex3f(-0.5,-0.5,-0.5);
674      glTexCoord2f( 0.0, 1.0);     glVertex3f( 0.5,-0.5,-0.5);
675      glTexCoord2f( 0.0, 0.0);     glVertex3f( 0.5,-0.5, 0.5);
676      glTexCoord2f( 1.0, 0.0);     glVertex3f(-0.5,-0.5, 0.5);
677    glEnd;
678  glEndList;
679
680end;
681
682var
683  CurTime: TDateTime;
684  MSecs: integer;
685begin
686  inc(FrameCount);
687  inc(LastFrameTicks,OpenGLControl1.FrameDiffTimeInMSecs);
688  if (LastFrameTicks>=1000) then begin
689    DebugLn(['TExampleForm.OpenGLControl1Paint Frames per second: ',FrameCount]);
690    dec(LastFrameTicks,1000);
691    FrameCount:=0;
692  end;
693
694  if OpenGLControl1.MakeCurrent then
695  begin
696    if not AreaInitialized then begin
697      myInit;
698      InitGL;
699      glMatrixMode (GL_PROJECTION);    { prepare for and then }
700      glLoadIdentity ();               { define the projection }
701      glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); { transformation }
702      glMatrixMode (GL_MODELVIEW);  { back to modelview matrix }
703      glViewport (0, 0, OpenGLControl1.Width, OpenGLControl1.Height);
704                                    { define the viewport }
705      AreaInitialized:=true;
706    end;
707
708    CurTime:=Now;
709    MSecs:=round(CurTime*86400*1000) mod 1000;
710    if MSecs<0 then MSecs:=1000+MSecs;
711    timer:=msecs-LastMsecs;
712    if timer<0 then timer:=1000+timer;
713    LastMsecs:=MSecs;
714
715    ParticleEngine.MoveParticles;
716
717    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
718    glLoadIdentity;             { clear the matrix }
719    glTranslatef (0.0, 0.0,-3.0);  // -2.5); { viewing transformation }
720    {rotate}
721
722    glPushMatrix;
723
724    if MoveBackground then begin
725      rrx:=rrx-0.6*(timer/10);
726      rry:=rry-0.5*(timer/10);
727      rrz:=rrz-0.3*(timer/10);
728    end;
729
730    glRotatef(rrx,1.0,0.0,0.0);
731    glRotatef(rry,0.0,1.0,0.0);
732    glRotatef(rrz,0.0,0.0,1.0);
733
734    // draw background
735    if blended then begin
736      glEnable(GL_BLEND);
737      glDisable(GL_DEPTH_TEST);
738    end;
739    glCallList(BackList);
740
741    glPopMatrix;
742
743    glPushMatrix;
744
745    if MoveCube then begin
746      rx:=rx+0.5*(timer/10);
747      ry:=ry+0.25*(timer/10);
748      rz:=rz+0.8*(timer/10);
749    end;
750
751    glRotatef(rx,1.0,0.0,0.0);
752    glRotatef(ry,0.0,1.0,0.0);
753    glRotatef(rz,0.0,0.0,1.0);
754
755    // draw cube
756    glCallList(CubeList);
757    if blended then begin
758      glDisable(GL_BLEND);
759      glEnable(GL_DEPTH_TEST);
760    end;
761
762    glPopMatrix;
763
764    if ParticleBlended then glEnable(GL_BLEND);
765    ParticleEngine.DrawParticles;
766    if ParticleBlended then glDisable(GL_BLEND);
767    //glFlush;
768    //glFinish;
769    // Swap backbuffer to front
770    OpenGLControl1.SwapBuffers;
771  end;
772end;
773
774procedure TExampleForm.OpenGLControl1Resize(Sender: TObject);
775begin
776  if (AreaInitialized)
777  and OpenGLControl1.MakeCurrent then
778    glViewport (0, 0, OpenGLControl1.Width, OpenGLControl1.Height);
779end;
780
781
782{ TglTexture }
783
784destructor TglTexture.Destroy;
785begin
786  if Data<>nil then FreeMem(Data);
787  inherited Destroy;
788end;
789
790end.
791