Example #1
0
Hit BVH::BVHNode::trace(const AABB_Ray & aabb_ray, const Ray & ray, Amount minT)
{
   Hit retHit(ray);
   //First check to see if this hit intersects with this node.
   Amount thisT = getBox().intersect(aabb_ray);

   if(thisT > 0 && (thisT < minT || minT < 0))
   {
      if(this->left != nullptr)
      {
         Hit hLeft = this->left->trace(aabb_ray,ray,minT);
         if(hLeft.didHit() && (hLeft.getT() < minT || minT < 0))
         {
            retHit = hLeft;
            minT = hLeft.getT();
         }
      }
      if(this->right != nullptr)
      {
         Hit hRight = this->right->trace(aabb_ray,ray,minT);
         if(hRight.didHit() && (hRight.getT() < minT || minT < 0))
         {
            retHit = hRight;
         }
      }
   }


   return retHit;
}
Example #2
0
bool Face::plane_intersect(const Ray &r, Hit &h, bool intersect_backfacing, bool* backfacing_hit) {

	// insert the explicit equation for the ray into the implicit equation of the plane

	// equation for a plane
	// ax + by + cz = d;
	// normal . p + direction = 0
	// plug in ray
	// origin + direction * t = p(t)
	// origin . normal + t * direction . normal = d;
	// t = d - origin.normal / direction.normal;

	Vec3f normal = computeNormal();
	double d = normal.Dot3((*this)[0]->get());

	double numer = d - r.getOrigin().Dot3(normal);
	double denom = r.getDirection().Dot3(normal);

	if (denom == 0) return 0;	// parallel to plane

	if (!intersect_backfacing && normal.Dot3(r.getDirection()) >= 0) 
		return 0; // hit the backside

	double t = numer / denom;
	if (t > EPSILON && t < h.getT()) {
		h.set(t,this->getMaterial(),normal,this);
		assert (h.getT() >= EPSILON);
		//hit the backside but that's okay in this case
		if (normal.Dot3(r.getDirection()) >= 0){
			*backfacing_hit = true;
		}
		return 1;
	}
	return 0;
}
Example #3
0
Vec3f RayTracer::shadow(const Vec3f &point,
			const Vec3f &pointOnLight,
			const Face *f,
			const Ray &ray,
			const Hit &hit) const
{
        const Vec3f normal(hit.getNormal());
        const Material *m = hit.getMaterial();

	Vec3f dirToLight = pointOnLight - point;
	dirToLight.Normalize();
	/* If dot product < 0, surface is not facing light */
	if (normal.Dot3(dirToLight) > 0) {
		Ray rayToLight(point, dirToLight);
		Hit hLight;
		bool blocked = CastRay(rayToLight, hLight, false);
		while (std::fabs(hLight.getT()) < SURFACE_EPSILON &&
				std::fabs((pointOnLight - point).Length()) > SURFACE_EPSILON) {
			rayToLight = Ray(rayToLight.pointAtParameter(SURFACE_EPSILON),
					dirToLight);
			blocked = CastRay(rayToLight, hLight, false);
		}
		if (hLight.getT() == FLT_MAX || hLight.getMaterial() != f->getMaterial()) {
			return Vec3f(0, 0, 0);
		}

		const Vec3f lightColor = 0.2 * f->getMaterial()->getEmittedColor() * f->getArea();
		return m->Shade(ray,hit,dirToLight,lightColor,args);
	}
	return Vec3f(0, 0, 0);
}
Example #4
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f v = center - r.getOrigin();
	float tp = v.Dot3(r.getDirection());
	float det = tp*tp - v.Dot3(v) + radius*radius;
	//intersect
	if(det > 0)
	{
		//t'
		det = sqrtf(det); 

		float t1 = tp - det;
		float t2 = tp + det;

		if(t1 > tmin && t1 < h.getT())
		{
			Vec3f normal = (r.pointAtParameter(t1) - center);
			normal /= radius;
			normal.Normalize();
			h.set(t1,material,normal,r);
			return 1;
		}
		else if(t2 > tmin && t2 < h.getT())
		{
			//sphere's normal
			Vec3f normal = (r.pointAtParameter(t2) - center);
			normal /= radius;
			normal.Normalize();
			h.set(t2,material,normal,r);
			return 1;
		}
	}
	return 0;
}
bool Face::plane_intersect(const Ray &r, Hit &h, bool intersect_backfacing) const {

  // insert the explicit equation for the ray into the implicit equation of the plane

  // equation for a plane
  // ax + by + cz = d;
  // normal . p + direction = 0
  // plug in ray
  // origin + direction * t = p(t)
  // origin . normal + t * direction . normal = d;
  // t = d - origin.normal / direction.normal;

  glm::vec3 normal = computeNormal();
  float d = glm::dot(normal,(*this)[0]->get());

  float numer = d - glm::dot(r.getOrigin(),normal);
  float denom = glm::dot(r.getDirection(),normal);

  if (denom == 0) return 0;  // parallel to plane

  if (!intersect_backfacing && glm::dot(normal,r.getDirection()) >= 0) 
    return 0; // hit the backside

  float t = numer / denom;
  if (t > EPSILON && t < h.getT()) {
    h.set(t,this->getMaterial(),normal);
    assert (h.getT() >= EPSILON);
    return 1;
  }
  return 0;
}
Example #6
0
bool Grid::intersect(const Ray &r, Hit &h, float tmin)
{
	MarchingInfo march;
	initialRayMarch(march,r,tmin);

	int currentI = march.GetI();
	int currentJ = march.GetJ();    
	int currentK = march.GetK();
	float currentT = march.GetT();
	int numObjects;
	//Object3DVector currentVector; 绝对不能新建一个Object3DVector,然后把isOpaque的值赋给这个Object3DVector,因为当这个函数结束时,会把Object3DVector销毁,对应的指针指向的对象也会被销毁。
	//当然还有一种方法是定义一个Object3DVector指针
	//printf("i:%d j:%d currentI:%d currentJ:%d currentK:%d\n",i,j,currentI,currentJ,currentK);

	Object3DVector isAlreadyIntersect;

	while(currentI>=0 && currentI<nx && currentJ>=0 && currentJ<ny && currentK>=0 && currentK<nz)
	{
		RayTracingStats::IncrementNumGridCellsTraversed();
		Object3DVector* currentVector = &isOpaque[currentI][currentJ][currentK];
		numObjects = currentVector->getNumObjects();
		//printf("%d %d %d\n",currentI,currentJ,currentK);
		for(int i=0; i<numObjects; ++i)
		{
			//already intersected object don't need intersect again
			if(isAlreadyIntersect.isInside(currentVector->getObject(i)))
				continue;
			RayTracingStats::IncrementNumIntersections();
			currentVector->getObject(i)->intersect(r,h,tmin);
			isAlreadyIntersect.addObject(currentVector->getObject(i));
		}
		if(h.getMaterial()!=NULL && h.getT()>=currentT && h.getT()<=march.GetNext_x() && h.getT()<=march.GetNext_y() && h.getT()<=march.GetNext_z())
		{
			return true;
		}

		march.nextCell();
		currentI = march.GetI();
		currentJ = march.GetJ();
		currentK = march.GetK();
		currentT = march.GetT();  //折射或反射,shadow时,光线圆点会在grid内
	}
	numObjects = others.getNumObjects();
	for(int i=0; i<numObjects; i++)
	{
		others.getObject(i)->intersect(r,h,tmin);
	}
	if(h.getMaterial()!=NULL)   //这里有问题,因为如果没有和平面相交的话,h的material也有可能不是null
		return true;

	return false;
}
Example #7
0
bool Transform::Intersect(const Ray &r, Hit &h, float tmin) const
{
  bool result = false;
  
  Matrix m = m_matrix;
  if ( m.Inverse() )
    {
      Vec3f org = r.getOrigin();
      Vec3f dir = r.getDirection();
      m.Transform(org);
      m.TransformDirection(dir);
      Ray r2 (dir, org);
      result = m_pObject->Intersect(r2, h, tmin);
      
      if (result)
	{
	  Matrix m1 = m;
	  m1.Transpose();
	  Vec3f n = h.getNormal();
	  m1.TransformDirection(n);
	  n.Normalize();
	  h.set(h.getT(), h.getMaterial(), n, r);
	}
    }
  return result;
}
Example #8
0
bool Plane::intersect(const Ray & r, Hit & h, float tmin)
{
	assert (tmin >= 0.0f);

	Vec3f org = r.getOrigin();
	Vec3f dir = r.getDirection();

	if (dir.Dot3(normal) < 1.0e-7 && dir.Dot3(normal) > -1.0e-7) {
		return false;
	}					// Appromately parrell to plane

	float tempT = (offset - org.Dot3(normal)) / dir.Dot3(normal);
	if (tempT <= 1e-6) {
		return false;
	}
	else if (tempT >= tmin && tempT < h.getT()) 
	{
		// Update Hit Point
		normal.Normalize();
		h.set(tempT, NULL, normal, color, r);

		return true;
	}
	
	return false;
}
Example #9
0
/*
The intersect routine will first transform the ray, 
then delegate to the intersect routine of the contained 
object. Make sure to correctly transform the resulting 
normal according to the rule seen in lecture. You may 
choose to normalize the direction of the transformed ray 
or leave it un-normalized. If you decide not to normalize 
the direction, you might need to update some of your intersection code.
*/
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f r0 = r.getOrigin();
	Vec3f rd = r.getDirection();
	Matrix inv;
	matrix.Inverse(inv);
	inv.Transform(r0);
	inv.TransformDirection(rd);
	if (object != NULL)
	{
		//这里的h是有问题的,作如下修改:
		bool judge = object->intersect(Ray(r0,rd), h, tmin);
		Vec3f normal = h.getNormal();
		//这里很奇怪,normal的方向没有修正,然而结果却是对的
		//改了之后反而是错的!!
		//这里确定normal没有错,那么就是之后应用normal的
		//问题
		//好吧,就是这里的问题
		//经过把图形摆正,发现求的法向量没有问题,但是没有单位化…………!
		matrix.TransformDirection(normal);
		normal.Normalize();
		//or:
		//Matrix change,res;
		//matrix.Inverse(change);
		//change.Transpose(res);
		//res.TransformDirection(normal);
		h.set(h.getT(), h.getMaterial(), normal, r);
		return judge;
	}
	return false;
}
Example #10
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin)
{
	//直线方程 P = t*D + R    ①
	//圆方程  ||P||= raduis   ②
	//将①带入②, 由点乘的性质(满足分配率,交换律),求得t^2+2RDt+R^2-r^2=0
	//得t = -RD±sqrt(RD^2-R^2+r^2)
	//选择距离较近的那个点t = -RD-sqrt(RD^2-R^2+r^2)
	Vec3f D = r.getDirection();
	Vec3f R = r.getOrigin()-center;


	float R2 = R.Dot3(R);
	float RD = R.Dot3(D);
	
	float b2_4ac = RD*RD-R2+radius*radius;//R2 RD RDRD这些其实可以存在ray里,但是算法研究以程序清晰为要
	if(b2_4ac<0)return 0;
	float t;
	t = -RD - sqrt(b2_4ac);
	if(t<0){
		t = -RD + sqrt(b2_4ac);
		if(t < 0)return 0;
	}
	if(t<h.getT())
	{
		h.set(t, &color, r);
	}

	return 1;
}
Example #11
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin){

	/*Vector equation for sphere
	P*P - r^2 = 0
	((R0-c) + td)*((R0-c) + td) - r^2 = 0
	(td)^2 + 2R0-c)td + (R0-c)^2 - r^2 =0
	Use quadratic equation solve for t
	a = (d^2)
	b = 2(R0-c)d
    c = ((R0-c)^2 - r^2)
	*/

	Vec3f rayOrigin, rayDirection,segment,Q;
	float tpos,tneg,a,b,c,discriminant;

	rayOrigin = r.getOrigin();
	rayDirection = r.getDirection();
	segment = rayOrigin - _center;

	a = rayDirection.Dot3(rayDirection);
	b = 2*segment.Dot3(rayDirection);
	c = segment.Dot3(segment) - _radius*_radius;

	discriminant = sqrt(b*b - 4*a*c); 

	tpos = (-b + discriminant)/(2*a);
	tneg = (-b - discriminant)/(2*a);

	if (tneg > tmin && tneg < h.getT()){
			Q = r.pointAtParameter(tneg);
			Q = Q - _center;
			Q.Normalize();
			h.set(tneg, _material,Q,r);
			return true;
		}
	else if (tpos > tmin && tpos < h.getT()){
			Q = r.pointAtParameter(tpos);
			Q = Q - _center;
			Q.Normalize();
			h.set(tpos,_material,Q,r);
			return true;
		}
	return false;

}
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, 
				const Vec3f &energy, int iter) {
  
  if(iter>args->num_bounces){
    return;
  }

  Hit h = Hit();
  Ray R = Ray(position, direction);
  bool intersect = raytracer->CastRay(R, h, false);
  if(!intersect){
    return;
  }
  Material *m = h.getMaterial();
  Vec3f normal = h.getNormal();
  Vec3f point = R.pointAtParameter(h.getT());
  Vec3f opDirec = direction;
  opDirec.Negate();
  opDirec.Normalize();
  Vec3f diffuse = m->getDiffuseColor(), reflec = m->getReflectiveColor();
  double diffuseAnswer = diffuse.x()+diffuse.y()+diffuse.z();
  double reflecAnswer = reflec.x()+reflec.y()+reflec.z();
  double total = reflecAnswer+diffuseAnswer;
  diffuseAnswer /= total;
  reflecAnswer /= total;
  double seed = GLOBAL_mtrand.rand();
  if(seed <= diffuseAnswer && seed >= 0){
    Vec3f newEnergy = energy * diffuse;
    Vec3f newPosition = point;
    Vec3f newDirection = Vec3f(GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand());
    newDirection.Normalize();
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  else if(seed>diffuseAnswer && seed <= 1){
    Vec3f newEnergy = energy * reflec;
    Vec3f newPosition = point;
    Vec3f newDirection = direction - 2 * direction.Dot3(normal) * normal;
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  // ==============================================
  // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING
  // ==============================================

  // Trace the photon through the scene.  At each diffuse or
  // reflective bounce, store the photon in the kd tree.

  // One optimization is to *not* store the first bounce, since that
  // direct light can be efficiently computed using classic ray
  // tracing.



}
Example #13
0
Vec3f RayTracer::shadows(const Ray &ray, const Hit &hit) const
{
	Vec3f answer(0, 0, 0);

	const int num_lights = mesh->getLights().size();
	if (args->num_shadow_samples == 0) {
		for (int i = 0; i < num_lights; ++i) {

			const Face *f = mesh->getLights()[i];
			Vec3f pointOnLight = f->computeCentroid();
			const Vec3f point(ray.pointAtParameter(hit.getT()));
			Vec3f dirToLight = pointOnLight - point;
			dirToLight.Normalize();
			const Vec3f lightColor = 0.2 * f->getMaterial()->getEmittedColor() * f->getArea();
			return hit.getMaterial()->Shade(ray,hit,dirToLight,lightColor,args);
		}
	}

	// ----------------------------------------------
	// add contributions from each light that is not in shadow

	for (int i = 0; i < num_lights; i++) {
		const Face *f = mesh->getLights()[i];
		Vec3f pointOnLight = f->computeCentroid();
		const Vec3f point(ray.pointAtParameter(hit.getT()));

		double answerx = 0, answery = 0, answerz = 0;
		{
			for (int s = 0; s <= args->num_shadow_samples; ++s) {
				const Vec3f sh = shadow(point, pointOnLight, f, ray, hit);
				answerx += sh.x();
				answery += sh.y();
				answerz += sh.z();
				pointOnLight = f->RandomPoint();
			}
		}
		answer += Vec3f(answerx, answery, answerz);
	}
	answer *= static_cast<double>(1) / ((args->num_shadow_samples + 1) * num_lights);
	return answer;
}
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, 
				const Vec3f &energy, int iter) {


  // ==============================================
  // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING
  // ==============================================

  // Trace the photon through the scene.  At each diffuse or
  // reflective bounce, store the photon in the kd tree.

  // One optimization is to *not* store the first bounce, since that
  // direct light can be efficiently computed using classic ray
  // tracing.

  //do ray cast
  Ray r(position,direction*(1/direction.Length()));
  Hit h;
  raytracer->CastRay(r,h,true);
  if (h.getT()>1000)
	  return;
  MTRand mtrand;
  Vec3f refl = h.getMaterial()->getReflectiveColor();
  Vec3f diff = h.getMaterial()->getDiffuseColor();
  double ran=mtrand.rand();
  if (iter==0)
	  ran= mtrand.rand(refl.Length()+diff.Length());
  //std::cout<<iter<<" "<<h.getT()<<" "<<refl.Length()+diff.Length()<<std::endl;
  //send reflective photon
  if (iter<args->num_bounces&&ran<=refl.Length())
	  TracePhoton(r.pointAtParameter(h.getT()),r.getDirection()-2*(r.getDirection().Dot3(h.getNormal()))*h.getNormal(),energy,iter+1);
  else if (iter<args->num_bounces&&ran<=refl.Length()+diff.Length())
	  TracePhoton(r.pointAtParameter(h.getT()),RandomDiffuseDirection(h.getNormal()),energy,iter+1);
  else
  {
	  Photon p(position,direction,energy,iter);
	  kdtree->AddPhoton(p);
  }


}
Example #15
0
Vec3f RayTracer::reflection(const Ray &start_ray, int bounce_count) const
{
	Ray ray(start_ray);
	Hit h;
	Vec3f answer = TraceRay(ray, h, bounce_count);
	while (h.getT() < SURFACE_EPSILON) {
		ray = Ray(ray.pointAtParameter(SURFACE_EPSILON),
				ray.getDirection());
		answer = TraceRay(ray, h, bounce_count);
	}
	return answer;
}
Example #16
0
bool Triangle::intersect( const Ray& r , Hit& h , float tmin){

	Vector3f R_o = r.getOrigin();
	Vector3f R_d = r.getDirection();

	Matrix3f A( this->a.x()-this->b.x() , this->a.x()-this->c.x() , R_d.x() ,
		    this->a.y()-this->b.y() , this->a.y()-this->c.y() , R_d.y() ,
		    this->a.z()-this->b.z() , this->a.z()-this->c.z() , R_d.z()  );

	Matrix3f BetaM( this->a.x()-R_o.x() , this->a.x()-this->c.x() , R_d.x() ,
		        this->a.y()-R_o.y() , this->a.y()-this->c.y() , R_d.y() ,
		        this->a.z()-R_o.z() , this->a.z()-this->c.z() , R_d.z()  );
	
	float beta = BetaM.determinant() / A.determinant();

	Matrix3f GammaM( this->a.x()-this->b.x() , this->a.x()-R_o.x() , R_d.x() ,
		         this->a.y()-this->b.y() , this->a.y()-R_o.y() , R_d.y() ,
		         this->a.z()-this->b.z() , this->a.z()-R_o.z() , R_d.z()  );
	
	float gamma = GammaM.determinant() / A.determinant();

	float alpha = 1.0f - beta - gamma;

	Matrix3f tM( this->a.x()-this->b.x() , this->a.x()-this->c.x() , this->a.x()-R_o.x() ,
		     this->a.y()-this->b.y() , this->a.y()-this->c.y() , this->a.y()-R_o.y() ,
		     this->a.z()-this->b.z() , this->a.z()-this->c.z() , this->a.z()-R_o.z()  );
	
	float t = tM.determinant() / A.determinant();

	if (beta + gamma > 1){
	    return false;
	} 
	if (beta < 0){
	    return false;
	} 
	if (gamma < 0){
	    return false;
	} 

	if (t > tmin && t < h.getT()){

	    Vector3f newNormal = (alpha*this->normals[0] + beta*this->normals[1] + gamma*this->normals[2]).normalized();
	    h.set(t, this->material, newNormal);

	    Vector2f newTexCoord = (alpha*this->texCoords[0] + beta*this->texCoords[1] + gamma*this->texCoords[2]);
	    h.setTexCoord(newTexCoord);

	    return true;	
	} 
	else{
	    return false;
	} 
}
// trace a ray through pixel (i,j) of the image an return the color
glm::vec3 TraceRay(double i, double j,tVals* arg) {
  // compute and set the pixel color
  int max_d = std::max(arg->args->width,arg->args->height);
  glm::vec3 color;

  if (arg->args->num_antialias_samples > 1)
  {
	  for (int n = 0; n < arg->args->num_antialias_samples; n++)
	  {
		  //Random sampling
		  WaitForSingleObject(*arg->ranLock,INFINITE);
		  double x = (GLOBAL_MTRAND.rand()*2 + i - arg->args->width / 2.0) / double(max_d) + 0.5;
		  double y = (GLOBAL_MTRAND.rand()*2 + j - arg->args->height / 2.0) / double(max_d) + 0.5;
		  ReleaseMutex(*arg->ranLock);
		  Ray r = arg->camera->generateRay(x, y);
		  Hit hit;
		  glm::vec3 part = arg->raytracer->TraceRay(r, hit, arg->args->num_bounces);
		  part /= arg->args->num_antialias_samples;
		  color += part;
		  // add that ray for visualization
		  RayTree::AddMainSegment(r, 0, hit.getT());
	  }
  }
  else
  {
	  // Here's what we do with a single sample per pixel:
	  // construct & trace a ray through the center of the pixel
	  double x = (i - arg->args->width / 2.0) / double(max_d) + 0.5;
	  double y = (j - arg->args->height / 2.0) / double(max_d) + 0.5;
	  Ray r = arg->camera->generateRay(x, y);
	  Hit hit;
	  color = arg->raytracer->TraceRay(r, hit, arg->args->num_bounces);
	  // add that ray for visualization
	  RayTree::AddMainSegment(r, 0, hit.getT());
  }
  // return the color
  return color;
}
Example #18
0
//normal.(r.origin + t*r.direction) +d = 0
bool Plane::intersect(const Ray &r, Hit &h, float tmin)
{
	float isParallel = normal.Dot3(r.getDirection());
	if(!Utility::isZero(isParallel))
	{
		float dist = -(normal.Dot3(r.getOrigin())-d)/isParallel;  //当时没有理解d的含义,构造是应该是ax+by+cz-d=0
		if(dist > tmin && dist < h.getT())
		{
			h.set(dist,material,normal,r);
			return 1;
		}
	}
	return 0;
}
bool CylinderRing::intersect(const Ray &r, Hit &h) const {

  // intersect with the 4 parts of the ring
  double outer_t;
  Vec3f outer_normal;
  bool outer = IntersectFiniteCylinder(r,center,outer_radius,height,outer_t,outer_normal);
  double inner_t;
  Vec3f inner_normal;
  bool inner = IntersectFiniteCylinder(r,center,inner_radius,height,inner_t,inner_normal);
  double top_t;
  Vec3f top_normal;
  bool top = IntersectAnnulus(r,center+Vec3f(0,height/2.0,0),inner_radius,outer_radius,top_t,top_normal);
  double bottom_t;
  Vec3f bottom_normal;
  bool bottom = IntersectAnnulus(r,center-Vec3f(0,height/2.0,0),inner_radius,outer_radius,bottom_t,bottom_normal);
  bool answer = false;

  // return the closest intersection
  if (outer && (outer_t < h.getT())) {
    h.set(outer_t,this->getMaterial(),outer_normal,NULL);
    answer = true;
  }
  if (inner && (inner_t < h.getT())) {
    h.set(inner_t,this->getMaterial(),-inner_normal,NULL);
    answer = true;
  }
  if (top && (top_t < h.getT())) {
    h.set(top_t,this->getMaterial(),top_normal,NULL);
    answer = true;
  }
  if (bottom && (bottom_t < h.getT())) {
    h.set(bottom_t,this->getMaterial(),-bottom_normal,NULL);
    answer = true;
  }
  return answer;
} 
bool Face::triangle_intersect(const Ray &r, Hit &h, Vertex *a, Vertex *b, Vertex *c, bool intersect_backfacing) const {

  // compute the intersection with the plane of the triangle
  Hit h2 = Hit(h);
  if (!plane_intersect(r,h2,intersect_backfacing)) return 0;  

  // figure out the barycentric coordinates:
  glm::vec3 Ro = r.getOrigin();
  glm::vec3 Rd = r.getDirection();
  // [ ax-bx   ax-cx  Rdx ][ beta  ]     [ ax-Rox ] 
  // [ ay-by   ay-cy  Rdy ][ gamma ]  =  [ ay-Roy ] 
  // [ az-bz   az-cz  Rdz ][ t     ]     [ az-Roz ] 
  // solve for beta, gamma, & t using Cramer's rule
  
  glm::mat3 detA_mat(a->get().x-b->get().x,a->get().x-c->get().x,Rd.x,
                     a->get().y-b->get().y,a->get().y-c->get().y,Rd.y,
                     a->get().z-b->get().z,a->get().z-c->get().z,Rd.z);
  float detA = glm::determinant(detA_mat);

  if (fabs(detA) <= 0.000001) return 0;
  assert (fabs(detA) >= 0.000001);
  
  glm::mat3 beta_mat(a->get().x-Ro.x,a->get().x-c->get().x,Rd.x,
                     a->get().y-Ro.y,a->get().y-c->get().y,Rd.y,
                     a->get().z-Ro.z,a->get().z-c->get().z,Rd.z);
  
  glm::mat3 gamma_mat(a->get().x-b->get().x,a->get().x-Ro.x,Rd.x,
                      a->get().y-b->get().y,a->get().y-Ro.y,Rd.y,
                      a->get().z-b->get().z,a->get().z-Ro.z,Rd.z);

  float beta = glm::determinant(beta_mat) / detA;
  float gamma = glm::determinant(gamma_mat) / detA;

  if (beta >= -0.00001 && beta <= 1.00001 &&
      gamma >= -0.00001 && gamma <= 1.00001 &&
      beta + gamma <= 1.00001) {
    h = h2;
    // interpolate the texture coordinates
    float alpha = 1 - beta - gamma;
    float t_s = alpha * a->get_s() + beta * b->get_s() + gamma * c->get_s();
    float t_t = alpha * a->get_t() + beta * b->get_t() + gamma * c->get_t();
    h.setTextureCoords(t_s,t_t);
    assert (h.getT() >= EPSILON);
    return 1;
  }

  return 0;
}
bool Plane::intersect( const Ray& r, Hit& h, float tmin ) const
{
	float nd = this->m_normal.dot(r.getDirection());
	if (nd == 0.0f) {
		return false;
	}

	float t = (this->m_d - (this->m_normal.dot(r.getOrigin())))/nd;

	if (t < h.getT() && t > tmin) {
		h.set(t, this->m_material, this->m_normal);
		return true;
	}

	return false;
}
Example #22
0
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f rTransOri = r.getOrigin();
	Vec3f rTransDir = r.getDirection();
	Matrix mInverse;
	m.Inverse(mInverse);
	mInverse.Transform(rTransOri);
	mInverse.TransformDirection(rTransDir);
	
	rTransDir.Normalize();
	Ray rTrans(rTransDir,rTransOri);
	Hit hTrans(10000,NULL,Vec3f(0,0,0));  //need a new hit,because the x-y-z had changed  就因为这里没有使用一个新的hit导致了自己debug了两天
	instance->intersect(rTrans,hTrans,tmin);
	if(hTrans.getT()<10000)
	{
		//world's t
		float t;
		//Vec3f hitPoint = rTransOri + rTransDir * hTrans.getT();
		Vec3f hitPoint = rTrans.pointAtParameter(hTrans.getT());
		m.Transform(hitPoint);
		Vec3f rOri = r.getOrigin();
		Vec3f rDir = r.getDirection();
		if((fabs(rDir[0])>=fabs(rDir[1]))&&(fabs(rDir[0])>=fabs(rDir[2]))){
			t = (hitPoint[0] - rOri[0]) / rDir[0]; 	
		}
		else if((fabs(rDir[1])>=fabs(rDir[0]))&&(fabs(rDir[1])>=fabs(rDir[2]))){
			t = (hitPoint[1] - rOri[1]) / rDir[1];
		}
		else if((fabs(rDir[2])>=fabs(rDir[0]))&&(fabs(rDir[2])>=fabs(rDir[1]))){
			t = (hitPoint[2] - rOri[2]) / rDir[2];
		}

		//world's normal
		mInverse.Transpose();
		Vec3f wNormal = hTrans.getNormal();
		mInverse.TransformDirection(wNormal);
		wNormal.Normalize();  //need normalize
		//h.setNormal(wNormal);

		if(t>=tmin && t<=h.getT())
		{
			h.set(t,hTrans.getMaterial(),wNormal,r);
			return 1;
		}
	}
	return 0;
}
Example #23
0
bool Face::triangle_intersect(const Ray &r, Hit &h, Vertex *a, Vertex *b, Vertex *c, bool intersect_backfacing, bool* backfacing_hit) {

	*backfacing_hit = false;
	// compute the intersection with the plane of the triangle
	Hit h2 = Hit(h);
	if (!plane_intersect(r,h2,intersect_backfacing, backfacing_hit)) return 0;	

	// figure out the barycentric coordinates:
	Vec3f Ro = r.getOrigin();
	Vec3f Rd = r.getDirection();
	// [ ax-bx	 ax-cx	Rdx ][ beta	]		 [ ax-Rox ] 
	// [ ay-by	 ay-cy	Rdy ][ gamma ]	=	[ ay-Roy ] 
	// [ az-bz	 az-cz	Rdz ][ t		 ]		 [ az-Roz ] 
	// solve for beta, gamma, & t using Cramer's rule
	
	double detA = Matrix::det3x3(a->get().x()-b->get().x(),a->get().x()-c->get().x(),Rd.x(),
						 a->get().y()-b->get().y(),a->get().y()-c->get().y(),Rd.y(),
						 a->get().z()-b->get().z(),a->get().z()-c->get().z(),Rd.z());
	
	if (fabs(detA) <= 0.000001) return 0;
	assert (fabs(detA) >= 0.000001);

	double beta	= Matrix::det3x3(a->get().x()-Ro.x(),a->get().x()-c->get().x(),Rd.x(),
				a->get().y()-Ro.y(),a->get().y()-c->get().y(),Rd.y(),
				a->get().z()-Ro.z(),a->get().z()-c->get().z(),Rd.z()) / detA;
	
	double gamma = Matrix::det3x3(a->get().x()-b->get().x(),a->get().x()-Ro.x(),Rd.x(),
				a->get().y()-b->get().y(),a->get().y()-Ro.y(),Rd.y(),
				a->get().z()-b->get().z(),a->get().z()-Ro.z(),Rd.z()) / detA;

	//Case of an intersection
	if (beta >= -0.00001 && beta <= 1.00001 &&
			gamma >= -0.00001 && gamma <= 1.00001 &&
			beta + gamma <= 1.00001) {
		h = h2;
		// interpolate the texture coordinates
		double alpha = 1 - beta - gamma;
		double t_s = alpha * a->get_s() + beta * b->get_s() + gamma * c->get_s();
		double t_t = alpha * a->get_t() + beta * b->get_t() + gamma * c->get_t();
		h.setTextureCoords(t_s,t_t);
		assert (h.getT() >= EPSILON);
		return 1;
	}

	return 0;
}
Example #24
0
Vector3f Material::Shade( const Ray& ray, const Hit& hit,
                          const Vector3f& dirToLight, const Vector3f& lightColor ) {
    Vector3f kd;
    if(t.valid() && hit.hasTex) {
        Vector2f texCoord = hit.texCoord;
        Vector3f texColor = t(texCoord[0],texCoord[1]);
        kd = texColor;
    } else {
        kd = this->diffuseColor;
    }
    //Diffuse Shading
    if(noise.valid()) {
        kd = noise.getColor(ray.getOrigin()+ray.getDirection()*hit.getT());
    }
    Vector3f n = hit.getNormal().normalized();
    Vector3f color = clampedDot( dirToLight ,n )*pointwiseDot( lightColor , kd);
    return color;
}
Example #25
0
bool Transform::intersect( const Ray& r , Hit& h , float tmin)
{
    Matrix4f iMatrix=TMatrix_.inverse();
	Matrix4f tMatrix=TMatrix_.transposed() ;
    
    //Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz().normalized());
	Ray newRay = Ray((iMatrix * Vector4f(r.getOrigin(), 1.0f)).xyz(), (iMatrix* Vector4f(r.getDirection(), 0.0f)).xyz());
    if(o->intersect(newRay, h , tmin))
    {
    	
		h.set(h.getT(), h.getMaterial(), (iMatrix.transposed() * Vector4f(h.getNormal(), 0.0f)).xyz().normalized());
		return true;

	}

    return false;

}
Example #26
0
bool Triangle::any_intersect(const Ray& ray, Hit& hit, float tmin)
{
	Vector3f direction = ray.getDirection();
	Vector3f origin = ray.getOrigin();
	float list[9] = { (a.x()) - (b.x()),(a.y()) - (b.y()),(a.z()) - (b.z()), (a.x()) - (c.x()),(a.y()) - (c.y()),(a.z()) - (c.z()),  (a[0]) - (origin[0]),(a[1]) - (origin[1]),(a[2]) - (origin[2]), };
	Matrix3f A = Matrix3f(list[0], list[3], direction[0], list[1], list[4], direction[1], list[2], list[5], direction[2]);
	float determinant = A.determinant();
	if (determinant == 0) { return false; }
	float t = Matrix3f::determinant3x3(list[0], list[3], list[6], list[1], list[4], list[7], list[2], list[5], list[8]) / determinant;
	if (t <= tmin || t >= hit.getT()) { return false; }
	float beta = Matrix3f::determinant3x3(list[6], list[3], direction[0], list[7], list[4], direction[1], list[8], list[5], direction[2]) / determinant;
	float gamma = Matrix3f::determinant3x3(list[0], list[6], direction[0], list[1], list[7], direction[1], list[2], list[8], direction[2]) / determinant;

	if ((beta >= 0 && gamma >= 0 && beta + gamma <= 1))
	{
		return true;
	}
	return false;
}
Example #27
0
bool Grid::intersectWithGridVisualization(const Ray & r, Hit & h, float tmin) const
{
	RayTracing_Stats::IncrementNumIntersections();

	MarchInfo mi;

	bool re = initializeRayMarch(mi, r, tmin);
	if ( re == false ) {
		return false;
	}

	int index_i, index_j, index_k;

	while ( IsCellValid(mi) ) 
	{
		RayTracing_Stats::IncrementNumGridCellsTraversed();

		index_i = mi.get_i();
		index_j = mi.get_j();
		index_k = mi.get_k();

		Object3DVector & obj_array = cells[num_y * num_z * index_i + num_z * index_j + index_k].objs;
		
		int num_objs = obj_array.getNumOfObjects();
		if ( num_objs > 0 ) 
		{
			if ( mi.tmin < h.getT() ) 
			{
				h.set(mi.tmin, selfRendering_m, mi.surfaceNormal, r);
				return true;
			}
			else
				return false;
		} else {
			mi.nextCell();
		}
	}

	return false;
}
Example #28
0
Vec3f RayTracer::reflections(const Ray &ray, const Hit &hit, int bounce_count, double roughness) const
{
	if (bounce_count <= 0)
		return Vec3f(0, 0, 0);
	const Vec3f point = ray.pointAtParameter(hit.getT());

	/* Get mirror direction */
	const Vec3f orig_dir = ray.getDirection();
	Vec3f norm = hit.getNormal();
	norm.Normalize();
	const Vec3f new_dir = orig_dir - 2 * orig_dir.Dot3(norm) * norm;

	const Ray new_ray(point, new_dir);
	Vec3f rand_vec(0, 0, 0);
	double answerx = 0, answery = 0, answerz = 0;
	/* sphere projection, what if the center of the sphere misses the
	 * object?
	 */

	{
		for (int i = 0; i <= args->num_glossy_samples; ++i) {
			/* Getting gloss ray */
			Ray start_ray(new_ray.getOrigin(),
					new_ray.getDirection() + rand_vec);
			const Vec3f answer(reflection(start_ray, bounce_count - 1));

			answerx += answer.x();
			answery += answer.y();
			answerz += answer.z();
			rand_vec = Vec3f(roughness * (static_cast<double>(rand()) / RAND_MAX),
				roughness * (static_cast<double>(rand()) / RAND_MAX),
				roughness * (static_cast<double>(rand()) / RAND_MAX));
		}
	}
	Vec3f answer = Vec3f(answerx, answery, answerz);
	answer *= static_cast<double>(1)/(args->num_glossy_samples + 1);
	return answer;
}
Example #29
0
bool Transform::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f original = r.getOrigin();
	Vec3f dir = r.getDirection();

	mReverseMat.Transform(original);
	mReverseMat.TransformDirection(dir);


	Ray transformedRay(original, dir);

	if (mObj->intersect(transformedRay, h, tmin))
	{
        Vec3f normal = h.getNormal();
        Matrix t;
        mReverseMat.Transpose(t);
        t.TransformDirection(normal);
        h.set(h.getT(), h.getMaterial(), normal, r);
        return true;
	}

    return false;
}
Example #30
0
bool Rectangle::intersect(const Ray& r, Hit& h, float tmin)
{
	Vector3f a = vertex0; 
	Vector3f b = vertex0 + side_1;
	Vector3f c = vertex0 + side_2;
	Vector3f direction = r.getDirection();
	Vector3f origin = r.getOrigin();
	float list[9] = { (a.x()) - (b.x()),(a.y()) - (b.y()),(a.z()) - (b.z()), (a.x()) - (c.x()),(a.y()) - (c.y()),(a.z()) - (c.z()),  (a[0]) - (origin[0]),(a[1]) - (origin[1]),(a[2]) - (origin[2]), };
	Matrix3f A = Matrix3f(list[0], list[3], direction[0], list[1], list[4], direction[1], list[2], list[5], direction[2]);
	float determinant = A.determinant();
	if (determinant == 0) { return false; }
	float t = Matrix3f::determinant3x3(list[0], list[3], list[6], list[1], list[4], list[7], list[2], list[5], list[8]) / determinant;
	if (t <= tmin || t >= h.getT()) { return false; }
	float beta = Matrix3f::determinant3x3(list[6], list[3], direction[0], list[7], list[4], direction[1], list[8], list[5], direction[2]) / determinant;
	float gamma = Matrix3f::determinant3x3(list[0], list[6], direction[0], list[1], list[7], direction[1], list[2], list[8], direction[2]) / determinant;

	if ((beta >= 0 && gamma >= 0 && beta <= 1 && gamma <= 1))
	{
		h.set(t, this->material, normal);
		return true;
	}
	return false;
}