int	intersect_shadow(float t, t_scene *scene, t_ray *ray)
{
	t_vec3	intersect_pt;
	t_ray	shadow;
	float	t_tmp;

	intersect_pt.x = ray->o.x + t * ray->d.x;
	intersect_pt.y = ray->o.y + t * ray->d.y;
	intersect_pt.z = ray->o.z + t * ray->d.z;
	init_coord(&shadow.o, 0, 0, -30);
	init_vec3(&(shadow.d), shadow.o.x - intersect_pt.x, shadow.o.y - intersect_pt.y, shadow.o.z - intersect_pt.z);
	t_tmp = -1;
	while (scene != NULL)
	{
		if (scene->type == CIRCLE)
			t_tmp = intersect_circle(&shadow, scene->object);
		else if (scene->type == PLANE)
			t_tmp = intersect_plane(&shadow, scene->object);
		else if (scene->type == CYLINDER)
			t_tmp = intersect_cylinder(&shadow, scene->object);
		if (t_tmp > 0)
		{
			return (1);
		}
		scene = scene->next;
	}
	return (0);
}
/* Function that returns whether a ray intersects a capped cylinder and fills out a variable
   for the distance from the ray's origin to the intersection if there is one and also
   fills out the "type" of the intersection -- 1 for a cylinder body intersection, 2 for a top cap
   intersection, and 3 for a bottom cap intersection */
bool intersect_capped_cylinder(const ray3f& ray, float r, float h, float& t, int& type) {
    bool valid_intersect = false;
    t = ray.tmax;
    vec3f intersect = zero3f;
    /* Check whether the ray intersects the cylinder body,
       ensuring that the intersection is not between the end caps.
       Note: most of this code is from the previous function, written
       by Jon Denning */
    if(intersect_cylinder(ray, r, h, t)) {
            valid_intersect = true;
            type = BODY;
    }

    /* Now check the circles on top/bottom of cylinder
       http://orca.st.usm.edu/~jchen/courses/graphics/lectures/Raytracing.pdf
       proved helpful for this section of the code */

    /* Using the notes on ray-plane intersection... */
    /* Intersect the top end cap, first; intersect the plane at {0, 0, h} */
    vec3f n = vec3f(0, 0, 1); // Normal
    vec3f c = vec3f(0, 0, h); // Center
    float t_cap;
    if (dot(ray.d, n) != 0) {
        t_cap = dot((c-ray.e), n)/dot(ray.d, n);
        if (t_cap >= ray.tmin && t_cap <= ray.tmax) {
            intersect = ray.eval(t_cap);
            if((intersect.x * intersect.x + intersect.y * intersect.y) <= r*r) {
                if(t_cap < t) {
                    t = t_cap;
                    valid_intersect = true;
                    type = CAP_TOP;
                }
            }
        }
    }

    /* Intersect the bottom end cap; intersect the plane at {0, 0, 0} */
    n = vec3f(0, 0, -1);
    c = vec3f(0, 0, 0);
    if (dot(ray.d, n) != 0) {
        t_cap = dot((c-ray.e), n)/dot(ray.d, n);
        if (t_cap >= ray.tmin && t_cap <= ray.tmax) {
            intersect = ray.eval(t_cap);
            if((intersect.x * intersect.x + intersect.y * intersect.y) <= r*r) {
                if(t_cap < t) {
                    t = t_cap;
                    valid_intersect = true;
                    type = CAP_BOT;
                }
            }
        }
    }

    if(valid_intersect) return true;
    else return false;
}
hit_test intersect (ray r, object o)
{
  switch (o.tag) {
  case SPHERE :
    return intersect_sphere(r, o.o.s);
  case POSTER :
    return intersect_poster(r, o.o.p);
  case CYLINDER :
    return intersect_cylinder(r, o.o.cyl);
  }
  fprintf(stderr, "invalid object tag\n");
  exit(1);
}
Exemple #4
0
int			intersect_prim(t_env *e, t_ray *ray, size_t prim, double *t)
{
	if (e->prim[prim]->type == PRIM_SPHERE)
		return (intersect_sphere(ray, e->prim[prim], t));
	if (e->prim[prim]->type == PRIM_HEMI_SPHERE)
		return (intersect_hemi_sphere(ray, e->prim[prim], t));
	if (e->prim[prim]->type == PRIM_PLANE)
		return (intersect_plane(ray, e->prim[prim], t));
	if (e->prim[prim]->type == PRIM_CYLINDER)
		return (intersect_cylinder(ray, e->prim[prim], t));
	if (e->prim[prim]->type == PRIM_CONE)
		return (intersect_cone(ray, e->prim[prim], t));
	if (e->prim[prim]->type == PRIM_DISK)
		return (intersect_disk(ray, e->prim[prim], t));
	return (0);
}
Exemple #5
0
void			get_nearest_cylinder(t_vector ray, t_object *cylinder,
	t_surface *surface, t_scene *scene)
{
	t_double2		distance;
	t_surface		*tmp;
	t_vector		ray_s;

	ray_s = transform_ray(ray, cylinder);
	if (intersect_cylinder(ray_s, cylinder, &distance))
	{
		tmp = cut_object(ray, cylinder, distance, scene);
		if (tmp->object != NULL && (surface->distance == -1 || surface->distance > tmp->distance))
		{
			surface->object = tmp->object;
			surface->distance = tmp->distance;
			surface->normal = tmp->normal;
			// surface->color = tmp->object->color;
			surface->color = cylindrical_mapping(scene, surface, ray_s, cylinder);
			free(tmp);
		}
	}
}
/* 
 *The timestep and collision situations are used to find points of
 * contact and new velocities after balls hit each other
 */
