//-----------------------------------------------------------------------------
// pick() -- Perform for select/pick operation; returns the selected (picked)
//           graphic or zero(0) if nothing was selected.
//
// 1) When item == 0, returns nearest (by depth buffer) selected entry.
// 2) When item < 0, returns furthest (by depth buffer) selected entry.
// 3) When item > 0, returns the item'th selected entry or the first entry if
//    there are less than 'item' entries
// 4) Returns zero(0) when there are no entries in the select buffer or if the
//    Graphic for the select ID is not found.
//-----------------------------------------------------------------------------
BasicGL::Graphic* GlutDisplay::pick(const int item)
{
   GLint viewport[4];
   glGetIntegerv(GL_VIEWPORT,viewport);

   // make sure we are starting at 0, 0
   int xm = 0, ym = 0;

   getMouse(&xm,&ym);
   int x = xm;
   int y = viewport[3] - ym;

   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
   gluPickMatrix(x, y, getPickWidth(), getPickHeight(), viewport);

   // Get our ortho parameters
   GLdouble oLeft(0), oRight(0), oBottom(0), oTop(0), oNear(0), oFar(0);
   getOrtho(oLeft, oRight, oBottom, oTop, oNear, oFar);

   glOrtho(oLeft, oRight, oBottom, oTop, oNear, oFar);
   glMatrixMode(GL_MODELVIEW);

   if (getDisplayOrientation() != NORMAL) {
      glPushMatrix();
      if (getDisplayOrientation() == CW90)
         glRotated(-90.0, 0.0, 0.0, 1.0);
      else if (getDisplayOrientation() == CCW90)
         glRotated(90.0, 0.0, 0.0, 1.0);
      else
         glRotated(180.0, 0.0, 0.0, 1.0);
   }

   static const unsigned int MAX_BUFF_SIZE = 1024;
   GLuint sbuff[MAX_BUFF_SIZE];
   clearSelectBuffer(sbuff,MAX_BUFF_SIZE);
   glSelectBuffer(MAX_BUFF_SIZE, sbuff);
   glRenderMode(GL_SELECT);

   glInitNames();
   draw();

   GLint hits = glRenderMode(GL_RENDER);

   if (getDisplayOrientation() != NORMAL) glPopMatrix();

   Graphic* selected = findSelected(hits, sbuff, item);

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);

   return selected;
}
Esempio n. 2
0
bool GraphicsManager::unproject(float x, float y,
                                float &x1, float &y1, float &z1,
                                float &x2, float &y2, float &z2) const {

	try {
		// Generate the inverse of the model matrix

		Common::TransformationMatrix model;

		float cPos[3];
		float cOrient[3];

		memcpy(cPos   , CameraMan.getPosition   (), 3 * sizeof(float));
		memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));

		// Apply camera position
		model.translate(cPos[0], cPos[1], -cPos[2]);

		// Apply camera orientation
		model.rotate( cOrient[2], 0.0f, 0.0f, 1.0f);
		model.rotate(-cOrient[1], 0.0f, 1.0f, 0.0f);
		model.rotate( cOrient[0], 1.0f, 0.0f, 0.0f);


		// Multiply with the inverse of our projection matrix
		model *= _projectionInv;


		// Coordinates at the near and far clipping planes
		Common::Vector3 coordsNear, coordsFar;

		if (_projectType == kProjectTypePerspective) {
			/* With a perspective projection, the viewport runs from -1.0 to 0.0
			 * on the x and y axes, and the clipping planes are at 0.0 and 1.0. */

			const float view[4] = { 0.0f, 0.0f, (float) _width, (float) _height };
			const float zNear   = 0.0f;
			const float zFar    = 1.0f;

			coordsNear._x = ((2 * (x - view[0])) / (view[2])) - 1.0f;
			coordsNear._y = ((2 * (y - view[1])) / (view[3])) - 1.0f;
			coordsNear._z = (2 * zNear) - 1.0f;
			coordsNear._w = 1.0f;

			coordsFar._x = ((2 * (x - view[0])) / (view[2])) - 1.0f;
			coordsFar._y = ((2 * (y - view[1])) / (view[3])) - 1.0f;
			coordsFar._z = (2 * zFar) - 1.0f;
			coordsFar._w = 1.0f;

		} else if (_projectType == kProjectTypeOrthogonal) {
			/* With an orthogonal projection, the viewport runs from 0.0 to width
			 * on the x axis and from 0.0 to height on the y axis (which already
			 * matches the coordinates we were given), and the clipping planes are
			 * at -clipNear and -clipFar. */

			coordsNear._x = x;
			coordsNear._y = y;
			coordsNear._z = -_clipNear;
			coordsNear._w = 1.0f;

			coordsFar._x = x;
			coordsFar._y = y;
			coordsFar._z = -_clipFar;
			coordsFar._w = 1.0f;
		}

		// Unproject
		Common::Vector3 oNear(model * coordsNear);
		Common::Vector3 oFar (model * coordsFar );
		if ((oNear._w == 0.0f) || (oFar._w == 0.0f))
			return false; // TODO: check for close to 0.0f, not exactly 0.0f.


		// And return the values

		oNear._w = 1.0f / oNear._w;

		x1 = oNear._x * oNear._w;
		y1 = oNear._y * oNear._w;
		z1 = oNear._z * oNear._w;

		oFar._w = 1.0f / oFar._w;

		x2 = oFar._x * oFar._w;
		y2 = oFar._y * oFar._w;
		z2 = oFar._z * oFar._w;

	} catch (Common::Exception &e) {
		Common::printException(e, "WARNING: ");
		return false;
	} catch (...) {
		return false;
	}

	return true;
}
Esempio n. 3
0
bool GraphicsManager::unproject(float x, float y,
                                float &x1, float &y1, float &z1,
                                float &x2, float &y2, float &z2) const {

	try {
		// Generate the inverse of the model matrix

		Common::TransformationMatrix model;

		float cPos[3];
		float cOrient[3];

		CameraMan.lock();
		memcpy(cPos   , CameraMan.getPosition   (), 3 * sizeof(float));
		memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));
		CameraMan.unlock();

		// Apply camera position
		model.translate(cPos[0], cPos[1], -cPos[2]);

		// Apply camera orientation
		model.rotate( cOrient[2], 0.0, 0.0, 1.0);
		model.rotate(-cOrient[1], 0.0, 1.0, 0.0);
		model.rotate( cOrient[0], 1.0, 0.0, 0.0);


		// Multiply with the inverse of our projection matrix
		model *= _projectionInv;


		// Viewport coordinates

		float view[4];

		view[0] = 0.0;
		view[1] = 0.0;
		view[2] = _screen->w;
		view[3] = _screen->h;

		float zNear = 0.0;
		float zFar  = 1.0;


		// Generate a matrix for the coordinates at the near plane

		Common::Matrix coordsNear(4, 1);

		coordsNear(0, 0) = ((2 * (x - view[0])) / (view[2])) - 1.0;
		coordsNear(1, 0) = ((2 * (y - view[1])) / (view[3])) - 1.0;
		coordsNear(2, 0) = (2 * zNear) - 1.0;
		coordsNear(3, 0) = 1.0;



		// Generate a matrix for the coordinates at the far plane

		Common::Matrix coordsFar(4, 1);

		coordsFar(0, 0) = ((2 * (x - view[0])) / (view[2])) - 1.0;
		coordsFar(1, 0) = ((2 * (y - view[1])) / (view[3])) - 1.0;
		coordsFar(2, 0) = (2 * zFar) - 1.0;
		coordsFar(3, 0) = 1.0;


		// Unproject
		Common::Matrix oNear(model * coordsNear);
		Common::Matrix oFar (model * coordsFar );
		if ((oNear(3, 0) == 0.0) || (oNear(3, 0) == 0.0))
			return false;


		// And return the values

		oNear(3, 0) = 1.0 / oNear(3, 0);

		x1 = oNear(0, 0) * oNear(3, 0);
		y1 = oNear(1, 0) * oNear(3, 0);
		z1 = oNear(2, 0) * oNear(3, 0);

		oFar(3, 0) = 1.0 / oFar(3, 0);

		x2 = oFar(0, 0) * oFar(3, 0);
		y2 = oFar(1, 0) * oFar(3, 0);
		z2 = oFar(2, 0) * oFar(3, 0);

	} catch (Common::Exception &e) {
		Common::printException(e, "WARNING: ");
		return false;
	} catch (...) {
		return false;
	}

	return true;
}