看看这段代码!相信你多少会明白了!
unit UrickGL;
interface
unit UrickGL;
interface
Uses Windows, Messages, SysUtils, Classes, GL, GLU, U3DPolys;
type
TsceneGL=class(Tobject)
DC:HDC;
HRC: HGLRC;
WindowHandle:Thandle;
Entities:Tlist;
Lights:Tlist;
Active:boolean;
Fperspective:boolean;
Angle,DistNear,DistFar:single;
texturing:boolean;
Constructor create;
Destructor destroy; override;
Procedure InitRC(iHandle:THandle);
Procedure Redraw;
Procedure SetDCPixelFormat;
Procedure ReleaseRC;
Procedure UpdateArea(width,height:integer);
Procedure SetPerspective(iAngle,iDistNear,iDistFar:single);
end;
Tlight=class(Tobject)
Source:Tvertex;
Fambient,
FdIffuse,
Fspecular:array[0..3] of GLfloat;
Number:LongInt;
Constructor Create(num:Byte);
Destructor Destroy; override;
Procedure Ambient(r,g,b,a:GLfloat);
Procedure DIffuse(r,g,b,a:GLfloat);
Procedure Specular(r,g,b,a:GLfloat);
Procedure Redraw;
end;
T3dMouse=class(Tobject)
Button1,
Button2:boolean;
Mode:integer;
Entity:Tentity;
Start:array[1..6] of single;
Scaling:array[1..6] of single;
BlockStatus:array[1..6] of boolean;
Constructor Create(iEntity:Tentity);
Procedure Move(x,y:single;Botones: TShIftState);
Procedure Scale(x,y,z,rx,ry,rz:single);
Procedure Block(num:integer;valor:boolean);
Procedure FindVertex(x,y:integer;Scene:TsceneGL;var pt:Tvertex);
end;
Const
MaxHits=200;
var
xxx,yyy,nnn:integer;
numFound:integer;
VertexHits:Array[1..MaxHits] of integer;
Function ConvertBMP(BMPname:string;RGBAname:string;Transparent:longint):integer;
Function MaskExceptions: Pointer;
Procedure UnmaskExceptions(OldMask: Pointer);
implementation
Constructor TsceneGL.create;
begin
inherited create;
Entities:=Tlist.create;
Lights:=Tlist.create;
Active:=false;
Fperspective:=true;
Angle:=30;
DistNear:=1;
DistFar:=100;
texturing:=true;
end;
Destructor TsceneGL.destroy;
begin
If Active then
ReleaseRC;
Lights.free;
Entities.free;
inherited destroy;
end;
Procedure TsceneGL.InitRC;
begin
WindowHandle:=iHandle;
DC := GetDC(WindowHandle);
SetDCPixelFormat;
HRC := wglCreateContext(DC);
wglMakeCurrent(DC, HRC);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
Active:=True;
end;
Procedure TsceneGL.SetDCPixelFormat;
var
nPixelFormat: Integer;
pfd: TPixelFormatDescriptor;
begin
FillChar(pfd, SizeOf(pfd),0);
with pfd do begin
nSize := sizeof(pfd);
nVersion := 1;
dwFlags := PFD_DRAW_TO_WINDOW or
PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER;
iPixelType:= PFD_TYPE_RGBA;
cColorBits:= 24;
cDepthBits:= 32;
iLayerType:= PFD_MAIN_PLANE; type
end;
nPixelFormat := ChoosePixelFormat(DC, @pfd);
SetPixelFormat(DC, nPixelFormat, @pfd);
DescribePixelFormat(DC, nPixelFormat, sizeof(TPixelFormatDescriptor), pfd);
end;
Procedure TsceneGL.ReleaseRC;
begin
wglMakeCurrent(0, 0);
wglDeleteContext(HRC);
ReleaseDC(WindowHandle, DC);
Active:=False;
end;
Procedure TsceneGL.UpdateArea;
var
gldAspect : GLdouble;
ratio,range:GlFloat;
begin
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
If Fperspective then
begin
gldAspect := width/height;
gluPerspective(Angle,
gldAspect,
DistNear,
DistFar);
end
else
begin { Orthogonal projection}
range:=6;
If width<=height then
begin
ratio:=height/width;
GlOrtho(-range,range,-range*ratio,range*ratio,-range*4,range*4);
end
else
begin
ratio:=width/height;
GlOrtho(-range*ratio,range*ratio,-range,range,-range*4,range*4);
end;
end;
glViewport(0, 0, width, height);
end;
Procedure TsceneGL.Redraw;
const
glfMaterialColor: Array[0..3] of GLfloat = (0.5, 1.0, 0.5, 1.0);
var
i,num:integer;
ps : TPaintStruct;
pp
ointer;
begin
If Active then
begin
{initialization}
pp:=MaskExceptions;
BeginPaint(WindowHandle, ps);
{place Lights}
i:=0;
num:=Lights.count;
while i<num do
begin
Tlight(Lights.items
).Redraw;
inc(i);
end;
{clear depht and color buffers}
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glenable(gl_color_material);
if texturing then
begin
gldisable(GL_texture_1d);
glenable(gl_texture_2d);
end
else
begin
glDisable(GL_texture_1d);
glDisable(gl_texture_2d);
end;
If PutNames then
begin
glInitNames;
glPushName(0);
end;
i:=0;
num:=Entities.count;
while i<num do
begin
Tentity(Entities.items).Redraw;
inc(i);
end;
SwapBuffers(DC);
EndPaint(WindowHandle, ps);
UnmaskExceptions(pp);
end;
end;
Procedure TsceneGL.SetPerspective;
begin
Angle:=iAngle;
DistNear:=iDistNear;
DistFar:=iDistFar;
end;
Constructor Tlight.Create;
begin
inherited create;
Source:=Tvertex.create(nil,0,0,0);
Source.Point:=Tpoint.Create(0,0,0);
Ambient(0.5,0.5,0.5,1);
DIffuse(0.25,0.25,0.25,1);
Specular(0.1,0.1,0.1,1);
case num of
1: Number:=GL_Light0;
2: Number:=GL_Light1;
3: Number:=GL_Light2;
4: Number:=GL_Light3;
5: Number:=GL_Light4;
6: Number:=GL_Light5;
7: Number:=GL_Light6;
8: Number:=GL_Light7;
end; {case}
end;
Destructor Tlight.destroy;
begin
Source.point.free;
Source.free;
end;
Procedure Tlight.Ambient;
begin
Fambient[0]:=r;
Fambient[1]:=g;
Fambient[2]:=b;
Fambient[3]:=a;
end;
Procedure Tlight.DIffuse;
begin
fDIffuse[0]:=r;
fDIffuse[1]:=g;
fDIffuse[2]:=b;
fDIffuse[3]:=a;
end;
Procedure Tlight.Specular;
begin
Fspecular[0]:=r;
Fspecular[1]:=g;
Fspecular[2]:=b;
Fspecular[3]:=a;
end;
Procedure Tlight.Redraw;
begin
glLightfv(Number, GL_AMBIENT, @Fambient);
glLightfv(Number, GL_DIfFUSE, @fDIffuse);
glLightfv(Number, GL_SPECULAR,@Fspecular);
glEnable(Number); {enable light number N}
end;
Constructor T3dMouse.Create;
var
i:integer;
begin
inherited create;
Entity:=iEntity;
Mode:=3;
Button1:=false;
Button2:=false;
for i:=1 to 6 do
BlockStatus:=false;
end;
Procedure T3dMouse.Move;
begin
If assigned(Entity) then
begin
If not Button1 then
begin
If ssLeft in botones then
begin
If mode=1 then {X,Y,Z}
begin
Start[1]:=x-Entity.Position[1]/Scaling[1];
Start[2]:=y-Entity.Position[2]/Scaling[2];
end;
If mode in [2,3] then
begin
Start[6]:=x-Entity.rotation[3]/Scaling[6];
Start[4]:=y-Entity.rotation[1]/Scaling[4];
end;
Button1:=true;
end;
end
else
begin
If ssLeft in botones then
begin
If mode=1 then
begin
If not BlockStatus[1] then
Entity.Position[1]:=(x-Start[1])* Scaling[1];
If not BlockStatus[2] then
Entity.Position[2]:=(y-Start[2])* Scaling[2];
end;
If mode in [2,3] then
begin
If not BlockStatus[4] then
Entity.rotation[3]:=(x-Start[6])* Scaling[6];
If not BlockStatus[5] then
Entity.rotation[1]:=(y-Start[4])* Scaling[4];
end;
end
else
Button1:=false;
end;
If not Button2 then
begin
If ssRight in botones then
begin
If mode in [1,3] then
Start[3]:=y-Entity.Position[3]/Scaling[3];
If mode in [2,3] then
Start[5]:=x-Entity.rotation[2]/Scaling[5];
Button2:=true;
end;
end
else
begin
If ssRight in botones then
begin
If mode in [1,3] then
If not BlockStatus[3] then
Entity.Position[3]:=(y-Start[3])* Scaling[3];
If mode in [2,3] then
If not BlockStatus[6] then
Entity.rotation[2]:=(x-Start[5])* Scaling[5];
end
else
Button2:=false;
end;
end;
end;
Procedure T3dMouse.Scale;
begin
Scaling[1]:=x;
Scaling[2]:=y;
Scaling[3]:=z;
Scaling[4]:=rx;
Scaling[5]:=ry;
Scaling[6]:=rz;
end;
Procedure T3dMouse.Block;
begin
If num in [1..6] then
BlockStatus[num]:=valor;
end;
Procedure T3dMouse.FindVertex;
const
tambuffer=8000;
radio=15;
var
buffer:array[0..tamBuffer] of GLfloat;
size,i,j,count:integer;
nx,ny:integer;
PreviousPutNames:boolean;
ActualVertex:LongInt;
begin
PreviousPutNames:=PutNames;
PutNames:=true;
numFound:=0;
GlFeedBackBuffer(tamBuffer,GL_2D,@buffer);
GlRenderMode(GL_feedBack);
Scene.Redraw;
size:=GlRenderMode(GL_render);
i:=0;
try
while i<size do
begin
If buffer=GL_Pass_Through_token then
If buffer[i+1]=Entity.id then
begin
inc(i,2);
while (buffer=GL_Pass_Through_token) do
begin
ActualVertex:=round(Buffer[i+1]);
If buffer[i+2]=GL_Polygon_Token then
begin
count:=trunc(buffer[i+3]);
inc(i,4);
for j:=0 to count-1 do
begin
nx:=round(buffer);
ny:=round(buffer[i+1]);
If (nx+radio>x) and (nx-radio<x)
and (ny+radio>y) and (ny-radio<y) and (NumFound<MaxHits) then
begin
inc(numFound);
VertexHits[numFound]:=ActualVertex+j;
end;
inc(i,2); {x and y}
end;
end
else
inc(i,2);
end;
end;
inc(i);
end;
except
end;
PutNames:=PreviousPutNames;
end;
Function MaskExceptions: Pointer;
var
OldMask : Pointer;
begin
asm
fnstcw WORD PTR OldMask;
mov eax, OldMask;
or eax, $3f;
mov WORD PTR OldMask+2,ax;
fldcw WORD PTR OldMask+2;
end;
result := OldMask;
end;
Procedure UnmaskExceptions(OldMask: Pointer);
begin
asm
fnclex;
fldcw WORD PTR OldMask;
end;
end;
end.