title: OpenGL: scale then translate? and how?
body: <p>I've got some 2D geometry. I want to take some bounding rect around my geometry, and then render a smaller version of it somewhere else on the plane. Here's more or less the code I have to do scaling and translation:</p>
  
  <pre><code>// source and dest are arbitrary rectangles.
  float scaleX = dest.width / source.width;
  float scaleY = dest.height / source.height;
  float translateX = dest.x - source.x;
  float translateY = dest.y - source.y;
  
  glScalef(scaleX, scaleY, 0.0);
  glTranslatef(translateX, translateY, 0.0);
  // Draw geometry in question with its normal verts.
  </code></pre>
  
  <p>This works exactly as expected for a given dimension when the dest origin is 0. But if the origin for, say, x, is nonzero, the result is still scaled correctly but looks like (?) it's translated to something near zero on that axis anyways-- turns out it's not exactly the same as if dest.x were zero.</p>
  
  <p>Can someone point out something obvious I'm missing?</p>
  
  <p>Thanks!</p>
  
  <p><strong>FINAL UPDATE</strong> Per Bahbar's and Marcus's answers below, I did some more experimentation and solved this. Adam Bowen's comment was the tip off. I was missing two critical facts: </p>
  
  <ol>
  <li>I needed to be scaling around the center of the geometry I cared about.</li>
  <li>I needed to apply the transforms in the opposite order of the intuition (for me).</li>
  </ol>
  
  <p>The first is kind of obvious in retrospect. But for the latter, for other good programmers/bad mathematicians like me: Turns out my intuition was operating in what the <a href="https://rads.stackoverflow.com/amzn/click/com/0321552628" rel="noreferrer" rel="nofollow noreferrer">Red Book</a> calls a "Grand, Fixed Coordinate System", in which there is an absolute plane, and your geometry moves around on that plane using transforms. This is OK, but given the nature of the math behind stacking multiple transforms into one matrix, it's the opposite of how things really work (see answers below or Red Book for more). Basically, the transforms are "applied" in "reverse order" to how they appear in code. Here's the final working solution:</p>
  
  <pre><code>// source and dest are arbitrary rectangles.
  float scaleX = dest.width / source.width;
  float scaleY = dest.height / source.height;
  Point sourceCenter = centerPointOfRect(source);
  Point destCenter = centerPointOfRect(dest);
  
  glTranslatef(destCenter.x, destCenter.y, 0.0);
  glScalef(scaleX, scaleY, 0.0);
  glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
  // Draw geometry in question with its normal verts.
  </code></pre>