title: Off-axis projection with glFrustum
body: <p>I am trying to do an off-axis projection of a scene with OpenGL and I gave a read to the document to <a href="http://csc.lsu.edu/~kooima/pdfs/gen-perspective.pdf" rel="noreferrer">Robert Kooima's off-axis projection</a> and have a much better idea now of what actually has to be done but there are still some pieces which I am finding tricky here. I got to know of the off-axis projection code for OpenGL to be somewhat as follows:</p>
  
  <p><strong>Code 1:</strong></p>
  
  <pre><code>glMatrixMode(GL_PROJECTION);  
      glLoadIdentity();            
      glFrustum(fNear*(-fFov * ratio + headX),  
                fNear*(fFov * ratio + headX),  
                fNear*(-fFov + headY),  
                fNear*(fFov + headY),  
                fNear, fFar);  
            
      glMatrixMode(GL_MODELVIEW);  
      glLoadIdentity();  
      gluLookAt(headX*headZ, headY*headZ, 0, headX*headZ, headY*headZ, -1, 0, 1, 0);
      glTranslatef(0.0,0.0,headZ);
  </code></pre>
  
  <p>Had this been a normal perspective projection with the user at the center of the screen, it is fairly easy to understand as I comprehend.</p>
  
  <pre><code>               Screen  
                     |
                     |  h = H/2
                     |  
  x----- n -----------
                     |
                     |  h = H/2
                     |
  </code></pre>
  
  <p>With the user at x and distance from screen being n, the top, bottom coordinates for <em>glFrustum</em> would be calculated as: (assume theta is the <em>Field of View (fov)</em> which I suppose is assumed as <em>30 degrees</em>)</p>
  
  <pre><code>h = n * tan (theta/2);
  tanValue = DEG_TO_RAD * theta/2;
  [EDIT Line additon here&gt;&gt;]: fFov = tan(tanValue);
  h = n * tan (tanValue);
  </code></pre>
  
  <p>Hence, top and bottom (negating top's value) are both obtained for <em>glFrustum</em> arguments. Left one's are left/right for now. </p>
  
  <pre><code>Now, Aspect Ratio, r = ofGetWidth()/ofGetHeight();
  Right = n * (fFov * r); , where r is the aspect ratio [Edit1&gt;&gt; Was written tanValue*r earlier here]
  </code></pre>
  
  <p><strong>Question</strong> 1) Is the above (tanValue*r) getting the <strong>horizontal fov angle</strong> and then applying the same to get left/right value?</p>
  
  <p>   <em>double msX = (double)ofGetMouseX();<br/>
      double msY = (double)ofGetMouseY();<br/>
      double scrWidth = (double)ofGetWidth();<br/>
      double scrHeight = (double)ofGetHeight();<br/><br/>
      headX = (msX / scrWidth) - 0.5;<br/>
      headY = ((scrHeight - msY) / scrHeight) - 0.5;<br/>
      headZ = -2.0;<br/></em></p>
  
  <p>Now, consider the projection off-axis and we have the <em>headX</em> and <em>headY</em> position computed (using mouse here instead of actual user's head):</p>
  
  <p><strong>Question</strong> 2) How is the headX and y being computed and what is the use subtracting -0.5 from the above? I observed that it brings the x-value to (-0.5 to 0.5) and y-value to (0.5 to -0.5) with msX and msY varying.</p>
  
  <p><strong>Question</strong> 3) In the above code (Code 1), how is headY being added to the calculated to the tan(fov/2) value? </p>
  
  <pre><code>-fFov + headY
  fFov + headY
  </code></pre>
  
  <p>What does this value provide us with? -fFov was the calculated tan of theta/2 but how can headY be added to directly?</p>
  
  <pre><code>-fFov * ratio + headX
  -fFov * ratio + headX
  </code></pre>
  
  <p>How does the abvoe give us a vlaue which wehn multiplied by n (near value) gives us left and right for the assymetric glFrustum call for off-axis projection?</p>
  
  <p><strong>Question</strong> 4) I understand that the glLookAt has to be done for View Point to shift the apex of the frustum to where the eye of the user is (in this case where the mouse is). Notice the line in the above code:</p>
  
  <p>gluLookAt(headX*headZ, headY*headZ, 0, headX*headZ, headY*headZ, -1, 0, 1, 0);</p>
  
  <p>How is <code>headX*headZ</code> giving me the xPosition of the eye, <code>headY*headZ</code> giving me the yPosition of the eye which I can use in <code>gluLookAt()</code> here?</p>
  
  <p>EDIT: Full problem description added here: <a href="http://pastebin.com/BiSHXspb" rel="noreferrer">pastebin.com/BiSHXspb</a></p>