Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>I'm trying to migrate graphics in my game to OpenGL for performance reasons.</p> <p>I need to draw an object using exact screen coordinates. Say a box 100x100 pixels in the center of 240x320 screen.</p> </blockquote> <p>For a perspective you also need some length for the lens, which determines the FOV. The FOV is the ratio of viewing plane distance to visible extents. In the case of the near plane it thus becomes <code>{left,right,top,bottom}/near</code>. For the sake of simplicity we assume horizontal FOV and a symmetric projection i.e.</p> <pre><code>FOV = 2*|left|/near = 2*|right|/near = extent/distance </code></pre> <p>or if you're more into angles</p> <pre><code>FOV = 2*tan(angular FOV / 2) </code></pre> <p>For a 90° FOV the length of the lens is half the width of the focal plane. Your focal plane is 240x320 pixels, so 120 to the left and right and 160 to the top and bottom. OpenGL does not really have a focus, but we can say that the middle plane between near and far is the "focal".</p> <p>So let's say the object will have in average a extent of about the order of magnitude of visible plane limits, i.e. for a visible plane of 240x360, an object will have in average a size of ~200px. It thus makes sense the distance of near to far clipping to be 200, so +- 100 about the focal plane. So for a FOV of 90° the focal plane has distance</p> <pre><code>2*tan(90°/2) = extent/distance 2*tan(45°) = 2 = 240/distance 2*distance = 240 distance = 120 </code></pre> <p>120, thus near and far clipping distances are 20 and 220.</p> <p>Last but not least the near clip plane limits must be scaled by near_distance/focal_distance = 20/120</p> <p>So</p> <pre><code>left = -120 * 20/120 = -20 right = 120 * 20/120 = 20 bottom = -180 * 20/120 = -30 top = 180 * 20/120 = 30 </code></pre> <p>So this gives us the glFrustum parameters:</p> <pre><code>glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-20, 20, -30, 30, 20, 220); </code></pre> <p>And last but not least we must move the world origin into the "focal" plane</p> <pre><code>glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -120); </code></pre> <blockquote> <p>I need to rotate it around Z axis, preserving its size.</p> </blockquote> <p>done.</p> <blockquote> <p>I need to rotate it around X axis, with perspective effect, preserving (or close to) its size. I need to rotate it around Y axis, with perspective effect, preserving (or close to) its size.</p> </blockquote> <p>Perspective does not preserve size. That's what's makes it a perspective. You can use a very long lens, i.e. small FOV.</p> <h3>Code Update</h3> <p>As a general pro-tip: Do all OpenGL operations in the drawing handler. Don't set the projection in the reshape handler. It's ugly and as soon as you want to have some HUD or other kind of overlay you'll have to discard it anyway. So here's how to change it:</p> <pre><code>public void onDrawFrame(GL10 gl) { // fov, extents are parameters set somewhere else // 2*tan(fov/2.) = width/distance =&gt; float distance = width/(2.*tan(fov)); float near = distance - extent/2; float far = distance + extent/2; if(near &lt; 1.) { near = 1.; } float left = (-width/2) * near/distance; float right = ( width/2) * near/distance; float bottom = (-height/2) * near/distance; float top = ( height/2) * near/distance; gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustum(left, right, bottom, top, near, far); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -focal); gl.glTranslatef(120, 160, 0); // move rotation point gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); // rotate gl.glTranslatef(-120, -160, 0); // restore rotation point mesh.draw(gl); // draws 100x100 px rectangle with the following coordinates: (70, 110, 170, 210) } public void onSurfaceChanged(GL10 gl, int new_width, int new_height) { width = new_width; height = new_height; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload