📄 openglapp.dpr
字号:
//------------------------------------------------------------------------
//
// Author : Jan Horn
// Email : jhorn@global.co.za
// Website : http://home.global.co.za/~jhorn
// Date : 7 October 2001
// Version : 1.0
// Description : Quake 3 Model Loader (MD3 Loader)
//
//------------------------------------------------------------------------
program OpenGLApp;
uses
Windows,
Messages,
OpenGL,
model,
Textures,
SysUtils;
const
WND_TITLE = 'Quake 3 MD3 Loader by Jan Horn';
FPS_TIMER = 1; // Timer to calculate FPS
FPS_INTERVAL = 1000; // Calculate FPS every 1000 ms
var
h_Wnd : HWND; // Global window handle
h_DC : HDC; // Global device context
h_RC : HGLRC; // OpenGL rendering context
keys : Array[0..255] of Boolean; // Holds keystrokes
FPSCount : Integer = 0; // Counter for FPS
ElapsedTime : Integer; // Elapsed time between frames
// User vaiables
YRot, XRot : glFloat; // Y Rotation
Depth : glFloat;
Xcoord, Ycoord, Zcoord : Integer;
MouseButton : Integer;
WireFrame : Boolean;
ShowFrames : Boolean;
fontBase : GLuint; // base to the font display lists
Player : Q3Player;
Weapon : TMD3Model;
{$R *.RES}
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32;
{------------------------------------------------------------------}
{ Function to convert int to string. (No sysutils = smaller EXE) }
{------------------------------------------------------------------}
function IntToStr(Num : Integer) : String; // using SysUtils increase file size by 100K
begin
Str(Num, result);
end;
{----------------------------------------------------------------}
{ Procedures used to create and write text }
{----------------------------------------------------------------}
procedure BuildFont;
var font : HFONT;
begin
fontBase := glGenLists(96); // Generate enough display lists to hold
font := CreateFont(-16, // height of font
0, // average character width
0, // angle of escapement
0, // base-line orientation angle
FW_BOLD, // font weight
0, // italic
0, // underline
0, // strikeout
ANSI_CHARSET, // character set
OUT_TT_PRECIS, // output precision
CLIP_DEFAULT_PRECIS, // clipping precision
ANTIALIASED_QUALITY, // output quality
FF_DONTCARE or DEFAULT_PITCH, // pitch and family
'Arial'); // font
SelectObject(h_DC, font); // Sets the new font as the current font in the device context
wglUseFontBitmaps(h_DC, 32, 96, fontBase); // Creates a set display lists containing the bitmap fonts
end;
procedure KillFont;
begin
glDeleteLists(fontBase, 96); // Delete the font display lists, returning used memory
end;
procedure glWrite(X, Y : GLUint; text : PChar);
var drawRect : TRect;
begin
glPushAttrib(GL_DEPTH_TEST); // Save the current Depth test settings (Used for blending )
glDisable(GL_DEPTH_TEST); // Turn off depth testing (otherwise we get no FPS)
glDisable(GL_TEXTURE_2D); // Turn off textures, don't want our text textured
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix
glPushMatrix(); // Save current projection matrix
glLoadIdentity();
GetWindowRect(GetDesktopWindow(), drawRect); // Get current window size
glOrtho(0, drawRect.right, 0, drawRect.bottom, -1, 1); // Change the projection matrix using an orthgraphic projection
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix
glPushMatrix(); // Save the current modelview matrix
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0); // Text color
glRasterPos2i(X, Y); // Position the Text
glPushAttrib(GL_LIST_BIT); // Save's the current base list
glListBase(fontBase - 32); // Set the base list to our character list
glCallLists(length(text), GL_UNSIGNED_BYTE, PChar(text)); // Display the text
glPopAttrib(); // Restore the old base list
glMatrixMode(GL_PROJECTION); // Switch to projection matrix
glPopMatrix(); // Restore the old projection matrix
glMatrixMode(GL_MODELVIEW); // Return to modelview matrix
glPopMatrix(); // Restore old modelview matrix
glEnable(GL_TEXTURE_2D); // Turn on textures, don't want our text textured
glPopAttrib(); // Restore depth testing
end;
{------------------------------------------------------------------}
{ Function used to write out the current upper and lower frames }
{------------------------------------------------------------------}
procedure DrawCurrentFrames;
begin
case Player.animLower of
BOTH_DEATH1 : glWrite(15, 700, 'Lower : Death 1');
BOTH_DEAD1 : glWrite(15, 700, 'Lower : Dead 1');
BOTH_DEATH2 : glWrite(15, 700, 'Lower : Death 2');
BOTH_DEAD2 : glWrite(15, 700, 'Lower : Dead 2');
BOTH_DEATH3 : glWrite(15, 700, 'Lower : Death 3');
BOTH_DEAD3 : glWrite(15, 700, 'Lower : Dead 3');
LEGS_WALKCR : glWrite(15, 700, 'Lower : Walk Crouch');
LEGS_WALK : glWrite(15, 700, 'Lower : Walk');
LEGS_RUN : glWrite(15, 700, 'Lower : Run');
LEGS_BACK : glWrite(15, 700, 'Lower : Backwarks');
LEGS_SWIM : glWrite(15, 700, 'Lower : Swim');
LEGS_JUMP : glWrite(15, 700, 'Lower : Jump');
LEGS_LAND : glWrite(15, 700, 'Lower : Land');
LEGS_JUMPB : glWrite(15, 700, 'Lower : Jump Backwards');
LEGS_LANDB : glWrite(15, 700, 'Lower : Land Backwards');
LEGS_IDLE : glWrite(15, 700, 'Lower : Idle');
LEGS_IDLECR : glWrite(15, 700, 'Lower : Idel Crouch');
LEGS_TURN : glWrite(15, 700, 'Lower : Turn');
end;
case Player.animUpper of
BOTH_DEATH1 : glWrite(800, 700, 'Upper : Death 1');
BOTH_DEAD1 : glWrite(800, 700, 'Upper : Dead 1');
BOTH_DEATH2 : glWrite(800, 700, 'Upper : Death 2');
BOTH_DEAD2 : glWrite(800, 700, 'Upper : Dead 2');
BOTH_DEATH3 : glWrite(800, 700, 'Upper : Death 3');
BOTH_DEAD3 : glWrite(800, 700, 'Upper : Dead 3');
TORSO_GESTURE : glWrite(800, 700, 'Upper : Gesture');
TORSO_ATTACK : glWrite(800, 700, 'Upper : Attack');
TORSO_ATTACK2 : glWrite(800, 700, 'Upper : Attack2');
TORSO_DROP : glWrite(800, 700, 'Upper : Drop');
TORSO_RAISE : glWrite(800, 700, 'Upper : Raise');
TORSO_STAND : glWrite(800, 700, 'Upper : Stand');
LEGS_LAND : glWrite(800, 700, 'Upper : Land');
TORSO_STAND2 : glWrite(800, 700, 'Upper : Stand2');
end;
end;
{------------------------------------------------------------------}
{ Function used to load a railgin and join it to the player }
{------------------------------------------------------------------}
procedure LoadRailgun;
procedure LoadMeshTexture(const imagename, meshname : String);
var I : Integer;
begin
// Find the right mesh item to assign the skin to
for I :=0 to Weapon.header.numMeshes-1 do
begin
// check it the two names are the same
if UpperCase(CharArrToStr(Weapon.meshes[i].MeshHeader.Name)) = Uppercase(meshname) then
begin
LoadTexture(ImageName, Weapon.meshes[i].Texture, FALSE);
Weapon.meshes[i].SetTexture :=TRUE;
end;
end;
end;
begin
Weapon.LoadModel('model\railgun\railgun.md3');
LoadMeshTexture('model\railgun\railgun1.jpg', 'w_railgun1');
LoadMeshTexture('model\railgun\railgun2.glow.jpg', 'w_railgun2');
LoadMeshTexture('model\railgun\railgun4.jpg', 'w_railgun4');
LoadMeshTexture('model\railgun\railgun3.glow.jpg', 'w_railgun3');
LoadMeshTexture('model\railgun\railgun1.jpg', 'w_railgun05');
Player.Upper.LinkModel('tag_weapon', Weapon);
end;
{------------------------------------------------------------------}
{ Function to draw the actual scene }
{------------------------------------------------------------------}
procedure glDraw();
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0, -10.0, Depth);
glRotatef(xRot, 1, 0, 0);
glRotatef(yRot, 0, 0, 1);
Player.Draw(ElapsedTime/1000);
if ShowFrames then
DrawCurrentFrames;
end;
{------------------------------------------------------------------}
{ Initialise OpenGL }
{------------------------------------------------------------------}
procedure glInit();
begin
glClearColor(0.0, 0.0, 0.0, 0.0); // Black Background
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glClearDepth(1.0); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enable Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Realy Nice perspective calculations
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
xRot :=-90;
yRot :=-85;
Depth :=-100;
ShowFrames :=TRUE;
BuildFont();
Player.LoadPlayer('model\sarge\', 'default');
LoadRailgun;
end;
{------------------------------------------------------------------}
{ Handle window resize }
{------------------------------------------------------------------}
procedure glResizeWnd(Width, Height : Integer);
begin
if (Height = 0) then // prevent divide by zero exception
Height := 1;
glViewport(0, 0, Width, Height); // Set the viewport for the OpenGL window
glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection
glLoadIdentity(); // Reset View
gluPerspective(45.0, Width/Height, 1.0, 500.0); // Do the perspective calculations. Last value = max clipping depth
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix
glLoadIdentity(); // Reset View
end;
{------------------------------------------------------------------}
{ Processes all the keystrokes }
{------------------------------------------------------------------}
procedure ProcessKeys;
begin
if keys[Ord('F')] then // Show the current upper and lower frames
begin
ShowFrames :=Not(ShowFrames);
keys[Ord('F')] :=FALSE;
end;
if keys[Ord('W')] then // Enable and Disable wireframe mode
begin
WireFrame :=Not(WireFrame);
if WireFrame then
begin
glDisable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
end
else
begin
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
end;
keys[Ord('W')] :=FALSE;
end;
if (keys[VK_SPACE]) then // Reset Position to default
begin
Player.animLower :=LEGS_WALK;
Player.animUpper :=TORSO_STAND;
Player.SetAnim(Player.animLower);
Player.SetAnim(Player.animUpper);
end;
if keys[Ord('Z')] then // Go to next leg movement
begin
Inc(Player.animLower);
if (Player.animLower > BOTH_DEAD3) AND (Player.animLower < LEGS_WALKCR) then
begin
Player.animLower := LEGS_WALKCR;
Player.animUpper := TORSO_STAND;
Player.SetAnim(Player.animUpper);
end;
if Player.animLower > LEGS_TURN then
Player.animLower :=BOTH_DEATH1;
Player.SetAnim(Player.animLower);
keys[Ord('Z')] :=FALSE;
end;
if keys[Ord('X')] then // go to previous leg movement
begin
Dec(Player.animLower);
if (Player.animLower > BOTH_DEAD3) AND (Player.animLower < LEGS_WALKCR) then
Player.animLower := BOTH_DEAD3;
if Player.animLower < BOTH_DEATH1 then
Player.animLower :=LEGS_TURN;
Player.SetAnim(Player.animLower);
keys[Ord('X')] :=FALSE;
end;
if keys[Ord('A')] then // go to next torso movement
begin
Inc(Player.animUpper);
if Player.animUpper > TORSO_STAND2 then
Player.animUpper :=TORSO_GESTURE;
Player.SetAnim(Player.animUpper);
keys[Ord('A')] :=FALSE;
end;
if keys[Ord('S')] then // go to previous torso movement
begin
Dec(Player.animUpper);
if Player.animUpper < TORSO_GESTURE then
Player.animUpper :=TORSO_STAND2;
Player.SetAnim(Player.animUpper);
keys[Ord('S')] :=FALSE;
end;
end;
{------------------------------------------------------------------}
{ Determines the application抯 response to the messages received }
{------------------------------------------------------------------}
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case (Msg) of
WM_CREATE:
begin
// Insert stuff you want executed when the program starts
end;
WM_CLOSE:
begin
PostQuitMessage(0);
Result := 0
end;
WM_KEYDOWN: // Set the pressed key (wparam) to equal true so we can check if its pressed
begin
keys[wParam] := True;
Result := 0;
end;
WM_KEYUP: // Set the released key (wparam) to equal false so we can check if its pressed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -