Beispiel #1
0
// Moeller-Trumbore
bool Triangle::hit(const Ray& ray, const Ray_Tracer* rt,
                    float t_min, float t_max, Ray_Hit& rh, bool shadow) const {

    // Absolute Triangle Vertex Positions
    V3& v0 = m->verts[inds[0]];
    V3& v1 = m->verts[inds[1]];
    V3& v2 = m->verts[inds[2]];

    // Two edges of triangle
    V3 e0, e1;
    e0 = v1 - v0;
    e1 = v2 - v0; 

    V3 p = ray.s.cross(e1);
    float deter = e0.dot(p);

    if (deter  > -EPSILON && deter < EPSILON)
        return false; 

    V3 t = ray.o - v0;
    
    // Store the inverse to reduce divisions
    float inv_deter = 1.0 / deter;
    float u = t.dot(p) * inv_deter;

    if (u < 0.0 || u > 1.0)
        return false;

    V3 q = t.cross(e0);
    float v = ray.s.dot(q) * inv_deter;

    if (v < 0.0 || u + v > 1.0)
        return false;

    float t_inter = e1.dot(q) * inv_deter;

    if (t_inter < t_min || t_inter > t_max) {
        //std::cout << "Cull: " << t_inter << '\t' <<t_min<< '\t' <<t_max<<  std::endl;
        return false;
    }

    rh.t = t_inter;
    rh.col = 0.2*m->mat.col;
    rh.shape = m;

    if (shadow || ray.depth >= rt->depth_limit)
        return true;

/*
    if (is_light) {     
        rh.col = Color(1.0, 1.0, 1.0);
        return true;
    }
*/

    V3 int_loc = ray.at(t_inter);
    // Shadow
    for (Shape* light : rt->lights) {

        // BIG ASSUMPTION THAT ALL LIGHTS ARE SPHERES
        Sphere* sph = static_cast<Sphere*>(light);

        // Make ray from intersection to light
        V3 int_to_light = sph->c - int_loc; 
        float dist_to_light = int_to_light.norm();
        int_to_light.normalize();
        Ray shadow_ray(int_loc + EPSILON*int_to_light, int_to_light, ray.depth + 1);
        Ray_Hit shadow_hit;
        if (rt->kd->hit_helper(true, rt->kd->root, shadow_ray, rt,
                EPSILON, dist_to_light, shadow_hit, true, 0)) {
            if (!shadow_hit.shape->is_light) {
                continue;
            }
        }

        float inner = int_to_light.dot(normal);
        if (inner > 0.0) {
            rh.col += sph->mat.col *inner* m->mat.diff * m->mat.col;
        }
    }

    // Reflection 
    V3 refl_dir = ray.s - 2.0f * (normal.dot(ray.s)) * normal;
    Ray refl_ray(int_loc + EPSILON*refl_dir, refl_dir, ray.depth + 1);
    Ray_Hit refl_hit;
    if (rt->kd->hit_helper(true, rt->kd->root, refl_ray, rt,
            EPSILON, FLT_MAX, refl_hit, false, 0)) {
    //if (rt->trace(refl_ray, EPSILON, FLT_MAX, refl_hit, false)) {
        rh.col += m->mat.refl*refl_hit.col * refl_hit.shape->mat.col;
    }

    return true;  
}
Beispiel #2
0
RGB Scene::trace(Ray ray, double ray_intensity, int trace_depth)
{
	RGB result(0.0, 0.0, 0.0);
	if (trace_depth > MAX_DEPTH) return (result);
	if (ray_intensity < MIN_INTENSITY) return (result);

	Intersection min_hit;
	min_hit.dist = MAX_DIST;
	bool intersected = false;

	for(int i = 0; i < active_prims; i++)
	{
		Intersection current_hit;
		if(prim_refs[i]->get_intersect(ray, current_hit)
			&& current_hit.dist < min_hit.dist) 
		{
			min_hit = current_hit;
			intersected = true;
		}
	}
	//std::cout << "intersection pos:" << intersect.pos.x[0] << " " << intersect.pos.x[1] << " " << intersect.pos.x[2] << "\n";

	//if(!intersected) std::cout << "wtf negz no hit\n";
	//  returns pure black
	if (!intersected) return (result);

	//  slight adjustment to prevent floating-point inaccuracy from 
	//  causing unwanted collisions
	min_hit.pos += min_hit.normal * 0.0001;

	//if (intersected) std::cout << "adjusted min_hition pos:" << min_hit.pos.x[0] << " " << min_hit.pos.x[1] << " " << min_hit.pos.x[2] << "\n";
	for (int i = 0; i < active_lights; i++)
	{
		Vec3 lightray;
		//  deposits lightray in lightray variable
		bool shadowed = check_shadowing(light_refs[i], min_hit.pos, lightray);
		if (!shadowed)
		{
			// currently ignores color of light
			result += min_hit.shape_ref->get_diff_mat() 
				* std::max( dot(min_hit.normal, lightray), 0.0 );

			//  reflection
			Vec3 R = lightray - min_hit.normal * 2 * dot( lightray, min_hit.normal );
			double specdot = dot( R, min_hit.dir );
			if (specdot > 0)
				result += min_hit.shape_ref->get_spec_mat() * pow( specdot, 20 );
		}
	//if(shadowed) std::cout <<" wtf negz shadowed at:" << min_hit.pos.x[0] << " " << min_hit.pos.x[1] << " " << min_hit.pos.x[2] << "\n";
	//else std::cout << "plane normal: " << min_hit.dir.x[0] << " " << min_hit.dir.x[1] << " " << min_hit.dir.x[2] << "\n";
	//else std::cout << "dot result: " << dot(min_hit.dir, lposdir) << "\n";
	}
	
	//  reflection
	double obj_refl = min_hit.shape_ref->get_reflection();
	if (obj_refl > 0.0) {
		Vec3 refl_dir = ray.dir - min_hit.normal * 2 * dot( ray.dir, min_hit.normal );
		Ray refl_ray ( min_hit.pos, refl_dir );
		result += trace( refl_ray, obj_refl * ray_intensity, trace_depth + 1 );
	}

	//  refraction
	double obj_transp = min_hit.shape_ref->get_transparency();
	if (obj_transp > 0.0) {
		//  check that when transp not 0, refr not 0.
		double obj_refr = min_hit.shape_ref->get_refraction();
		//  check htis
		double cos_term = dot( ray.dir, min_hit.normal ) ;
		double nr = (cos_term < 0.0) ? (1 / obj_refr) : (obj_refr);
		double sin0t2 = nr*nr * (1 - pow(cos_term, 2));
		if (sin0t2 < 1.0)
		{
			Vec3 refracted_dir = ray.dir * nr
				- min_hit.normal * (nr * abs(cos_term) - sqrt(1 - sin0t2));
			assert(refracted_dir.mag() > 0.0);
			Vec3 irpos = (cos_term < 0.0) ? 
				(min_hit.pos - min_hit.normal * 0.0002) : (min_hit.pos);
			Ray refr_ray ( irpos, refracted_dir);
			result += trace( refr_ray, obj_transp * ray_intensity, trace_depth + 1 );
		}
	}

	for (int i = 0; i < 3; i++) result.x[i] = std::min(result.x[i], 1.0);

	assert(ray_intensity <= 1.0);

	return (result * ray_intensity);
}