⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openglapp.dpr

📁 自己刚刚作的一个关于opengl的小离子
💻 DPR
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------
//
// OBJECT PICKING TUTORIAL
// Author: Ben Humphrey - http://www.gametutorials.com
// Delphi Converter: David "DavesLord" Caouette - http://blueberry.sourceforge.net
// OpenGL Template Author: Jan Horn - http://www.sulaco.co.za
//
//------------------------------------------------------------------------
program OpenGLApp;

uses
  Windows,
  Messages,
  OpenGL,
  Textures;

const
  WND_TITLE = 'OpenGL App by Jan Horn';
  FPS_TIMER = 1;                     // Timer to calculate FPS
  FPS_INTERVAL = 1000;               // Calculate FPS every 1000 ms

  SUN = 100;								// This is the object ID for the SUN	
  EARTH = 101;								// This is the object ID for the EARTH
  PLUTO	= 102;								// This is the object ID for PLUTO

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 : cardinal;             // Elapsed time between frames

  // Textures
  SunTex :  glUInt;
  EarthTex: glUInt;
  PlutoTex: glUInt;

  // User variables
  pObj: GLUQuadricObj;
  SunRotation   : single = 90;								// This holds our sun's current rotation
  EarthRotation : single = 90;								// This holds our earth's current rotation
  PlutoRotation : single = 90;								// This holds pluto's current rotation
  g_Fullscreen: boolean;

{$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;


{------------------------------------------------------------------}
{  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 matrix

  // We make our position a bit high and back to view the whole scene

  // 	  Position      View	   Up Vector
  gluLookAt(0, 3, 6,     0, 0, 0,     0, 1, 0);		// This determines where the camera's position and view is

  glInitNames();										// This clears the name stack so we always start with 0 names.

  // This next line is important.  If you don't push on at least ONE name,
  // The selection won't work.  Instead of glLoadName()/glEnd() you can use
  // glPushName(TheID) and glPopName();  Then you don't need to glPushName(0);

  glPushName(0);										// This starts off the first object in the stack

  pObj := gluNewQuadric();				// Get a new Quadric off the stack

  gluQuadricTexture(pObj, true);						// This turns on texture coordinates for our Quadrics

  // Bind the sun texture to the sun quadratic
  glBindTexture(GL_TEXTURE_2D, SunTex);			// Bind the Sun texture to the sun

  // Below we call glLoadName().  We need to pass in an ID that we can check later that will
  // be associated with the polygons drawn next.  Here is how it works.  We call glLoadName()
  // and pass an ID.  Then we draw any primitives or shapes, then we call glEnd() which
  // stops assigning polys to that object name.  We now have a group of polygons that are
  // given an ID.  Our ID SUN now refers to the sun Quadric we draw below.

  glLoadName(SUN);									// Push on our SUN label (IMPORTANT)

  // If we use glLoadName(), then we need to end it with glEnd().  There is a problem
  // though with some video cards that MUST have a glBegin()/glEnd() between
  // the calls to glLoadName()/glEnd().  This is strange but some cards grind
  // to a 2 FPS speed (VoodooCards).  Since we are using Quadrics there is
  // no glBegin()/glEnd() being called explicitly, so we need to fake it.  
  // *Remember, you only have to do this if you are using Quadrics.*  So, to fix 
  // this we just put a empty glBegin()/glEnd() statement between each object ID passed in.
  glBegin(GL_LINES);							
  glEnd();

  // Here we push on a new matrix so we don't affect any other quadrics.
  // We first translate the quadric to the origin (0, 0, 0), Then we rotate it
  // about the Y axis.  This gives it the spinning effect.  Then we draw the
  // largest of the spheres.  This represents the sun with its texture map.
	
  glPushMatrix();										// Push on a new matrix scope
    glTranslatef(0, 0, 0);							// Translate this sphere to the left
    glRotatef(SunRotation, 0, 1.0, 0);				// Rotate the sphere around the Y axis to make it spin
    gluSphere(pObj, 0.5, 20, 20);					// Draw the sunwith a radius of 0.5
  glPopMatrix();										// End the current scope of this matrix

  // Now that we drew the sun, we want to end our Object name.  We call glPopName()
  // to do that.  Now nothing else will be associated with the SUN ID.
  
  glEnd();											// Stop assigning polygons to the SUN label (IMPORTANT)

  // Next, we want to bind the Earth texture to our Earth sphere
  glBindTexture(GL_TEXTURE_2D, EarthTex);

  // Once again, we want to create a object ID for our earth, so we push on the EARTH ID.
  // Now, when we draw the next sphere, it will be associated with the EARTH ID.

  glLoadName(EARTH);									// Push on our EARTH label (IMPORTANT)

  // Pass in our empty glBegin()/glEnd() statement because we are using Quadrics.
  // If we don't do this when using glLoadName(), it will grind to a hault on some cards.
  glBegin(GL_LINES);
  glEnd();

  // Once again, we want to pop on a new matrix as not to affect any other spheres.
  // We rotate the sphere by its current rotation value FIRST before we translate it.
  // This makes it rotate around the origin, which is where the sun is.
  // Then we rotate it again about the Y-axis to make it spin around itself.

  glPushMatrix();										// Push on a new matrix scope		
	glRotatef(EarthRotation / 3, 0, 1.0, 0);		// Rotate the sphere around the origin (the sun)
	glTranslatef(-2, 0, 0);							// Translate this sphere to the left
	glRotatef(EarthRotation, 0, 1.0, 0);			// Rotate the sphere to make it spin
	gluSphere(pObj, 0.2, 20, 20);					// Draw the sphere with a radius of 0.2 so it's smaller than the sun
  glPopMatrix();										// End the current scope of this matrix

  // We are done assigning the EARTH object, so we need 
  // to stop assigning polygons to the current ID.

  glEnd();											// Stop assigning polygons to the EARTH label (IMPORTANT)

  // Bind the pluto texture to the last sphere
  glBindTexture(GL_TEXTURE_2D, PlutoTex);

  // Finally, we want to be able to click on Pluto, so we need a pluto ID.

  glLoadName(PLUTO);									// Push on our PLUTO label (IMPORTANT)

  // Like we did with the earth, we rotate Pluto around the sun first,
  // then we translate it farther away from the sun.  Next, we rotate Pluto
  // around the Y axis to give it some spin.

  // Pass in our empty glBegin()/glEnd() statement because we are using Quadrics.
  // If we don't do this when using glLoadName(), it will grind to a hault on some cards.
  glBegin(GL_LINES);
  glEnd();

  glPushMatrix();										// Push on a new matrix scope
  glRotatef(PlutoRotation / 2, 0, 1.0, 0);		// Rotate the sphere around the sun
  glTranslatef(3, 0, 0);							// Translate this sphere farther away from the sun than the earth
	glRotatef(PlutoRotation, 0, 1.0, 0);			// Rotate the sphere around itself to produce the spin
	gluSphere(pObj, 0.1, 20, 20);					// Draw the sphere with a radius of 0.1 (smallest planet)
  glPopMatrix();										// End the current scope of this matrix

	// We are finished with the PLUTO object ID, so we need to pop it off the name stack.
  glEnd();											// Stop assigning polygons to our PLUTO label (IMPORTANT)

  //SwapBuffers(h_DC);									// Swap the backbuffers to the foreground

  gluDeleteQuadric(pObj);								// Free the Quadric

  glPopName();										// We pushed a name on the stack, we must pop it back off 

  // Below we increase the rotations for each sphere.

  SunRotation   := SunRotation   + 0.2;								// Rotate the sun slowly
  EarthRotation := EarthRotation + 0.5;								// Increase the rotation for the each
  PlutoRotation := PlutoRotation + 0.6;								// Make pluto go the fastest
end;

function RetrieveObjectID(x, y: integer): integer;
var
   objectsFound: integer;
   viewportCoords: array [0..3] of integer;
   selectBuffer: array[0..31] of cardinal;
   lowestDepth: cardinal;
   selectedObject: cardinal;
   i: integer;
begin
   objectsFound := 0;								// This will hold the amount of objects clicked
   ZeroMemory(@viewportCoords, sizeof(viewportCoords));						// We need an array to hold our view port coordinates
   ZeroMemory(@selectBuffer, sizeof(selectBuffer));
	// This will hold the ID's of the objects we click on.
	// We make it an arbitrary number of 32 because openGL also stores other information
	// that we don't care about.  There is about 4 slots of info for every object ID taken up.
														
	// glSelectBuffer is what we register our selection buffer with.  The first parameter
	// is the size of our array.  The next parameter is the buffer to store the information found.
	// More information on the information that will be stored in selectBuffer is further below.

	glSelectBuffer(32, @selectBuffer);					// Setup our selection buffer to accept object ID's

	// This function returns information about many things in OpenGL.  We pass in GL_VIEWPORT
	// to get the view port coordinates.  It saves it like a RECT with {top, left, bottom, right}

	glGetIntegerv(GL_VIEWPORT, @viewportCoords);			// Get the current view port coordinates

	// Now we want to get out of our GL_MODELVIEW matrix and start effecting our
	// GL_PROJECTION matrix.  This allows us to check our X and Y coords against 3D space.

	glMatrixMode(GL_PROJECTION);						// We want to now effect our projection matrix
	
	glPushMatrix();										// We push on a new matrix so we don't effect our 3D projection

		// This makes it so it doesn't change the frame buffer if we render into it, instead, 
		// a record of the names of primitives that would have been drawn if the render mode was
		// GL_RENDER are now stored in the selection array (selectBuffer).

		glRenderMode(GL_SELECT);						// Allows us to render the objects, but not change the frame buffer

		glLoadIdentity();								// Reset our projection matrix

		// gluPickMatrix allows us to create a projection matrix that is around our
		// cursor.  This basically only allows rendering in the region that we specify.
		// If an object is rendered into that region, then it saves that objects ID for us (The magic).
		// The first 2 parameters are the X and Y position to start from, then the next 2
		// are the width and height of the region from the starting point.  The last parameter is
		// of course our view port coordinates.  You will notice we subtract "y" from the
		// BOTTOM view port coordinate.  We do this to flip the Y coordinates around.  The 0 y
		// coordinate starts from the bottom, which is opposite to window's coordinates.
		// We also give a 2 by 2 region to look for an object in.  This can be changed to preference.

		gluPickMatrix(x, viewportCoords[3]-y-Integer(not g_Fullscreen)*(GetSystemMetrics(SM_CYCAPTION)+ GetSystemMetrics(SM_CYSIZEFRAME) shl 1), 2, 2, @viewportCoords);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -