Beispiel #1
0
        //! Intersect ray and sphere, returning true if there is an intersection.
        bool intersect(const ray<Type>& r, Type& tmin, Type& tmax) const
        {
            const vec3<Type> r_to_s = r.getOrigin() - m_center;

            //Compute A, B and C coefficients
            const Type A = r.getDirection().sqrLength();
            const Type B = 2.0f * r_to_s.dot(r.getDirection());
            const Type C = r_to_s.sqrLength() - m_radius * m_radius;

            //Find discriminant
            Type disc = B * B - 4.0 * A * C;

            // if discriminant is negative there are no real roots
            if (disc < 0.0)
                return false;

            disc = (Type)std::sqrt((double)disc);

            tmin = (-B + disc) / (2.0 * A);
            tmax = (-B - disc) / (2.0 * A);

            // check if we're inside it
            if ((tmin < 0.0 && tmax > 0) || (tmin > 0 && tmax < 0))
                return false;

            if (tmin > tmax)
                std::swap(tmin, tmax);

            return (tmin > 0);
        }
Beispiel #2
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;
	}
}
Beispiel #3
0
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
bool intersectCircle(const ray& r0, double& tnear, double& tfar, const vec3f& center)
{
	ray r(r0.getPosition() - center, r0.getDirection());

	vec3f v = -r.getPosition();
	double b = v.dot(r.getDirection());
	double discriminant = b*b - v.dot(v) + 1;

	if (discriminant < 0.0) {
		return false;
	}

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

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



	double t1 = b - discriminant;

	if (t1 > RAY_EPSILON) {
		tnear = t1;
		tfar = t2;
	}
	else {
		tnear = 0;
		tfar = t2;
	}

	return true;
}
Beispiel #8
0
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;
}
Beispiel #9
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point. Uses shaddowAttenuation which sends a shadow ray
// to check if there is an intersection that blocks the light sources.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
  Vec3d retVal = ke(i) + prod(ka(i), scene->ambient());
  
  // Applies calculations for each light source
  for (vector<Light*>::const_iterator litr = scene->beginLights(); 
       litr != scene->endLights(); ++litr) {
    Vec3d point = r.getPosition() + r.getDirection() * i.t;
    Light* pLight = *litr;
  
    Vec3d reflectionAngle = 2 * (i.N * pLight->getDirection(point)) * i.N - pLight->getDirection(point);

    Vec3d diffIntensity = kd(i) * (max(0, i.N * pLight->getDirection(point)));

    Vec3d viewerAngle = scene->getCamera().getEye() - point;
    viewerAngle.normalize();
    Vec3d specIntensity = ks(i) * pow(max(0, viewerAngle * reflectionAngle), shininess(i));

    Vec3d lcolor = pLight->getColor(point);

    Vec3d totalColor = prod(diffIntensity + specIntensity, lcolor);
    totalColor = totalColor * pLight->distanceAttenuation(point);
    totalColor = prod(totalColor, pLight->shadowAttenuation(point));

    retVal = retVal + totalColor;	
  }
  return retVal;
}
Beispiel #10
0
bool CSGTree::intersect(const ray& r, isect& i) const{
	if (!root)return false;
	Segments inters = root->intersectLocal(r);
	SegmentPoint sp;
	if(!inters.firstPositive(sp))return false;
	i.t = sp.t;
	if (sp.isRight){//right - out
		if (sp.normal*r.getDirection() > RAY_EPSILON)i.N = sp.normal;
		else i.N = -sp.normal;
	}
	else {//left - in
		if (sp.normal*r.getDirection() > RAY_EPSILON)i.N = -sp.normal;
		else i.N = sp.normal;
	}
	return true;
}
Beispiel #11
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;
}
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;
}
Beispiel #13
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;
}
Beispiel #14
0
bool Metaball::intersectLocal(const ray& r, isect& i) const
{
	bool inside = false;
	if (calvalue(r.getPosition(), ball1pos, ball2pos)>threshold)inside = true;

	//determine possible intersect range
	double t11=0, t12=0, t21=0, t22=0;
	double tmin, tmax;
	bool i1, i2;
	i1 = intersectCircle(r, t11, t12, ball1pos);
	i2 = intersectCircle(r, t21, t22, ball2pos);
	if (!i1 && !i2) return false;
	else if (!i1 && i2)
	{
		tmin = t21;
		tmax = t22;
	}
	else if (i1 && !i2)
	{
		tmin = t11;
		tmax = t12;
	}
	else
	{
		tmin = min(t11, t21);
		tmax = max(t12, t22);
	}

	for (double t = tmin; t < tmax; t += 0.001)
	{
		vec3f point = r.getPosition() + t * r.getDirection();
		double value = calvalue(point, ball1pos, ball2pos);

		if ((!inside && value > threshold) || (inside && value < threshold))
		{
			// prevent fake intersect
			if (inside && t < 0.01)return false;

			vec3f normal;
			normal += 2 * (point - ball1pos) / ((point - ball1pos).length()*(point - ball1pos).length());
			normal += 2 * (point - ball2pos) / ((point - ball2pos).length()*(point - ball2pos).length());
			normal = normal.normalize();
			i.t = t;
			i.N = normal;
			i.obj = this;
			return true;
		}
	}
	return false;
}
Beispiel #15
0
// 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;
}
Beispiel #16
0
// if the ray hits the box, put the "t" value of the intersection
// closest to the origin in tMin and the "t" value of the far intersection
// in tMax and return true, else return false.
// Using Kay/Kajiya algorithm.
bool BoundingBox::intersect(const ray& r, double& tMin, double& tMax) const
{
	vec3f R0 = r.getPosition();
	vec3f Rd = r.getDirection();

	tMin = -1.0e308; // 1.0e308 is close to infinity... close enough for us!
	tMax = 1.0e308;
	double ttemp;
	
	for (int currentaxis = 0; currentaxis < 3; currentaxis++)
	{
		double vd = Rd[currentaxis];
		
		// if the ray is parallel to the face's plane (=0.0)
		if( vd > -RAY_EPSILON && vd < RAY_EPSILON ) {
			if(R0[currentaxis] <= min[currentaxis] - RAY_EPSILON || R0[currentaxis] >= max[currentaxis] + RAY_EPSILON) {
				return false;
			}
			else {
				continue;
			}
		}

		double v1 = min[currentaxis] - R0[currentaxis];
		double v2 = max[currentaxis] - R0[currentaxis];

		// two slab intersections
		double t1 = v1/vd;
		double t2 = v2/vd;
		
		if ( t1 > t2 ) { // swap t1 & t2
			ttemp = t1;
			t1 = t2;
			t2 = ttemp;
		}

		if (t1 > tMin)
			tMin = t1;
		if (t2 < tMax)
			tMax = t2;

		if (tMin > tMax) // box is missed
			return false;
		if (tMax < -RAY_EPSILON) // box is behind ray
			return false;
	}
	return true; // it made it past all 3 axes.
}
Beispiel #17
0
bool Box::intersectLocal( const ray& r, isect& i ) const
{
	BoundingBox bounds = ComputeLocalBoundingBox();
	vec3f p = r.getPosition();
	vec3f d = r.getDirection();
	//find tmin and tmax
	vec3f tmin;
	vec3f tmax;
	vec3f nmin(0, 0, 0);
	vec3f nmax(0, 0, 0);
	double min;
	double max;
	for(int j=0; j<3; j++) {
		if(d[j]>=0) {
			tmin[j] = (bounds.min[j] - p[j]) / d[j];
			tmax[j] = (bounds.max[j] - p[j]) / d[j];
			nmin[j] = -1;	
			nmax[j] = 1;
		} else {
			tmin[j] = (bounds.max[j] - p[j]) / d[j];
			tmax[j] = (bounds.min[j] - p[j]) / d[j];
			nmin[j] = 1;
			nmax[j] = -1;
		}
	}

	//min of tmax, max of tmin
	max = std::min( std::min(tmax[0], tmax[1]), tmax[2]);
	min = std::max( std::max(tmin[0], tmin[1]), tmin[2]);
	if(min > max || max < RAY_EPSILON) return false;
	i.obj = this;
	vec3f N(0, 0, 0);
	if(min >= RAY_EPSILON) {
		i.t = min;
		for(int i=0; i<3; i++) {
			if(tmin[i] == min) { N[i] = nmin[i]; break; }
		}
	} else {
		i.t = max;
		for(int i=0; i<3; i++) {
			if(tmax[i] == max) { N[i] = nmax[i]; break; }
		}
	}
	i.N = N;
	return true;
}
Beispiel #18
0
bool Geometry::intersect(const ray&r, isect&i) const {
	double tmin, tmax;
	if (hasBoundingBoxCapability() && !(bounds.intersect(r, tmin, tmax))) return false;
	// Transform the ray into the object's local coordinate space
	Vec3d pos = transform->globalToLocalCoords(r.getPosition());
	Vec3d dir = transform->globalToLocalCoords(r.getPosition() + r.getDirection()) - pos;
	double length = dir.length();
	dir /= length;

	ray localRay( pos, dir, r.type() );

	if (intersectLocal(localRay, i)) {
		// Transform the intersection point & normal returned back into global space.
		i.N = transform->localToGlobalCoordsNormal(i.N);
		i.t /= length;
		return true;
	} else return false;
}
Beispiel #19
0
bool Geometry::intersect(const ray&r, isect&i) const
{
    // Transform the ray into the object's local coordinate space
    vec3f pos = transform->globalToLocalCoords(r.getPosition());
    vec3f dir = transform->globalToLocalCoords(r.getPosition() + r.getDirection()) - pos;
    double length = dir.length();
    dir /= length;

    ray localRay( pos, dir );

    if (intersectLocal(localRay, i)) {
        // Transform the intersection point & normal returned back into global space.
		i.N = transform->localToGlobalCoordsNormal(i.N);
		i.t /= length;
		return true;
    } else {
        return false;
    }
}
Beispiel #20
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;
}
Beispiel #21
0
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;
}
Beispiel #22
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;
}
Beispiel #23
0
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;
}
Beispiel #24
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 );
	}
}
Beispiel #25
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 );
		}
	}
}
Beispiel #26
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;

}
Beispiel #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 )
{

  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 );
  }
}
Beispiel #28
0
Vec3d CubeMap::getColor(ray r) const {

	int axis, front, left, right, top, bottom;
	double u,v;
	Vec3d dir = r.getDirection();
	
	if (fabs(dir[0]) > fabs(dir[1]))
		if (fabs(dir[0]) > fabs(dir[2])) {
			axis = 0;
			bottom = 3;
			top = 2;
			if (dir[0] > 0.0) {
				front = 0;
				left = 4;
				right = 5;
			}
			else {
				front = 1;
				left = 5;
				right = 4;
			}
		}
		else {
			axis = 2;
			bottom = 3;
			top = 2;
			if (dir[2] > 0.0) {
				front = 5;
				left = 0;
				right = 1;
			}
			else {
				front = 4;
				left = 1;
				right = 0;
			}
		}
	else
		if (fabs(dir[1]) > fabs(dir[2])) {
			axis = 1;
			left = 1;
			right = 0;
			if (dir[1] > 0.0) {
				front = 2;
				bottom = 4;
				top = 5;
			}
			else {
				front = 3;
				bottom = 5;
				top = 4;
			}
		}
		else {
			axis = 2;
			bottom = 3;
			top = 2;
			if (dir[2] > 0.0) {
				front = 5;
				left = 0;
				right = 1;
			}
			else {
				front = 4;
				left = 1;
				right = 0;
			}
		}

	if (axis == 0) {
		u = dir[2]/dir[0];
		if (dir[0] > 0.0) v = dir[1]/dir[0];
		else v = -dir[1]/dir[0];
	}
	else if (axis == 1) {
		if (dir[1] > 0.0) u = dir[0]/dir[1];
		else u = -dir[0]/dir[1];
		v = dir[2]/dir[1];
	}
	else if (axis == 2) {
		u = -dir[0]/dir[2];
		if (dir[2] > 0.0) v = dir[1]/dir[2];
		else v = -dir[1]/dir[2];
	}

	u = (u + 1.0)/2.0;
	v = (v + 1.0)/2.0;

	int filterwidth = traceUI->getFilterWidth();
	if (filterwidth == 1) return tMap[front]->getMappedValue(Vec2d(u, v)); // Why even bother with expensive computation when we can grab straight from the image?
	int fw = (filterwidth + 1)/2 - 1;
	int rm = filterwidth - fw;
	int width = tMap[front]->getWidth();
	int height = tMap[front]->getHeight();
	double delu = 1.0/width;
	double delv = 1.0/height;
	int x = floor(0.5 + u * (width - 1));
	int y = floor(0.5 + v * (height - 1));
	double startu = delu * (x - fw);
	double startv = delv * (y - fw);
	double nextu = startu;
	double nextv = startv;
	double xslope = 1.0/(((double)filterwidth + 1) / 2.0 * delu);
	double yslope = 1.0/(((double)filterwidth + 1) / 2.0 * delv);
	double correct = 0.0;
	Vec3d thePixel = Vec3d(0.0, 0.0, 0.0);
	for (int jj = -fw; jj < rm; jj++) {
		for (int ii = -fw; ii < rm; ii++) {
			int xindex = x + ii;
			int yindex = y + jj;
			if (xindex < 0 && yindex < 0) continue;
			if (xindex >= width && yindex >= height) continue;
			if (xindex >= width && yindex < 0) continue;
			if (xindex < 0 && yindex >= height) continue;
			int theMap = front;
			if (yindex < 0) {
				theMap = bottom;
				if (axis == 0)
					if (dir[0] > 0) {
						yindex = height - 1 - xindex;
						xindex = width + jj;
					}
					else {
						yindex = xindex;
						xindex = -1 - jj;
					}
				else if (axis == 1)
					if (dir[1] > 0) yindex = height + jj;
					else {
						yindex = -1 - jj;
						xindex = width - 1 - xindex;
					}
				else if (axis == 2)
					if (dir[2] > 0) {
						yindex = -1 - jj;
						xindex = width - 1 - xindex;
					}
					else yindex = height + jj;
			}
			else if (yindex >= height) {
				theMap = top;
				if (axis == 0)
					if (dir[0] > 0) {
						yindex = xindex;
						xindex = width - jj;
					}
					else {
						yindex = height - 1 - xindex;
						xindex = jj - 1;
					}
				else if (axis == 1)
					if (dir[1] > 0)  {
						yindex = height - jj;
						xindex = width - 1 - xindex;
					}
					else yindex = jj - 1;
				else if (axis == 2)
					if (dir[2] > 0) {
						yindex =  height - jj;
						xindex = width - 1 - xindex;
					}
					else yindex = jj - 1;
			}
			else if (xindex < 0) {
				theMap = left;
				if (axis == 0  || axis == 2) xindex = width + ii;
				else if (axis == 1)
					if (dir[1] > 0)  {
						xindex = width - 1 - yindex;
						yindex = height + ii;
					}
					else {
						xindex = yindex;
						yindex = -1 - ii;
					}
			}
			else if (xindex >= width) {
				theMap = right;
				if (axis == 0  || axis == 2) xindex = ii - 1;
				else if (axis == 1)
					if (dir[1] > 0)  {
						xindex = yindex;
						yindex = height - ii;
					}
					else {
						xindex = width - 1 - yindex;
						yindex = ii - 1;
					}
			}
			double du = u - nextu;
			double dv = v - nextv;
			double weight = (1.0 - fabs(du * xslope)) * (1.0 - fabs(dv * yslope));
			nextu += delu;
			correct += weight;
			thePixel += tMap[theMap]->getPixelAt(xindex, yindex) * weight;
		}
		nextu = startu;
		nextv += delv;
	}
	thePixel /= correct;
	return thePixel;
}
// 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;
}
Beispiel #30
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;
}