DLLEXPORT miBoolean domeAFL_FOV( miColor *result, miState *state, register struct dsDomeAFL_FOV *params) { miScalar fov_angle_deg = *mi_eval_scalar(¶ms->FOV_Angle); miGeoScalar fov_angle_rad; miVector viewpt_offset = *mi_eval_vector(¶ms->View_Offset); miVector ray; miGeoScalar x, y, r, phi, theta; /* normalize image coordinates btwn [-1,1]... */ /* [ah] Rotate the cartesian axis 90 deg CW */ x = -2.0*state->raster_y/state->camera->y_resolution+1.0; y = 2.0*state->raster_x/state->camera->x_resolution-1.0; /* Calcaulate the radius value */ r = MI_SQRT( ( x * x ) + ( y * y ) ); if ( r < 1.0 ) { /* Calculate phi... */ if ( (r > -EPSILON) && (r < EPSILON) ) { phi = 0.0; } else { phi = atan2(x,y); // [rz] using atan2 instead of original if-then formula } /* Convert FOV angle of fisheye from degrees to radians... */ fov_angle_rad = fov_angle_deg * M_PI / 180.0; /* Calculate theta... */ theta = r * ( fov_angle_rad / 2.0 ); /* Calculate Ray direction vector... */ ray.x = (float)(sin(theta) * cos(phi)); ray.y = (float)(-sin(theta) * sin(phi)); /* -Z is Look At Direction*/ ray.z = (float)(-cos(theta)); /* Account for view offset... */ /* Offset is added to y & z components because they are negative values...*/ ray.x = ray.x - viewpt_offset.x; ray.y = ray.y + viewpt_offset.y; /* Add because MR uses -Z as Look At */ ray.z = ray.z + viewpt_offset.z; /* Flip the ray direction about the y-axis */ if(*mi_eval_boolean(¶ms->Flip_Ray_X)) { ray.x = (-ray.x); } /* Flip the ray direction about the x-axis */ if(*mi_eval_boolean(¶ms->Flip_Ray_Y)) { ray.y = (-ray.y); } /* Convert ray from camera space */ mi_vector_from_camera(state, &ray, &ray); /* Trace new ray... */ return(mi_trace_eye(result, state, &state->org, &ray)); } else { /* Set the return colors to Black */ result->r = result->g = result->b = result->a = 0; return(miFALSE); } } /* end of dome_FOV_AFL() */
DLLEXPORT miBoolean domeAFL_FOV_Stereo( miColor *result, miState *state, struct dsDomeAFL_FOV_Stereo *params) { miScalar cameras_separation_multiplier = *mi_eval_scalar(¶ms->Cameras_Separation_Map); miScalar head_turn_multiplier = *mi_eval_scalar(¶ms->Head_Turn_Map); miScalar head_tilt = *mi_eval_scalar(¶ms->Head_Tilt_Map); miVector org, ray, target, htarget; miMatrix tilt; double x, y, r, phi, theta, rot, tmp, tmpY, tmpZ; double sinP, cosP, sinT, cosT, sinR, cosR; // normalize image coordinates btwn [-1,1]... // [rz] swap X-Y to match camera view and apply a vertical symmetry // [rz] basically, we rotate the cartesian axis 90deg CW x = -2.0*state->raster_y/state->camera->y_resolution+1.0; y = 2.0*state->raster_x/state->camera->x_resolution-1.0; // Calculate the radius value r = MI_SQRT((x*x)+(y*y)); if (r < 1.0) { // Calculate phi... if ((r > -EPSILON) && (r < EPSILON) ) { phi = 0.0; } else { phi = atan2(y,x); } // Calculate theta... theta = r*(fov_angle/2.0); // start by matching camera (center camera) // mi_point_to_camera(state, &org, &state->org); org.x = org.y = org.z = 0.0; // saves common used values for performance reasons sinP = sin(phi); cosP = cos(phi); sinT = sin(theta); cosT = cos(theta); // center camera target vector (normalized) target.x = (miScalar)(sinP*sinT); target.y = (miScalar)(-cosP*sinT); target.z = (miScalar)(-cosT); if (camera != CENTERCAM) { // camera selection and initial position // @@@ use switch? if (camera == LEFTCAM) { org.x = (miScalar)(-cameras_separation*cameras_separation_multiplier/2); } if (camera == RIGHTCAM) { org.x = (miScalar)(cameras_separation*cameras_separation_multiplier/2); } if (dome_tilt_compensation) { // tilted dome mode // head rotation // @@@ need to check atan2 params for 0 values? // @@@ save values of sin/cos tmpY = target.y*cos(-dome_tilt)-target.z*sin(-dome_tilt); tmpZ = target.z*cos(-dome_tilt)+target.y*sin(-dome_tilt); rot = atan2(target.x,-tmpY)*head_turn_multiplier; if (vertical_mode) rot *= fabs(sinP); sinR = sin(rot); cosR = cos(rot); // rotate camera tmp = org.x*cosR-org.y*sinR; org.y = (miScalar)(org.y*cosR+org.x*sinR); org.x = (miScalar)tmp; // compensate for dome tilt // @@@ save values of sin/cos tmp = org.y*cos(dome_tilt)-org.z*sin(dome_tilt); org.z = (miScalar)(org.z*cos(dome_tilt)+org.y*sin(dome_tilt)); org.y = (miScalar)tmp; // calculate head target tmp = sqrt(target.x*target.x+tmpY*tmpY); htarget.x = (miScalar)(sin(rot)*tmp); htarget.y = (miScalar)(-cos(rot)*tmp); htarget.z = (miScalar)tmpZ; // dome rotation again on head target tmp = htarget.y*cos(dome_tilt)-htarget.z*sin(dome_tilt); htarget.z = (miScalar)(htarget.z*cos(dome_tilt)+htarget.y*sin(dome_tilt)); htarget.y = (miScalar)tmp; } else { if (vertical_mode) { // vertical mode // head rotation // @@@ need to check atan2 params for 0 values? rot = atan2(target.x,-target.z)*head_turn_multiplier*fabs(sinP); sinR = sin(rot); cosR = cos(rot); // rotate camera tmp = org.x*cosR-org.z*sinR; org.z = (miScalar)(org.z*cosR+org.x*sinR); org.x = (miScalar)tmp; // calculate head target tmp = sqrt(target.x*target.x+target.z*target.z); htarget.x = (miScalar)(sin(rot)*tmp); htarget.y = (miScalar)target.y; htarget.z = (miScalar)(-cos(rot)*tmp); } else { // horizontal mode // head rotation rot = phi*head_turn_multiplier; sinR = sin(rot); cosR = cos(rot); // rotate camera tmp = org.x*cosR-org.y*sinR; org.y = (miScalar)(org.y*cosR+org.x*sinR); org.x = (miScalar)tmp; // calculate head target htarget.x = (miScalar)(sin(rot)*sinT); htarget.y = (miScalar)(-cos(rot)*sinT); htarget.z = (miScalar)target.z; } } // head tilt head_tilt = (miScalar)((head_tilt-0.5)*M_PI); mi_matrix_ident(tilt); mi_matrix_rotate_axis(tilt, &htarget, head_tilt); mi_vector_transform(&org, &org, tilt); // calculate ray from camera to target target.x *= dome_radius; target.y *= dome_radius; target.z *= dome_radius; ray.x = target.x-org.x; ray.y = target.y-org.y; ray.z = target.z-org.z; mi_vector_normalize(&ray); } else { // center camera ray = target; } // Account for view offset... // Offset is added to y & z components because they are negative values... // @@@ ray.x = ray.x - viewport_offset.x; // @@@ ray.y = ray.y + viewport_offset.y; // @@@ ray.z = ray.z + viewport_offset.z; //mi_debug("II->,Phi=%f,Theta=%f,rot=%f,camx=%f,camy=%f", (miScalar)phi, (miScalar)theta, (miScalar)rot, (miScalar)org.x, (miScalar)org.y); // Flip the ray direction about the y-axis // @@@ if(*mi_eval_boolean(¶ms->Flip_Ray_X)) { // @@@ ray.x = (-ray.x); // @@@ } // Flip the ray direction about the x-axis // @@@ if(*mi_eval_boolean(¶ms->Flip_Ray_Y)) { // @@@ ray.y = (-ray.y); // @@@ } // Convert ray from camera space mi_vector_from_camera(state, &ray, &ray); mi_point_from_camera(state, &org, &org); // Trace new ray... return(mi_trace_eye(result, state, &org, &ray)); } else { // Set the return colors to Black result->r = result->g = result->b = result->a = 0; return(miFALSE); } }
DLLEXPORT miBoolean domeAFL_WxH( miColor *result, miState *state, register struct dsDomeAFL_WxH *params) { miScalar diameter = *mi_eval_scalar(¶ms->Diameter); miScalar height = *mi_eval_scalar(¶ms->Height); miGeoScalar fov; /* Field-of-View of specified dome */ miGeoScalar radius; /* Radius of dome being subtended */ /* Does this need to be a pointer? */ miVector viewpt_offset = *mi_eval_vector(¶ms->View_Offset); miVector ray; miGeoScalar x, y, r, phi, theta; /* normalize image coordinates btwn [-1,1]... */ x = (2.0 * state->raster_x) / state->camera->x_resolution - 1.0; y = (2.0 * state->raster_y) / state->camera->y_resolution - 1.0; /* Calculate FOV for given Diameter & height of dome... */ /* Equations obtained from: */ /* http://mathforum.org/dr.math/faq/faq.circle.segment.html#8 */ radius = ((diameter * diameter) + (4 * height * height)) / (8 * height); fov = 2 * asin(diameter / (2 * radius)); /* Calcaulate the radius value */ r = MI_SQRT( ( x * x ) + ( y * y ) ); if ( r < 1.0 ) { /* Calculate phi... */ if ( (r > -EPSILON) && (r < EPSILON) ) { phi = 0.0; } else { phi = atan2(x,y); // [rz] using atan2 instead of original if-then formula } /* Calculate theta... */ theta = r * ( fov / 2.0 ); /* Calculate Ray direction vector... */ ray.x = (float)(sin(theta) * cos(phi)); ray.y = (float)(-sin(theta) * sin(phi)); /* -Z is Look At Direction*/ ray.z = (float)(-cos(theta)); /* Account for view offset... */ /* Offset is added to y & z components because they are negative values...*/ ray.x = ray.x - viewpt_offset.x; ray.y = ray.y + viewpt_offset.y; /* Add because MR uses -Z as Look At */ ray.z = ray.z + viewpt_offset.z; // Flip the ray direction about the y-axis if(*mi_eval_boolean(¶ms->Flip_Ray_X)) { ray.x = (-ray.x); } /* Flip the ray direction about the x-axis */ if(*mi_eval_boolean(¶ms->Flip_Ray_Y)) { ray.y = (-ray.y); } /* Convert ray from camera space */ mi_vector_from_camera(state, &ray, &ray); /* Trace new ray... */ return(mi_trace_eye(result, state, &state->org, &ray)); } else { /* Set return color to Black */ result->r = result->g = result->b = result->a = 0; return(miFALSE); } } /* end of domeAFL_WxH() */