/* * 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; }