示例#1
0
double			inter_triangle(t_object *obj, t_ray *ray)
{
	t_triangle	*tri;
	t_vec		w;
	t_vec		tmp;
	double		d;
	double		a;
	double		b;
	double		t;

	tri = &obj->prim.triangle;
	normalize(&ray->dir);
	if (!(d = -dot_product(&ray->dir, &tri->normal))) // si le triangle est parallele au rayon, on return 0
		return (0);
	w.x = ray->ori.x - tri->v1.x;
	w.y = ray->ori.y - tri->v1.y;
	w.z = ray->ori.z - tri->v1.z;
	mul_vec(&tmp, &w, &tri->v3);
	a = -dot_product(&tmp, &ray->dir) / d;
	mul_vec(&tmp, &tri->v2, &w);
	b = -dot_product(&tmp, &ray->dir) / d;
	mul_vec(&tmp, &tri->v2, &tri->v3);
	t = dot_product(&tmp, &w) / d;
	if (a > 0 && b > 0 && a + b <= 1)
		return (t);
	return (0);
}
示例#2
0
float CylinderObject::hit_test(const Ray &ray, Vector &normal, const Point *max_pos, bool *inside)
{
	Ray inv_ray;
	inv_ray.origin = mul_point(inv_trans, ray.origin);
	inv_ray.direction = mul_vec(inv_trans, ray.direction);
	inv_ray.direction.normalize();

	Vector c_normal;
	bool c_inside;
	double t = FLT_MAX;

	// check collision with cylinder body
	double c_t = hit_cylinder(inv_ray, c_normal, c_inside);
	if(c_t > FLT_EPSILON && c_t < t)
	{
		t = c_t;
		normal = c_normal;
		if(inside)
			*inside = c_inside;
	}

	// check collision with bottom disk
	c_t = hit_disk(inv_ray, c_normal, Vector(0, -1, 0), Point(0, bottom, 0));
	if(c_t > FLT_EPSILON && c_t < t)
	{
		t = c_t;
		normal = c_normal;
		if(inside)
			*inside = false;
	}

	// check collision with top disk
	c_t = hit_disk(inv_ray, c_normal, Vector(0, 1, 0), Point(0, top, 0));
	if(c_t > FLT_EPSILON && c_t < t)
	{
		t = c_t;
		normal = c_normal;
		if(inside)
			*inside = false;
	}

	double max_t;
    if(max_pos)
        max_t = (max_pos->x - ray.origin.x) / ray.direction.x;
    else
        max_t = FLT_MAX;

	if(t < max_t)
	{
		normal = mul_vec(inv_trans, normal);
		normal.normalize();
		return t;
	}
	else
		return -1.0;
}
示例#3
0
float SphereObject::hit_test(const Ray &ray, Vector &normal, const Point *max_pos, bool *inside)
{
	Ray inv_ray;
	inv_ray.origin = mul_point(inv_trans, ray.origin);
	inv_ray.direction = mul_vec(inv_trans, ray.direction);
	inv_ray.direction.normalize();

	Vector e = (inv_ray.origin - pos);
    double a = Vector::dot(inv_ray.direction, inv_ray.direction);
    double b = 2.0f * Vector::dot(inv_ray.direction, e);
    double c = Vector::dot(e, e) - std::pow(radius, 2);
    double delta = std::pow(b, 2) - 4*a*c;

	if(delta < FLT_EPSILON)
        return -1.0f;

    // Resolving the equation.
    delta = std::sqrt(delta);

    // Test both solutions.
    double t1 = (-b - delta) / (2.0f * a);
    double t2 = (-b + delta) / (2.0f * a);

    // Calculate the maximum t.
    double max_t;
    if(max_pos)
        max_t = (max_pos->x - inv_ray.origin.x) / inv_ray.direction.x;
    else
        max_t = FLT_MAX;

    // t1 is always smaller than t2 because it uses -b -discriminant.
    if(t1 > FLT_EPSILON && t1 < max_t)
	{
        if(inside)	*inside = false;
		Point intersection = inv_ray.origin + t1 * inv_ray.direction;
		normal = (intersection - pos).normalize();
		normal = mul_vec(inv_trans, normal);
		normal.normalize();
        return t1;
    }
    else if(t2 > FLT_EPSILON && t2 < max_t)
	{
        if(inside)	*inside = true;
		Point intersection = inv_ray.origin + t2* inv_ray.direction;
		normal = (intersection - pos).normalize();
		normal = mul_vec(inv_trans, normal);
		normal.normalize();
        return t2;
    }
    else
        return -1.0f;
}
示例#4
0
int			ft_interconew(t_vec rayorg, t_vec raydir, t_obj *obj)
{
	t_cylinder cone;

	cone.a = ft_dotw(raydir, raydir) - obj->radius * (raydir.w * raydir.w);
	cone.b = ft_dotw(mul_vec(sub_vec(rayorg, obj->pos), 2.0), raydir) \
			- obj->radius * (raydir.w * raydir.w);
	cone.c = ft_dotw(obj->pos, obj->pos) + ft_dotw(rayorg, rayorg) - (2.0 * \
			ft_dotw(rayorg, obj->pos)) - obj->radius * (raydir.w * raydir.w);
	cone.delt = pow(cone.b, 2) - (4.0 * cone.a * cone.c);
	if (cone.delt >= 0)
	{
		cone.a1 = ((-1.0 * cone.b) - sqrt(cone.delt)) / (2.0 * cone.a);
		cone.b1 = ((-1.0 * cone.b) + sqrt(cone.delt)) / (2.0 * cone.a);
		if (cone.b1 > cone.a1)
			cone.ret = cone.a1;
		else
			cone.ret = cone.b1;
		if (cone.a1 <= 0 && cone.b1 <= 0)
			return (0);
	}
	else
		return (0);
	return (cone.ret);
}
示例#5
0
t_vec	raytracer(t_rayparams *params)
{
	t_raytracer *ray;

	ray = init_ray(params->over.l);
	first_loop(ray, params->dir, params->o);
	if (!ray->ret)
		return (ray->color);
	*(params->distance) = ray->ret2;
	if (ray->ret->light == TRUE)
		return (set_vec(1, 1, 1));
	ray->pi = add_vec(params->o, mul_vec(params->dir, ray->ret2));
	ray->tmp = params->over.l;
	while (ray->tmp)
	{
		if (ray->tmp->light == TRUE)
		{
			set_nray(ray, params->over.l, params->dir, params->o);
			shade(ray, params->dir);
		}
		ray->tmp = ray->tmp->next;
	}
	reflexion(ray, params);
	refraction(ray, params);
	return (ray->color);
}
示例#6
0
void	specular(t_raytracer *ray, t_vec dir)
{
	t_specular spc;

	if (ray->ret->specular > 0)
	{
		spc.r_spect = 2.0f * DOT(ray->l, ray->n);
		spc.r_spec = mul_vec(ray->n, spc.r_spect);
		spc.r_spec = sub_vec(ray->l, spc.r_spec);
		spc.dot_spec = DOT(dir, spc.r_spec);
		if (spc.dot_spec > 0)
		{
			spc.spect_diff = powf(spc.dot_spec, 20)
				* ray->ret->specular * ray->shade;
			spc.ret_spec = mul_vec(ray->tmp->col, spc.spect_diff);
			ray->color = add_vec(ray->color, spc.ret_spec);
		}
	}
}
示例#7
0
void	set_nray(t_raytracer *ray, t_obj *l, t_vec dir, t_vec o)
{
	ray->shade = 1.0f;
	if (ray->tmp->type == SPHERE)
		tmp_type_sphere(ray, l);
	if (ray->ret->type == SPHERE)
	{
		ray->n = sub_vec(ray->pi, ray->ret->pos);
		ray->n = mul_vec(ray->n, 1.0f / ray->ret->radius);
	}
	else if (ray->ret->type == PLAN)
		ray->n = ray->ret->pos;
	else
		ray->n = set_nvec(ray->ret, dir, o, ray->ret2);
}
示例#8
0
float TorusObject::hit_test(const Ray &ray, Vector &normal, const Point *max_pos, bool *inside)
{
	Ray inv_ray;
	inv_ray.origin = mul_point(inv_trans, ray.origin);
	inv_ray.direction = mul_vec(inv_trans, ray.direction);
	inv_ray.direction.normalize();

	double x1 = inv_ray.origin.x; double y1 = inv_ray.origin.y; double z1 = inv_ray.origin.z;
	double d1 = inv_ray.direction.x; double d2 = inv_ray.direction.y; double d3 = inv_ray.direction.z;

	double coeffs[5];	// coefficient array
	double roots[4];	// solution array

	//define the coefficients
	double sum_d_sqrd = d1*d1 + d2*d2 + d3*d3;
	double e = x1*x1 + y1*y1 + z1*z1 - radius*radius - thickness*thickness;
	double f = x1*d1 + y1*d2 + z1*d3;
	double four_a_sqrd = 4.0 * radius*radius;

	coeffs[0] = e*e - four_a_sqrd * (thickness*thickness-y1*y1);	// constante term
	coeffs[1] = 4.0 * f * e + 2.0 * four_a_sqrd * y1 *d2;
	coeffs[2] = 2.0 * sum_d_sqrd * e + 4.0 * f * f + four_a_sqrd * d2 * d2;
	coeffs[3] = 4.0 * sum_d_sqrd * f;
	coeffs[4] = sum_d_sqrd * sum_d_sqrd;	// coefficient of t^4

	//fin the roots
	int num_real_roots = solveQuartic(coeffs, roots);

	bool intersected = false;
	double t = FLT_MAX;

	if ( num_real_roots == 0)	// ray misses the torus
		return -1.0;

	//find the smallest root greater than FLT_EPSILON, if any
	for( int j = 0; j < num_real_roots; j++)
	{
		if(roots[j] > FLT_EPSILON)
		{
			intersected = true;
			if(roots[j] < t)
				t = roots[j];
		}
	}

	double max_t;
    if(max_pos)
        max_t = (max_pos->x - ray.origin.x) / ray.direction.x;
    else
        max_t = FLT_MAX;

	if( t > max_t || !intersected)
		return -1.0;


	Point hit = inv_ray.origin + t*inv_ray.direction;
	normal = compute_normal(hit);
	normal = mul_vec(inv_trans, normal);
	normal.normalize();
	return t;
}