atom feed11 messages in net.sourceforge.lists.gdalgorithms-listRe: [Algorithms] Sphere to rectangle
FromSent OnAttachments
Diogo de AndradeJan 8, 2010 4:45 am 
driz...@libero.itJan 8, 2010 5:54 am 
Diogo de AndradeJan 8, 2010 6:28 am 
Benjamin RouveyrolJan 8, 2010 7:02 am 
Diogo de AndradeJan 8, 2010 7:51 am 
Fabian GiesenJan 8, 2010 7:56 am 
Benjamin RouveyrolJan 8, 2010 8:35 am 
Diogo de AndradeJan 8, 2010 8:50 am 
Diogo de AndradeJan 11, 2010 4:02 am 
Diogo de AndradeJan 11, 2010 4:36 am 
Gino van den BergenJan 13, 2010 12:56 am 
Subject:Re: [Algorithms] Sphere to rectangle
From:Fabian Giesen (f.gi@49games.de)
Date:Jan 8, 2010 7:56:38 am
List:net.sourceforge.lists.gdalgorithms-list

Benjamin Rouveyrol wrote:

Hi,

The way I solved this (but a bit math heavy): If R is the light Radius and D the distance between the camera and the light: NewR = D * tan(asin(R/D))

Then you compute Up and right vectors based on the camera and light positions (and the camera Up). You end up with 4 corners: LightCenter +|- Up * NewR +|- Right * NewR

You can project them and this should give you your bounding rectangle. If someone has a simpler solution, I'd be most interested ^_^

Eric Lengyel explains one way to solve this on the last page of his "The Mechanics of Robust Stencil Shadows" article:

http://www.gamasutra.com/view/feature/2942/the_mechanics_of_robust_stencil_.php?page=6

I derived an alternative method for some hobby project around 2004 that is somewhat more straightforward. I don't have the original derivation anymore, but I remember that it was fairly straightforward trig:

// Calculates bounding rectangle in normalized device coordinates for // the view-space sphere with center "center" and radius "r". "zoom" // contains the first two diagonal entries of your projection matrix // (which is assumed to be perspective). You should do a rough rejection // test of the sphere against the frustum first.

static void CalcSphereBounds(const Vector& center, float r, const float zoom[2], float minb[2], float maxb[2]) { // by default, assume that full screen covered minb[0] = minb[1] = -1.0f; maxb[0] = maxb[1] = 1.0f;

// once for x, once for y for(int i=0;i<2;i++) { float x = center[i]; float z = center.z; float ds = x*x + z*z; float l = ds - r * r;

if(l > 0.0f) { float s,c; l = sqrt(l);

s = x * l - z * r; // ds*sin(alpha) c = x * r + z * l; // ds*cos(alpha) if(z*ds > -r*s) // left/top intersection has positive z minb[i] = max(-1.0f, s*zoom[i]/c);

s = z * r + x * l; // ds*sin(beta) c = z * l - x * r; // ds*cos(beta) if(z*ds > r*s) // right/bottom intersection has positive z maxb[i] = min(1.0f, s*zoom[i]/c); } } }

I'll try to re-derive this so as not to leave a bunch of unexplained formulas standing in the room, but it's a relatively short solution and it's worked fine for me, so I guess it's of interest.

Kind regards, -Fabian