- unit OpenGLTemplateForm;
- interface
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- StdCtrls, ExtCtrls, ComCtrls, DglOpenGL;
- type
- TDGLForm = class(TForm)
- procedure FormKeyPress(Sender: TObject; var Key: Char);
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- TOpenGLRender = class(TThread)
- private
- DC:HDC;
- RC:HGLRC;
- angle: integer;
- fHandle: cardinal;
- fOptions: TRCOptions;
- fPixelDepth: byte;
- fDepthBuffer: byte;
- public
- destructor Destroy; override;
- procedure Init;
- procedure Draw;
- procedure Stop;
- procedure Execute; override;
- property Handle: cardinal read fHandle write fHandle;
- property Options: TRCOptions read fOptions write fOptions;
- property PixelDepth: byte read fPixelDepth write fPixelDepth;
- property DepthBuffer: byte read fDepthBuffer write fDepthBuffer;
- end;
- var
- DGLForm: TDGLForm;
- OpenGLRender: TOpenGLRender;
- implementation
- {$R *.DFM}
- type
- PGLarrayd3 = ^TGLArrayd3;
- TGLArrayd4 = array[0..3] of GLDouble;
- PGLArrayd4 = ^TGLArrayd4;
- TGLArrayd6 = array[0..5] of GLDouble;
- PGLArrayd6 = ^TGLArrayd6;
- TGLArrayvertex4 = array[0..3] of TGLArrayd6;
- PGLArrayvertex4 = ^TGLArrayvertex4;
- function getNormal(p1,p2,p3:TGLArrayf3):TGLArrayf3;
- var a,b:TGLArrayf3;
- begin
- a[0]:=p2[0]-p1[0]; a[1]:=p2[1]-p1[1]; a[2]:=p2[2]-p1[2];
- b[0]:=p3[0]-p1[0]; b[1]:=p3[1]-p1[1]; b[2]:=p3[2]-p1[2];
- result[0]:=a[1]*b[2]-a[2]*b[1];
- result[1]:=a[2]*b[0]-a[0]*b[2];
- result[2]:=a[0]*b[1]-a[1]*b[0];
- end;
- //TOpenGLRender
- destructor TOpenGLRender.Destroy;
- begin
- inherited;
- end;
- procedure TOpenGLRender.Execute;
- begin
- Init;
- while not terminated do
- begin
- Draw;
- sleep(1);
- end;
- Stop;
- end;
- procedure TOpenGLRender.Init;
- const
- light0_position:TGLArrayf4=( -8.0, 8.0, -16.0, 0.0);
- ambient: TGLArrayf4=( 0.3, 0.3, 0.3, 0.3);
- begin
- InitOpenGL;
- DC := GetDC(fHandle);
- // Create RenderContext (32 Bit PixelDepth, 24 Bit DepthBuffer, Doublebuffering)
- RC := CreateRenderingContext(DC, fOptions, fPixelDepth, fDepthBuffer, 0, 0, 0, 0);
- // Activate RenderContext
- ActivateRenderingContext(DC, RC);
- // set viewing projection
- glMatrixMode(GL_PROJECTION);
- glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);
- // position viewer
- glMatrixMode(GL_MODELVIEW);
- // Active DepthBuffer
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glShadeModel(GL_SMOOTH); // shading mathod: GL_SMOOTH or GL_FLAT
- // track material ambient and diffuse from surface color, call it before glEnable(GL_COLOR_MATERIAL)
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
- // Set lighting
- glEnable(GL_LIGHTING);
- glLightfv(GL_LIGHT0, GL_POSITION, @light0_position);
- glLightfv(GL_LIGHT0, GL_AMBIENT, @ambient);
- glEnable(GL_LIGHT0);
- // Set clear background color
- glClearColor(0,0,0,0);
- end;
- procedure tessBeginCB(which: GLenum); stdcall;
- begin
- glBegin(which);
- end;
- procedure tessEndCB(); stdcall;
- begin
- glEnd();
- end;
- procedure tessErrorCB(errorCode: GLenum); stdcall;
- var
- errorStr: string;
- begin
- errorStr := gluErrorString(errorCode);
- end;
- procedure tessVertexCB(data: PGLArrayd6); stdcall;
- begin
- glColor3d(data[3], data[4], data[5]);
- glVertex3d( data[0], data[1], data[2] );
- end;
- var
- vertices: array[0..64] of TGLArrayd6;
- vertexIndex: integer = 0;
- procedure tessCombineCB(newVertex : PGLArrayd6; neighborVertex : Pointer;
- neighborWeight : PGLArrayd4; var outData : Pointer); stdcall;
- type
- PGLArrayd3= ^TGLArrayd3;
- var
- vertice: PGLarrayd3;
- test: pointer;
- begin
- vertices[vertexIndex][0] := newVertex[0];
- vertices[vertexIndex][1] := newVertex[1];
- vertices[vertexIndex][2] := newVertex[2];
- vertices[vertexIndex][3] := neighborWeight[0] * PGLArrayvertex4(neighborVertex)[0][3] + // red
- neighborWeight[1] * PGLArrayvertex4(neighborVertex)[1][3] +
- neighborWeight[2] * PGLArrayvertex4(neighborVertex)[2][3] +
- neighborWeight[3] * PGLArrayvertex4(neighborVertex)[3][3];
- vertices[vertexIndex][4] := neighborWeight[0] * PGLArrayvertex4(neighborVertex)[0][4] + // green
- neighborWeight[1] * PGLArrayvertex4(neighborVertex)[1][4] +
- neighborWeight[2] * PGLArrayvertex4(neighborVertex)[2][4] +
- neighborWeight[3] * PGLArrayvertex4(neighborVertex)[3][4];
- vertices[vertexIndex][5] := neighborWeight[0] * PGLArrayvertex4(neighborVertex)[0][5] + // blue
- neighborWeight[1] * PGLArrayvertex4(neighborVertex)[1][5] +
- neighborWeight[2] * PGLArrayvertex4(neighborVertex)[2][5] +
- neighborWeight[3] * PGLArrayvertex4(neighborVertex)[3][5];
- // return output data (vertex coords and others)
- outData := @vertices[vertexindex];
- vertexIndex := vertexIndex + 1; // increase index for next vertex
- end;
- procedure TOpenGLRender.Draw;
- var
- test: TGLArrayd3;
- star: array[0..4] of TGLArrayd6;
- tess: pointer;
- begin
- vertexindex:=0;
- angle:=180;//angle+1;
- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
- glLoadIdentity;
- glTranslatef(0.0, 0.0, -12.0);
- glRotatef(angle, 0.0, 1.0, 0.0);
- star[0][0] := 0.0;
- star[0][1] := 3.0;
- star[0][2] := 0.0;
- star[0][3] := 1;
- star[0][4] := 0;
- star[0][5] := 0;
- star[1][0] := -1.0;
- star[1][1] := 0.0;
- star[1][2] := 0.0;
- star[1][3] := 0;
- star[1][4] := 1;
- star[1][5] := 0;
- star[2][0] := 1.6;
- star[2][1] := 1.9;
- star[2][2] := 0.0;
- star[2][3] := 1;
- star[2][4] := 0;
- star[2][5] := 1;
- star[3][0] := -1.6;
- star[3][1] := 1.9;
- star[3][2] := 0.0;
- star[3][3] := 1;
- star[3][4] := 1;
- star[3][5] := 0;
- star[4][0] := 1.0;
- star[4][1] := 0.0;
- star[4][2] := 0.0;
- star[4][3] := 0;
- star[4][4] := 0;
- star[4][5] := 1;
- tess := gluNewTess();
- gluTessCallback(tess, GLU_TESS_BEGIN, @tessBeginCB);
- gluTessCallback(tess, GLU_TESS_END, @tessEndCB);
- gluTessCallback(tess, GLU_TESS_ERROR, @tessErrorCB);
- gluTessCallback(tess, GLU_TESS_VERTEX, @tessVertexCB);
- gluTessCallback(tess, GLU_TESS_COMBINE, @tessCombineCB);
- gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
- gluTessBeginPolygon(tess, 0); // with NULL data
- gluTessBeginContour(tess);
- test[0] := star[0][0];
- test[1] := star[0][1];
- test[2] := star[0][2];
- gluTessVertex(tess, test, @star[0]);
- test[0] := star[1][0];
- test[1] := star[1][1];
- test[2] := star[1][2];
- gluTessVertex(tess, test, @star[1]);
- test[0] := star[2][0];
- test[1] := star[2][1];
- test[2] := star[2][2];
- gluTessVertex(tess, test, @star[2]);
- test[0] := star[3][0];
- test[1] := star[3][1];
- test[2] := star[3][2];
- gluTessVertex(tess, test, @star[3]);
- test[0] := star[4][0];
- test[1] := star[4][1];
- test[2] := star[4][2];
- gluTessVertex(tess, test, @star[4]);
- gluTessEndContour(tess);
- gluTessEndPolygon(tess);
- gluDeleteTess(tess); // delete after tessellation
- SwapBuffers(DC);
- end;
- procedure TOpenGLRender.Stop;
- begin
- DeactivateRenderingContext; // Deactivate RenderContext
- wglDeleteContext(RC); //Delete RenderContext
- ReleaseDC(Handle, DC);
- end;
- //TDGLForm
- procedure TDGLForm.FormCreate(Sender: TObject);
- begin
- DecimalSeparator:='.'; //always use . as decimal seperator
- OpenGLRender := TOpenGLRender.Create(true);
- OpenGLRender.Handle := Handle;
- OpenGLRender.Options := [opDoubleBuffered];
- OpenGLRender.PixelDepth := 32;
- OpenGLRender.DepthBuffer := 24;
- OpenGLRender.Resume;
- end;
- procedure TDGLForm.FormDestroy(Sender: TObject);
- begin
- OpenGLRender.Suspend;
- OpenGLRender.Free;
- end;
- procedure TDGLForm.FormKeyPress(Sender: TObject; var Key: Char);
- begin
- case Key of
- #27 : Close;
- end;
- end;
- end.