📄 openglapp.dpr
字号:
// Next, we just call our normal gluPerspective() function, exactly as we did on startup.
// This is to multiply the perspective matrix by the pick matrix we created up above.
gluPerspective(45.0, viewportCoords[2]/viewportCoords[3], 0.5, 150.0);
glMatrixMode(GL_MODELVIEW); // Go back into our model view matrix
glDraw(); // Now we render into our selective mode to pinpoint clicked objects
// If we return to our normal render mode from select mode, glRenderMode returns
// the number of objects that were found in our specified region (specified in gluPickMatrix())
objectsFound := glRenderMode(GL_RENDER); // Return to render mode and get the number of objects found
glMatrixMode(GL_PROJECTION); // Put our projection matrix back to normal.
glPopMatrix(); // Stop effecting our projection matrix
glMatrixMode(GL_MODELVIEW); // Go back to our normal model view matrix
// PHEW! That was some stuff confusing stuff. Now we are out of the clear and should have
// an ID of the object we clicked on. objectsFound should be at least 1 if we found an object.
if (objectsFound > 0) then
begin
// If we found more than one object, we need to check the depth values
// of all the objects found. The object with the LEAST depth value is
// the closest object that we clicked on. Depending on what you are doing,
// you might want ALL the objects that you clicked on (if some objects were
// behind the closest one), but for this tutorial we just care about the one
// in front. So, how do we get the depth value? Well, The selectionBuffer
// holds it. For every object there is 4 values. The first value is
// "the number of names in the name stack at the time of the event, followed
// by the minimum and maximum depth values of all vertices that hit since the
// previous event, then followed by the name stack contents, bottom name first." - MSDN
// The only ones we care about are the minimum depth value (the second value) and
// the object ID that was passed into glLoadName() (This is the fourth value).
// So, [0 - 3] is the first object's data, [4 - 7] is the second object's data, etc...
// Be carefull though, because if you are displaying 2D text in front, it will
// always find that as the lowest object. So make sure you disable text when
// rendering the screen for the object test. I use a flag for RenderScene().
// So, lets get the object with the lowest depth!
// Set the lowest depth to the first object to start it off.
// 1 is the first object's minimum Z value.
// We use an unsigned int so we don't get a warning with selectBuffer below.
lowestDepth := selectBuffer[1];
// Set the selected object to the first object to start it off.
// 3 is the first object's object ID we passed into glLoadName().
selectedObject := selectBuffer[3];
// Go through all of the objects found, but start at the second one
for i := 1 to objectsFound - 1 do
begin
// Check if the current objects depth is lower than the current lowest
// Notice we times i by 4 (4 values for each object) and add 1 for the depth.
if (selectBuffer[(i * 4) + 1] < lowestDepth) then
begin
// Set the current lowest depth
lowestDepth := selectBuffer[(i * 4) + 1];
// Set the current object ID
selectedObject := selectBuffer[(i * 4) + 3];
end
end;
// Return the selected object
result := selectedObject;
exit;
end;
// We didn't click on any objects so return 0
result := 0;
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
LoadTexture('Sun.bmp', SunTex, false); // Load "Sun.bmp" into openGL as a texture for the Sun
LoadTexture('Earth.bmp', EarthTex, false); // Load "Earth.bmp" into openGL as a texture for the Earth
LoadTexture('Pluto.bmp', PlutoTex, false); // Load "Pluto.bmp" into openGL as a texture for Pluto
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, 0.5, 150.0);
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix
glLoadIdentity(); // Reset View
end;
{------------------------------------------------------------------}
{ Processes all the keystrokes }
{------------------------------------------------------------------}
procedure ProcessKeys;
begin
end;
{------------------------------------------------------------------}
{ Determines the application抯 response to the messages received }
{------------------------------------------------------------------}
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
objectID: integer;
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
begin
keys[wParam] := False;
Result := 0;
end;
WM_SIZE: // Resize the window with the new width and height
begin
glResizeWnd(LOWORD(lParam),HIWORD(lParam));
Result := 0;
end;
WM_TIMER : // Add code here for all timers to be used.
begin
if wParam = FPS_TIMER then
begin
FPSCount :=Round(FPSCount * 1000/FPS_INTERVAL); // calculate to get per Second incase intercal is less or greater than 1 second
SetWindowText(h_Wnd, PChar(WND_TITLE + ' [' + intToStr(FPSCount) + ' FPS]'));
FPSCount := 0;
Result := 0;
end;
end;
WM_LBUTTONDOWN:
begin // If the left mouse button was clicked
// Here we pass in the cursors X and Y coordinates to test for an object under the mouse.
objectID := RetrieveObjectID(LOWORD(lParam), HIWORD(lParam));
// Now we just do a switch on our object ID's to see if we hit one.
case (objectID) of // Check the objectID passed back
SUN: MessageBox(0, 'The Sun!', 'Click', MB_OK);
EARTH: MessageBox(0, 'The Earth!', 'Click', MB_OK);
PLUTO: MessageBox(0, 'Pluto!', 'Click', MB_OK);
end;
end;
else
Result := DefWindowProc(hWnd, Msg, wParam, lParam); // Default result if nothing happens
end;
end;
{---------------------------------------------------------------------}
{ Properly destroys the window created at startup (no memory leaks) }
{---------------------------------------------------------------------}
procedure glKillWnd(Fullscreen : Boolean);
begin
if Fullscreen then // Change back to non fullscreen
begin
ChangeDisplaySettings(devmode(nil^), 0);
ShowCursor(True);
end;
// Makes current rendering context not current, and releases the device
// context that is used by the rendering context.
if (not wglMakeCurrent(h_DC, 0)) then
MessageBox(0, 'Release of DC and RC failed!', 'Error', MB_OK or MB_ICONERROR);
// Attempts to delete the rendering context
if (not wglDeleteContext(h_RC)) then
begin
MessageBox(0, 'Release of rendering context failed!', 'Error', MB_OK or MB_ICONERROR);
h_RC := 0;
end;
// Attemps to release the device context
if ((h_DC > 0) and (ReleaseDC(h_Wnd, h_DC) = 0)) then
begin
MessageBox(0, 'Release of device context failed!', 'Error', MB_OK or MB_ICONERROR);
h_DC := 0;
end;
// Attempts to destroy the window
if ((h_Wnd <> 0) and (not DestroyWindow(h_Wnd))) then
begin
MessageBox(0, 'Unable to destroy window!', 'Error', MB_OK or MB_ICONERROR);
h_Wnd := 0;
end;
// Attempts to unregister the window class
if (not UnRegisterClass('OpenGL', hInstance)) then
begin
MessageBox(0, 'Unable to unregister window class!', 'Error', MB_OK or MB_ICONERROR);
hInstance := 0;
end;
end;
{--------------------------------------------------------------------}
{ Creates the window and attaches a OpenGL rendering context to it }
{--------------------------------------------------------------------}
function glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer) : Boolean;
var
wndClass : TWndClass; // Window class
dwStyle : DWORD; // Window styles
dwExStyle : DWORD; // Extended window styles
dmScreenSettings : DEVMODE; // Screen settings (fullscreen, etc...)
PixelFormat : GLuint; // Settings for the OpenGL rendering
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -