Example #1
0
/* @param d direction of the ray into intersection
 * @param l direction of intersection to light
 * @param n surface normal
 */
static void compute_specular_diffuse(double *diffuse,
                                     double *specular,
                                     const point3 d, const point3 l,
                                     const point3 n, double phong_pow)
{
    point3 d_copy, l_copy, middle, r;

    /* Calculate vector to eye V */
    COPY_POINT3(d_copy, d);
    multiply_vector(d_copy, -1, d_copy);
    normalize(d_copy);

    /* Calculate vector to light L */
    COPY_POINT3(l_copy, l);
    multiply_vector(l_copy, -1, l_copy);
    normalize(l_copy);

    /* Calculate reflection direction R */
    double tmp = dot_product(n, l_copy);
    multiply_vector(n, tmp, middle);
    multiply_vector(middle, 2, middle);
    subtract_vector(middle, l_copy, r);
    normalize(r);

    /* diffuse = max(0, dot_product(n, -l)) */
    *diffuse = MAX(0, dot_product(n, l_copy));

    /* specular = (dot_product(r, -d))^p */
    *specular = pow(MAX(0, dot_product(r, d_copy)), phong_pow);
}
Example #2
0
static void localColor(color local_color,
                       const color light_color, double diffuse,
                       double specular, const object_fill *fill)
{
    color ambi = { 0.1, 0.1, 0.1 };
    color diff, spec, lightCo, surface;

    /* Local Color = ambient * surface +
     *               light * ( kd * surface * diffuse + ks * specular)
     */

    COPY_COLOR(diff, fill->fill_color);
    multiply_vector(diff, fill->Kd, diff);
    multiply_vector(diff, diffuse, diff);
    COPY_COLOR(lightCo, light_color);
    multiply_vectors(diff, lightCo, diff);

    COPY_COLOR(spec, light_color);
    multiply_vector(spec, fill->Ks, spec);
    multiply_vector(spec, specular, spec);

    COPY_COLOR(surface, fill->fill_color);
    multiply_vectors(ambi,surface, ambi);
    add_vector(diff, ambi, diff);
    add_vector(diff, spec, diff);
    add_vector(local_color, diff, local_color);
}
Example #3
0
/* @param t t distance
 * @return 1 means hit, otherwise 0
 */
static int raySphereIntersection(const point3 ray_e,
                                 const point3 ray_d,
                                 const sphere *sph,
                                 intersection *ip, double *t1)
{
    point3 l;
    subtract_vector(sph->center, ray_e, l);
    double s = dot_product(l, ray_d);
    double l2 = dot_product(l, l);
    double r2 = sph->radius * sph->radius;

    if (s < 0 && l2 > r2)
        return 0;
    float m2 = l2 - s * s;
    if (m2 > r2)
        return 0;
    float q = sqrt(r2 - m2);
    *t1 = (l2 > r2) ? (s - q) : (s + q);
    /* p = e + t1 * d */
    multiply_vector(ray_d, *t1, ip->point);
    add_vector(ray_e, ip->point, ip->point);

    subtract_vector(ip->point, sph->center, ip->normal);
    normalize(ip->normal);
    if (dot_product(ip->normal, ray_d) > 0.0)
        multiply_vector(ip->normal, -1, ip->normal);
    return 1;
}
Example #4
0
/* @param d direction of ray
 * @param w basic vectors
 */
static void rayConstruction(point3 d, const point3 u, const point3 v,
                            const point3 w, unsigned int i, unsigned int j,
                            const viewpoint *view, unsigned int width,
                            unsigned int height)
{
    double xmin = -0.0175;
    double ymin = -0.0175;
    double xmax =  0.0175;
    double ymax =  0.0175;
    double focal = 0.05;

    point3 u_tmp, v_tmp, w_tmp, s;

    double w_s = focal;
    double u_s = xmin + ((xmax - xmin) * (float) i / (width - 1));
    double v_s = ymax + ((ymin - ymax) * (float) j / (height - 1));

    /* s = e + u_s * u + v_s * v + w_s * w */
    multiply_vector(u, u_s, u_tmp);
    multiply_vector(v, v_s, v_tmp);
    multiply_vector(w, w_s, w_tmp);
    add_vector(view->vrp, u_tmp, s);
    add_vector(s, v_tmp, s);
    add_vector(s, w_tmp, s);

    /* p(t) = e + td = e + t(s - e) */
    subtract_vector(s, view->vrp, d);
    normalize(d);
}
Example #5
0
/* reference: https://www.opengl.org/sdk/docs/man/html/refract.xhtml */
static void refraction(point3 t, const point3 I, const point3 N,
                       double n1, double n2)
{
    double eta = n1 / n2;
    double dot_NI = dot_product(N,I);
    double k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
    if (k < 0.0 || n2 <= 0.0)
        t[0] = t[1] = t[2] = 0.0;
    else {
        point3 tmp;
        multiply_vector(I, eta, t);
        multiply_vector(N, eta * dot_NI + sqrt(k), tmp);
        subtract_vector(t, tmp, t);
    }
}
//function to scale aroud the world coordinate axes
void scale(IFS_DATA* ifs_data,float scale_x,float scale_y,float scale_z)
{
  int i,j;
  
    Matrix trans_matrix=return_scale_Matrix(scale_x,scale_y,scale_z);
    object_x*=scale_x;
    object_y*=scale_y;
    object_z*=scale_z;
    //print(trans_matrix);
    for (i=0; i<ifs_data->numVertices; ++i) 
    {
    vector v;
    v.A[0]=ifs_data->vertices[i].x;
    v.A[1]=ifs_data->vertices[i].y;
    v.A[2]=ifs_data->vertices[i].z;
    v.A[3]=1.0;
    
    //v=create_scale_Matrix(&v,scale_x,scale_y,scale_z);
    
    v=multiply_vector(&trans_matrix,&v);
    
    ifs_data->vertices[i].x=v.A[0];
    ifs_data->vertices[i].y=v.A[1];
    ifs_data->vertices[i].z=v.A[2];
      
  }
    
    
}
Example #7
0
  value value::multiply(const value& that) const
  {
    if (that.is(m_type))
    {
      switch (m_type)
      {
        case type::number:
          return multiply_number(*m_value_number, *that.m_value_number);

        case type::vector:
          return multiply_vector(*m_value_vector, *that.m_value_vector);

        default:
          break;
      }
    }

    throw error(
      error::type::type,
      U"Cannot multiply " +
      type_description(that.m_type) +
      U" with " +
      type_description(m_type)
    );
  }
Example #8
0
/*
 * Returns a pointer to the intersection between a cone and a ray.
 *
 * eye: Position from which the ray is thrown.
 * dir_vec: Direction towards which the ray is thrown. Must be normalized.
 * object_ptr: Pointer to the Object struct that represents the cone.
 * length: Output parameter for the number of intersections found.
 */
void* get_cone_intersection(Vector eye, Vector dir_vec, void* object_ptr, int *length)
{
	Cone* cone_ptr =  (Cone*) ((Object*)object_ptr)->figure;
	long double termQD, termQE;
	Vector varD, varE, anchor_to_anchor;
	anchor_to_anchor = subtract_vectors(eye, cone_ptr->anchor);

	termQD = do_dot_product(cone_ptr->direction, dir_vec);
	termQE = do_dot_product(cone_ptr->direction, anchor_to_anchor);

	varD = subtract_vectors(multiply_vector(termQD, cone_ptr->direction), dir_vec);
	varE = get_ray_position(cone_ptr->anchor, subtract_vectors(multiply_vector(termQE, cone_ptr->direction), eye), 1);

	long double a = pow(varD.x, 2) + pow(varD.y, 2) + pow(varD.z, 2) - pow(cone_ptr->radius, 2) * pow(termQD, 2);
	long double b = 2 * (do_dot_product(varE, varD) - pow(cone_ptr->radius, 2) * termQD * termQE);
	long double c = pow(varE.x, 2) + pow(varE.y, 2) + pow(varE.z, 2) - pow(cone_ptr->radius, 2) * pow(termQE, 2);

	return get_cyl_cone_intersection(a, b, c, eye, dir_vec, object_ptr, length);
}
//function to rotate along the world coordinate system
void rotate_along(IFS_DATA* ifs_data,int axes)
{
  Matrix k;
  switch(axes)
  {
    case 1:
      k=return_rotate_x(theta);
      break;
    case 2:
      k=return_rotate_y(theta);
      break;
    case 3:
      k=return_rotate_z(theta);
      break;
  }
  
  vector temp;
  temp.A[0]=object_x;
  temp.A[1]=object_y;
  temp.A[2]=object_z;
  temp.A[3]=1.0;
  
  temp=multiply_vector(&k,&temp);
  
  object_x=temp.A[0];
  object_y=temp.A[1];
  object_z=temp.A[2];

int i,j;
  for (i=0; i<ifs_data->numVertices; ++i) 
  {
    vector v;
    v.A[0]=ifs_data->vertices[i].x;
    v.A[1]=ifs_data->vertices[i].y;
    v.A[2]=ifs_data->vertices[i].z;
    v.A[3]=1.0;

    switch(axes)
    {
      case 1:
	v=rotate_x(&v,angle_x);
	break;
      case 2:
	v=rotate_y(&v,angle_y);
	break;
      case 3:
	v=rotate_z(&v,angle_z);
	break;
    }
    ifs_data->vertices[i].x=v.A[0];
    ifs_data->vertices[i].y=v.A[1];
    ifs_data->vertices[i].z=v.A[2];   
  }
}
Example #10
0
/*
 * Returns the normal vector of a cone on a given position. The vector is
 * already normalized.
 *
 * posn: Position at which the intersection occured
 * cone_ptr: Pointer to a cone figure.
 */
Vector get_cone_normal_vector(Vector posn, void* cone_ptr)
{
	Cone cone = *((Cone*) cone_ptr);
	Vector border, normal_vec;
	border = subtract_vectors(posn, cone.anchor);
	long double distance = normalize_vector(&border);
	if(do_dot_product(border, cone.direction) < 0)
		distance *= -1;
	normal_vec = multiply_vector(1.0/ fabsl(distance), subtract_vectors(posn, get_ray_position(cone.anchor, cone.direction, distance * sqrt(2))));
	normalize_vector(&normal_vec);
	return normal_vec;
}
Example #11
0
//function to rotate the camera around camera coordinate system
Rotate_Camera_around_own_axis(float theta,int axes)
{
  vector v;
  v.A[0]=c_x;
  v.A[1]=c_y;
  v.A[2]=c_z;
  v.A[3]=1.0;
  
  vector v1;
  v1.A[0]=u_x;//-e_x;
  v1.A[1]=u_y;//-e_y;
  v1.A[2]=u_z;//-e_z;
  v1.A[3]=1.0;

  
  Matrix m;
  switch(axes)
  {
    case 1:
      m=return_rotate_x(theta);
      break;
    case 2:
      m=return_rotate_y(theta);
      break;
    case 3:
      m=return_rotate_z(theta);
      break;
  }
  
  v=multiply_vector(&m,&v);
//  printf("vector v again is \n");
 // print_vector(v);
  v1=multiply_vector(&m,&v1);
//  printf("vector v1 again is \n");
 // print_vector(v1);

 
 look_ortho(data,e_x,e_y,e_z,v.A[0],v.A[1],v.A[2],v1.A[0],v1.A[1],v1.A[2]);
  
}
Example #12
0
// my implementation of arbitrary axis
void rotate_arbit_axis(IFS_DATA *ifs_data,float x1,float y1,float z1,float x2,float y2,float z2,float theta)
{
  Matrix trans_matrix;
  int A[4][4]={{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};
  int i,j;
  for(i=0;i<4;i++)
    for(j=0;j<4;j++)
      trans_matrix.A[i][j]=A[i][j];
  
    Matrix T=return_translate(-x1,-y1,-z1);
  
  trans_matrix=T;

  
  float u=sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) +(z2-z1)*(z2-z1));
  float x=(x2-x1)/u;
  float y=(y2-y1)/u;
  float z=(z2-z1)/u;
  //printf("%f %f %f \n\n\n",x,y,z);
  
  Matrix R;
  float B[4][4]={{x*x*(1-cos(theta))+cos(theta),x*(1-cos(theta))*y+z*sin(theta),z*x*(1-cos(theta))-y*sin(theta),0.0}
	      ,{x*(1-cos(theta))*y-z*sin(theta),y*y*(1-cos(theta))+cos(theta),z*y*(1-cos(theta))+x*sin(theta),0.0}
	      ,{z*(1-cos(theta))*x+y*sin(theta),z*(1-cos(theta))*y-x*sin(theta),z*z*(1-cos(theta))+cos(theta),0.0}
	      ,{0.0,0.0,0.0,1.0}};
	

  for(i=0;i<4;i++)
    for(j=0;j<4;j++)
      R.A[i][j]=B[i][j];
  
  trans_matrix=multiply(R,trans_matrix);
    T=return_translate(x1,y1,z1);
    trans_matrix=multiply(T,trans_matrix);

  for (i=0; i<ifs_data->numVertices; ++i) 
  {
    vector v;
    v.A[0]=ifs_data->vertices[i].x;
    v.A[1]=ifs_data->vertices[i].y;
    v.A[2]=ifs_data->vertices[i].z;
    v.A[3]=1.0;
	v=multiply_vector(&trans_matrix,&v);
    //for(=0;i<4;i++)
    ifs_data->vertices[i].x=v.A[0];
    ifs_data->vertices[i].y=v.A[1];
    ifs_data->vertices[i].z=v.A[2];   
  }
    
    
}
Example #13
0
void Reflection::reciprocalAxes(vec *aStar, vec *bStar, vec *cStar)
{
    double volume = unitCellVolume();
    vec avec, bvec, cvec;
    realSpaceAxes(&avec, &bvec, &cvec);
    double alpha, beta, gamma;
    anglesAsRadians(&alpha, &beta, &gamma);
    double sinAlpha = sin(alpha);
    double sinBeta = sin(beta);
    double sinGamma = sin(gamma);
    
    *aStar = cross_product_for_vectors(bvec, cvec);
    double scalar = sinAlpha / volume;
    multiply_vector(aStar, scalar);

    *bStar = cross_product_for_vectors(avec, cvec);
    scalar = sinBeta / volume;
    multiply_vector(bStar, scalar);

    *cStar = cross_product_for_vectors(avec, bvec);
    scalar = sinGamma / volume;
    multiply_vector(cStar, scalar);
}
Example #14
0
void draw_vector_balls(SDL_Renderer* r, SDL_Texture* t, struct vector3d ball[], int size, int width, int height) {
	
	SDL_Rect  dest;

	dest.w = 20;
	dest.h = 20;

	int i;

	for (i = 0; i < size; i++) {

		struct vector3d z_translate = {0,0,2};	
		struct vector3d screen_translate = {width / 2 , height / 2, 0};	

		struct vector3d world = {ball[i].x, ball[i].y, ball[i].z};
		
		add_vector(&world, &z_translate);
		multiply_vector(&world, 100);
		add_vector(&world, &screen_translate);
		
		float inv = 400 - world.z;
		float interp = inv / 342;

		dest.w = 30 * interp;
		dest.h = 30 * interp;
		
		/*

		if (i == 0) {
			
			dest.w = 30;
			dest.h = 30;
			printf("z = %.1f\n", world.z);
		
		} else {
		
			dest.w = 20;
			dest.h = 20;
		}
		*/

		dest.x = world.x;
		dest.y = world.y;
		
		SDL_RenderCopy(r, t, NULL, &dest);	//draw screen pixel_buffer
	}

}
Example #15
0
/* @param t distance */
static intersection ray_hit_object(const point3 e, const point3 d,
                                   double t0, double t1,
                                   const rectangular_node rectangulars,
                                   rectangular_node *hit_rectangular,
                                   const sphere_node spheres,
                                   sphere_node *hit_sphere)
{
    /* set these to not hit */
    *hit_rectangular = NULL;
    *hit_sphere = NULL;

    point3 biased_e;
    multiply_vector(d, t0, biased_e);
    add_vector(biased_e, e, biased_e);

    double nearest = t1;
    intersection result, tmpresult;

    for (rectangular_node rec = rectangulars; rec; rec = rec->next) {
        if (rayRectangularIntersection(biased_e, d, &(rec->element),
                                       &tmpresult, &t1) && (t1 < nearest)) {
            /* hit is closest so far */
            *hit_rectangular = rec;
            nearest = t1;
            result = tmpresult;
        }
    }

    /* check the spheres */
    for (sphere_node sphere = spheres; sphere; sphere = sphere->next) {
        if (raySphereIntersection(biased_e, d, &(sphere->element),
                                  &tmpresult, &t1) && (t1 < nearest)) {
            *hit_sphere = sphere;
            *hit_rectangular = NULL;
            nearest = t1;
            result = tmpresult;
        }
    }

    return result;
}
void spacing_simulator_step(spacing_simulator *ss) {
    linked_list* vertices = ss->vg->vertices;
    linked_list* edges = ss->vg->edges;
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        v1->sim_data.speed = subtract_vector(make_vector_2d(400, 300), v1->position);
        v1->sim_data.speed = multiply_vector(normalize(v1->sim_data.speed), ss->origin_point_force);
        //debug_vector2d(v1->position, "POSITION");
        //debug_vector2d(v1->sim_data.speed, "SPEED");
        //debug("VVVVVVVVVV\n");
    }
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        for(node* j = i->next;j != NULL;j = j->next){
            visual_vertex* v2 = (visual_vertex*)j->element;
            vector_2d speed1 = subtract_vector(v1->position, v2->position);
            vector_2d speed2 = subtract_vector(v2->position, v1->position);
            float distance = calculate_distance(v1->position, v2->position);
            float force_factor = 100-distance;
            force_factor = (force_factor > 0 ? force_factor : 0)*2;
            speed1 = normalize(speed1);
            speed2 = normalize(speed2);
            speed1 = multiply_vector(speed1, force_factor);
            speed2 = multiply_vector(speed2, force_factor);
            v1->sim_data.speed = add_vector(v1->sim_data.speed, speed1);
            v2->sim_data.speed = add_vector(v2->sim_data.speed, speed2);
            //debug_vector2d(speed1, "SPEED1");
            //debug_vector2d(speed2, "SPEED2");
        }
    }
    for(node* i = edges->first;i != NULL;i = i->next){
        visual_edge* e = (visual_edge*)i->element;
        vector_2d pos1 = e->v1->position;
        vector_2d pos2 = e->v2->position;
        float distance = calculate_distance(pos1, pos2);
        vector_2d direction1 = normalize(subtract_vector(pos2, pos1));
        vector_2d direction2 = normalize(subtract_vector(pos1, pos2));
        vector_2d speed1 = multiply_vector(direction1, distance*distance/500);
        vector_2d speed2 = multiply_vector(direction2, distance*distance/500);
        e->v1->sim_data.speed = add_vector(e->v1->sim_data.speed, speed1);
        e->v2->sim_data.speed = add_vector(e->v2->sim_data.speed, speed2);
    }
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        v1->sim_data.speed = multiply_vector(v1->sim_data.speed, ss->friction_factor);
        v1->position = add_vector(v1->position, v1->sim_data.speed);
    }
}
Example #17
0
//function to scale the object around its own center
void scale_constant(IFS_DATA* ifs_data,float scale_x,float scale_y,float scale_z)
{
  int i,j;
  
    Matrix trans_matrix;
    
    Matrix T=return_translate(-1*object_x,-1*object_y,-1*object_z);
    Matrix scale=return_scale_Matrix(scale_x,scale_y,scale_z);
    
    trans_matrix=multiply(scale,T);
    
    T=return_translate(object_x,object_y,object_z);
    
    trans_matrix=multiply(trans_matrix,T);

    //print(trans_matrix);
    for (i=0; i<ifs_data->numVertices; ++i) 
  {
    vector v;
    v.A[0]=ifs_data->vertices[i].x;
    v.A[1]=ifs_data->vertices[i].y;
    v.A[2]=ifs_data->vertices[i].z;
    v.A[3]=1.0;
    
    //v=create_scale_Matrix(&v,scale_x,scale_y,scale_z);
    
    v=multiply_vector(&trans_matrix,&v);
    
    ifs_data->vertices[i].x=v.A[0];
    ifs_data->vertices[i].y=v.A[1];
    ifs_data->vertices[i].z=v.A[2];
      
  }
    
    
}
Example #18
0
/* @param r direction of reflected ray
 * @param d direction of primary ray into intersection
 * @param n surface normal at intersection
 */
static void reflection(point3 r, const point3 d, const point3 n)
{
    /* r = d - 2(d . n)n */
    multiply_vector(n, -2.0 * dot_product(d, n), r);
    add_vector(r, d, r);
}
Example #19
0
void look_ortho(IFS_DATA *ifs_data,float eye1_x,float eye1_y,float eye1_z,float center1_x,float center1_y,float center1_z,float up1_x,float up1_y,float up1_z)
{

    
    vector w, v, up,u;
    
    Matrix m;	
    
    
    w.A[0] = -1*(center1_x - eye1_x);
    w.A[1] = -1*(center1_y - eye1_y);
    w.A[2] = -1*(center1_z - eye1_z);
    w.A[3]=1.0;
    
   // printf("printing w\n");
   // print_vector(w);
    
    up.A[0] = up1_x;
    up.A[1] = up1_y;
    up.A[2] = up1_z;
    up.A[3]=1.0;

   // printf("printing up\n");
   // print_vector(up);
    
    w=normalize(w);

    float dot=up.A[0]*w.A[0]+up.A[1]*w.A[1]+up.A[2]*w.A[2];
    v.A[0]=up.A[0]-dot*w.A[0];
    v.A[1]=up.A[1]-dot*w.A[1];
    v.A[2]=up.A[2]-dot*w.A[2];
    v.A[3]=1.0;
    v=normalize(v);

    /* Side = forward x up */
    u=cross_product(v, w);
    //print_vector(side);
 //   side=normalize(side);

    /* Recompute up as: up = side x forward */
   // up=cross_product(side, f);

    //print_vector(up);  
    
    m.A[0][0] = u.A[0];
    m.A[1][0] = u.A[1];
    m.A[2][0] = u.A[2];
    m.A[3][0] = 0.0;

    
    m.A[0][1] = v.A[0];
    m.A[1][1] = v.A[1];
    m.A[2][1] = v.A[2];
    m.A[3][1] = 0.0;

    m.A[0][2] = w.A[0];
    m.A[1][2] = w.A[1];
    m.A[2][2] = w.A[2];
    m.A[3][2] = 0.0;
    
        m.A[0][3] = 0.0;
        m.A[1][3] = 0.0;
        m.A[2][3] = 0.0;
        m.A[3][3] = 1.0;
	Matrix T=return_translate(-eye1_x,-eye1_y,-eye1_z);
//	print(T);
    Matrix trans_matrix=multiply(m,T);
    
    
    vector o;
    o.A[0]=object_x;
    o.A[1]=object_y;
    o.A[2]=object_z;
    o.A[3]=1.0;
    o=multiply_vector(&trans_matrix,&o);
    
    object_x=o.A[0];
    object_y=o.A[1];
    object_z=o.A[2];

    //print_vector(o);
    
 //   print(trans_matrix);
    int i,j;
    
    
    
  for (i=0; i<ifs_data->numVertices; ++i) 
  {
    vector v;
    v.A[0]=ifs_data->vertices[i].x;
    v.A[1]=ifs_data->vertices[i].y;
    v.A[2]=ifs_data->vertices[i].z;
    v.A[3]=1.0;
	v=multiply_vector(&trans_matrix,&v);
    //for(=0;i<4;i++)
    ifs_data->vertices[i].x=v.A[0];
    ifs_data->vertices[i].y=v.A[1];
    ifs_data->vertices[i].z=v.A[2];   
  }

	

//    glMultMatrixf(&m[0][0]);
    //glTranslated(-eyex, -eyey, -eyez);

}
Example #20
0
/*
 * Adds the effect of the given light over the given intersection.
 *
 * light: Light that is being applied.
 * inter: Intersection over which the light is being applied.
 * normal_vec:  Normal vector of the intersection point. It is passed by as a
 *              parameter for optimization purposes.
 * rev_dir_vec: Reverse vector of the direction of the ray that comes from the
 *              eye. It is passed by as a parameter for optimization purposes.
 * all_lights_color: Accumulated amount of light sources effect. The effect of
 *              the given light is added to this total.
 * all_lights_color: Accumulated amount of the specular light effect. The
 *              specular effect of the given light is added to this total.
 * conf: Configuration of the scene.
 */
void apply_light_source(Light light,
                        Intersection inter,
                        Vector normal_vec,
                        Vector rev_dir_vec,
                        Color *all_lights_color,
                        long double *all_spec_light,
                        SceneConfig conf)
{
    Vector light_vec;
    long double light_distance, illum_cos, att_factor, spec_cos;
    Color light_filter;
    Intersection* shadow_inter;
    int shadow_i, shadow_inter_length;
    Object shadow_obj;

    // Find the vector that points from the intersection point to the light
    // source, and normalize it
    light_vec = subtract_vectors(light.anchor, inter.posn);
    light_distance = normalize_vector(&light_vec);
    // We check for any object making a shadow from that light
    light_filter = (Color){ .red = 1.0, .green = 1.0, .blue = 1.0 };;
    shadow_inter = get_intersections(inter.posn, light_vec, &shadow_inter_length, conf);
    // If the intersection is beyond the light source, we ignore it
    if(shadow_inter)
    {   // Object(s) is/are actually behind the light
        for(shadow_i = 0; shadow_i < shadow_inter_length && !is_color_empty(light_filter); shadow_i++)
        {
            if(shadow_inter[shadow_i].distance < light_distance)
            {
                shadow_obj = shadow_inter[shadow_i].obj;
                if(shadow_obj.translucency_material)
                {
                    light_filter = multiply_color(shadow_obj.translucency_material, multiply_colors(light_filter, shadow_obj.color));
                }
                else
                {
                    light_filter = get_empty_color();
                }
            }

        }
        if(!is_color_empty(light_filter))
        {
            free(shadow_inter);
            shadow_inter = NULL;
        }
    }
    // If there aren't any shadows
    if(!shadow_inter)
    {
        illum_cos = do_dot_product(normal_vec, light_vec);
        // We only take it into account if the angle is lower than 90 degrees
        if(illum_cos > 0)
        {
            Vector light_mirror_vec = subtract_vectors(multiply_vector(2 * illum_cos, normal_vec), light_vec);
            // Attenuation factor, reduces the light energy depending on the distance
            att_factor = get_attenuation_factor(light, light_distance);
            spec_cos = do_dot_product(rev_dir_vec, light_mirror_vec);
            // We add the light source effect
            light_filter = multiply_color(illum_cos * inter.obj.light_material * att_factor, light_filter);
            *all_lights_color = add_colors(*all_lights_color, multiply_colors(light_filter, light.color));
            // The specular light, is the white stain on the objects
            if(spec_cos > 0)
            {
                *all_spec_light += pow(spec_cos * inter.obj.specular_material * att_factor, inter.obj.specular_pow);
            }
        }
    }
    else free(shadow_inter);
}

/*
 * Gets the color of the intersection by calculating light intensity,
 * (which includes specular light, shadows, transparency, etc)
 *
 * light: Light for which the attenuation factor is calculated.
 * distance: Distance between the light and an illuminated spot.
 * mirror_level: Current level of reflection.
 * conf: Configuration of the scene.
 */
Color get_intersection_color(Vector eye,
                             Vector dir_vec,
                             Intersection *inter_list,
                             int inter_length,
                             int mirror_level,
                             int transparency_level,
                             SceneConfig conf)
{
    Intersection inter;
    int light_index;
    long double spec_light_factor, mirror_factor, transparency_factor;
    Vector normal_vec, rev_dir_vec, reflection_vec;
    Light light;
    Color all_lights_color, color_found, reflection_color,
          transparency_color, final_color;

    inter = inter_list[transparency_level];
    // Light intensity
    all_lights_color = (Color){ .red = 0.0, .green = 0.0, .blue = 0.0 };
    // Specular light intensity
    spec_light_factor = 0.0;
    normal_vec = get_normal_vector(&inter);
    // Pick up the normal vector that is pointing to the eye
    if(do_dot_product(normal_vec, dir_vec) > 0)
        normal_vec = multiply_vector(-1, normal_vec);
    // Initialize reverse direction vector for mirrors and specular light
    rev_dir_vec = multiply_vector(-1, dir_vec);
    for(light_index = 0; light_index < conf.lights_length; light_index++)
    {
        light = conf.lights[light_index];
        apply_light_source(light, inter, normal_vec, rev_dir_vec, &all_lights_color, &spec_light_factor, conf);
    }
    // We add the environmental light of the scene
    all_lights_color = add_colors(all_lights_color, multiply_color(inter.obj.light_ambiental, conf.environment_light));
    if(spec_light_factor > 1.0)
        spec_light_factor = 1.0;
    color_found = multiply_colors(all_lights_color, inter.obj.color);
    // Specular light gives a color between enlightened color and the light color.
    color_found.red += (1 - color_found.red) * spec_light_factor;
    color_found.green += (1 - color_found.green) * spec_light_factor;
    color_found.blue += (1 - color_found.blue) * spec_light_factor;
    // Get transparency color
    transparency_factor = inter.obj.transparency_material;
    if (transparency_level < conf.max_transparency_level &&
        transparency_factor > 0.0)
    {
        if(transparency_level + 1 < inter_length)
        {
            transparency_color = get_intersection_color(eye,dir_vec,inter_list,inter_length,0,transparency_level+1, conf);
        }
        else
        {
            transparency_color = conf.background;
        }
    }
    else
    {
        transparency_factor = 0.0;
        transparency_color = get_empty_color();
    }
    // Get reflection color
    mirror_factor = inter.obj.mirror_material;
    if (mirror_level < conf.max_mirror_level &&
        mirror_factor > 0.0)
    {
        reflection_vec = subtract_vectors(multiply_vector(2 * do_dot_product(normal_vec, rev_dir_vec), normal_vec), rev_dir_vec);
        reflection_color = get_color(inter.posn, reflection_vec, mirror_level + 1, conf);
    }
    else
    {
        mirror_factor = 0;
        reflection_color = get_empty_color();
    }
    // Calculate final color
    transparency_color = multiply_color(transparency_factor, transparency_color);
    reflection_color = multiply_color((1.0-transparency_factor) * mirror_factor, reflection_color);
    color_found = multiply_color((1.0-transparency_factor) * (1.0-mirror_factor), color_found);
    final_color = add_colors(transparency_color, add_colors(reflection_color, color_found));
    return final_color;
}

/*
 * Returns the color that is seen from the position 'eye' when looking at the
 * tridimensional scene towards the direction 'dir_vec'.
 *
 * eye: Position from which the scene is seen.
 * dir_vec: Direction at which the eye is looking. This vector must be normalized.
 * mirror_level: Current level of reflection.
 * conf: Configuration of the scene.
 */
Color get_color(Vector eye, Vector dir_vec, int mirror_level, SceneConfig conf)
{
	Intersection *inter_list;
	Color color;
	// Get intersections on the given direction. Intersections are ordered from the nearest to the farthest.
	int inter_list_length;
	inter_list = get_intersections(eye, dir_vec, &inter_list_length, conf);
	// If we don't find an intersection we return the background, otherwise we check for the intersections's color.
	if (!inter_list) return conf.background;
	color = get_intersection_color(eye, dir_vec, inter_list, inter_list_length, mirror_level, 0, conf);
	free(inter_list);
	return color;
}
Example #21
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

/* @param background_color this is not ambient light */
void raytracing(void* args)
{
    arg *data = (arg*) args;
    point3 u, v, w, d;
    color object_color = { 0.0, 0.0, 0.0 };

    const viewpoint *view = (*data).View;
    color back = { 0.0 , 0.1 , 0.1 };
    uint8_t *pixels = data->pixels;
    int start_j,end_j;

    /*	Separate to count the pixels  */
    if(pthread_equal(pthread_self(),THREAD[0])) {
        start_j = 0;
        end_j = 128;
    } else if(pthread_equal(pthread_self(),THREAD[1])) {
        start_j = 128;
        end_j = 256;
    } else if(pthread_equal(pthread_self(),THREAD[2])) {
        start_j = 256;
        end_j = 384;
    } else if(pthread_equal(pthread_self(),THREAD[3])) {
        start_j = 384;
        end_j = 512;
    }

    /* calculate u, v, w */
    calculateBasisVectors(u, v, w, view);

    idx_stack stk;

    int factor = sqrt(SAMPLES);

    #pragma omp parallel for num_threads(64)	\
    private(stk), private(d),	\
    private(object_color)
    for (int j = start_j ; j < end_j; j++) {
        for (int i = 0 ; i < (*data).row; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, u, v, w,
                                i * factor + s / factor,
                                j * factor + s % factor,
                                view,
                                (*data).row * factor, (*data).col * factor);
                if (ray_color(view->vrp, 0.0, d, &stk,(*data).rectangulars,
                              (*data).spheres, (*data).lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += back[0];
                    g += back[1];
                    b += back[2];
                }
                pixels[((i + (j * (*data).row)) * 3) + 0] = r * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 1] = g * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
}
Example #22
0
int main (int argc, char* args[]) {

	//SDL Window setup
	if (init(SCREEN_WIDTH, SCREEN_HEIGHT) == 1) {
		
		return 0;
	}

	int i = 0;
	int j = 0;
	int offset = 0;
	struct vector2d translation = {-SCREEN_WIDTH / 2, -SCREEN_HEIGHT / 2};

	//set up icons used to represent player lives
	for (i = 0; i < LIVES; i++) {
			
		init_player(&lives[i]);
		lives[i].lives = 1;

		//shrink lives
		for (j = 0; j < P_VERTS; j++) {
		
			divide_vector(&lives[i].obj_vert[j], 2);
		}

		//convert screen space vector into world space
		struct vector2d top_left = {20 + offset, 20};
		add_vector(&top_left, &translation);
		lives[i].location = top_left;
		update_player(&lives[i]);
		offset += 20;
	}

	//set up player and asteroids in world space
	init_player(&p);
	init_asteroids(asteroids, ASTEROIDS);

	int sleep = 0;
	int quit = 0;
	SDL_Event event;
	Uint32 next_game_tick = SDL_GetTicks();
	
	//render loop
	while(quit == 0) {
		
		//check for new events every frame
		SDL_PumpEvents();

		const Uint8 *state = SDL_GetKeyboardState(NULL);
		
		if (state[SDL_SCANCODE_ESCAPE]) {
		
			quit = 1;
		}
			
		if (state[SDL_SCANCODE_UP]) {

			struct vector2d thrust = get_direction(&p);
			multiply_vector(&thrust, .06);
			apply_force(&p.velocity, thrust);
		}
		
		if (state[SDL_SCANCODE_LEFT]) {
			
			rotate_player(&p, -4);
		}

		if (state[SDL_SCANCODE_RIGHT]) {
			
			rotate_player(&p, 4);
		}

		while (SDL_PollEvent(&event)) {
		
			switch(event.type) {
					
				case SDL_KEYDOWN:
					
					switch( event.key.keysym.sym ) {
					
						case SDLK_SPACE:
							
							if (p.lives > 0) {
								
								shoot_bullet(&p);
							}

							break; 
					}
			}
		}

		//draw to the pixel buffer
		clear_pixels(pixels, 0x00000000);
		draw_player(pixels, &p);
		draw_player(pixels, &lives[0]);
		draw_player(pixels, &lives[1]);
		draw_player(pixels, &lives[2]);
		draw_asteroids(pixels, asteroids, ASTEROIDS);
		update_player(&p);
		bounds_player(&p);
		bounds_asteroids(asteroids, ASTEROIDS);

		int res = collision_asteroids(asteroids, ASTEROIDS, &p.location, p.hit_radius);

		if (res != -1) {
			
			p.lives--;
			p.location.x = 0;
			p.location.y = 0;
			p.velocity.x = 0;
			p.velocity.y = 0;

			int i = LIVES - 1;

			for ( i = LIVES; i >= 0; i--) {
				
				if(lives[i].lives > 0) {
					
					lives[i].lives = 0;
					break;
				}
			}
		}
		
		int i = 0;
		struct vector2d translation = {-SCREEN_WIDTH / 2, -SCREEN_HEIGHT / 2};

		for (i = 0; i < BULLETS; i++) {
				
			//only check for collision for bullets that are shown on screen
			if (p.bullets[i].alive == TRUE) {
				
				//convert bullet screen space location to world space to compare
				//with asteroids world space to detect a collision
				struct vector2d world = add_vector_new(&p.bullets[i].location, &translation);
				int index = collision_asteroids(asteroids, ASTEROIDS, &world, 1);
				
				//collision occured
				if (index != -1) {
					
					asteroids[index].alive = 0;
					p.bullets[i].alive = FALSE;

					if (asteroids[index].size != SMALL) {
						
						spawn_asteroids(asteroids, ASTEROIDS, asteroids[index].size, asteroids[index].location);
					}
				}
			}
		}
		
		update_asteroids(asteroids, ASTEROIDS);

		//draw buffer to the texture representing the screen
		SDL_UpdateTexture(screen, NULL, pixels, SCREEN_WIDTH * sizeof (Uint32));

		//draw to the screen
		SDL_RenderClear(renderer);
		SDL_RenderCopy(renderer, screen, NULL, NULL);
		SDL_RenderPresent(renderer);
				
		//time it takes to render 1 frame in milliseconds
		next_game_tick += 1000 / 60;
		sleep = next_game_tick - SDL_GetTicks();
	
		if( sleep >= 0 ) {
            				
			SDL_Delay(sleep);
		}
	}

	//free the screen buffer
	free(pixels);
	
	//Destroy window 
	SDL_DestroyWindow(window);

	//Quit SDL subsystems 
	SDL_Quit(); 
	 
	return 0;
}
Example #23
0
/* @return 1 means hit, otherwise 0; */
static int rayRectangularIntersection(const point3 ray_e,
                                      const point3 ray_d,
                                      rectangular *rec,
                                      intersection *ip, double *t1)
{
    point3 e01, e03, p;
    subtract_vector(rec->vertices[1], rec->vertices[0], e01);
    subtract_vector(rec->vertices[3], rec->vertices[0], e03);

    cross_product(ray_d, e03, p);

    double det = dot_product(e01, p);

    /* Reject rays orthagonal to the normal vector.
     * I.e. rays parallell to the plane.
     */
    if (det < 1e-4)
        return 0;

    double inv_det = 1.0 / det;

    point3 s;
    subtract_vector(ray_e, rec->vertices[0], s);

    double alpha = inv_det * dot_product(s, p);

    if ((alpha > 1.0) || (alpha < 0.0))
        return 0;

    point3 q;
    cross_product(s, e01, q);

    double beta = inv_det * dot_product(ray_d, q);
    if ((beta > 1.0) || (beta < 0.0))
        return 0;

    *t1 = inv_det * dot_product(e03, q);

    if (alpha + beta > 1.0f) {
        /* for the second triangle */
        point3 e23, e21;
        subtract_vector(rec->vertices[3], rec->vertices[2], e23);
        subtract_vector(rec->vertices[1], rec->vertices[2], e21);

        cross_product(ray_d, e21, p);

        det = dot_product(e23, p);

        if (det < 1e-4)
            return 0;

        inv_det = 1.0 / det;
        subtract_vector(ray_e, rec->vertices[2], s);

        alpha = inv_det * dot_product(s, p);
        if (alpha < 0.0)
            return 0;

        cross_product(s, e23, q);
        beta = inv_det * dot_product(ray_d, q);

        if ((beta < 0.0) || (beta + alpha > 1.0))
            return 0;

        *t1 = inv_det * dot_product(e21, q);
    }

    if (*t1 < 1e-4)
        return 0;

    COPY_POINT3(ip->normal, rec->normal);
    if (dot_product(ip->normal, ray_d)>0.0)
        multiply_vector(ip->normal, -1, ip->normal);
    multiply_vector(ray_d, *t1, ip->point);
    add_vector(ray_e, ip->point, ip->point);

    return 1;
}
Example #24
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

static void *parallel (void* range1)
{
    Thread_range *range = (Thread_range *)range1;

    point3 d;
    idx_stack stk;
    color object_color = { 0.0, 0.0, 0.0 };

    for (int j = range->height1; j < range->height2; j++) {
        for (int i = 0; i < range->ptr->width; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, range->ptr->u,
				range->ptr->v, range->ptr->w,
                                i * range->ptr->factor + s / range->ptr->factor,
                                j * range->ptr->factor + s % range->ptr->factor,
                                range->ptr->view,
                                range->ptr->width * range->ptr->factor, 
				range->ptr->height * range->ptr->factor);
                if (ray_color(range->ptr->view->vrp, 0.0, d,
			      &(stk), range->ptr->rectangulars,
			      range->ptr->spheres,
                              range->ptr->lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += range->ptr->background_color[0];
                    g += range->ptr->background_color[1];
                    b += range->ptr->background_color[2];
                }
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 0] = r * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 1] = g * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
	return NULL;
}