DelphiでのOpenGL開発入門

14131 ワード

unit Unit1;

interface

uses
  OpenGL,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    angle:single;
    procedure Draw; //Draws an OpenGL scene on request
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
function getNormal(p1,p2,p3:TGLArrayf3):TGLArrayf3;
var a,b:TGLArrayf3; 
begin 
//make two vectors 
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]; 
//calculate cross-product 
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; 

procedure setupPixelFormat(DC:HDC);
const 
pfd:TPIXELFORMATDESCRIPTOR = ( 
  nSize:sizeof(TPIXELFORMATDESCRIPTOR); // size 
  nVersion:1;                           // version 
  dwFlags:PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or 
    PFD_DOUBLEBUFFER;                   // support double-buffering 
  iPixelType:PFD_TYPE_RGBA;             // color type 
  cColorBits:24;                        // preferred color depth 
  cRedBits:0; cRedShift:0;              // color bits (ignored) 
  cGreenBits:0; cGreenShift:0; 
  cBlueBits:0; cBlueShift:0; 
  cAlphaBits:0; cAlphaShift:0;          // no alpha buffer 
  cAccumBits: 0; 
  cAccumRedBits: 0;                     // no accumulation buffer, 
  cAccumGreenBits: 0;                   // accum bits (ignored) 
  cAccumBlueBits: 0; 
  cAccumAlphaBits: 0; 
  cDepthBits:16;                        // depth buffer 
  cStencilBits:0;                       // no stencil buffer 
  cAuxBuffers:0;                        // no auxiliary buffers 
  iLayerType:PFD_MAIN_PLANE;            // main layer 
  bReserved: 0; 
  dwLayerMask: 0; 
  dwVisibleMask: 0; 
  dwDamageMask: 0;                      // no layer, visible, damage masks 
); 
var pixelFormat:integer; 
begin 
pixelFormat := ChoosePixelFormat(DC, @pfd); 
if (pixelFormat = 0) then 
exit; 
if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) then 
exit; 
end; 

procedure GLInit; 
const 
light0_position:TGLArrayf4=( -8.0, 8.0, -16.0, 0.0); 
ambient: TGLArrayf4=( 0.3, 0.3, 0.3, 0.3); 
begin 
// set viewing projection 
glMatrixMode(GL_PROJECTION); 
glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0); 
// position viewer */ 
glMatrixMode(GL_MODELVIEW); 
glEnable(GL_DEPTH_TEST); 

// set lights 
glEnable(GL_LIGHTING); 
glLightfv(GL_LIGHT0, GL_POSITION, @light0_position); 
glLightfv(GL_LIGHT0, GL_AMBIENT, @ambient); 
glEnable(GL_LIGHT0); 
end; 

procedure TForm1.Draw;
const D=1.5; 
H1=D/1.732; 
H2=D*1.732-H1; // D/H = tg(30) = 1/sqrt(3) 
HY=3.0; 
const //vertexes 
a1:TGLArrayf3=(-D, 0, -H1); 
a2:TGLArrayf3=(D, 0, -H1); 
a3:TGLArrayf3=(0, 0, H2); 
a4:TGLArrayf3=(0, HY, 0); 
var n1, n2, n3, n4: TGLArrayf3; //normals 
begin 
n1 := getNormal(a1,a3,a2); 
n2 := getNormal(a1,a2,a4); 
n3 := getNormal(a2,a3,a4); 
n4 := getNormal(a3,a1,a4); 
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); 
glEnable(GL_NORMALIZE); 
glShadeModel(GL_FLAT); 
glCullFace(GL_BACK); 
glLoadIdentity; 
glTranslatef(0.0, 0.0, -12.0); 
glBegin(GL_TRIANGLES);

glNormal3fv(@n1);

glVertex3fv(@a1); glVertex3fv(@a2); glVertex3fv(@a3);

glNormal3fv(@n2); 
glVertex3fv(@a1); glVertex3fv(@a2); glVertex3fv(@a4);
 
glNormal3fv(@n3);

glVertex3fv(@a2); glVertex3fv(@a3); glVertex3fv(@a4); 
glNormal3fv(@n4);

glVertex3fv(@a3); glVertex3fv(@a1); glVertex3fv(@a4);
glEnd; 
SwapBuffers(wglGetCurrentDC);
end; 

procedure TForm1.FormCreate(Sender: TObject);
var DC:HDC; 
RC:HGLRC; 
i:integer; 
begin 
DC:=GetDC(Handle); //Actually, you can use any windowed control here 
SetupPixelFormat(DC); 
RC:=wglCreateContext(DC); //makes OpenGL window out of DC 
wglMakeCurrent(DC, RC); //makes OpenGL window active 
GLInit; //initialize OpenGL 
end; 

procedure TForm1.FormPaint(Sender: TObject);
begin
  Draw;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin 
angle:=angle+1.0; 
Draw; 
end;
end.