void compute_velocities()
{
  double rt,rt2,rt4,lamda=10000;
  TVector norm,uveloc;
  TVector normal,point;
  double RestTime,BallTime;
  TVector col_pos;
  int ball=0,ball1,ball2;
  TVector Nc;
  int j;
  
  RestTime = TimeStep;
  lamda = 1000;

  /* Compute velocity for next timestep using Euler equations */
  for (j = 0; j < ball_count; j++) {
    ball_vel[j]-= (ball_vel[j] * friction);
  }

  /* while timestep not over */
  while (RestTime>ZERO) {
    lamda = 10000;   /* initialize to very large value */
    
    /* For all the balls find closest intersection between 
     * balls and planes/cylinders */
    for (int i = 0; i < ball_count; i++) {
      /* compute new position and distance */
      old_pos[i] = ball_pos[i];
      TVector::unit(ball_vel[i],uveloc);
      ball_pos[i] = ball_pos[i]+ball_vel[i]*RestTime;
      rt2 = old_pos[i].dist(ball_pos[i]);

      /* Now test intersection with the outer cylinder */      
      if (intersect_cylinder(cyl1,old_pos[i],uveloc,rt,norm,Nc)) {

	rt4 = rt*RestTime / rt2;

	if (rt4 <= lamda) { 
	  if (rt4 <= RestTime+ZERO)
	    if (! ((rt <= ZERO)&&(uveloc.dot(norm) < ZERO)) ) {
	      normal=norm;
	      point=Nc;
	      lamda=rt4;
	      ball=i;
	    }
	}	
      }
    }
    
    /* After all balls were tested with planes/cylinders test for collision 
     * between them and replace if collision time smaller */
    if (find_collision(col_pos,BallTime,RestTime,ball1,ball2)) {
      if ( (lamda == 10000) || (lamda > BallTime) ) {
	RestTime = RestTime-BallTime;
	
	TVector pb1,pb2,xaxis,U1x,U1y,U2x,U2y,V1x,V1y,V2x,V2y;
	double a,b;
	
	pb1=old_pos[ball1]+ball_vel[ball1]*BallTime; // Find position of ball1
	pb2=old_pos[ball2]+ball_vel[ball2]*BallTime; // Find position of ball2
	xaxis=(pb2-pb1).unit();
	
	a=xaxis.dot(ball_vel[ball1]);

	/* U1 and U2 are the velocity vectors of the two spheres at the 
	 * time of impact */
	U1x=xaxis*a;
	U1y=ball_vel[ball1]-U1x;
	
	xaxis=(pb1-pb2).unit();


	b=xaxis.dot(ball_vel[ball2]);
	U2x=xaxis*b;
	U2y=ball_vel[ball2]-U2x;


	/* V1,V2 are the new velocities after the impact */
	V1x=( (U1x*mass[ball1]+U2x*mass[ball2] - 
	     (U1x-U2x))*mass[ball2] ) * 
	  (1 / (mass[ball1] + mass[ball2]));
	V2x=( (U1x*mass[ball1]+U2x*mass[ball2] - 
	     (U2x-U1x))*mass[ball1] ) * 
	  (1 / (mass[ball1] + mass[ball2]));
	V1y=U1y;
	V2y=U2y;
	
	for (j=0;j<ball_count;j++)
	  ball_pos[j]=old_pos[j]+ball_vel[j]*BallTime;
	
	ball_vel[ball1]=V1x+V1y;
	ball_vel[ball2]=V2x+V2y;
	/* continue; */
	
	give_point(ball1, ball2);
      }
    }
    
    /* End of tests */
    /* If test occured move simulation for the correct timestep */
    /* and compute response for the colliding ball */
    if (lamda!=10000) {		 
      RestTime-=lamda;
      
      for (j=0;j<ball_count;j++)
	ball_pos[j]=old_pos[j]+ball_vel[j]*lamda;
      
      rt2=ball_vel[ball].mag();
      ball_vel[ball].unit();
      ball_vel[ball]=TVector::unit( (normal*(2*normal.dot(-ball_vel[ball]))) + 
				      ball_vel[ball] );
      ball_vel[ball]=ball_vel[ball]*rt2;
    }
    else {
      RestTime=0;    
    }
  }
}
Exemple #7
0
GimpRGB
get_ray_color_cylinder (GimpVector3 *pos)
{
  GimpVector3       lvp, ldir, vp, p, dir, ns, nn;
  GimpRGB            color, color2;
  gfloat            m[16];
  gint              i;
  FaceIntersectInfo face_intersect[2];

  color = background;
  vp = mapvals.viewpoint;
  p = *pos;

  vp.x = vp.x - mapvals.position.x;
  vp.y = vp.y - mapvals.position.y;
  vp.z = vp.z - mapvals.position.z;

  p.x = p.x - mapvals.position.x;
  p.y = p.y - mapvals.position.y;
  p.z = p.z - mapvals.position.z;

  /* Compute direction */
  /* ================= */

  gimp_vector3_sub (&dir, &p, &vp);
  gimp_vector3_normalize (&dir);

  /* Compute inverse of rotation matrix and apply it to   */
  /* the viewpoint and direction. This transforms the     */
  /* observer into the local coordinate system of the box */
  /* ==================================================== */

  memcpy (m, rotmat, sizeof (gfloat) * 16);

  transpose_mat (m);

  vecmulmat (&lvp, &vp, m);
  vecmulmat (&ldir, &dir, m);

  if (intersect_cylinder (lvp, ldir, face_intersect) == TRUE)
    {
      /* We've hit the cylinder. Transform the hit points and */
      /* normals back into the world coordinate system        */
      /* ==================================================== */

      for (i = 0; i < 2; i++)
        {
          vecmulmat (&ns, &face_intersect[i].s, rotmat);
          vecmulmat (&nn, &face_intersect[i].n, rotmat);

          ns.x = ns.x + mapvals.position.x;
          ns.y = ns.y + mapvals.position.y;
          ns.z = ns.z + mapvals.position.z;

          face_intersect[i].s = ns;
          face_intersect[i].n = nn;
        }

      color = get_cylinder_color (face_intersect[0].face,
				  face_intersect[0].u,
				  face_intersect[0].v);

      /* Check for transparency... */
      /* ========================= */

      if (color.a < 1.0)
        {
          /* Hey, we can see  through here!      */
          /* Lets see what's on the other side.. */
          /* =================================== */

          color = phong_shade (&face_intersect[0].s,
			       &mapvals.viewpoint,
			       &face_intersect[0].n,
			       &mapvals.lightsource.position,
			       &color,
			       &mapvals.lightsource.color,
			       mapvals.lightsource.type);

          gimp_rgb_clamp (&color);

          color2 = get_cylinder_color (face_intersect[1].face,
				       face_intersect[1].u,
				       face_intersect[1].v);

          /* Make the normal point inwards */
          /* ============================= */

          gimp_vector3_mul (&face_intersect[1].n, -1.0);

          color2 = phong_shade (&face_intersect[1].s,
				&mapvals.viewpoint,
				&face_intersect[1].n,
				&mapvals.lightsource.position,
				&color2,
				&mapvals.lightsource.color,
				mapvals.lightsource.type);

          gimp_rgb_clamp (&color2);

          if (mapvals.transparent_background == FALSE && color2.a < 1.0)
            {
	      gimp_rgb_composite (&color2, &background,
				  GIMP_RGB_COMPOSITE_BEHIND);
            }

          /* Compute a mix of the first and second colors */
          /* ============================================ */

	  gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
          gimp_rgb_clamp (&color);
        }
      else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT)
        {
	  color = phong_shade (&face_intersect[0].s,
			       &mapvals.viewpoint,
			       &face_intersect[0].n,
			       &mapvals.lightsource.position,
			       &color,
			       &mapvals.lightsource.color,
			       mapvals.lightsource.type);

	  gimp_rgb_clamp (&color);
        }
    }
  else
    {
      if (mapvals.transparent_background == TRUE)
	gimp_rgb_set_alpha (&color, 0.0);
    }

  return color;
}