118 lines
3.3 KiB
C
118 lines
3.3 KiB
C
#include <math.h>
|
|
#include "ri.h"
|
|
#include "camset.h"
|
|
|
|
#define min(a,b) ((a)<(b)?(a):(b))
|
|
#define PI 3.1415926535897932384626433832795
|
|
|
|
|
|
/* PlaceCamera(): establish a viewpoint, viewing direction and orientation
|
|
* for a scene. This routine must be called before RiWorldBegin().
|
|
* position: a point giving the camera position
|
|
* direction: a point giving the camera direction relative to position
|
|
* roll: an optional rotation of the camera about its direction axis
|
|
*/
|
|
void PlaceCamera(RtPoint position, RtPoint direction, float roll)
|
|
{
|
|
RiIdentity(); /* Initialize the camera transformation */
|
|
if (roll != 0.0)
|
|
RiRotate(-roll, 0.0, 0.0, 1.0);
|
|
AimZ(direction);
|
|
RiTranslate(-position[0], -position[1], -position[2]);
|
|
}
|
|
|
|
void AimZ(RtPoint direction)
|
|
{
|
|
double xzlen, yzlen, yrot, xrot;
|
|
|
|
if (direction[0]==0 && direction[1]==0 && direction[2]==0)
|
|
return;
|
|
/*
|
|
* The initial rotation about the y axis is given by the projection of
|
|
* the direction vector onto the x,z plane: the x and z components
|
|
* of the direction.
|
|
*/
|
|
|
|
xzlen = sqrt(direction[0]*direction[0]+direction[2]*direction[2]);
|
|
if (xzlen == 0)
|
|
yrot = (direction[1] < 0) ? 180 : 0;
|
|
else
|
|
yrot = 180*acos(direction[2]/xzlen)/PI;
|
|
|
|
/*
|
|
* The second rotation, about the x axis, is given by the projection on
|
|
* the y,z plane of the y-rotated direction vector: the original y
|
|
* component, and the rotated x,z vector from above.
|
|
*/
|
|
|
|
yzlen = sqrt(direction[1]*direction[1]+xzlen*xzlen);
|
|
xrot = 180*acos(xzlen/yzlen)/PI; /* yzlen should never be 0 */
|
|
|
|
if (xrot != 0.0)
|
|
{
|
|
if (direction[1] > 0)
|
|
RiRotate(xrot, 1.0, 0.0, 0.0);
|
|
else
|
|
RiRotate(-xrot, 1.0, 0.0, 0.0);
|
|
}
|
|
|
|
/* The last rotation declared gets performed first */
|
|
if (yrot != 0.0)
|
|
{
|
|
if (direction[0] > 0)
|
|
RiRotate(-yrot, 0.0, 1.0, 0.0);
|
|
else
|
|
RiRotate(yrot, 0.0, 1.0, 0.0);
|
|
}
|
|
}
|
|
|
|
/* FrameCamera(): give physical parameters for a camera.
|
|
Parameters:
|
|
focallength: the "camera's" focal length.
|
|
framewidth: the width of the film frame
|
|
frameheight: the height of the film frame
|
|
*/
|
|
void FrameCamera(float focallength, float framewidth, float frameheight)
|
|
{
|
|
RtFloat normwidth, normheight;
|
|
|
|
/* Focal length of 0 is taken to be an orthographic projection */
|
|
if (focallength != 0.0)
|
|
{
|
|
RiProjection("perspective", RI_NULL);
|
|
normwidth = (framewidth*.5)/focallength;
|
|
normheight = (frameheight*.5)/focallength;
|
|
}
|
|
else
|
|
{
|
|
RiProjection("orthographic", RI_NULL);
|
|
normwidth = framewidth*.5;
|
|
normheight = frameheight*.5;
|
|
}
|
|
|
|
RiScreenWindow(-normwidth, normwidth, -normheight, normheight);
|
|
}
|
|
|
|
/* FrameCamera2(): give physical parameters for a camera.
|
|
* Parameters:
|
|
* focallength: controls the width of the camera's field of view.
|
|
* framewidth: the width of the film image
|
|
* frameheight: the height of the film image*/
|
|
void FrameCamera2(float focallength, float framewidth, float frameheight)
|
|
{
|
|
RtFloat fov;
|
|
|
|
/* A nonzero focal length is taken to be a "normal" lens */
|
|
if(focallength != 0.0)
|
|
{
|
|
fov = 2 * atan((min(framewidth,frameheight)*.5)/focallength) * 180.0/3.14159;
|
|
RiProjection("perspective", RI_FOV, (RtPointer)&fov, RI_NULL);
|
|
}
|
|
else
|
|
{
|
|
RiProjection("orthographic", RI_NULL);
|
|
}
|
|
|
|
RiFrameAspectRatio((RtFloat)(framewidth/frameheight));
|
|
}
|