Radius of the designed sphere

I want to clarify the previous question :

How to create a sphere on the screen?

(2) gives a simple solution:

  approximate radius on screen [CLIP SPACE] = world radius * cot (fov / 2) / Z

 with:
 fov = field of view angle
 Z = z distance from camera to sphere

 result is in clipspace , multiply by viewport size to get size in pixels

Now my problem is that I do not have FOV. Only matrixes of representations and projections are known. (And viewport size if that helps)

Does anyone know how to extract the FOV from the projection matrix?

Update:

This approximation works better in my case:

float radius = glm::atan(radius/distance); radius *= glm::max(viewPort.width, viewPort.height) / glm::radians(fov); 
+4
source share
4 answers

Update: see below.

Since you have a matrix of views and projections, here is one way to do this, although it's probably not the shortest:

  • transform the center of the sphere into the viewing space using the matrix of the form: call the result point C
  • converts a point on the surface of a sphere, for example. C + (r, 0, 0) in world coordinates, where r is the radius of the sphere sphere in the space of representations; call result point S
  • calculate rv = distance from C to S (in viewing space)
  • let the point S1 in the coordinates of the form C + (rv, 0, 0) be another point on the surface of the sphere in the view space for which the line C → S1 is perpendicular to the vector “look”
  • project C and S1 into screen coordinates using the projection matrix in the form of Cs and S1s
  • calculate screen radius = distance between Cs and S1s

But, as Brandorf said, if you can save camera variables like FOVy, it would be much simpler. :-)

Update: Here's a more efficient option: output the inverse projection matrix. Use it to convert the edges of the viewport back to the viewing space. Then you will not need to design each cell in the coordinates of the screen.

Even better, do the same with the view matrix and transform the camera back into world space. This would be more effective for comparing many drawers against; but harder to understand math.

+2
source

I'm a little late for this party. But I ran into this problem when I was looking for the same problem. I spent the whole day on this and worked, although some excellent articles I found here are: http://www.antongerdelan.net/opengl/virtualcamera.html

I finished working with the projection matrix and worked back. I got the same formula that you mentioned in your post above. (where cot (x) = 1 / tan (x))

 radius_pixels = (radius_worldspace / {tan(fovy/2) * D}) * (screen_height_pixels / 2) 

(where D is the distance from the camera to the target boundary sphere)

I use this approach to determine the radius of an imaginary trackball that I use to rotate my object.

Btw Florian, you can extract fovy from the Projection matrix as follows:

If you take the Sy component from the projection matrix, as shown below:

 Sx 0 0 0 0 Sy 0 0 0 0 Sz Pz 0 0 -1 0 where Sy = near / range and where range = tan(fovy/2) x near 

(you can find these definitions on the page above)

if you replace the range in Sy eqn above, you will get:

 Sy = 1 / tan(fovy/2) = cot(fovy/2) 

permutations:

 tan(fovy/2) = 1 / Sy 

taking arctan (reverse tan) on both sides, we get:

 fovy/2 = arctan(1/Sy) 

So,

 fovy = 2 x arctan(1/Sy) 

Not sure if you care - it has been a while! - but maybe it will help someone else.

+3
source

The answer was sent via your link radiusClipSpace = radius * cot(fov / 2) / Z , where fov is the angle of the field of view, and Z is the distance z from the sphere, it definitely works. However, keep in mind that radiusClipSpace must be multiplied by the width of the viewport to get a measure of the pixel. The value measured in radiusClipSpace will have a value from 0 to 1 if the object is on the screen.

An alternative solution could be to use the solid angle of the sphere. The solid angle hidden by a sphere in the sky is basically the area that it covers when projecting onto a unit of sphere.

enter image description here

The formulas are given in this link , but roughly what I am doing is:

 if( (!radius && !distance) || fabsf(radius) > fabsf(distance) ) ; // NAN conditions. do something special. theta=arcsin( radius/distance ) sphereSolidAngle = ( 1 - cosf( theta ) ) ; // not multiplying by 2PI since below ratio used only frustumSolidAngle = ( 1 - cosf( fovy / 2 ) ) / M_PI ; // I cheated here. I assumed // the solid angle of a frustum is (conical), then divided by PI // to turn it into a square (area unit square=area unit circle/PI) numPxCovered = 768.f*768.f * sphereSolidAngle / frustumSolidAngle ; // 768x768 screen radiusEstimate = sqrtf( numPxCovered/M_PI ) ; // area=pi*r*r 

This works around the same numbers as radius * cot(fov / 2) / Z If you only need to estimate the area covered by the projection of the sphere into px, this can be a simple way.

I am not sure if it is easy to find the best estimate of the solid angle of a truncated cone. This method includes more comps than radius * cot(fov / 2) / Z

+1
source

FOV is not stored directly in the projection matrix, but is used when you call gluPerspective to build the resulting matrix.

A better approach would be to simply keep all your camera variables in their own class, for example the frustum class, whose member variables are used when calling gluPerspective or similar.

It may be possible to return FOVy from the matrix, but the required math is eluding me.

0
source

All Articles