Beispiel #1
0
int main(void)
{
    int matrix[3][5] = {{ 1, 2, 3, 4, 5},
        { 11, 12, 13, 14,15},
        { 21, 22, 23, 24, 25}
    };

    void scalar_multiply(int matrix[3][5], int scalar);
    void display_matrix(int matrix[3][5]);

    printf("Original Matrix:\n");
    display_matrix(matrix);

    scalar_multiply(matrix, 2);

    printf("\nMultiplied by 2:\n");
    display_matrix(matrix);

    scalar_multiply(matrix, -1);

    printf("\nMultiplied by -1:\n");
    display_matrix(matrix);

    return 0;
}
Beispiel #2
0
//Rotate a vector by a given angle about a given unit vector
void rotate_vector(double (&result)[3], double* vect, double* axis, double angle) {
	
	double identity[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
	double w_hat[] = {0, *(axis+2), -*(axis+1), -*(axis+2), 0, *(axis+0), *(axis+1), -*(axis+0), 0};
	
	double temp[9], temp2[9], temp3[9];
	
	scalar_multiply(temp, w_hat, 3, 3, sin(angle));
	multiply(temp2, w_hat, 3, 3, w_hat, 3);
	scalar_multiply(temp3, temp2, 3, 3, 1-cos(angle));
	
	matrix_add(temp2, identity, temp, 3, 3);
	matrix_add(temp, temp2, temp3, 3, 3);
	
	multiply(result, temp, 3, 3, vect, 1);
}
Head scalar_multiply(
    Head head
  , Tail... tail
    )
{
    if (sizeof...(tail))
        head *= scalar_multiply(tail...);
    return head;
}
Beispiel #4
0
Ray Raytracer::make_reflection_ray(const Vector3d &normal,
                                 const Ray &ray,
                                 const Point3d &intersection)
{
    Ray reflection(intersection,
                   normalize(
                       vector_subtract(ray.direction(),
                           scalar_multiply(normal,
                               2 * dot_product(ray.direction(), normal)))));
     return reflection;
}
Beispiel #5
0
int hdnode_public_ckd(HDNode *inout, uint32_t i)
{
	uint8_t data[1 + 32 + 4];
	uint8_t I[32 + 32];
	uint8_t fingerprint[32];
	curve_point a, b;
	bignum256 c;

	if (i & 0x80000000) { // private derivation
		return 0;
	} else { // public derivation
		memcpy(data, inout->public_key, 33);
	}
	write_be(data + 33, i);

	sha256_Raw(inout->public_key, 33, fingerprint);
	ripemd160(fingerprint, 32, fingerprint);
	inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3];

	memset(inout->private_key, 0, 32);
	if (!ecdsa_read_pubkey(inout->public_key, &a)) {
		return 0;
	}

	hmac_sha512(inout->chain_code, 32, data, sizeof(data), I);
	memcpy(inout->chain_code, I + 32, 32);
	bn_read_be(I, &c);

	if (!bn_is_less(&c, &order256k1)) { // >= order
		return 0;
	}

	scalar_multiply(&c, &b); // b = c * G
	point_add(&a, &b);       // b = a + b

#if USE_PUBKEY_VALIDATE
	if (!ecdsa_validate_pubkey(&b)) {
		return 0;
	}
#endif

	inout->public_key[0] = 0x02 | (b.y.val[0] & 0x01);
	bn_write_be(&b.x, inout->public_key + 1);

	inout->depth++;
	inout->child_num = i;

	return 1;
}
void RPYSolver::orientationSolver(double* output, double phi, double theta, double psi, double yaw1, double pitch1, double roll1, double yaw2, double pitch2, double roll2, int attempt) 
{
  /**************************************************************************/
  //Is the desired orientation possible to attain with the given joint limits?
  /**************************************************************************/
  double wrist_pitch_limit_max;         //Used to express the wrist pitch limit in radians
  double wrist_pitch_limit_min;         //Used to express the wrist pitch limit in radians
  //The wrist pitch limit in radians
  wrist_pitch_limit_max=(PI/180.0)*WRIST_PITCH_LIMIT_MAX;
  wrist_pitch_limit_min=(PI/180.0)*WRIST_PITCH_LIMIT_MIN;

  //The PR2 FK is defined such that pitch is negative upward. Hence, the input pitch values are negated, because the following portion of the code was written assuming that pitch is positive upward.
  theta=-theta;
  pitch1=-pitch1;
  pitch2=-pitch2;

  double v1[] = {cos(theta)*cos(phi), cos(theta)*sin(phi), sin(theta)};
  double v2[] = {cos(pitch2)*cos(yaw2), cos(pitch2)*sin(yaw2), sin(pitch2)};
  double dp_v = dot_product(v1, v2, 3);
  double check_flag=dp_v<0;
  double check_flag2=fabs(dp_v)>fabs(cos(wrist_pitch_limit_max));
  double check_flag3=dp_v>0;
  double check_flag4=dp_v>cos(wrist_pitch_limit_min);

  if((check_flag && check_flag2) || (check_flag3 && check_flag4)) {
    //  std::cout << "Impossible." << std::endl;
    output[0]=0;
    output[1]=0;
    output[2]=0;
    output[3]=0;
    return;
  }

  /*****************************************************/
  //Firstly, all variables are declared and some defined
  /*****************************************************/

  double hand1[]={0, -0.5, 0, 0, 0.5, 0};
  double hand2[]={0, -0.5, 0, 0, 0.5, 0};
  double hand1_fo[6];
  double hand2_fo[6];
  double hand1_vect[3], hand2_vect[3];
  double grip1[]={0, 0, 0, 1, 0, 0};
  double grip2[]={0, 0, 0, 1, 0, 0};
  double grip1_fo[6];
  double grip2_fo[6];
  double grip1_vect[3], grip2_vect[3];
  double indicator1[]={-2.5, 0, 0, -2.5, 0, 1};
  double indicator2[]={-2.5, 0, 0, -2.5, 0, 1};
  double indicator1_fo[6];
  double indicator2_fo[6];
  double ind1_vect[3],ind2_vect[3];
  double comp1_vect[3], comp2_vect[3], project1_vect[3], project2_vect[3];
  double rot1[9], rot2[9], rot3[9];
  double temp[6], temp1[9], temp2[9], temp3[9], temp_var, temp_vect[3], temp2_vect[3];
  double w[3], w_hat[9];
  double rot_world[9], rot_world_trans[9];
  double identity[]={1, 0, 0,
                     0, 1, 0,
                     0, 0, 1};
  double unit_x[3]={1, 0, 0};
  double zero_vect[3]={0, 0, 0};
  double fo_arm_roll, wrist_pitch, wrist_roll, fs_angle, fe_angle;
  double is_orient_possible_flag=1;     //Flag returned indicates whether desired orientation is possible
  //with wrist limits. 1-possible, 0-impossible
  double c_alpha, c_beta, c_gamma, c_delta, c_eps;

  /******************************/
  //Accepting the input arguments
  /******************************/

  create_rotation_matrix(rot_world,phi,theta,psi);
  transpose(rot_world_trans, rot_world, 3, 3);

  //The start and the end orientations in the world frame
  rot1[0]=cos(yaw1);      rot1[3]=-sin(yaw1);     rot1[6]=0;
  rot1[1]=sin(yaw1);      rot1[4]=cos(yaw1);      rot1[7]=0;
  rot1[2]=0;              rot1[5]=0;              rot1[8]=1;

  rot2[0]=cos(pitch1);    rot2[3]=0;              rot2[6]=-sin(pitch1);
  rot2[1]=0;              rot2[4]=1;              rot2[7]=0;
  rot2[2]=sin(pitch1);    rot2[5]=0;              rot2[8]=cos(pitch1);

  multiply(rot3,rot1,3,3,rot2,3); //Yaw and pitch rotations
  multiply(temp,rot3,3,3,hand1,2);
  equate(hand1,temp,3,2);
  multiply(temp,rot3,3,3,grip1,2);
  equate(grip1,temp,3,2);

  w[0]=grip1[3]; //Unit vector along grip
  w[1]=grip1[4];
  w[2]=grip1[5];

  w_hat[0]=0;         w_hat[3]=-w[2];     w_hat[6]=w[1];
  w_hat[1]=w[2];      w_hat[4]=0;         w_hat[7]=-w[0];
  w_hat[2]=-w[1];     w_hat[5]=w[0];      w_hat[8]=0;

  scalar_multiply(temp1,w_hat,3,3,sin(roll1));
  multiply(temp2,w_hat,3,3,w_hat,3);
  scalar_multiply(temp3,temp2,3,3,1-cos(roll1));
  matrix_add(temp2,temp1,temp3,3,3);
  matrix_add(rot1,identity, temp2,3,3);

  multiply(temp1,rot1,3,3,hand1,2);
  equate(hand1,temp1,3,2);

  rot1[0]=cos(yaw2);      rot1[3]=-sin(yaw2);     rot1[6]=0;
  rot1[1]=sin(yaw2);      rot1[4]=cos(yaw2);      rot1[7]=0;
  rot1[2]=0;              rot1[5]=0;              rot1[8]=1;

  rot2[0]=cos(pitch2);    rot2[3]=0;              rot2[6]=-sin(pitch2);
  rot2[1]=0;              rot2[4]=1;              rot2[7]=0;
  rot2[2]=sin(pitch2);    rot2[5]=0;              rot2[8]=cos(pitch2);

  multiply(rot3,rot1,3,3,rot2,3); //Yaw and pitch rotations
  multiply(temp,rot3,3,3,hand2,2);
  equate(hand2,temp,3,2);
  multiply(temp,rot3,3,3,grip2,2);
  equate(grip2,temp,3,2);

  w[0]=grip2[3]; //Unit vector along grip
  w[1]=grip2[4];
  w[2]=grip2[5];

  w_hat[0]=0;         w_hat[3]=-w[2];     w_hat[6]=w[1];
  w_hat[1]=w[2];      w_hat[4]=0;         w_hat[7]=-w[0];
  w_hat[2]=-w[1];     w_hat[5]=w[0];      w_hat[8]=0;

  scalar_multiply(temp1,w_hat,3,3,sin(roll2));
  multiply(temp2,w_hat,3,3,w_hat,3);
  scalar_multiply(temp3,temp2,3,3,1-cos(roll2));
  matrix_add(temp2,temp1,temp3,3,3);
  matrix_add(rot1,identity,temp2,3,3);

  multiply(temp1,rot1,3,3,hand2,2);
  equate(hand2,temp1,3,2);

  //The start and the end orientations in the forearm frame
  multiply(hand1_fo,rot_world_trans,3,3,hand1,2);
  multiply(hand2_fo,rot_world_trans,3,3,hand2,2);
  multiply(grip1_fo,rot_world_trans,3,3,grip1,2);
  multiply(grip2_fo,rot_world_trans,3,3,grip2,2);

  grip1_vect[0]=grip1_fo[3];
  grip1_vect[1]=grip1_fo[4];
  grip1_vect[2]=grip1_fo[5];

  temp_var=dot_product(grip1_vect, unit_x, 3);
  scalar_multiply(comp1_vect, unit_x,3,1,temp_var);
  subtract(project1_vect,grip1_vect,comp1_vect,3,1);

  grip2_vect[0]=grip2_fo[3];
  grip2_vect[1]=grip2_fo[4];
  grip2_vect[2]=grip2_fo[5];

  temp_var=dot_product(grip2_vect, unit_x, 3);
  scalar_multiply(comp2_vect, unit_x,3,1,temp_var);
  subtract(project2_vect,grip2_vect,comp2_vect,3,1);

  ind1_vect[0]=indicator1[3]-indicator1[0];
  ind1_vect[1]=indicator1[4]-indicator1[1];
  ind1_vect[2]=indicator1[5]-indicator1[2];

  ind2_vect[0]=indicator2[3]-indicator2[0];
  ind2_vect[1]=indicator2[4]-indicator2[1];
  ind2_vect[2]=indicator2[5]-indicator2[2];

  if(!check_equality(grip1_vect, comp1_vect, 3)) {
    c_delta=dot_product(ind1_vect, project1_vect, 3)/vect_norm(project1_vect,3);
    fs_angle=acos(c_delta);

    cross_product(temp_vect, ind1_vect, project1_vect);

    if(vect_divide(temp_vect, unit_x, 3)<0) {
      fs_angle=-fs_angle;
    }

    rot1[0]=1;              rot1[3]=0;               rot1[6]=0;
    rot1[1]=0;              rot1[4]=cos(fs_angle);   rot1[7]=-sin(fs_angle);
    rot1[2]=0;              rot1[5]=sin(fs_angle);   rot1[8]=cos(fs_angle);

    multiply(temp, rot1, 3,3, indicator1, 2);
    equate(indicator1_fo, temp, 3, 2);
  }
  else {
    equate(indicator1_fo, indicator1, 3,2);
  }

  if(!check_equality(grip2_vect, comp2_vect, 3)) {
    c_eps=dot_product(ind2_vect, project2_vect, 3)/vect_norm(project2_vect, 3);
    fe_angle=acos(c_eps);

    cross_product(temp_vect, ind2_vect, project2_vect);

    if(vect_divide(temp_vect, unit_x, 3)<0) {
      fe_angle=-fe_angle;
    }

    rot1[0]=1;              rot1[3]=0;               rot1[6]=0;
    rot1[1]=0;              rot1[4]=cos(fe_angle);   rot1[7]=-sin(fe_angle);
    rot1[2]=0;              rot1[5]=sin(fe_angle);   rot1[8]=cos(fe_angle);

    multiply(temp, rot1, 3,3, indicator2, 2);
    equate(indicator2_fo, temp, 3, 2);
  }
  else {
    equate(indicator2_fo, indicator2, 3,2);
  }

  /*********************************/
  //Forearm roll is calculated now
  /*********************************/

  ind1_vect[0]=indicator1_fo[3]-indicator1_fo[0];
  ind1_vect[1]=indicator1_fo[4]-indicator1_fo[1];
  ind1_vect[2]=indicator1_fo[5]-indicator1_fo[2];

  ind2_vect[0]=indicator2_fo[3]-indicator2_fo[0];
  ind2_vect[1]=indicator2_fo[4]-indicator2_fo[1];
  ind2_vect[2]=indicator2_fo[5]-indicator2_fo[2];

  c_gamma=dot_product(ind1_vect, ind2_vect, 3);

  cross_product(temp_vect, ind1_vect, ind2_vect);
  if(vect_divide(temp_vect, unit_x, 3)>0) {
    fo_arm_roll=acos(c_gamma);
  }       
  else {
    fo_arm_roll=-acos(c_gamma);
  } 

  //In the second attempt try rotating the other way around to the same orientation
  if(attempt == 2) {fo_arm_roll = -(2*PI - fo_arm_roll);}

  rot1[0]=1;              rot1[3]=0;                  rot1[6]=0;
  rot1[1]=0;              rot1[4]=cos(fo_arm_roll);   rot1[7]=-sin(fo_arm_roll);
  rot1[2]=0;              rot1[5]=sin(fo_arm_roll);   rot1[8]=cos(fo_arm_roll);

  multiply(temp1,rot1,3,3,hand1_fo,2);
  equate(hand1_fo,temp1,3,2);
  multiply(temp1,rot1,3,3,grip1_fo,2);
  equate(grip1_fo,temp1,3,2);

  /*********************************/
  //Wrist pitch is calculated now
  /*********************************/

  grip1_vect[0]=grip1_fo[3];
  grip1_vect[1]=grip1_fo[4];
  grip1_vect[2]=grip1_fo[5];

  grip2_vect[0]=grip2_fo[3];
  grip2_vect[1]=grip2_fo[4];
  grip2_vect[2]=grip2_fo[5];

  cross_product(temp_vect, grip1_vect, grip2_vect);

  if(!check_equality(temp_vect, zero_vect, 3)) {
    c_alpha=dot_product(grip1_vect, grip2_vect, 3);

    cross_product(temp2_vect,ind2_vect,temp_vect);

    if(vect_divide(temp2_vect, unit_x, 3)>0) {
      wrist_pitch=-acos(c_alpha);
      temp_vect[0]=-temp_vect[0];
      temp_vect[1]=-temp_vect[1];
      temp_vect[2]=-temp_vect[2];
    }
    else {
      wrist_pitch=acos(c_alpha);

    }        

    scalar_multiply(w, temp_vect, 3,1,1/vect_norm(temp_vect, 3));

    w_hat[0]=0;         w_hat[3]=-w[2];     w_hat[6]=w[1];
    w_hat[1]=w[2];      w_hat[4]=0;         w_hat[7]=-w[0];
    w_hat[2]=-w[1];     w_hat[5]=w[0];      w_hat[8]=0;

    scalar_multiply(temp1,w_hat,3,3,sin(wrist_pitch));
    multiply(temp2,w_hat,3,3,w_hat,3);
    scalar_multiply(temp3,temp2,3,3,1-cos(wrist_pitch));
    matrix_add(temp2,temp1,temp3,3,3);
    matrix_add(rot1,identity, temp2,3,3);

    multiply(temp1,rot1,3,3,hand1_fo,2);
    equate(hand1_fo,temp1,3,2);
    multiply(temp1,rot1,3,3,grip1_fo,2);
    equate(grip1_fo,temp1,3,2);
  }
  else {
    wrist_pitch=0;
  }

  /**Somehow the wrist_roll calculations from within this code don't seem to be right.
    This problem has been temporarily solved by invoking FK from environment_robarm3d.cpp**/
  /*********************************/
  //Wrist roll is calculated now
  /*********************************/
  wrist_roll=0;
  hand1_vect[0]=hand1_fo[3]-hand1_fo[0];
  hand1_vect[1]=hand1_fo[4]-hand1_fo[1];
  hand1_vect[2]=hand1_fo[5]-hand1_fo[2];

  hand2_vect[0]=hand2_fo[3]-hand2_fo[0];
  hand2_vect[1]=hand2_fo[4]-hand2_fo[1];
  hand2_vect[2]=hand2_fo[5]-hand2_fo[2];

  grip1_vect[0]=grip1_fo[3];
  grip1_vect[1]=grip1_fo[4];
  grip1_vect[2]=grip1_fo[5];

  c_beta=dot_product(hand1_vect, hand2_vect, 3);
  cross_product(temp_vect, hand1_vect, hand2_vect);

  if(!check_equality(temp_vect, zero_vect, 3)) {
    if(vect_divide(temp_vect, grip1_vect, 3)>0) {
      wrist_roll=acos(c_beta);
    }
    else {
      wrist_roll=-acos(c_beta);
    }
  }

  //The output
  output[0]=is_orient_possible_flag;
  output[1]=fo_arm_roll;   
  output[2]=wrist_pitch;
  output[3]=wrist_roll;
}
Beispiel #7
0
void Estimator::run_estimator(const vector_t& accel, const vector_t& gyro, const uint64_t& imu_time)
{
    _current_state.now_us = imu_time;
    if (last_time == 0 || _current_state.now_us <= last_time)
    {
        last_time = _current_state.now_us;
        return;
    }

    float dt = (_current_state.now_us - last_time) * 1e-6f;
    last_time = _current_state.now_us;

    // Crank up the gains for the first few seconds for quick convergence
    if (imu_time < (uint64_t)params->get_param_int(Params::PARAM_INIT_TIME)*1000)
    {
        kp = params->get_param_float(Params::PARAM_FILTER_KP)*10.0f;
        ki = params->get_param_float(Params::PARAM_FILTER_KI)*10.0f;
    }
    else
    {
        kp = params->get_param_float(Params::PARAM_FILTER_KP);
        ki = params->get_param_float(Params::PARAM_FILTER_KI);
    }

    // Run LPF to reject a lot of noise
    run_LPF(accel, gyro);

    // add in accelerometer
    float a_sqrd_norm = _accel_LPF.x*_accel_LPF.x + _accel_LPF.y*_accel_LPF.y + _accel_LPF.z*_accel_LPF.z;

    if (use_acc && a_sqrd_norm < 1.15f*1.15f*9.80665f*9.80665f && a_sqrd_norm > 0.85f*0.85f*9.80665f*9.80665f)
    {
        // Get error estimated by accelerometer measurement
        vector_t a = vector_normalize(_accel_LPF);
        // Get the quaternion from accelerometer (low-frequency measure q)
        // (Not in either paper)
        quaternion_t q_acc_inv = quaternion_inverse(quat_from_two_vectors(a, g));
        // Get the error quaternion between observer and low-freq q
        // Below Eq. 45 Mahoney Paper
        q_tilde = quaternion_multiply(q_acc_inv, q_hat);
        // Correction Term of Eq. 47a and 47b Mahoney Paper
        // w_acc = 2*s_tilde*v_tilde
        w_acc.x = -2.0f*q_tilde.w*q_tilde.x;
        w_acc.y = -2.0f*q_tilde.w*q_tilde.y;
        w_acc.z = 0.0f; // Don't correct z, because it's unobservable from the accelerometer

                        // integrate biases from accelerometer feedback
                        // (eq 47b Mahoney Paper, using correction term w_acc found above)
        b.x -= ki*w_acc.x*dt;
        b.y -= ki*w_acc.y*dt;
        b.z = 0.0;  // Don't integrate z bias, because it's unobservable
    }
    else
    {
        w_acc.x = 0.0f;
        w_acc.y = 0.0f;
        w_acc.z = 0.0f;
    }

    // Pull out Gyro measurements
    if (quad_int)
    {
        // Quadratic Integration (Eq. 14 Casey Paper)
        // this integration step adds 12 us on the STM32F10x chips
        wbar = vector_add(vector_add(scalar_multiply(-1.0f/12.0f,w2), scalar_multiply(8.0f/12.0f,w1)),
            scalar_multiply(5.0f/12.0f,_gyro_LPF));
        w2 = w1;
        w1 = _gyro_LPF;
    }
    else
    {
        wbar = _gyro_LPF;
    }

    // Build the composite omega vector for kinematic propagation
    // This the stuff inside the p function in eq. 47a - Mahoney Paper
    wfinal = vector_add(vector_sub(wbar, b), scalar_multiply(kp, w_acc));

    // Propagate Dynamics (only if we've moved)
    float sqrd_norm_w = sqrd_norm(wfinal);
    if (sqrd_norm_w > 0.0f)
    {
        float p = wfinal.x;
        float q = wfinal.y;
        float r = wfinal.z;

        if (mat_exp)
        {
            // Matrix Exponential Approximation (From Attitude Representation and Kinematic
            // Propagation for Low-Cost UAVs by Robert T. Casey)
            // (Eq. 12 Casey Paper)
            // This adds 90 us on STM32F10x chips
            float norm_w = sqrtf(sqrd_norm_w);
            quaternion_t qhat_np1;
            float t1 = cosf((norm_w*dt)/2.0f);
            float t2 = 1.0f/norm_w * sinf((norm_w*dt)/2.0f);
            qhat_np1.w = t1*q_hat.w   + t2*(          - p*q_hat.x - q*q_hat.y - r*q_hat.z);
            qhat_np1.x = t1*q_hat.x   + t2*(p*q_hat.w             + r*q_hat.y - q*q_hat.z);
            qhat_np1.y = t1*q_hat.y   + t2*(q*q_hat.w - r*q_hat.x             + p*q_hat.z);
            qhat_np1.z = t1*q_hat.z   + t2*(r*q_hat.w + q*q_hat.x - p*q_hat.y);
            q_hat = quaternion_normalize(qhat_np1);
        }
        else
        {
            // Euler Integration
            // (Eq. 47a Mahoney Paper), but this is pretty straight-forward
            quaternion_t qdot = {0.5f * (           - p*q_hat.x - q*q_hat.y - r*q_hat.z),
                0.5f * ( p*q_hat.w             + r*q_hat.y - q*q_hat.z),
                0.5f * ( q*q_hat.w - r*q_hat.x             + p*q_hat.z),
                0.5f * ( r*q_hat.w + q*q_hat.x - p*q_hat.y)
            };
            q_hat.w += qdot.w*dt;
            q_hat.x += qdot.x*dt;
            q_hat.y += qdot.y*dt;
            q_hat.z += qdot.z*dt;
            q_hat = quaternion_normalize(q_hat);
        }
    }

    // Save attitude estimate
    _current_state.q = q_hat;

    // Extract Euler Angles for controller
    euler_from_quat(_current_state.q, &_current_state.euler.x, &_current_state.euler.y, &_current_state.euler.z);

    // Save off adjust gyro measurements with estimated biases for control
    _current_state.omega = vector_sub(_gyro_LPF, b);
}
Beispiel #8
0
Color Raytracer::trace(Scene *scene, Ray ray, int depth)
{
    if (depth >= m_max_depth)
    {
        return scene->background();
    }

    Intersection *intersection = get_closest_intersection(scene, ray);

    // If this ray hits nothing, return the background color
    if (intersection == nullptr)
    {
        return scene->background();
    }

    // local illumination
    Color rv = m_phong_shader.shade(scene, intersection);

    float kr = intersection->intersected_shape()->reflective_constant();
    float kt = intersection->intersected_shape()->transmissive_constant();

    // spawn reflection ray
    if (kr > 0)
    {
        Ray reflection = make_reflection_ray(intersection->normal(), ray,
                                           intersection->intersection_point());
        rv += trace(scene, reflection, depth + 1) * kr;
    }

    // spawn transmission ray
    if (kt > 0)
    {
        float alpha;
        bool insideShape =
            (dot_product(negate_vector(ray.direction()), intersection->normal()) < 0);

        if (insideShape)
        {
            intersection->set_normal(negate_vector(intersection->normal()));
            alpha = intersection->intersected_shape()->refraction_index();
        }
        else
        {
            alpha = 1.0 / intersection->intersected_shape()->refraction_index();
        }

        float cosine = dot_product(negate_vector(ray.direction()), intersection->normal());

        float discriminant = 1.0 + ( (alpha * alpha) *
            ((cosine * cosine) - 1.0) );

        bool total_internal_reflection = (discriminant < 0);

        if (total_internal_reflection)
        {
            // use the reflection ray with the kt value
            Ray reflection = make_reflection_ray(intersection->normal(), ray,
                                               intersection->intersection_point());
            rv += trace(scene, reflection, depth + 1) * kt;
        }
        else
        {
            // spawn a transmission ray
            Ray transmission(intersection->intersection_point(),
                             normalize(
                                vector_add(scalar_multiply(ray.direction(), alpha),
                                    scalar_multiply(intersection->normal(),
                                        (alpha * cosine) -
                                            sqrt(discriminant)))));

            rv += trace(scene, transmission, depth + 1) * kt;
        }
    }
    delete intersection;

    return rv;
}
Beispiel #9
0
int main(void)
{
  int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
  int b[] = {4, 6, 8, 2, 4, 3, 5, 8};
  int c[8];
  int size = sizeof(a) / sizeof(a[0]);

  int v1[] = {1, 2, 3};
  int v2[] = {3, 4, 7};
  int vsize = sizeof(v1) / sizeof(v1[0]);
  int v3[sizeof(v1) / sizeof(v1[0])];
  int product;

    /* reverse an array */
  printf("Array a:\n");
  print_array(a, size);
  reverse_array(a, size);
  printf("Array a reversed:\n");
  print_array(a, size);
  printf("\n");

    /* add two arrays into a third array */
  printf("Array b:\n");
  print_array(b, size);
  add_arrays(a, b, c, size);
  printf("Array c (sum of array a and array b):\n");
  print_array(c, size);
  printf("\n");

    /* multiply each element by 10 */
  scalar_multiply(c, size, 10);
  printf("All values of c multiplied by 10:\n");
  print_array(c, size);  
  printf("\n");

    /* multiply two arrays (dot product) */
  printf("Array v1:");
  print_array(v1, vsize);
  printf("Array v2:");
  print_array(v2, vsize);
  product = dot_product(v1, v2, vsize);
  printf("The dot product of v1 * v2 is %i\n", product);
  printf("\n");

    /* multiply two arrays (cross product) */
  printf("Array v1:");
  print_array(v1, vsize);
  printf("Array v2:");
  print_array(v2, vsize);
  cross_product(v1, v2, v3);
  printf("The cross product of v1 x v2 is:");
  print_array(v3, 3);
  printf("\n");

    /* more tests */
  test1();
  test2();
  printf("\n");

  return 0;
}