「実践CGの誘い」や、RenderMan Fastの解説サイト、RenderDotCサイトのマニュアルページに、placecam.cがある。pythonで書き換えるのもできるし、簡単にコンパイルができます。今日もありがとうございます。
/*
* 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
* aim: a point giving the location at which the camera is aimed
* roll: an optional rotation of the camera about its direction axis
* coneangle: an optional spotlight shader cone angle
*/
#include
#include
#include
#define PI 3.1415926535897932
void usage(void)
{
printf("usage: placecam pos_x pos_y pos_z aim_x aim_y aim_z\n");
printf(" [coneangle] [roll_angle]\n");
printf(" Calculate RenderMan transforms needed for camera transform\n");
printf(" from light position to aim point with the given roll angle.\n");
exit(1);
}
typedef double RtPoint[3];
void RiRotate(double angle, double x, double y, double z)
{
if (fabs(angle) > 0.001) {
printf("Rotate %0.2f %0.2f %0.2f %0.2f\n", angle, x, y, z);
}
}
void RiTranslate(double dx, double dy, double dz)
{
printf("Translate %0.2f %0.2f %0.2f\n", dx, dy, dz);
}
/*
* AimZ(): rotate the world so the direction vector points in
* positive z by rotating about the y axis, then x. The cosine
* of each rotation is given by components of the normalized
* direction vector. Before the y rotation the direction vector
* might be in negative z, but not afterward.
*/
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 (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 (direction[0] > 0)
RiRotate(-yrot, 0.0, 1.0, 0.0);
else
RiRotate(yrot, 0.0, 1.0, 0.0);
}
void PlaceCamera(RtPoint position, RtPoint direction, float roll)
{
RiRotate(-roll, 0.0, 0.0, 1.0);
AimZ(direction);
RiTranslate(-position[0], -position[1], -position[2]);
}
int main(int argc, char *argv[])
{
RtPoint pos, aim, dir;
double roll;
double coneangle, fov;
if (argc < 7) usage();
pos[0] = atof(argv[1]);
pos[1] = atof(argv[2]);
pos[2] = atof(argv[3]);
aim[0] = atof(argv[4]);
aim[1] = atof(argv[5]);
aim[2] = atof(argv[6]);
if (argc > 7) coneangle = atof(argv[7]);
else coneangle = 0.0;
if (argc > 8) roll = atof(argv[8]);
else roll = 0.0;
printf("position: %0.2f, %0.2f, %0.2f\n", pos[0], pos[1], pos[2]);
printf("aim: %0.2f, %0.2f, %0.2f\n", aim[0], aim[1], aim[2]);
printf("coneangle: %0.4f\n", coneangle);
printf("roll: %0.2f\n\n", roll);
if (coneangle != 0.0) {
fov = coneangle * 360.0 / PI;
printf("Projection \"perspective\" \"fov\" [%0.2f]\n", fov);
}
dir[0] = aim[0] - pos[0];
dir[1] = aim[1] - pos[1];
dir[2] = aim[2] - pos[2];
PlaceCamera(pos, dir, roll);
return 0;
}