예제 #1
0
파일: Cone.cpp 프로젝트: JeffOwOSun/Trace
bool Cone::intersectBody( const ray& r, isect& i ) const
{
	vec3f d = r.getDirection();
	vec3f p = r.getPosition();

	double a = (d[0]*d[0]) + (d[1]*d[1]) - (C*d[2]*d[2]);
	double b = 2.0 * (d[0]*p[0] + d[1]*p[1] - C*d[2]*p[2]) - B*d[2];
	double c = (p[0]*p[0]) + (p[1]*p[1]) - A - (B*p[2]) - (C*p[2]*p[2]);

	double disc = b*b - 4.0*a*c;

	if( disc <= 0.0 ) {
		return false;
	}

	disc = sqrt( disc );

	double t1 = (-b - disc) / (2.0 * a);
	double t2 = (-b + disc) / (2.0 * a);

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= height ) {
			// It's okay.
			i.t = t1;
			double p3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
			i.N = vec3f(P[0], P[1], p3).normalize();
#ifdef _DEBUG
			printf("two intersections!\n");
#endif
			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= height ) {
		i.t = t2;
		double p3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
		i.N = vec3f(P[0], P[1], p3).normalize();
		// In case we are _inside_ the _uncapped_ cone, we need to flip the normal.
		// Essentially, the cone in this case is a double-sided surface
		// and has _2_ normals
	
		if( !capped && (i.N).dot( r.getDirection() ) > 0 )
				i.N = -i.N;
#ifdef _DEBUG
		printf("one intersection!\n");
#endif
        return true;
	}

	return false;
}
예제 #2
0
bool Sphere::intersectLocal( const ray& r, isect& i ) const
{
	Vec3d v = -r.getPosition();
	double b = v * r.getDirection();
	double discriminant = b*b - v*v + 1;

	if( discriminant < 0.0 ) {
		return false;
	}

	discriminant = sqrt( discriminant );
	double t2 = b + discriminant;

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	i.obj = this;

	double t1 = b - discriminant;

	if( t1 > RAY_EPSILON ) {
		i.t = t1;
		i.N = r.at( t1 );
		i.N.normalize();
	} else {
		i.t = t2;
		i.N = r.at( t2 );
		i.N.normalize();
	}

	return true;
}
예제 #3
0
Segments CSGNode::intersectLocal(const ray& r) const{
	Segments ret;
	if (isLeaf){
		SegmentPoint pNear, pFar;
		isect i;
		ray backR(r.at(-10000), r.getDirection());
		if(!item->intersect(backR, i))return ret;
		pNear.t = i.t - 10000;
		pNear.normal = i.N;
		pNear.isRight = false;
		ray contiR(r.at(pNear.t+RAY_EPSILON*10),r.getDirection());
		if (!item->intersect(contiR, i))pFar = pNear;
		else {
			pFar.t = i.t + pNear.t;
			pFar.normal = i.N;
		}
		pFar.isRight = true;
		ret.addPoint(pNear);
		ret.addPoint(pFar);
		return ret;
	}
	else {
		if (!lchild || !rchild)return ret;
		Segments leftSeg, rightSeg;
		leftSeg = lchild->intersectLocal(r);
		rightSeg = rchild->intersectLocal(r);
		leftSeg.Merge(rightSeg,relation);
		return leftSeg;
	}
}
bool Cylinder::intersectCaps( const ray& r, isect& i ) const
{
	if( !capped ) {
		return false;
	}

	double pz = r.getPosition()[2];
	double dz = r.getDirection()[2];

	if( 0.0 == dz ) {
		return false;
	}

	double t1;
	double t2;

	if( dz > 0.0 ) {
		t1 = (-pz)/dz;
		t2 = (1.0-pz)/dz;
	} else {
		t1 = (1.0-pz)/dz;
		t2 = (-pz)/dz;
	}

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 >= RAY_EPSILON ) {
		vec3f p( r.at( t1 ) );
		if( (p[0]*p[0] + p[1]*p[1]) <= 1.0 ) {
			i.t = t1;
			if( dz > 0.0 ) {
				// Intersection with cap at z = 0.
				i.N = vec3f( 0.0, 0.0, -1.0 );
			} else {
				i.N = vec3f( 0.0, 0.0, 1.0 );
			}
			return true;
		}
	}

	vec3f p( r.at( t2 ) );
	if( (p[0]*p[0] + p[1]*p[1]) <= 1.0 ) {
		i.t = t2;
		if( dz > 0.0 ) {
			// Intersection with cap at z = 1.
			i.N = vec3f( 0.0, 0.0, 1.0 );
		} else {
			i.N = vec3f( 0.0, 0.0, -1.0 );
		}
		return true;
	}

	return false;
}
예제 #5
0
파일: Cone.cpp 프로젝트: logchan/COMP4411
bool Cone::intersectBody( const ray& r, isect& i ) const
{
	vec3f d = r.getDirection();
	vec3f p = r.getPosition();

	double a = (d[0]*d[0]) + (d[1]*d[1]) - (C*d[2]*d[2]);
	double b = 2.0 * (d[0]*p[0] + d[1]*p[1] - C*d[2]*p[2]) - B*d[2];
	double c = (p[0]*p[0]) + (p[1]*p[1]) - A - (B*p[2]) - (C*p[2]*p[2]);

	double disc = b*b - 4.0*a*c;

	if( disc <= 0.0 ) {
		return false;
	}

	disc = sqrt( disc );

	double t1 = (-b - disc) / (2.0 * a);
	double t2 = (-b + disc) / (2.0 * a);

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= height ) {
			double n3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
			i.t = t1;
            i.N = vec3f( P[0], P[1], n3).normalize();
				
			if (!capped && (i.N).dot(r.getDirection()) > 0)
				i.N = -i.N;

			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= height ) {
		double n3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
		i.t = t2;
        i.N = vec3f( P[0], P[1], n3).normalize();
	
		if( !capped && (i.N).dot( r.getDirection() ) > 0 )
				i.N = -i.N;

        return true;
	}

	return false;
}
예제 #6
0
// Intersect ray r with the triangle abc.  If it hits returns true,
// and puts the t parameter, barycentric coordinates, normal, object id,
// and object material in the isect object
bool TrimeshFace::intersectLocal( const ray& r, isect& i ) const
{
  const Vec3d& a = parent->vertices[ids[0]];
  const Vec3d& b = parent->vertices[ids[1]];
  const Vec3d& c = parent->vertices[ids[2]];

  // tangent vectors
  Vec3d t1 = b - a;
  Vec3d t2 = c - a;
  
  Vec3d n = crossProd(t1,t2);

  double D = -n*a;

  // if the surface is parallel to the ray there is no intersection
  if(r.getDirection()*n == 0)
  {
    return false;
  }  

  double t = -(n*r.getPosition() + D)/(n*r.getDirection() );
  if (t <= RAY_EPSILON)
    return false;

  // point of intersection with the same plane (doesn't mean intersection with triangle) p(t)=p+t*d
  Vec3d p = r.at(t);

  // triangle area
  double A = n.length()/2.0;

  // barycentric coords
  double wa = crossProd(c-b, p-b).length() / (2.0*A);
  double wb = crossProd(a-c, p-c).length() / (2.0*A);
  double wc = crossProd(b-a, p-a).length() / (2.0*A);

  if((wa >= 0.0) && (wb >= 0.0) && (wc >= 0.0) && (wa+wb+wc-1.0 <= 0.00001)) {
    i.setT(t);
    i.setBary(wa, wb, wc);
    if (parent->normals.size() == 0) {
      i.setN(n);
    } else {
      Vec3d inter_n = wa*parent->normals[ids[0]] + wb*parent->normals[ids[1]]
                    + wc*parent->normals[ids[2]];
      inter_n.normalize();
      i.setN(inter_n);
    }
    i.setObject(this);
    if (parent->materials.size() == 0) {
      i.setMaterial(this->getMaterial() );
    } else {
      Material inter_m = wa*(*parent->materials[ids[0]]);
      inter_m += wb*(*parent->materials[ids[1]]);
      inter_m += wc*(*parent->materials[ids[2]]);
      i.setMaterial(inter_m);
    }
    return true;
  }

  return false;
}
예제 #7
0
파일: Square.cpp 프로젝트: logchan/COMP4411
bool Square::intersectLocal( const ray& r, isect& i ) const
{
	vec3f p = r.getPosition();
	vec3f d = r.getDirection();

	if( d[2] == 0.0 ) {
		return false;
	}

	double t = -p[2]/d[2];

	if( t <= RAY_EPSILON ) {
		return false;
	}

	vec3f P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = vec3f( 0.0, 0.0, -1.0 );
	} else {
		i.N = vec3f( 0.0, 0.0, 1.0 );
	}

	return true;
}
예제 #8
0
// Apply the Blinn-Phong model to this point on the surface of the object, 
//  returning the color of that point.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
	// YOUR CODE HERE

		// For now, this method just returns the diffuse color of the object.
		// This gives a single matte color for every distinct surface in the
		// scene, and that's it.  Simple, but enough to get you started.
		// (It's also inconsistent with the Phong model...)

		// Your mission is to fill in this method with the rest of the phong
		// shading model, including the contributions of all the light sources.
		// You will need to call both distanceAttenuation() and shadowAttenuation()
		// somewhere in your code in order to compute shadows and light falloff.
		if (debugMode)
			std::cout << "Debugging the Phong code (or lack thereof...)" << std::endl;

		// When you're iterating through the lights,
		// you'll want to use code that looks something
		// like this:
		Vec3d light = ke(i);
		Vec3d normal = i.N;
		Vec3d iDot = r.at(i.t);
		if (r.getDirection() * normal > 0) {
			normal = -normal;
			light += prod(prod(scene->ambient(), ka(i)), kt(i));
		}
		else {
			light += prod(scene->ambient(), ka(i));
		}

		for (vector<Light*>::const_iterator litr = scene->beginLights();
			litr != scene->endLights();
			++litr)
		{
			Light* pLight = *litr;

			double distAttenuation = pLight->distanceAttenuation(iDot);
			Vec3d shadowAttenuation = pLight->shadowAttenuation(iDot);
			Vec3d atten = distAttenuation * shadowAttenuation;
			Vec3d L = pLight->getDirection(iDot);


			if (L * normal > 0) {
				Vec3d H = (L + -1 * r.getDirection());
				if (H.length() != 0)
					H.normalize();

				double sDot = max(0.0, normal * H);
				Vec3d dTerm = kd(i) * (normal * L);
				Vec3d sTerm = ks(i) * (pow(sDot, shininess(i)));
				Vec3d newLight = dTerm + sTerm;
				newLight = prod(newLight, pLight->getColor());

				light += prod(atten, newLight);
			}
		}

	return light;
}
예제 #9
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade(Scene *scene, const ray& r, const isect& i) const
{
  const Material& m = i.getMaterial();

  Vec3d I = m.ke(i) + prod(m.ka(i) ,scene->ambient());
  Vec3d R = 2*(-r.getDirection() * i.N)*i.N +r.getDirection();

  for ( vector<Light*>::const_iterator litr = scene->beginLights(); 
  		litr != scene->endLights(); 
  		++litr )
  {
  		Vec3d atten = (*litr)->distanceAttenuation(r.at(i.t)) * (*litr)->shadowAttenuation(r,r.at(i.t));
      I += prod(atten,(m.kd(i)*max((i.N * (*litr)->getDirection(r.at(i.t)) ), 0.0) + m.ks(i) * max(((scene->getCamera().getEye() - r.at(i.t)) *R),0.0)));
  }

  // You will need to call both the distanceAttenuation() and
  // shadowAttenuation() methods for each light source in order to
  // compute shadows and light falloff.

  return I;
}
예제 #10
0
	double surface_planeDIY::hit(const ray &emission_ray, const surface **hit_surface_ptr) const {
		double t = surface_plane::hit(emission_ray, hit_surface_ptr);
		point3D hit_point;
		double x, y;

		if (t < epsilon) return -1;
		hit_point = emission_ray.at(t);
		x = (hit_point - point_on_plane) * axis_x;
		y = (hit_point - point_on_plane) * axis_y;
		if (fn(x, y)) return t;
		return -1;
	}
예제 #11
0
파일: material.cpp 프로젝트: ohwang/Trace
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
vec3f Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
	// YOUR CODE HERE

	// For now, this method just returns the diffuse color of the object.
	// This gives a single matte color for every distinct surface in the
	// scene, and that's it.  Simple, but enough to get you started.
	// (It's also inconsistent with the phong model...)

	// Your mission is to fill in this method with the rest of the phong
	// shading model, including the contributions of all the light sources.
    // You will need to call both distanceAttenuation() and shadowAttenuation()
    // somewhere in your code in order to compute shadows and light falloff.
	
	//intersection point
	vec3f point = r.at(i.t);
	bool istransmissive = abs(index - 1.0) > NORMAL_EPSILON || !kt.iszero();
	vec3f rate = vec3f(1, 1, 1) - kt;

	vec3f I = ke;

	//ambient
	if (istransmissive) I += scene->ambient.time(ka).time(rate).clamp();
	else I += scene->ambient.time(ka).clamp();

	list<Light*>::const_iterator begin = scene->beginLights();
	list<Light*>::const_iterator end = scene->endLights();
	while (begin != end)
	{
		vec3f atten = (*begin)->shadowAttenuation(point) * (*begin)->distanceAttenuation(point);
		vec3f L = (*begin)->getDirection(point);
		double NL = i.N.dot(L);

		//diffuse
		if (istransmissive) I += (atten * NL).time(kd).time(rate).clamp();
		else I += (atten * NL).time(kd).clamp();

		//specular
		vec3f R = i.N * (2 * NL) - L;
		double RV = -R.dot(r.getDirection());
		
		//TODO: where is n£¿
		double n = 64;
		I += (atten * pow(RV, n)).time(ks).clamp();

		begin++;
	}

	return I;
}
예제 #12
0
//Test
// now the object is in the local coordinate rather than the global
bool Square::intersectLocal( const ray& r, isect& i ) const
{
	// get the parameters of the ray 
	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	// if the ray is perpendicular to the z-axis
	if( d[2] == 0.0 ) {
		return false;
	}

	// calculate the value of t
	double t = -p[2]/d[2];

	// if the intersection is too close to the source
	// then we don't count that as a intersection
	if( t <= RAY_EPSILON ) {
		return false;
	}

	
	Vec3d P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = Vec3d( 0.0, 0.0, -1.0 );
	} else {
		i.N = Vec3d( 0.0, 0.0, 1.0 );
	}

    i.setUVCoordinates( Vec2d(P[0] + 0.5, P[1] + 0.5) );
	return true;
}
예제 #13
0
파일: light.cpp 프로젝트: JeffOwOSun/Trace
vec3f PointLight::_shadowAttenuation(const vec3f& P, const ray& r) const
{
	double distance = (position - P).length();
	vec3f d = r.getDirection();
	vec3f result = getColor(P);
	vec3f curP = r.getPosition();
	isect isecP;
	ray newr(curP, d);
	while (scene->intersect(newr, isecP))
	{
		//prevent going beyond this light
		if ((distance -= isecP.t) < RAY_EPSILON) return result;
		//if not transparent return black
		if (isecP.getMaterial().kt.iszero()) return vec3f(0, 0, 0);
		//use current intersection point as new light source
		curP = r.at(isecP.t);
		newr = ray(curP, d);
		result = prod(result, isecP.getMaterial().kt);
	}
	return result;
}
예제 #14
0
	intersection_context surface_mobius::intersect(const ray &emission_ray) const {
		if (!collision_test(emission_ray)) {
			return null_intersect;
		}

		double ox = emission_ray.origin.x;
		double oy = emission_ray.origin.y;
		double oz = emission_ray.origin.z;
		double dx = emission_ray.dir.x;
		double dy = emission_ray.dir.y;
		double dz = emission_ray.dir.z;
		double R = radius;
		
		double coef_0 = 0, coef_1 = 0, coef_2 = 0, coef_3 = 0;

		coef_0 = ox * ox * oy + oy * oy * oy - 2 * ox * ox * oz - 2 * oy * oy * oz + oy * oz * oz - 2 * ox * oz * R - oy * R * R;
		coef_1 = dy * ox * ox - 2 * dz * ox * ox + 2 * dx * ox * oy + 3 * dy * oy * oy - 2 * dz * oy * oy - 4 * dx * ox * oz - 4 * dy * oy * oz + 2 * dz * oy * oz + dy * oz * oz - 2 * dz * ox * R - 2 * dx * oz * R - dy * R * R;
		coef_2 = 2 * dx * dy * ox - 4 * dx * dz * ox + dx * dx * oy + 3 * dy * dy * oy - 4 * dy * dz * oy + dz * dz * oy - 2 * dx * dx * oz - 2 * dy * dy * oz + 2 * dy * dz * oz - 2 * dx * dz * R;
		coef_3 = dx * dx * dy + dy * dy * dy - 2 * dx * dx * dz - 2 * dy * dy * dz + dy * dz * dz;

		std::vector<double> coef, result;

		coef.push_back(coef_0);
		coef.push_back(coef_1);
		coef.push_back(coef_2);
		coef.push_back(coef_3);

		result = equation_solve(coef, 3);

		for (std::vector<double>::iterator iter = result.begin(); iter != result.end(); ++iter) {
			if (*iter > epsilon && inside(emission_ray.at(*iter))) {
				return intersection_context(*iter);
			}
		}

		return null_intersect;
	}
예제 #15
0
//Test
bool Square::intersectLocal(ray& r, isect& i) const
{
	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	if( d[2] == 0.0 ) {
		return false;
	}

	double t = -p[2]/d[2];

	if( t <= RAY_EPSILON ) {
		return false;
	}

	Vec3d P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.setMaterial(this->getMaterial());
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = Vec3d( 0.0, 0.0, -1.0 );
	} else {
		i.N = Vec3d( 0.0, 0.0, 1.0 );
	}

    i.setUVCoordinates( Vec2d(P[0] + 0.5, P[1] + 0.5) );
	return true;
}
예제 #16
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
vec3f RayTracer::traceRay( Scene *scene, const ray& r, 
	const vec3f& thresh, int depth )
{
	isect i;
	const double maxDepth = TraceUI::getInstance()->getDepth();

	if (scene->intersect(r, i)) {
		// YOUR CODE HERE
		// An intersection occured!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		if (isLeavingObject(&m)) {
			i.N = -i.N;								// Normal has to be flipped when leaving object
		}

		vec3f result = m.shade(scene, r, i);

		if (depth < maxDepth) {
			//reflection
			const vec3f& u = r.getDirection();										//ray direction
			const vec3f& refl_dir = (u - 2.0 * u.dot(i.N) * i.N).normalize();		//reflection direction
			const vec3f& isect_pos = r.at(i.t);										//intersection point
			//new ray, push forward a bit to avoid intersect itself
			const ray refl_r(isect_pos + refl_dir * RAY_EPSILON, refl_dir);
			const vec3f& refl_contri = prod(m.kr, traceRay(scene, refl_r, thresh, depth + 1));
			result = result + refl_contri;

			//refraction
			if (!m.kt.iszero()) {
				double eta;
				if (isLeavingObject(&m)) {
					material_stack.pop_front();
					eta = m.index / material_stack.front()->index; 			// refraction index ratio
				}
				else {
					eta = material_stack.front()->index / m.index;			// refraction index ratio
					material_stack.push_front(&m);
				}

				const double k = 1.0 - eta * eta * (1.0 - u.dot(i.N) * u.dot(i.N));

				if (!(k < 0.0)) {							// k < 0.0 = internal reflection
					const vec3f& refr_dir = eta * u - (eta * u.dot(i.N) + sqrt(k)) * u;
					const ray refr_r(isect_pos + refr_dir * RAY_EPSILON, refr_dir);
					const vec3f& refr_contri = prod(m.kt, traceRay(scene, refr_r, thresh, depth + 1));
					result = result + refr_contri;
				}
			}
		}

		return result;
	
	} else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		return vec3f( 0.0, 0.0, 0.0 );
	}
}
예제 #17
0
파일: Cone.cpp 프로젝트: JeffOwOSun/Trace
bool Cone::intersectCaps( const ray& r, isect& i ) const
{
	if( !capped ) {
		return false;
	}

	double pz = r.getPosition()[2];
	double dz = r.getDirection()[2];

	if( 0.0 == dz ) {
		return false;
	}

	double t1;
	double t2;
	double r1;
	double r2;

	if( dz > 0.0 ) {
		t1 = (-pz)/dz;
		t2 = (height-pz)/dz;
		r1 = b_radius;
		r2 = t_radius;
	} else {
		t1 = (height-pz)/dz;
		t2 = (-pz)/dz;
		r1 = t_radius;
		r2 = b_radius;
	}

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 >= RAY_EPSILON ) {
		vec3f p( r.at( t1 ) );
		if( (p[0]*p[0] + p[1]*p[1]) <= r1 * r1 ) {
			i.t = t1;
			if( dz > 0.0 ) {
				// Intersection with cap at z = 0.
				i.N = vec3f( 0.0, 0.0, -1.0 );
			} else {
				i.N = vec3f( 0.0, 0.0, 1.0 );
			}
			return true;
		}
	}

	vec3f p( r.at( t2 ) );
	if( (p[0]*p[0] + p[1]*p[1]) <= r2 * r2 ) {
		i.t = t2;
		if( dz > 0.0 ) {
			// Intersection with interior of cap at z = 1.
			i.N = vec3f( 0.0, 0.0, 1.0 );
		} else {
			i.N = vec3f( 0.0, 0.0, -1.0 );
		}
		return true;
	}

	return false;
}
예제 #18
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
Vec3d RayTracer::traceRay(ray& r, int depth)
{
    isect i;
    Vec3d colorC;
    if(scene->intersect(r, i))
    {
        const Material& m = i.getMaterial();
        colorC = m.shade(scene, r, i);

        if(depth <= 0)
            return colorC;

        Vec3d q = r.at(i.t);

        Vec3d rayDir = -1 * r.getDirection();
        rayDir.normalize();

        //REFLECTION
        Vec3d reflectionIntensity = m.kr(i);

        Vec3d reflectDir = 2 * (rayDir * i.N) * i.N - rayDir;
        reflectDir.normalize();

        ray reflected(q, reflectDir, ray::REFLECTION);

        reflectionIntensity %= traceRay(reflected, depth - 1);
        colorC += reflectionIntensity;
        //END REFLECTION

        //REFRACTION
        Vec3d refractionIntensity = m.kt(i);
        double indexRatio, flip;

        if(refractionIntensity[0] <= 0.0 && refractionIntensity[1] <= 0.0 && refractionIntensity[2] <= 0.0)
        {
            return colorC;
        }

        if(i.N * r.getDirection() < 0.0)
        {
            indexRatio = 1.0 / m.index(i);
            flip = -1;
        }
        else
        {
            indexRatio = m.index(i) / 1.0;
            flip = 1;
        }

        //Check for TIR
        if(i.N * r.getDirection() > 0.0f)
        {
            double iAngle = i.N * r.getDirection();
            if((1 - (indexRatio*indexRatio*(1.0f - iAngle * iAngle))) < 0.0)
                return colorC;
        }

        Vec3d rayNormalPart = (rayDir * i.N) * i.N;
        Vec3d rayTangentialPart = rayNormalPart - rayDir;

        Vec3d refractTangential = (indexRatio) * rayTangentialPart;

        double temp = refractTangential * refractTangential;
        if(temp > 1) temp = 0;

        Vec3d refractNormal = (flip * i.N) * sqrt( 1.0 - temp);

        Vec3d refractDir = refractNormal + refractTangential;
        reflectDir.normalize();

        ray refracted(q, refractDir, ray::REFRACTION);
        refractionIntensity %= traceRay(refracted, depth - 1);

        colorC += refractionIntensity;
        //END REFRACTION
    }
    else
    {
        //do cube mapping?
        if(!traceUI->doCubeMap())
            return Vec3d(0,0,0);


        TextureMap* texture;
        double u, v;
        Vec3d direction = r.getDirection();
        double x = direction.n[0];
        double y = direction.n[1];
        double z = direction.n[2];

        double max = std::abs(x);
        if(std::abs(y) > max) max = std::abs(y);
        if(std::abs(z) > max) max = std::abs(z);


        if(max == std::abs(x))
        {
            if(x < 0)
            {
                texture = cubeMap->getXnegMap();
                u = ((z/std::abs(x)) + 1)/2;
                v = ((y/std::abs(x)) + 1)/2;
            }
            else
            {
                texture = cubeMap->getXposMap();
                u = ((-z/std::abs(x)) + 1)/2;
                v = ((y/std::abs(x)) + 1)/2;
            }
        }
        else if(max == std::abs(y))
        {
            if(y < 0)
            {
                texture = cubeMap->getYnegMap();
                u = ((x/std::abs(y)) + 1)/2;
                v = ((z/std::abs(y)) + 1)/2;
            }
            else
            {
                texture = cubeMap->getYposMap();
                u = ((x/std::abs(y)) + 1)/2;
                v = ((-z/std::abs(y)) + 1)/2;
            }
        }
        else
        {
            if(z < 0)
            {
                texture = cubeMap->getZnegMap();
                u = ((-x/std::abs(z)) + 1)/2;
                v = ((y/std::abs(z)) + 1)/2;
            }
            else
            {
                texture = cubeMap->getZposMap();
                u = ((x/std::abs(z)) + 1)/2;
                v = ((y/std::abs(z)) + 1)/2;
            }
        }

        colorC = texture->getMappedValue(Vec2d(u,v));

    }
    return colorC;
}
예제 #19
0
vec3f RayTracer::traceRay( Scene *scene, const ray& r, 
	const vec3f& thresh, int depth, isect& i, vector<const SceneObject*>& stack )
{
	if( depth>=0
		&& thresh[0] > threshold - RAY_EPSILON && thresh[1] > threshold - RAY_EPSILON && thresh[2] > threshold - RAY_EPSILON
		&& scene->intersect( r, i ) ) {
		// YOUR CODE HERE

		// An intersection occured!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.
		
		const Material& m = i.getMaterial();
		vec3f color = m.shade(scene, r, i);
		//calculate the reflected ray
		vec3f d = r.getDirection();
		vec3f position = r.at(i.t);
		vec3f direction = d - 2 * i.N * d.dot(i.N);
		ray newray(position, direction);
		if(!m.kr.iszero()) {
			vec3f reflect = m.kr.multiply(traceRay(scene, newray, thresh.multiply(m.kr), depth-1, stack).clamp());
			color += reflect;
		}

		//calculate the refracted ray
		double ref_ratio;
		double sin_ang = d.cross(i.N).length();
		vec3f N = i.N;
		//Decide going in or out
		const SceneObject *mi = NULL, *mt = NULL;
		int stack_idx = -1;
		vector<const SceneObject*>::reverse_iterator itr;
		//1 use the normal to decide whether to go in or out
		//0: travel through, 1: in, 2: out
		char travel = 0;
		if(i.N.dot(d) <= -RAY_EPSILON) {
			//from outer surface in
			//test whether the object has two face
			ray test_ray(r.at(i.t) + d * 2 * RAY_EPSILON, -d);
			isect test_i;
			if(i.obj->intersect(r, test_i) && test_i.N.dot(N) > -RAY_EPSILON) {
				//has interior
				travel = 1;
			}
		}
		else {
			travel = 2;
		}

		if(travel == 1) {
			if(!stack.empty()) {
				mi = stack.back();
			}
			mt = i.obj;
			stack.push_back(mt);
		}
		else if(travel == 2) {
			//if it is in our stack, then we must pop it
			for(itr = stack.rbegin(); itr != stack.rend(); ++itr) {
				if(*itr == i.obj) {
					mi = *itr;
					vector<const SceneObject*>::iterator ii = itr.base() - 1;
					stack_idx = ii - stack.begin();
					stack.erase(ii);
					break;
				}
			}
			if(!stack.empty()) {
				mt = stack.back();
			}
		}

		if(N.dot(d) >= RAY_EPSILON) {
			N = -N;
		}
		
		ref_ratio = (mi?(mi->getMaterial().index):1.0) / (mt?(mt->getMaterial().index):1.0);

		if(!m.kt.iszero() && (ref_ratio < 1.0 + RAY_EPSILON || sin_ang < 1.0 / ref_ratio + RAY_EPSILON)) {
			//No total internal reflection
			//We do refraction now
			double c = N.dot(-d);
			direction = (ref_ratio * c - sqrt(1 - ref_ratio * ref_ratio * (1 - c * c))) * N + ref_ratio * d;
			newray = ray(position, direction);
			vec3f refraction = m.kt.multiply(traceRay(scene, newray, thresh.multiply(m.kt), depth-1, stack).clamp());
			color += refraction;
		}

		if(travel == 1) {
			stack.pop_back();
		}
		else if(travel == 2) {
			if(mi) {
				stack.insert(stack.begin() + stack_idx, mi);
			}
		}

		return color;

	} else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		if(m_bBackground && bg) {
			double u, v;
			angleToSphere(r.getDirection(), u, v);
			//Scale to [0, 1];
			u /= 2 * M_PI;
			v /= M_PI;
			int tx = int(u * bg_width), ty = bg_height - int(v * bg_height);
			return vec3f(bg[3 * (ty * bg_width + tx)] / 255.0, bg[3 * (ty * bg_width + tx) + 1] / 255.0, bg[3 * (ty * bg_width + tx) + 2] / 255.0);
		}
		else {
			return vec3f( 0.0, 0.0, 0.0 );
		}
	}
}
예제 #20
0
// Apply the Phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i, bool isInAir ) const
{
	// YOUR CODE HERE

	// For now, this method just returns the diffuse color of the object.
	// This gives a single matte color for every distinct surface in the
	// scene, and that's it.  Simple, but enough to get you started.
	// (It's also inconsistent with the Phong model...)

	// Your mission is to fill in this method with the rest of the phong
	// shading model, including the contributions of all the light sources.
    // You will need to call both distanceAttenuation() and shadowAttenuation()
    // somewhere in your code in order to compute shadows and light falloff.

	// When you're iterating through the lights,
	// you'll want to use code that looks something
	// like this:
	//
	// for ( vector<Light*>::const_iterator litr = scene->beginLights();
	// 		litr != scene->endLights(); 
	// 		++litr )
	// {
	// 		Light* pLight = *litr;
	// 		.
	// 		.
	// 		.
	// }

    const Vec3d point = r.at(i.t);

    // Start with emitted light.
    Vec3d shade = ke(i);
    
    // Add ambient light effects.
    Vec3d ambient = prod(ka(i), scene->ambient());
    if (!isInAir)
    {
        // If shading a point inside an object, ambient light had to pass through the object first.
        // So apply the transmission factor to the ambient light to account for object's affect on light.
        ambient = prod(kt(i), ambient);
    }
    shade += ambient;
    
    // For each light source...
    for (vector<Light*>::const_iterator literator = scene->beginLights(); literator != scene->endLights(); ++literator)
    {
        const Light* light = *literator;
        const Vec3d lightDirection = light->getDirection(point);
        const Vec3d shadowAttenuation = light->shadowAttenuation(point);
        const double distanceAttenuation = light->distanceAttenuation(point);
        const Vec3d intensity = prod(light->getColor(point), shadowAttenuation * distanceAttenuation);
        if (debugMode) cerr << "Shadow: " << shadowAttenuation << ", Distance: " << distanceAttenuation << endl;
        
        // Calculate diffuse term.
        const Vec3d diffuseTerm = kd(i) * max(0.0, i.N * lightDirection);
        
        // Calculate specular term.
        const Vec3d reflectionDir = 2.0 * (lightDirection * i.N) * i.N - lightDirection;
        const Vec3d viewingDir = -r.getDirection();
        const Vec3d specularTerm = ks(i) * pow(max(0.0, viewingDir * reflectionDir), shininess(i));
        
        // Apply diffuse and specular terms to light source.
        shade += prod(intensity, diffuseTerm + specularTerm);
        if (debugMode) cerr << "Diffuse: " << diffuseTerm << ", Specular: " << specularTerm << endl;
    }
    
	return shade;
}
예제 #21
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade(Scene *scene, const ray& r, const isect& i) const
{
  //YOUR CODE HERE
  Vec3d part_e = ke(i);
  Vec3d part_a = ka(i) % scene->ambient();

  Vec3d part_ds(0, 0, 0);

  for ( vector<Light*>::const_iterator litr = scene->beginLights(); 
    litr != scene->endLights(); 
    ++litr )
  {
    Light* pLight = *litr;

    Vec3d N = i.N;
    Vec3d L = pLight->getDirection(r.at(i.t));
    L.normalize();

    Vec3d V = r.d;
    V.normalize();

    Vec3d R = 2*max((L*N), 0.0)*N-L;
    R.normalize();

    double ns = shininess(i);

    Vec3d shadowAttenuation = pLight->shadowAttenuation(r, r.at(i.t));
    double distanceAttenuation = min(pLight->distanceAttenuation(r.at(i.t)), 1.0);

    Vec3d lightIntensity;
    if(traceUI->shadowSw()){
      lightIntensity = pLight->getColor() % shadowAttenuation * distanceAttenuation;
    }else{
      lightIntensity = pLight->getColor() * distanceAttenuation;
    }
    part_ds += prod(lightIntensity, (kd(i)*max(N*L, 0.0)+ks(i)*pow(max((-V*R), 0.0), ns)));

  }

  return part_e + part_a + part_ds;


  // For now, this method just returns the diffuse color of the object.
  // This gives a single matte color for every distinct surface in the
  // scene, and that's it.  Simple, but enough to get you started.
  // (It's also inconsistent with the phong model...)

  // Your mission is to fill in this method with the rest of the phong
  // shading model, including the contributions of all the light sources.

  // When you're iterating through the lights,
  // you'll want to use code that looks something
  // like this:
  //
  // for ( vector<Light*>::const_iterator litr = scene->beginLights(); 
  // 		litr != scene->endLights(); 
  // 		++litr )
  // {
  // 		Light* pLight = *litr;
  // 		.
  // 		.
  // 		.
  // }

  // You will need to call both the distanceAttenuation() and
  // shadowAttenuation() methods for each light source in order to
  // compute shadows and light falloff.

  //return kd(i);

  



}
예제 #22
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
Vec3d RayTracer::traceRay( const ray& r, const Vec3d& thresh, int depth )
{

  if (depth > traceUI->getDepth())
    return Vec3d( 0.0, 0.0, 0.0 );

  ++depth;

  isect i;

  if( scene->intersect( r, i ) ) {
    // YOUR CODE HERE

    // An intersection occured!  We've got work to do.  For now,
    // this code gets the material for the surface that was intersected,
    // and asks that material to provide a color for the ray.  

    // This is a great place to insert code for recursive ray tracing.
    // Instead of just returning the result of shade(), add some
    // more steps: add in the contributions from reflected and refracted
    // rays.


    const Material& m = i.getMaterial();

    Vec3d iPoint = r.at(i.t);  // point of intersection
/*
    // --Shadows--
    Vec3d shadow = Vec3d(1.0, 1.0, 1.0);
    //for (vector<Light*>::const_iterator litr = scene->beginLights();
    //  litr != scene->endLights(); ++litr )
    //{
      vector<Light*>::const_iterator litr = scene->beginLights();
      Light* pLight = *litr;
      Vec3d shadowDir = pLight->getDirection(iPoint);
      isect aux;
      ray shadow_ray (iPoint,shadowDir,ray::SHADOW);
      if(scene->intersect(shadow_ray, aux)) {
        const Material& mm = aux.getMaterial();
        shadow = prod(shadow, mm.kt(aux));
      }
    //}
*/
    // --Reflection--
    Vec3d reflection = Vec3d(0.0,0.0,0.0);
    if (m.kr(i) != Vec3d(0.0,0.0,0.0)) {
      Vec3d reflecDir = 2*((-1*r.getDirection()*i.N)*i.N) + r.getDirection();
      reflecDir.normalize();
      ray ReflRay (iPoint, reflecDir, ray::REFLECTION);
      reflection = traceRay(ReflRay, Vec3d(1.0,1.0,1.0), depth);
      
      // use threshold
      for(int i=0; i < 3; i++){
        if(reflection[i] > thresh[i]){
          reflection[i] = 1;
        }
      }
        
    }

    // --Refraction--
    Vec3d refraction = Vec3d(0.0,0.0,0.0);
    if (m.kt(i) != Vec3d(0.0,0.0,0.0)) {
      double IofR = 1.0 / m.index(i);  // the index of refraction
      Vec3d inorm = i.N;
      Vec3d d = -1.0*r.getDirection();  // reverse the ray direction for calculations
      double cos_i = inorm*d;
      // if the ray is inside of the object
      if (cos_i < 0.0) {
       IofR = m.index(i);
       cos_i *= -1.0;
       inorm *= -1.0;
      }
      double cos_t = 1.0 - (IofR*IofR)*(1.0 - (cos_i*cos_i));
      // if not Total Internal Reflection
      if (cos_t >= 0.0) {
        Vec3d refractDir = (IofR*cos_i - sqrt(cos_t))*inorm - IofR*d;
        refractDir.normalize();
        ray RefrRay (iPoint, refractDir, ray::REFRACTION);
        refraction = traceRay(RefrRay, Vec3d(1.0,1.0,1.0), depth);
        
        // use threshold
        for(int i=0; i < 3; i++){
          if(refraction[i] > thresh[i]){
            refraction[i] = 1;
          }
        }
      }
    }

    return m.shade(scene, r, i) + prod(m.kr(i), reflection) + prod(m.kt(i), refraction);

	
  } else {
    // No intersection.  This ray travels to infinity, so we color
    // it according to the background color, which in this (simple) case
    // is just black.

    return Vec3d( 0.0, 0.0, 0.0 );
  }
}
예제 #23
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
    // YOUR CODE HERE

    // For now, this method just returns the diffuse color of the object.
    // This gives a single matte color for every distinct surface in the
    // scene, and that's it.  Simple, but enough to get you started.
    // (It's also inconsistent with the phong model...)

    // Your mission is to fill in this method with the rest of the phong
    // shading model, including the contributions of all the light sources.
    // You will need to call both distanceAttenuation() and shadowAttenuation()
    // somewhere in your code in order to compute shadows and light falloff.

    if( debugMode )
        std::cout << "Debugging Phong code..." << std::endl;
    Vec3d intensity(0.0f,0.0f,0.0f);
    Vec3d emmisiveIntensity = ke(i);
    Vec3d ambientIntensity = ka(i);
    ambientIntensity %=  scene->ambient();

        // When you're iterating through the lights,
        // you'll want to use code that looks something
        // like this:
        //
        const Vec3d intersectionPoint = r.at(i.t);

    const Vec3d blue(0.0f,0.0f,0.4f);
    const Vec3d yellow(0.4f,0.4f,0.0f);
    double alpha = 0.2f;
    double beta = 0.6f;
    bool bNonRealism = traceUI->nonRealism();
        for ( vector<Light*>::const_iterator litr = scene->beginLights(); litr != scene->endLights(); ++litr ){
            Light* pLight = *litr;
            Vec3d lightDirection = pLight->getDirection(intersectionPoint);
            Vec3d surfaceNormal = i.N;
            surfaceNormal.normalize();
            double aLightToNormal = surfaceNormal * lightDirection;
            Vec3d lightReflectedDirectionCi = (lightDirection*surfaceNormal)*surfaceNormal;
            Vec3d lightReflectedDirectionSi = lightReflectedDirectionCi - lightDirection;
            Vec3d lightReflectedDirection = lightReflectedDirectionCi + lightReflectedDirectionSi;
                        lightReflectedDirection.normalize();
            double aRayToLight = (-1 * r.getDirection()) * lightReflectedDirection;
            Vec3d shadowLight(1.0f,1.0f,1.0f);

            if(bNonRealism){
                if(bump(i)[0]!= 2.0f){
                    Vec3d perturbed = 2.0f*bump(i)-1.0f;
                    perturbed[0] *= traceUI->getBumpScale();
                    perturbed[1] *= traceUI->getBumpScale();
                    perturbed %=surfaceNormal;
                    perturbed.normalize();
                    aLightToNormal = perturbed * lightDirection;}
                double coolFac = (1.0f+ (-1.0f)* aLightToNormal)/2.0f;
                double warmFac = 1.0f - coolFac;
                Vec3d diffuseIntensity = (coolFac * ( blue + kd(i) * alpha)) + (warmFac * ( yellow + kd(i) * beta));
                //Vec3d specularIntensity = ks(i) * pLight->getColor(intersectionPoint);
                shadowLight %= diffuseIntensity; //+ specularIntensity * std::pow(std::max(aRayToLight,0.0),shininess(i)));
            } else {
                if(bump(i)[0]!= 2.0f){
                    Vec3d perturbed = 2.0f*bump(i)-1.0f;
                    perturbed[0] *= traceUI->getBumpScale();
                    perturbed[1] *= traceUI->getBumpScale();
                    perturbed %=surfaceNormal;
                    perturbed.normalize();
                    aLightToNormal = perturbed * lightDirection;}
                Vec3d diffuseIntensity = kd(i);
                Vec3d specularIntensity = ks(i);
                diffuseIntensity%=pLight->getColor(intersectionPoint);
                specularIntensity%=pLight->getColor(intersectionPoint);
                shadowLight = pLight->shadowAttenuation(intersectionPoint);
                shadowLight %= (diffuseIntensity * std::max(aLightToNormal, 0.0) + specularIntensity * std::pow(std::max(aRayToLight,0.0),shininess(i)));
            }
            intensity += shadowLight*pLight->distanceAttenuation(intersectionPoint);
    }
    return intensity + emmisiveIntensity + ambientIntensity;
}
bool Cylinder::intersectBody( const ray& r, isect& i ) const
{
	double x0 = r.getPosition()[0];
	double y0 = r.getPosition()[1];
	double x1 = r.getDirection()[0];
	double y1 = r.getDirection()[1];

	double a = x1*x1+y1*y1;
	double b = 2.0*(x0*x1 + y0*y1);
	double c = x0*x0 + y0*y0 - 1.0;

	if( 0.0 == a ) {
		// This implies that x1 = 0.0 and y1 = 0.0, which further
		// implies that the ray is aligned with the body of the cylinder,
		// so no intersection.
		return false;
	}

	double discriminant = b*b - 4.0*a*c;

	if( discriminant < 0.0 ) {
		return false;
	}
	
	discriminant = sqrt( discriminant );

	double t2 = (-b + discriminant) / (2.0 * a);

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	double t1 = (-b - discriminant) / (2.0 * a);

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= 1.0 ) {
			// It's okay.
			i.t = t1;
			i.N = vec3f( P[0], P[1], 0.0 ).normalize();
			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= 1.0 ) {
		i.t = t2;

		vec3f normal( P[0], P[1], 0.0 );
		// In case we are _inside_ the _uncapped_ cone, we need to flip the normal.
		// Essentially, the cone in this case is a double-sided surface
		// and has _2_ normals
		if( !capped && normal.dot( r.getDirection() ) > 0 )
			normal = -normal;

		i.N = normal.normalize();
		return true;
	}

	return false;
}
예제 #25
0
bool Box::intersectLocal( const ray& r, isect& i ) const
{

        Vec3d p = r.getPosition();
        Vec3d d = r.getDirection();

        int it;
        double x, y, t, bestT; 
        int mod0, mod1, mod2, bestIndex;

        bestT = HUGE_DOUBLE;
        bestIndex = -1;

        for(it=0; it<6; it++){ 
                mod0 = it%3;

                if(d[mod0] == 0){
                        continue;
                }
                
                t = ((it/3) - 0.5 - p[mod0]) / d[mod0];                 

                if(t < RAY_EPSILON || t > bestT){
                        continue;
                }

                mod1 = (it+1)%3;
                mod2 = (it+2)%3;
                x = p[mod1]+t*d[mod1];
                y = p[mod2]+t*d[mod2];
                
                if(     x<=0.5 && x>=-0.5 &&
                        y<=0.5 && y>=-0.5)
                {
                        if(bestT > t){
                                bestT = t;
                                bestIndex = it;
                        }
                }                       
                
        }

        if(bestIndex < 0) return false;
        
        i.setT(bestT);
        i.setObject(this);

		Vec3d intersect_point = r.at(i.t);

		int i1 = (bestIndex + 1) % 3;
		int i2 = (bestIndex + 2) % 3;

        if(bestIndex < 3)
		{
                i.setN(Vec3d(-double(bestIndex == 0), -double(bestIndex == 1), -double(bestIndex == 2)));
				i.setUVCoordinates( Vec2d(	0.5 - intersect_point[ min(i1, i2) ], 
											0.5 + intersect_point[ max(i1, i2) ] ) );
		}
        else
		{
                i.setN(Vec3d(double(bestIndex==3), double(bestIndex == 4), double(bestIndex == 5)));
				i.setUVCoordinates( Vec2d(	0.5 + intersect_point[ min(i1, i2) ],
											0.5 + intersect_point[ max(i1, i2) ] ) );

		}
        return true;

}
예제 #26
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
  if( debugMode )
    std::cout << "Debugging Phong code..." << std::endl;
  Vec3d pos = r.at(i.t);
  Camera cam = scene->getCamera();
  Vec3d view = cam.getEye() - pos;
  view.normalize();
  Vec3d color = Vec3d(0, 0, 0);
  Vec3d norm = i.N;
  norm.normalize();
  Vec3d reflect = Vec3d(0, 0, 0);
  Vec3d amb = ka(i);
  Vec3d diff = kd(i);
  if (debugMode) 
    cout << diff << endl;
  Vec3d spec = ks(i);
  Vec3d emis = ke(i);
  double shiny = max(shininess(i), 0.0);
  Vec3d ambIntensity = scene->ambient();
  Vec3d diffIntensity = Vec3d(0, 0, 0);
  Vec3d specIntensity = Vec3d(0, 0, 0);
  Vec3d shadowTerm = Vec3d(1, 1, 1);
  Vec3d diffTerm = Vec3d(0, 0, 0);
  Vec3d specTerm = Vec3d(0, 0, 0);
  Vec3d ambTerm = prod(amb, ambIntensity);
  Vec3d shadAtten = Vec3d(0, 0, 0);
  for ( vector<Light*>::const_iterator litr = scene->beginLights(); 
   		litr != scene->endLights(); 
   		++litr)
  {
    Light* pLight = *litr;
    Vec3d tColor = Vec3d(0, 0, 0);
    Vec3d lightDir = Vec3d(0, 0, 0);
    double distAtten = pLight->distanceAttenuation(pos);
    shadAtten = pLight->shadowAttenuation(pos);
    if(shadAtten[0] != -1){
      shadowTerm = shadAtten;
    }
    lightDir = pLight->getDirection(pos);
    lightDir.normalize();
    tColor = pLight->getColor(tColor);
    reflect = (2.0 * (lightDir * norm) * norm) - lightDir;
    reflect.normalize();
    diffIntensity = tColor;
    specIntensity = tColor;
    // update diffuse term
    diffTerm[0] += diff[0] * max((lightDir * norm), 0.0)
      * diffIntensity[0] * shadowTerm[0];
    diffTerm[1] += diff[1] * max((lightDir * norm), 0.0)
      * diffIntensity[1] * shadowTerm[1];
    diffTerm[2] += diff[2] * max((lightDir * norm), 0.0)
      * diffIntensity[2] * shadowTerm[2];
    diffTerm = diffTerm * distAtten;
    // update specular term
    specTerm[0] += spec[0] * pow(max((view * reflect),0.0), max(shiny, 0.0))
      * specIntensity[0] * shadowTerm[0];
    specTerm[1] += spec[1] * pow(max((view * reflect),0.0), max(shiny, 0.0))
      * specIntensity[1] * shadowTerm[1];
    specTerm[2] += spec[2] * pow(max((view * reflect),0.0), max(shiny, 0.0))
      * specIntensity[2] * shadowTerm[2];
    specTerm = specTerm  * distAtten;
    // reset the shadowTerm for next loop
    shadowTerm = Vec3d(1,1,1);
  }
  return emis + ambTerm + diffTerm + specTerm;
}
예제 #27
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
Vec3d RayTracer::traceRay( const ray& r, 
						  const Vec3d& thresh, int depth )
{
	isect i;

	if( scene->intersect( r, i ) ) {
		// YOUR CODE HERE

		// An intersection occured!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		Vec3d ret = m.shade(scene, r, i);


		if (depth == traceUI->getDepth())
			return ret;


		Vec3d d = r.getDirection();
		double n;
		Vec3d NN = i.N;
		if (i.N * (-d) >= 0)
		{
			// entering the object
			n = 1.0 / m.index(i);
		}
		else
		{
			// leaving
			n = m.index(i);
			NN = -NN;
		}


		double c1 = -(NN * d);
		Vec3d Rl = d + 2 * NN * c1;
		ray reflection = ray(r.at(i.t), Rl, r.REFLECTION);
		ret += prod(m.kr(i), traceRay(reflection, thresh, depth+1));


		double c2 = 1 - n*n * (1 - c1*c1);
		if (c2 >= 0)
		{
			// not total internal reflection
			c2 = sqrt(c2);
			Vec3d Rr = (n * d) + (n * c1 - c2) * NN;
			
			ray refraction = ray(r.at(i.t), Rr, r.REFRACTION);
			ret += prod(m.kt(i), traceRay(refraction, thresh, depth+1));
		}


		return ret;



	} else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		return Vec3d( 0.0, 0.0, 0.0 );
	}
}
예제 #28
0
// Do recursive ray tracing!  You'll want to insert a lot of code here
// (or places called from here) to handle reflection, refraction, etc etc.
vec3f RayTracer::traceRay( Scene *scene, const ray& r, const vec3f& thresh, int depth )
{
	isect i;
	vec3f colorC;
	if (scene->intersect(r, i)) {
		// YOUR CODE HERE

		// An intersection occurred!  We've got work to do.  For now,
		// this code gets the material for the surface that was intersected,
		// and asks that material to provide a color for the ray.  

		// This is a great place to insert code for recursive ray tracing.
		// Instead of just returning the result of shade(), add some
		// more steps: add in the contributions from reflected and refracted
		// rays.

		const Material& m = i.getMaterial();
		vec3f intensity = m.shade(scene, r, i);
		if (depth == 0) return intensity;
		if (thresh.length() < AdaptiveThreshold) return intensity;

		vec3f Qpt = r.at(i.t);
		vec3f minusD = -1 * r.getDirection();
		vec3f cosVector = i.N * (minusD * i.N);
		vec3f sinVector = cosVector + r.getDirection();
		vec3f newThresh = thresh;

		// Reflected Ray
		if (!m.kr(i).iszero())
		{
			vec3f reflectedDirection = cosVector + sinVector;
			reflectedDirection.normalize();
			ray reflectedRay(Qpt, reflectedDirection, ray::REFLECTION);
			newThresh = prod(newThresh, i.getMaterial().kr(i)); // change the threshold value
			intensity = intensity + prod(m.kr(i), traceRay(scene, reflectedRay, newThresh, depth - 1));
		}

		//Refracted Ray
		if (!m.kt(i).iszero())
		{
			double cosineAngle = acos(i.N * r.getDirection()) * 180 / M_PI;
			double n_i, n_r;
			double criticalAngle = 360;
			int iDirection;
			// bool goingIn = true;
			// double cosThetaI = 0;
			if (cosineAngle > 90) // Coming into an object from air
			{
				n_i = 1;
				n_r = m.index(i);
				iDirection = 1;
				// cosThetaI = i.N * -1 * r.d;
			}
			else // Going out from object to air
			{
				n_i = m.index(i);
				n_r = 1;
				// goingIn = false;
				// cosThetaI = i.N * r.d;
				iDirection = -1;
			}
			
			double n = n_i / n_r;
			if (1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)) > 0.0) // NO total internal refraction
			{
				vec3f sinT = n * sinVector;
				// vec3f cosT = (-1 * i.N) * sqrt(1 - sinT*sinT);
				// not sure if there are any differences between the two eqn, please check!!!!!!
				vec3f cosT = (-1 * i.N) * sqrt(1 - n * n * (1 - (minusD * i.N) * (minusD * i.N)));
				vec3f refractedDirection = cosT + iDirection*sinT;
				refractedDirection.normalize();
				ray refractedRay(Qpt, iDirection * refractedDirection, ray::REFRACTION);
				newThresh = prod(newThresh, i.getMaterial().kt(i)); // change the threshold value
				intensity = intensity + prod(m.kt(i), traceRay(scene, refractedRay, newThresh, depth - 1));
			}
		}
		colorC = intensity;
	}
	else {
		// No intersection.  This ray travels to infinity, so we color
		// it according to the background color, which in this (simple) case
		// is just black.
		colorC = vec3f (0.0, 0.0, 0.0);
	}
	return colorC;
}
예제 #29
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{ 
	// YOUR CODE HERE

	// For now, this method just returns the diffuse color of the object.
	// This gives a single matte color for every distinct surface in the
	// scene, and that's it.  Simple, but enough to get you started.
	// (It's also inconsistent with the phong model...)

	// Your mission is to fill in this method with the rest of the phong
	// shading model, including the contributions of all the light sources.
    // You will need to call both distanceAttenuation() and shadowAttenuation()
    // somewhere in your code in order to compute shadows and light falloff.
	if( debugMode )
		std::cout << "Debugging Phong code..." << std::endl;

    //Intersection Point
    Vec3d P = r.at(i.t);
    Vec3d L = Vec3d(0,0,0);
    Vec3d V = -r.getDirection();

    //======[ Emission ]======
    L += ke(i);
    if(debugMode)
        std::cout << "ke(i): " << ke(i) <<"\n";

    //======[ Ambient ]======
    //missing Ka
    L += prod(ka(i),scene->ambient());
    if(debugMode){
        std::cout << "ambient: " << scene->ambient() <<"\n";
        std::cout << "ka(i): " << ka(i) <<"\n";
    }

    //iterate through lights
    for ( std::vector<Light*>::const_iterator litr = scene->beginLights(); 
         litr != scene->endLights(); 
         ++litr )
    {
        Vec3d Lc; //light contribution
        Light* pLight = *litr;
        Vec3d sa = pLight->shadowAttenuation(P);
        double da = pLight->distanceAttenuation(P);

        //======[ Diffuse ]======
        Vec3d direction = pLight->getDirection(P);
        Vec3d normal = i.N;
        if(debugMode)
        {
            std::cout << "D: ";
            clamp((normal*direction)*kd(i)).print();   
        }
        Lc =  clamp((normal*direction)*kd(i));
        
        //======[ Specular ]======
        Vec3d H = (V+direction)/2.0;
        if(debugMode)
        {
            std::cout << "S: ";
            clamp(ks(i)*pow((normal*H),shininess(i))).print();   
            std::cout <<"sa: ";
            sa.print();
        }
        Lc += clamp(ks(i)*pow((normal*H),shininess(i)));

        Lc = da * prod(Lc,sa);
        
        L+=Lc;
    }
	
    if(debugMode){
        std::cout <<"L: ";
        L.print();
    }
	return L;
}
예제 #30
0
bool Sphere::intersectLocal( const ray& r, isect& i ) const
{
    // YOUR CODE HERE:
    // Add sphere intersection code here.
    // it currently ignores all spheres and just return false.

	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	// a unit sphere
	double a = d*d;
	double b = 2.0*(p*d);
	double c = p*p - 1.0;

	// d cannot be zero vector actually
	//if( 0.0 == a ) {
	//	// This implies that x1 = 0.0 and y1 = 0.0, which further
	//	// implies that the ray is aligned with the body of the cylinder,
	//	// so no intersection.
	//	return false;
	//}

	// early failure methods:
	//	if the ray and the sphere intersect
	//	then the angle btw rouge and d are \geq 0
	Vec3d rouge = Vec3d(0, 0, 0) - p ;
	rouge.normalize();
	double cos_isect = rouge * d ;
	if ( cos_isect < 0 )
		return false;
	//	it seems that the radius of sphere is 1.0
	//	then we can do the following, calculate the tangent angle
	//	and the compare it with our ray angle towards center of the sphere - origin
	double cos_tan = sqrt(1 - 1 / rouge.length());
	if ( cos_isect < cos_tan )
		return false;


	double discriminant = b*b - 4.0*a*c;

	if( discriminant < 0.0 ) {
		return false;
	}
	
	discriminant = sqrt( discriminant );

	double t2 = (-b + discriminant) / (2.0 * a);

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	double t1 = (-b - discriminant) / (2.0 * a);

	i.obj = this;
	if( t1 > RAY_EPSILON ) {
		// Two intersections. Pick smaller one
		Vec3d P = r.at( t1 );
		double z = P[2];
		if( z >= -1.0 && z <= 1.0 ) {
			// Just check
			i.t = t1;
			i.N = Vec3d( P[0], P[1], P[2]);
			return true;
		}
	}


	return false;
  
}