[comp.sys.sgi] perspective<->ortho switching

Dan Karron@UCBVAX.BERKELEY.EDU (12/28/90)

Some time ago someone asked for a subroutine to switch from
a perspective to ortho viewing transform, and back again.

Appended below is some code to do just that. In addition, there is a
routine to draw the clipping planes. In perspective mode, the clipping
planes form a viewing frustrum (4 sided pyramid with the apex clipped off). 
In ortho mode they form a rectangular box. I use a view of the clipping 
planes in a scout window for the main window.

The subroutine uses the near, screen aspect, and fovy to make a
near ortho clipping box. The far defines the back face of the viewing
box. You can adjust the size of the ortho viewing box with either the
fovy or the near. Of course the near box is the same size as the far
box.

The last argument, PorO (perspective or ortho) switches modes. A zero 
value for PorO gives a perspective viewing transform. A nonzero value for
PorO gives an ortho viewing transform.

An dual of this subroutine could be made to go from an ortho spec to
a perspective viewing transform. I have not given it enough thought as yet,
and it might be harder than I might want to do, given that you can have
an implicit viewing transform translation in the spec for an ortho call.

Enjoy, and let me know if you find this of use!


/****************************************************************************************/
/* allows parameters for perspective xform to setup an ortho xform */
void ViewingTransform(Angle fovy,float yxaspect,Coord near,Coord far,Boolean PorO)
{
if(PorO)
	{
	static float converter= M_PI/1800.0;
	float fov_radians=fovy*converter;
	float t=ftan(fov_radians);
	float ny=t*near;
	float nx=ny*yxaspect;
	ortho(-nx,nx,-ny,ny,near,far);
	}
else perspective(fovy,yxaspect,near,far);
}
/**********************************************************************************/
/* draw clipping planes/viewing box/frustrum for a scout window to a main window */
#define V(x,y,z) {v[i][0]= x;v[i][1]= y;v[i][2]= z;i++;}


float DrawClippingPlanes(Angle fovy,float yxaspect,Coord near,Coord far,Boolean PorO)
{
static float converter= M_PI/1800.0;
static float v[20][3];
float fx,fy;

register int i=0;
float tt=fovy*converter;
float t=ftan(tt);
float n= -near;
float f= -far;
float ny= t*n;
float nx= ny*yxaspect;

if(PorO)
	{
	fx=nx; /* if ortho, near box=far box */
	fy=ny;
	}
	else
	{
	fy=t*f;
	fx=fy*yxaspect;
	}
V( nx, ny,n);
V( nx,-ny,n);
V(-nx,-ny,n);
V(-nx, ny,n);

V( fx, fy,f);
V( fx,-fy,f);
V(-fx,-fy,f);
V(-fx, fy,f);

V( nx, ny,n);
V( fx, fy,f);

V( nx,-ny,n);
V( fx,-fy,f);

V(-nx,-ny,n);
V(-fx,-fy,f);

V(-nx, ny,n);
V(-fx, fy,f);
#undef V
bgnclosedline();/* make the near box */
v3f(v[0]);
v3f(v[1]);
v3f(v[2]);
v3f(v[3]);
endclosedline();
bgnclosedline();/* make the far box */
v3f(v[4]);
v3f(v[5]);
v3f(v[6]);
v3f(v[7]);
endclosedline();

bgnline();/* connect the verticies of the near and far box */
v3f(v[8]);
v3f(v[9]);
endline();
bgnline();
v3f(v[10]);
v3f(v[11]);
endline();
bgnline();
v3f(v[12]);
v3f(v[13]);
endline();
bgnline();
v3f(v[14]);
v3f(v[15]);
endline();
return n;
}
/***********************************************************************************/

+-----------------------------------------------------------------------------+
| karron@nyu.edu (E-mail alias that will always find me)                      |
| Fax: 212 340 7190           *           Dan Karron, Research Associate      |
| . . . . . . . . . . . . . . *           New York University Medical Center  |
| 560 First Avenue           \*\    Pager <1> (212) 397 9330                  |
| New York, New York 10016    \**\        <2> 10896   <3> <your-number-here>  |
| (212) 340 5210               \***\_________________________________________ |
| Main machine: karron.med.nyu.edu (128.122.135.3) IRIS 85GT                  |
+-----------------------------------------------------------------------------+