Ejemplo n.º 1
0
static void project(GLdouble objX,GLdouble objY,GLdouble objZ,
		GLdouble *winX, GLdouble *winY, GLdouble *winZ) {

#ifdef GTK2_OGL
	gluProject(objX,	//objX,
	 	objY, //objY,
	 	objZ, //objZ,
	 	modelMat3D, //model,
	 	projMat3D, //proj,
	 	viewport3D,    //view,
	 	winX,  	//winX,
	 	winY, 	//winY,
	 	winZ);  	//winZ);
#else
	GLfloat winXf,winYf,winZf;
	gluProjectf(objX,	//objX,
			   objY, //objY,
			   objZ, //objZ,
			   modelMat3D, //model,
			   projMat3D, //proj,
			   viewport3D,    //view,
			   &winXf,  	//winX,
			   &winYf, 	//winY,
			   &winZf);  	//winZ);
	*winX= winXf;
	*winY= winYf;
	*winZ= winZf;
#endif// GTK2_OGL
	/*
	 * Invert Y coordinate- because
	 *
http://lwjgl.org/forum/index.php?action=printpage;topic=3050.0
It's usually important to note that OpenGL's coordinate system has its origin in the bottom left corner (which is the mathematical standard). Some libraries like Slick (and I think Java's imaging classes) put the origin in the top left corner and invert the y coordinate. Not totally sure why, though. I always wondered what the rationale might be to invert the y axis. Maybe it's due to regional tradition. Anyway, gluOrtho2D(0, resolutionWidth, resolutionHeight, 0);  also sets up a top left origin. gluOrtho2D(0, resolutionWidth, 0, resolutionHeight) sets up a bottom left origin.
That's a source of confusion and takes some extra work to get code from one representation to the other. Just so you know, in case you wonder why objects or textures suddenly appear upside down.
   	 */
   	*winY= viewport3D[3]- (*winY);

}
Ejemplo n.º 2
0
void View::zoomToFit(int margin)
{
  if (margin < 0) margin = properties["margin"];

  // The bounding box of model
  GLfloat rect3d[8][3] = {{min[0], min[1], min[2]},
    {min[0], min[1], max[2]},
    {min[0], max[1], min[2]},
    {min[0], max[1], max[2]},
    {max[0], min[1], min[2]},
    {max[0], min[1], max[2]},
    {max[0], max[1], min[2]},
    {max[0], max[1], max[2]}
  };

  //3d rect vertices, object and window coords
  GLfloat modelView[16];
  GLfloat projection[16];
  int viewport[4];
  int count = 0;
  double error = 1, scale2d, adjust = ADJUST;
  glGetIntegerv(GL_VIEWPORT, viewport);
  glGetFloatv(GL_PROJECTION_MATRIX, projection);

  // Continue scaling adjustments until within tolerance
  while (count < 30 && fabs(error) > 0.005)
  {
    float min_x = 10000, min_y = 10000, max_x = -10000, max_y = -10000;
    GLfloat win3d[8][3];
    int i;

    // Set camera and get modelview matrix defined by viewpoint
    apply();
    glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
    for (i = 0; i < 8; i++)
    {
      gluProjectf(rect3d[i][0], rect3d[i][1], rect3d[i][2],
                  modelView, projection, viewport, &win3d[i][0]);
      //Save max/min x and y - define bounding 2d rectangle
      if (win3d[i][0] < min_x) min_x = win3d[i][0];
      if (win3d[i][0] > max_x) max_x = win3d[i][0];
      if (win3d[i][1] < min_y) min_y = win3d[i][1];
      if (win3d[i][1] > max_y) max_y = win3d[i][1];
      //printf("  %d) rect %f,%f,%f win %f,%f,%f\n", i, rect3d[i][0], rect3d[i][1], rect3d[i][2], win3d[i][0], win3d[i][1], win3d[i][2]);
    }

    // Calculate min bounding rectangle centered in viewport (with margins)
    {
      // Offset to viewport edges as gluProject returns window coords
      min_x -= (viewport[0] + margin);
      min_y -= (viewport[1] + margin);
      max_x -= (viewport[0] + margin);
      max_y -= (viewport[1] + margin);

      double width = viewport[2] - margin*2;
      double height = viewport[3] - margin*2;
      double centrex = width/2.0;
      double centrey = height/2.0;

      double dminx = fabs(min_x - centrex);
      double dmaxx = fabs(max_x - centrex);
      double new_max_x = centrex + (dminx > dmaxx ? dminx : dmaxx);
      double new_min_x = width - new_max_x;

      double dminy = fabs(min_y - centrey);
      double dmaxy = fabs(max_y - centrey);
      double new_max_y = centrey + (dminy > dmaxy ? dminy : dmaxy);
      double new_min_y = height - new_max_y;

      double xscale = 1.0, yscale = 1.0;
      float rwidth = (new_max_x - new_min_x);
      float rheight = (new_max_y - new_min_y);

      xscale = width / rwidth;
      yscale = height / rheight;
      if (xscale < yscale) scale2d = xscale;
      else scale2d = yscale;
    }

    // debug_print("BB new_min_x %f new_max_x %f === ", new_min_x, new_max_x);
    //   debug_print("Bounding rect: %f,%f - %f,%f === ",  min_x, min_y, max_x, max_y);
    //   debug_print(" Min rect: 0,0 - %f,%f\n", max_x - min_x, max_y - min_y);

    //Self-adjusting: did we overshoot aim? - compare last error to current 2d scale
    if (count > 0)
    {
      if ((error > 0 && scale2d < 1.0) ||
          (error < 0 && scale2d > 1.0))
      {
        adjust *= 0.75;
        if (adjust > ADJUST) adjust = ADJUST;
      }
      else
      {
        adjust *= 1.5;
        if (adjust < ADJUST) adjust = ADJUST;
      }
    }

    // Try to guess the best value adjustment using error margin
    //If error (devergence from 1.0) is > 0, scale down, < 0 scale up
    error = (scale2d - 1.0) / scale2d;

    //Adjust zoom translation by error * adjust (0.5 default)
    //float oldz = model_trans[2];
    model_trans[2] -= (model_trans[2] * error * adjust);
    //if (count > 4) {
    //   debug_print("[%d iterations] ... 2D Scaling factor %f ", count, scale2d);
    //   debug_print(" --> error: %f (adjust %f) zoom from %f to %f\n", error, adjust, oldz, model_trans[2]);
    //}
    count++;
  }
}