Ejemplo n.º 1
0
bool SceneNode::intersect(const Ray& ray, Intersection& i) const
{
  // Transform the ray from WCS->MCS for this node
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  bool intersects = false;
  for(auto child : m_children)
  {
    Intersection j;
    if(child->intersect(r, j))
    {
      // We need to see if this intersection point is closer than the previous intersection point
      // If it is than replace the previous intersection
      if(std::isinf(i.q[0]) || std::isinf(i.q[1]) || std::isinf(i.q[2]) || (j.q-r.origin()).length() < (i.q-r.origin()).length()) i = j;
      intersects = true;
    }
  }

  // If intersection occurs than transform the intersection point and the normal from MCS->WCS
  // We have to convert the intersection point from MCS->WCS and the normal from MCS->WCS
  // Normals must be multiplied by the transpose of the inverse to throw away scaling (no translations either, but the normal is 
  // a vector and vectors can't be translated) but preserve rotation
  if(intersects)
  {
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
  }
  
  return intersects;
}
Ejemplo n.º 2
0
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSquare, which is
	// defined on the xy-plane, with vertices (0.5, 0.5, 0), 
	// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
	// (0, 0, 1).
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_hit.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
    
    Ray3D modelRay;                     // To store transformed model space ray.
    Vector3D surfaceNormal(0, 0, 1);    // Constant surface normal.
    double t;                           // Intersection parameter.
    
    // Transform ray to model space.
    modelRay.origin = worldToModel * ray.origin;
    modelRay.dir = worldToModel * ray.dir;;

    // Compute intersection between ray and XY-plane.
    double d_dot_n = modelRay.dir.dot(surfaceNormal);
  
    // TODO: NEED MORE STABLE FLOAT EQUAL CHECK!
    if (d_dot_n == 0.0) {
        // Ray is parallel to plane.
        return false;
    }
    
    // Compute intersection and check if it occurs infront or behind the camera.
    t = -(Vector3D(modelRay.origin[0], modelRay.origin[1], modelRay.origin[2]).dot(surfaceNormal)) / d_dot_n;
    if (t < ray.intersection.t_min || t > ray.intersection.t_max) {
        return false;
    }
    
    if (!ray.intersection.none && t > ray.intersection.t_hit) {
        return false;
    }
    
    // Compute intersection point and check againt unit square bounds.
    Point3D intPoint = modelRay.origin + (t * modelRay.dir);
    if (!(intPoint[0] >= -0.5 && intPoint[0] <= 0.5 &&
          intPoint[1] >= -0.5 && intPoint[1] <= 0.5)) {
        return false;
    }
    
    // Transform and set intersection info.
    ray.intersection.point = modelToWorld * intPoint;
    ray.intersection.normal = transNorm(worldToModel, surfaceNormal);
    ray.intersection.normal.normalize();
    ray.intersection.t_hit = t;
    ray.intersection.none = false;
    ray.intersection.inside = false;
    
	return true;
}
Ejemplo n.º 3
0
bool SceneNode::intersect (Point3D eye, Vector3D ray, Results &res, bool quit_early) const {
  bool ret = false;
  //std::cout << "start " << m_name << std::endl;
  eye = m_invtrans * eye;
  ray = m_invtrans * ray;
  res.normal = transNorm(m_trans, res.normal);
  ChildList::const_iterator it = m_children.begin();
  for (it=m_children.begin(); it != m_children.end(); ++it) {
    //std::cout << m_name << std::endl;
    bool sub_ret = (*it)->intersect(eye, ray, res);
    ret = ret || sub_ret;
    if (ret && quit_early) return ret;
  }

  res.normal = transNorm(m_invtrans, res.normal);

  return ret;
}
Ejemplo n.º 4
0
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// DONE: implement intersection code for UnitSquare, which is
	// defined on the xy-plane, with vertices (0.5, 0.5, 0),
	// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
	// (0, 0, 1).
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point,
	// intersection.normal, intersection.none, intersection.t_value.
	//
	// HINT: Remember to first transform the ray into object space
	// to simplify the intersection test.

	// transform the ray into object space
	Ray3D obj_ray;
	obj_ray.origin = worldToModel * ray.origin;
	obj_ray.dir = worldToModel * ray.dir;

	// case 1: if the ray is in xy-plane, it will not intersect with the unit square
	if(obj_ray.dir[2] == 0)
	{
		return false;
	}

	// case 2: the general case, the ray is not in xy-plane
	double t_value = (-obj_ray.origin[2])/obj_ray.dir[2];
	if(t_value <= 0)
	{
		return false;
	}
	// 1. x componet of the intersection
	double x = obj_ray.origin[0] + t_value * obj_ray.dir[0];
	// 2. y componet of the intersection
	double y = obj_ray.origin[1] + t_value * obj_ray.dir[1];
	// 3. z componet of the intersection
	double z = 0.0;

	if(x < -0.5 || x > 0.5 || y < -0.5 || y > 0.5)
	{
		return false;
	}

	if(ray.intersection.none || t_value < ray.intersection.t_value)
	{
		Point3D intersection = modelToWorld * Point3D(x, y, z);
		Vector3D normal(0, 0, 1);
		normal = transNorm(worldToModel, normal);
		ray.intersection.point = intersection;
		ray.intersection.normal = normal;
		ray.intersection.mat = ray.intersection.mat;
		ray.intersection.t_value = t_value;
		ray.intersection.none = false;
		return true;
	}

}
Ejemplo n.º 5
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	Point3D world_origin(0, 0, 0);
	
	double lambda;
	
	Vector3D d = worldToModel * ray.dir;
	Point3D a = worldToModel * ray.origin;
	Point3D c(0, 0, 0);
	Vector3D nmb = a - c;
	
	double A = d.dot(d);
	double B = nmb.dot(d);
	double C = nmb.dot(nmb) - 1;
	
	double D = (B * B) - (A * C);
	
	if (D < 0){
		return false;
	}
	else if(D == 0){
		lambda = - (B / A);
	}
	else{
		double lambda1 = - (B / A) + (sqrt(D) / A);
		double lambda2 = - (B / A) - (sqrt(D) / A);
		lambda = std::min(lambda1, lambda2);
		if (lambda < 0){
			lambda = std::max(lambda1, lambda2);
			if (lambda < 0){
				return false;
			}
		}
	}
	Point3D intersect_point = a + (lambda * d);
    Vector3D normal_vector = intersect_point - c;
    normal_vector.normalize();
    
	ray.intersection.t_value = lambda;
    ray.intersection.normal = transNorm(worldToModel, normal_vector);
    ray.intersection.normal.normalize();
    ray.intersection.point = modelToWorld * intersect_point;
    ray.intersection.none = false;
	return true;
}
Ejemplo n.º 6
0
// Intersection code for UnitSphere, which is centred on the origin.
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
    const Matrix4x4& modelToWorld ) {

  // The sphere's radius
  double radius = 1;

  // Transform ray into object space
  Point3D modelPoint = worldToModel*ray.origin;
  Vector3D modelDirection = worldToModel*ray.dir;

  // Detemine if there is an intersection
  double a = dot(modelDirection, modelDirection);
  double b = dot(modelPoint, modelDirection);
  double c = dot(modelPoint, modelPoint) - radius;
  double d = b * b - a * c;
  double didIntersect = d >= 0;

  // Find how close the intersection is
  if (d >= 0) {
    double lambda = - b / a;
    double ld1, ld2;
    ld1 = ld2 = 0;
    if (d > 0) {
      ld1 = lambda + sqrt(d)/a;
      ld2 = lambda - sqrt(d)/a;
      if (ld1 > 0 && ld2 < 0) {
        lambda = ld1;
      } else if (ld1 > ld2 && ld2 > 0){
        lambda = ld2;
      } else {
        lambda = ld1;
      }
    }

    // If a closer intersection exists, ignore this one
    if ((ray.intersection.t_value < lambda && !ray.intersection.none) || (ld1 < 0 && ld2 < 0)) {
      return false;
    }

    // Find the intersection and associated normal
    Point3D intersection = modelPoint + lambda*modelDirection;
    Vector3D normal = Vector3D(2 * intersection[0], 2 * intersection[1], 2 * intersection[2]);

    // Populate ray.intersection values
    ray.intersection.none = !didIntersect;
    ray.intersection.point = modelToWorld*intersection;
    ray.intersection.t_value = lambda;
    normal = transNorm(worldToModel, normal);
    normal.normalize();
    ray.intersection.normal = normal;
  }

  return didIntersect;
}
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	
	Ray3D r;
	r.origin = worldToModel * ray.origin;
	r.dir = worldToModel * ray.dir;

	Point3D sphere(0,0,0);
	Vector3D s_dist = r.origin - sphere;
	double int0 = -1, int1;

	double a = r.dir.dot(r.dir);
	double b = s_dist.dot(r.dir);
	double c = s_dist.dot(s_dist) - 1;
	double d = b * b - a * c;

	if (d == 0) int0 = -b/a;
	else if (d > 0) {
		int0 = (-b + sqrt(d)) / a;
		int1 = (-b - sqrt(d)) / a;
		int0 = int0 < int1 ? int0 : int1;
	}


	if (int0 <= 0) return false;

	if (ray.intersection.none || int0 < ray.intersection.t_value) {

		Point3D ip = r.origin + int0 * r.dir;
		Vector3D n = 2 * (ip - sphere);
		n.normalize();

		ray.intersection.t_value = int0;
		ray.intersection.point = modelToWorld * ip;
		ray.intersection.normal = transNorm(worldToModel, n);
		ray.intersection.normal.normalize();
		ray.intersection.none = false;
		return true;
	}

	return false;
}
Ejemplo n.º 8
0
bool DifferenceNode::intersect(const Ray& ray, Intersection& i) const
{
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  Intersection j, k;
  bool intersects_a = m_A->intersect(r, j);
  bool intersects_b = m_B->intersect(r, k);

  bool intersects = false;
  if(intersects_a)
  {
    double epsilon = std::numeric_limits<double>::epsilon();
    if(intersects_b && ((k.q-r.origin()).length() < (j.q-r.origin()).length()))
    {
      int idx = (fabs(r.direction()[0]) > epsilon) ? 0 : ((fabs(r.direction()[1]) > epsilon) ? 1 : 2);
      double t = (j.q[idx] - r.origin()[idx]) / r.direction()[idx];
      Ray nray(r.origin() + (t+1000*epsilon)*r.direction(), r.direction());

      Intersection u, v;
      intersects_a = m_A->intersect(nray, u);
      intersects_b = m_B->intersect(nray, v);

      if(!intersects_b)
      {
        i = j;
        intersects = true;
      }
      else if(intersects_a && ((v.q-r.origin()).length() < (u.q-r.origin()).length()))
      {
        i = v;
        i.n = -i.n;
        intersects = true;
      }
    }
    else
    {
      i = j;
      intersects = true;
    }
  }

  if(intersects)
  {
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
  }
    
  return (intersects || SceneNode::intersect(ray, i));
}
Ejemplo n.º 9
0
bool GeometryNode::intersect (Point3D eye, Vector3D ray, Results &res, bool quit_early) const {
  //std::cout << m_name << std::endl;
  // Find intersection with shape
  if (m_primitive->intersect(m_invtrans*eye, m_invtrans*ray, res)) {
    // Convert normal to WCS
    //*(res.normal) = m_revert * *(res.normal);
    res.normal = transNorm(m_invtrans, res.normal);

    // Update return value with material
    res.material = m_material;
    return true;
  } else {
    // No intersection
    return false;
  }
}
Ejemplo n.º 10
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
    
    Vector3D d = worldToModel*ray.dir;
    // d.normalize();
    Point3D e = worldToModel*ray.origin;
    Point3D c;
    float A = d.dot(d);
    float B = d.dot(e-c);
    float C = (e-c).dot(e-c)-1.0;
    if ((B*B - A*C) < 0)
    {
        ray.intersection.none = true;
        return false;
    }
    else
    {
        float t1 = (-B - sqrt(B*B - A*C)) / A;
        float t2 = (-B + sqrt(B*B - A*C)) / A;
        float t = fmin(t1, t2);
        if (t > 0)
        {
            if (!ray.intersection.none && ray.intersection.t_value < t)
            {
                return false;
            }
            Vector3D n = e + t*d - c;
            n.normalize();
            ray.intersection.point = modelToWorld * (e + t*d);
            ray.intersection.normal = transNorm(worldToModel, n);
            ray.intersection.none = false;
            ray.intersection.t_value = t;
            return true;
        }
        else
            return false;
    }
}
Ejemplo n.º 11
0
bool IntersectionNode::intersect(const Ray& ray, Intersection& i) const
{
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  Intersection j, k;
  bool intersects_a = m_A->intersect(r, j);
  bool intersects_b = m_B->intersect(r, k);

  if(intersects_a && intersects_b)
  {
    i = ((k.q-r.origin()).length() > (j.q-r.origin()).length()) ? k : j;
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
  }

  return ((intersects_a && intersects_b) || SceneNode::intersect(ray, i));
}
Ejemplo n.º 12
0
bool UnionNode::intersect(const Ray& ray, Intersection& i) const
{
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  Intersection j, k;
  bool intersects_a = m_A->intersect(r, j);
  bool intersects_b = m_B->intersect(r, k);

  if(intersects_a || intersects_b)
  {
    i = (std::isinf(j.q[0]) || std::isinf(j.q[1]) || std::isinf(j.q[2]) || (k.q-r.origin()).length() < (j.q-r.origin()).length()) ? k : j;
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
  }

  return (intersects_a || intersects_b || SceneNode::intersect(ray, i));
}
Ejemplo n.º 13
0
bool GeometryNode::intersect(const Ray& ray, Intersection& i) const
{
  // Test for intersection
  // But first transform ray to geometry's model coordinates (inverse transform from WCS->MCS)
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  Intersection k;
  bool intersects = m_primitive->intersect(r, k);
  if(intersects) 
  {
    i = k;
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
    i.m = m_material;
  }

  return (intersects || SceneNode::intersect(ray, i));
}
Ejemplo n.º 14
0
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
                           const Matrix4x4& modelToWorld ) {
    
    //tranform ray into object space
    Vector3D obj_dir = worldToModel * ray.dir;
    Point3D obj_ori = worldToModel * ray.origin;
    //ray =obj_ori + t*obj_dir
    // N·(E + tD - Q) = 0
    // t = N·(Q - E) / N·D
    Vector3D plane_norm = Vector3D(0,0,1);
    double result = plane_norm.dot(obj_dir);
    if(result == 0){
        return false;
    }else{
        Point3D plane_ptr = Point3D();//origin point is on the plane
        Vector3D m = plane_ptr - obj_ori;
        double t = plane_norm.dot(m)/result;
        if(t > 0){
            double inter_x = obj_ori[0] + t * obj_dir[0];
            double inter_y = obj_ori[1] + t * obj_dir[1];
            if(inter_x < 0.5 && inter_x > -0.5 && inter_y < 0.5 && inter_y > -0.5 && (t < ray.intersection.t_value || ray.intersection.none)){
                ray.intersection.point = modelToWorld * Point3D(inter_x, inter_y, 0);
                ray.intersection.t_value = t;
                ray.intersection.none = false;
                Vector3D n =  Vector3D(0, 0, 1);
                Vector3D inter_norm = transNorm(worldToModel, n);
                ray.intersection.normal = inter_norm;
                ray.intersection.normal.normalize();
                Point3D point = worldToModel * ray.intersection.point;
                ray.intersection.textcoor = Point3D(point[0] + 0.5, 0.5 - point[1], 0);
                return true;
            }else{
                return false;
            }
        }else{
            //no intersection
            return false;
        }
    }
}
Ejemplo n.º 15
0
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSquare, which is
	// defined on the xy-plane, with vertices (0.5, 0.5, 0), 
	// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
	// (0, 0, 1).
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	Vector3D d = worldToModel * ray.dir;
	Point3D a = worldToModel * ray.origin;
	
	double lambda = - a[2] / d[2];
	
	Point3D p = a + (lambda * d);
	
	if (ray.intersection.none || ray.intersection.t_value > lambda){
		if(p[0] > 0.5 || p[0] < -0.5 || p[1] > 0.5 || p[1] < -0.5){
			return false;
		}
		
		Vector3D normal_vector(0, 0, 1);
		
		ray.intersection.t_value = lambda;
		ray.intersection.normal = transNorm(worldToModel, normal_vector);
		ray.intersection.normal.normalize();
		ray.intersection.point = modelToWorld * p;
		ray.intersection.none = false;
		
		return true;
	}
	
	return false;
}
Ejemplo n.º 16
0
// Finds intersection for UnitSquare, which is
// defined on the xy-plane, with vertices (0.5, 0.5, 0),
// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
// (0, 0, 1).
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
    const Matrix4x4& modelToWorld ) {

  // Half oof the unit square's edge length
  double bound = 0.5;

  // Transform ray into object space
  Point3D modelPoint = worldToModel*ray.origin;
  Vector3D modelDirection = worldToModel*ray.dir;

  // The square's normal and a point on the square
  Vector3D normal = Vector3D(0, 0, 1);
  Point3D q1 = Point3D(0, 0, 0);

  // Find how close the intersection is
  double lambda = dot(q1 - modelPoint, normal)/dot(modelDirection, normal);

  // If a closer intersection exists, ignore this one
  if (ray.intersection.t_value < lambda && !ray.intersection.none) {
    return false;
  }

  // Find the intersection
  Point3D intersection = modelPoint + lambda*modelDirection;
  bool intersectionInBounds = intersection[0] >= -bound && intersection[0] <= bound && intersection[1] >= -bound && intersection[1] <= bound;

  // Populate ray.intersection values
  if (intersectionInBounds) {
    ray.intersection.point = modelToWorld*intersection;
    ray.intersection.normal = transNorm(worldToModel, normal);
    ray.intersection.normal.normalize();
    ray.intersection.t_value = lambda;
    ray.intersection.none = false;
  }

  return intersectionInBounds;
}
Ejemplo n.º 17
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_hit.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.

    Ray3D modelRay;
    double discriminant;
    double a, b, c;
    double t, t0, t1;
    int inside = 1;
    
    // Transform ray to model space.
    modelRay.origin = worldToModel * ray.origin;
    modelRay.dir = worldToModel * ray.dir;
    
    // Compute coefficients of quadractic formula.
    Vector3D vOrigin(modelRay.origin[0], modelRay.origin[1], modelRay.origin[2]);
    a = modelRay.dir.dot(modelRay.dir);
    b = modelRay.dir.dot(vOrigin);
    c = vOrigin.dot(vOrigin) - 1.0;
    
    // Compute discriminant of quadractic formula.
    discriminant = (b * b) - (a * c);
  
    if (discriminant < 0) {
        // No real roots. No intersection.
        return false;
    }
    
    t0 = (-b - sqrt(discriminant)) / a;
    t1 = (-b + sqrt(discriminant)) / a;
    
    t = t0;
    if (t < ray.intersection.t_min || t > ray.intersection.t_max) {
        t = t1;
        if (t < ray.intersection.t_min || t > ray.intersection.t_max) {
            return false;
        }
        inside = -1;
        ray.intersection.inside = true;
    }
    
    if (!ray.intersection.none && t > ray.intersection.t_hit) {
        return false;
    }
  
    Point3D intPoint = modelRay.origin + (t * modelRay.dir);
    Vector3D surfaceNormal = inside * (intPoint - Point3D(0, 0, 0));
    
    ray.intersection.point = modelToWorld * intPoint;
    ray.intersection.normal = transNorm(worldToModel, surfaceNormal);
    ray.intersection.normal.normalize();
    ray.intersection.t_hit = t;
    ray.intersection.none = false;
    
    return true;
}
Ejemplo n.º 18
0
bool UnitFiniteCone::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
                                   const Matrix4x4& modelToWorld ) {
    bool insideFlag1=false,insideFlag2=false;
    
    Point3D ray_origin = worldToModel*ray.origin;
    Vector3D ray_dir = worldToModel*ray.dir;
    Vector3D va(0,1,0);//axis for cylinder
    Point3D pa(0,0,0);
    Point3D pb(0, -1, 0);//the apex of the cone
    double cos_sqr= 0.5;
    double sin_sqr = 0.5;
    Point3D inter_pt_tmp;
    //At^2+B*t+C-1=0
   
    
    
    double vva=ray_dir.dot(va);//the projection
    double A=cos_sqr*(ray_dir-vva*va).dot(ray_dir-vva*va)-sin_sqr*vva*vva;
    double B = 2*cos_sqr*(ray_dir-vva*va).dot((ray_origin-pa)-(ray_origin-pa).dot(va)*va)-2*sin_sqr*vva*(ray_origin-pa).dot(va);
    double C=cos_sqr*((ray_origin-pa)-(ray_origin-pa).dot(va)*va).dot((ray_origin-pa)-(ray_origin-pa).dot(va)*va)-sin_sqr*((ray_origin-pa).dot(va))*((ray_origin-pa).dot(va));
    double t=0;
    double test = B*B-4*A*C;
    if(test<0||A==0){ return false;//no intersection
    }else if(test==0){
        t=-B/(2*A);
        
    }else{//there are two roots.
        //testing for the infinite cylinder
        
        double t1 = (-B+ sqrt(test))/(2*A);
        double t2 = (-B - sqrt(test))/(2*A);
        if(t1>0 && t2<0){
            t = t1;
            insideFlag1=true;
        }else if(t1<0 && t2>0){
            t = t2;
            insideFlag1=true;
        }else if(t1 > 0 && t2 > 0){
            if(t1 > t2){
                t = t2;
            }else{
                t = t1;
            }
        }else{//cylinder is behind the ray_origin so no intersection
            return false;
        }
    }
        inter_pt_tmp = ray_origin+t*ray_dir;
        
        if(((inter_pt_tmp-pb).dot(va)>=0)&&((inter_pt_tmp-pa).dot(va)<=0)){//between the two caps
            
        }else{
            t=std::numeric_limits<double>::max();
        }
        
    
    //testing for caps
  
    double t3 = (pb-ray_origin).dot(va)/ray_dir.dot(va);//intersection with the lower cap
    double tt=0;
   
    if(t3<0){
        return false;
    }else{
        tt=t3;
    }
    
    Point3D inter_pt_tmp1 = ray_origin+tt*ray_dir;
    if((inter_pt_tmp1-pb).length()<1){//in the cylinder
        insideFlag2=true;
    }else{//must on the cylinders
        tt=std::numeric_limits<double>::max();
    }
    
    if(t<=tt){
     
        if(t==std::numeric_limits<double>::max()) return false;
        if(ray.intersection.none||t<ray.intersection.t_value){
           // std::cout<<"Here......1.."<<std::endl;
        inter_pt_tmp = ray_origin+t*ray_dir;
        ray.intersection.point = modelToWorld*inter_pt_tmp;
            Vector3D v;
            Vector3D cone_norm;
            if(insideFlag1){
                v =Point3D(0,inter_pt_tmp[1],0)-inter_pt_tmp;

                cone_norm = v+Vector3D(0, inter_pt_tmp[1], 0);
            }else{
                v =inter_pt_tmp-Point3D(0,inter_pt_tmp[1],0);
                cone_norm = v-Vector3D(0, inter_pt_tmp[1], 0);
            }
            cone_norm.normalize();
        ray.intersection.normal = transNorm(modelToWorld, cone_norm);
        ray.intersection.normal.normalize();
        ray.intersection.t_value=t;
        ray.intersection.none=false;
        ray.intersection.insideCrash = insideFlag1;
        return true;
        }else{
            return true;
        }
    }else{
      //  std::cout<<"Here......2.."<<std::endl;
        if(ray.intersection.none||tt<ray.intersection.t_value){
            
            inter_pt_tmp = ray_origin+tt*ray_dir;
            ray.intersection.point = modelToWorld*inter_pt_tmp;
            if(insideFlag2){
                ray.intersection.normal = transNorm(modelToWorld, va);
            }else{
            ray.intersection.normal = transNorm(modelToWorld, -va);
            }
            ray.intersection.normal.normalize();
            ray.intersection.t_value=tt;
            ray.intersection.none=false;
            ray.intersection.insideCrash = insideFlag2;
            return true;
        }else{
            return true;
        }
    }

    return false;

}
Ejemplo n.º 19
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// DONE: implement intersection code for UnitSphere, which is centred
	// on the origin.
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point,
	// intersection.normal, intersection.none, intersection.t_value.
	//
	// HINT: Remember to first transform the ray into object space
	// to simplify the intersection test.

	// transform the ray into object space
	Ray3D obj_ray;
	obj_ray.origin = worldToModel * ray.origin;
	obj_ray.dir = worldToModel * ray.dir;

	// referred to the solution at:
	// http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

	// analytic solution
	Vector3D L = obj_ray.origin - Point3D(0, 0, 0);
	double a = obj_ray.dir.dot(obj_ray.dir);
	double b = 2 * obj_ray.dir.dot(L);
	double c = L.dot(L) - 1.0;

	double discriminant = b * b - 4 * a * c;
	double x, y, z, t_value, t_value1, t_value2;

	// no solution
	if(discriminant < 0)
	{
		return false;
	}

	// 1 solution
	if(discriminant == 0)
	{
		t_value = - 0.5 * b / a;
	}

	// 2 solutions
	if(discriminant > 0)
	{
		float q = (b > 0) ? -0.5 * (b + sqrt(discriminant)) : -0.5 * (b - sqrt(discriminant));
		t_value1 = q / a;
		t_value2 = c / q;
	}

	if (t_value1 < t_value2){
		t_value = t_value1;
	}
	else{
		t_value = t_value2;
	}

	if(ray.intersection.none || t_value < ray.intersection.t_value)
	{
		// 1. x componet of the intersection
		double x = obj_ray.origin[0] + t_value * obj_ray.dir[0];
		// 2. y componet of the intersection
		double y = obj_ray.origin[1] + t_value * obj_ray.dir[1];
		// 3. z componet of the intersection
		double z = obj_ray.origin[2] + t_value * obj_ray.dir[2];

		Point3D intersection = modelToWorld * Point3D(x, y, z);
		Vector3D normal(x, y, z);
		normal = transNorm(worldToModel, normal);
		normal.normalize();

		ray.intersection.point = intersection;
		ray.intersection.normal = normal;
		ray.intersection.mat = ray.intersection.mat;
		ray.intersection.t_value = t_value;
		ray.intersection.none = false;
		return true;
	}
}
Ejemplo n.º 20
0
bool UnitFiniteCylinder::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
                                     const Matrix4x4& modelToWorld ) {
    Point3D ray_origin = worldToModel*ray.origin;
    Vector3D ray_dir = worldToModel*ray.dir;
    Vector3D va(0,1,0);//axis for cylinder
    Point3D pa(0,0,0);
    Point3D pb(0, 1, 0);
    bool insideFlag1=false,insideFlag2=false;
   //At^2+B*t+C-1=0
    double vva=ray_dir.dot(va);//the projection
    double A=(ray_dir-vva*va).dot(ray_dir-vva*va);
    double B = 2*(ray_dir-vva*va).dot(((ray_origin-pa)-(ray_origin-pa).dot(va)*va));
    double C=(ray_origin-pa-(ray_origin-pa).dot(va)*va).dot(ray_origin-pa-vva*va)-1;
    double t=0;
    double test = B*B-4*A*C;
    if(test<0||A==0){ return false;//no intersection
    }else if(test==0){
        t=-B/(2*A);
        
    }else{//there are two roots.
        //testing for the infinite cylinder
       
        
        double t1 = (-B+ sqrt(test))/(2*A);
        double t2 = (-B - sqrt(test))/(2*A);
        if(t1>0 && t2<0){
            t = t1;
            insideFlag1=true;
        }else if(t1<0 && t2>0){
            t = t2;
            insideFlag1 = true;
        }else if(t1 > 0 && t2 > 0){
            if(t1 > t2){
                t = t2;
            }else{
                t = t1;
            }
        }else{//cylinder is behind the ray_origin so no intersection
            return false;
        }
        
        //testing for between the two planes.
        
        Point3D inter_pt_tmp = ray_origin+t*ray_dir;
        if(((inter_pt_tmp-pa).dot(va)>0)&&((inter_pt_tmp-pb).dot(va)<0)){//between the two caps
        }else{
            t=std::numeric_limits<double>::max();
        }

        
        //testing for caps
        double t3 = (pa-ray_origin).dot(va)/ray_dir.dot(va);//intersection with the lower cap
        double t4 = (pb-ray_origin).dot(va)/ray_dir.dot(va);//intersection with the upper cap
        double tt=0;
        Point3D po;
        if(t3<0&&t4<0){
            return false;
        }else if(t3>0&&t4<0){
            tt=t3;
            po=pa;
            insideFlag2 = true;
        }else if(t3<0&&t4>0){
            tt=t4;
            po=pb;
            insideFlag2 = true;
        }else{
            if(t4 > t3){
                tt=t3;
                po=pa;
            }else{
                tt=t4;
                po=pb;
            }
        }
        
        Point3D inter_pt_tmp1 = ray_origin+tt*ray_dir;
       if((inter_pt_tmp1-po).length()<1){//in the cylinder

        }else{//must on the cylinders
            tt=std::numeric_limits<double>::max();
        }
        
        if(t<=tt){
        if(t==std::numeric_limits<double>::max()) return false;
        if(ray.intersection.none||t<ray.intersection.t_value){
            inter_pt_tmp = ray_origin+t*ray_dir;
            ray.intersection.point = modelToWorld*inter_pt_tmp;
            
            Vector3D cylinder_norm;
            if(insideFlag1){
                 cylinder_norm =Point3D(0,inter_pt_tmp[1],0)-inter_pt_tmp;
            }else{
                 cylinder_norm =inter_pt_tmp-Point3D(0,inter_pt_tmp[1],0);
            }
            cylinder_norm.normalize();
            ray.intersection.normal = transNorm(modelToWorld,cylinder_norm );
            ray.intersection.normal.normalize();
            ray.intersection.t_value=t;
            ray.intersection.none=false;
            ray.intersection.insideCrash = insideFlag1;
            return true;
        }else{
            return true;
        }
        }else{
            if(ray.intersection.none||tt<ray.intersection.t_value){
                inter_pt_tmp = ray_origin+tt*ray_dir;
                ray.intersection.point = modelToWorld*inter_pt_tmp;
//                if(tt==t3){
//                    ray.intersection.normal = transNorm(modelToWorld, -va);
//                }else{
//                ray.intersection.normal = transNorm(modelToWorld, va);
//                }
                                if((tt==t3&&insideFlag1==false)||(tt==t4&&insideFlag1)){
                                    ray.intersection.normal = transNorm(modelToWorld, -va);
                                }else if((tt==t4&&insideFlag1==false)||(tt==t3&&insideFlag1)){
                                ray.intersection.normal = transNorm(modelToWorld, va);
                                }

                ray.intersection.normal.normalize();
                ray.intersection.t_value=tt;
                ray.intersection.none=false;
                ray.intersection.insideCrash = insideFlag2;
                return true;
            }else{
                return true;
            }
        }
    }
    return false;
    }
Ejemplo n.º 21
0
//----------------------------------------------------------------------------------------------------------------
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel, const Matrix4x4& modelToWorld )
{
	// Implement intersection code for UnitSquare, which is
	// defined on the xy-plane, with vertices (0.5, 0.5, 0), 
	// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
	// (0, 0, 1).
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	// The original point is at 0,0,0 at its own model coordinates 

	// Get ray direction in model coordinates
	Ray3D ObjectRay = Ray3D(worldToModel*ray.origin, worldToModel * ray.dir);
	Point3D origin(0,0,0);
	// always assume unitsquare is on x,y plane 
	Vector3D squareNormal(0,0,1);
	double t_value;
	Point3D intersectionPoint;

	// If the ray is not moving towards the square, it means there is no intersection since
	// the square lies on the x and y axis, ray must move at some value on the z direction 
	if (ObjectRay.dir[2] != 0)
	{
		t_value  = -ObjectRay.origin[2]/ObjectRay.dir[2];
		// Check for no self intersection 
		if ((t_value )< 0.001)
		{
			return false;
		}
	}

	//the ray and the square are on the same plane
	else if (ObjectRay.dir[2] == 0 && ObjectRay.origin[2] == 0)
	{
		double temp1 = (-1.5 - ObjectRay.origin[0])/ObjectRay.dir[0];
		double temp2 = (1.5 - ObjectRay.origin[0])/ObjectRay.dir[0];
		double temp3 = (-1.5 - ObjectRay.origin[1])/ObjectRay.dir[1];
		double temp4 = (1.5 - ObjectRay.origin[1])/ObjectRay.dir[1];
		t_value  = temp1;
		if (temp2 < t_value )
		{
			t_value  = temp2;
		}
		if (temp3 < t_value )
		{
			t_value  =temp3;
		}
		if (temp4< t_value )
		{
			t_value  = temp4;
		}
	}
	else
	{

		return false;
	}
	
	// Compute t_value from z intersection at z = 0
	
	// If the ray already has an intersection at an earlier t_value, return but don't update
	// ray.intersection fields
	if(ray.intersection.none == false) 
	{
		if(t_value > ray.intersection.t_value) 
		{
			return false;
		}
	}

	// Compute coordinates
	Vector3D intersection(ObjectRay.origin[0] + ObjectRay.dir[0] * t_value, ObjectRay.origin[1] + ObjectRay.dir[1] * t_value, 0);
	double x = ObjectRay.origin[0] + ObjectRay.dir[0] * t_value;
	double y = ObjectRay.origin[1] + ObjectRay.dir[1] * t_value;

	// Test x
	if(x >= -0.5 && x <= 0.5) {
		// Text y
		if(y >= -0.5 && y <= 0.5) {
			// We have an intersection
			ray.intersection.t_value = t_value;
			ray.intersection.point = modelToWorld * Point3D(x, y, 0);
			ray.intersection.normal = Vector3D(0, 0, 1);

			// For Image Mapping 			
			ray.intersection.CenterPoint = modelToWorld * Point3D(0,0,0); // every model thinks it is in the center 
			ray.intersection.normal = transNorm(worldToModel, ray.intersection.normal);
			ray.intersection.normal.normalize();
			ray.intersection.none = false; // false means there is an intersection 

			return true;
		}
	}

	return false;
}
Ejemplo n.º 22
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel, const Matrix4x4& modelToWorld )
{
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   

	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	
	Ray3D ObjectRay = Ray3D(worldToModel * ray.origin, worldToModel * ray.dir);
	double a = pow(ObjectRay.dir[0], 2) + pow(ObjectRay.dir[1], 2) + pow(ObjectRay.dir[2], 2);
	double b = 2 * (ObjectRay.origin[0] * ObjectRay.dir[0] +
					ObjectRay.origin[1] * ObjectRay.dir[1] +
					ObjectRay.origin[2] * ObjectRay.dir[2]);

	double c = pow(ObjectRay.origin[0], 2) + 
			   pow(ObjectRay.origin[1], 2) + 
			   pow(ObjectRay.origin[2], 2) -1;

	double discriminant = pow(b, 2) - 4 * a * c;

	// No intersection since no real roots 
	if(discriminant < 0) 
	{ 
		return false;

	} 
	else 
	{
		double t_1 = (-1 * b + sqrt(discriminant)) / (2 * a);
		double t_2 = (-1 * b - sqrt(discriminant)) / (2 * a);
		double t_value = 0;

		if ( t_2 < 0 && t_1 < 0)
			return false;
		else if ( t_1 < 0 )
			t_value = t_2;
		else if ( t_2 < 0 )
			t_value = t_1;

		else
			t_value = fmin(t_1, t_2);

		// If the ray already has an intersection at an earlier t_value, return but don't update
		// ray.intersection fields

		if(ray.intersection.none == false) 
		{
			if(t_value > ray.intersection.t_value) 
			{
				return true;
			}
		}


		double x = ObjectRay.origin[0] + ObjectRay.dir[0]*t_value;
		double y = ObjectRay.origin[1] + ObjectRay.dir[1]*t_value;
		double z = ObjectRay.origin[2] + ObjectRay.dir[2]*t_value;
		
		Vector3D intersection = Vector3D(x, y, z);
		ray.intersection.t_value = t_value;		
		ray.intersection.point = modelToWorld * Point3D(x, y, z);
		ray.intersection.normal = transNorm(worldToModel, intersection);
		ray.intersection.normal.normalize();	
		// FOR TEXTURE MAPPING!
		ray.intersection.CenterPoint = modelToWorld * Point3D(0,0,0); // every model thinks it is in the center 
		ray.intersection.none = false;
		return true;
	}
}
Ejemplo n.º 23
0
bool UnitCylinder::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
        const Matrix4x4& modelToWorld ) {
 
    Ray3D modelRay;
    Point3D intPoint;
    Vector3D surfaceNormal;
    double discriminant;
    double a, b, c;
    double t0, t1, h, r, p_x, p_z, d_x, d_z;
    double t;
    bool isParallel = false;
   
    // 0 - cylinder_t0, 1 - cylinder_t1, 2 - top, 3 - bot
    double intersection_ts[4];
    double inf = std::numeric_limits<double>::infinity();
    
    // initialize intersection_ts to infinities
    for (int i=0; i < 4; i++) {
	    intersection_ts[i] = inf;
    }
    
    h = 1.0;
    r = 0.5;
   
    // Transform ray to model space.
    modelRay.origin = worldToModel * ray.origin;
    modelRay.dir = worldToModel * ray.dir;
    //modelRay.dir.normalize();

    // Compute coefficients of quadractic formula.
    p_x = modelRay.origin[0];
    p_z = modelRay.origin[2];
   
    d_x = modelRay.dir[0];
    d_z = modelRay.dir[2];
   
    a = pow(d_x, 2) + pow(d_z, 2);
    b = (2 * p_x * d_x) + (2 * p_z * d_z);
    c = pow(p_x, 2) + pow(p_z, 2) - pow(r, 2);
   
    // Compute discriminant of quadractic formula.
    discriminant = (b * b) - (4 * a * c);

    if (discriminant >= 0) {

	    t0 = (-b - sqrt(discriminant)) / (2 * a);
	    t1 = (-b + sqrt(discriminant)) / (2 * a);
	    Point3D intPoint_0 = modelRay.origin + (t0 * modelRay.dir);
	    Point3D intPoint_1 = modelRay.origin + (t1 * modelRay.dir);

        if (t0 >= ray.intersection.t_min && t0 <= ray.intersection.t_max) {
            if ((intPoint_0[1] >= 0 && intPoint_0[1] <= h)) {
 
                intersection_ts[0] = t0;
            }
        }   

        if (t1 >= ray.intersection.t_min && t1 <= ray.intersection.t_max) {
            if ((intPoint_1[1] >= 0 && intPoint_1[1] <= h)) {
   
            intersection_ts[1] = t1;
            }
        }

        ray.intersection.inside = true;
    }

    // Check if it intersected the top or bottom cap
    Vector3D surfaceNormalTopCirc(0, 1, 0);    // Constant surface normal.
    Vector3D surfaceNormalBotCirc(0, -1, 0);   // Constant surface normal.
    double t_top, t_bot;                       // Intersection parameter.
   
    // Compute intersection between ray and ZX-plane.
    double d_dot_n_top = modelRay.dir.dot(surfaceNormalTopCirc);
    double d_dot_n_bot = modelRay.dir.dot(surfaceNormalBotCirc);

    if (d_dot_n_top == 0.0) {
  
        // Ray is parallel to planes
        isParallel = true;
    } 

    if (!isParallel) {
      
        Vector3D vOrigin(modelRay.origin[0], modelRay.origin[1], modelRay.origin[2]);
      
        t_top = -(vOrigin.dot(surfaceNormalTopCirc) - h) / d_dot_n_top;
        t_bot = -(vOrigin.dot(surfaceNormalBotCirc)) / d_dot_n_bot;
      
        Point3D intPoint_top = modelRay.origin + (t_top * modelRay.dir);
        Point3D intPoint_bot = modelRay.origin + (t_bot * modelRay.dir);
      
        if ((t_top >= ray.intersection.t_min && t_top <= ray.intersection.t_max) &&
            ((pow(intPoint_top[0], 2) + pow(intPoint_top[2], 2) - pow(r, 2)) <= 0)) {
   
            intersection_ts[2] = t_top;
        }
      
        if ((t_bot >= ray.intersection.t_min && t_bot <= ray.intersection.t_max) &&
            ((pow(intPoint_bot[0], 2) + pow(intPoint_bot[2], 2) - pow(r, 2)) <= 0)) {
 
            intersection_ts[3] = t_bot;
        }
    }

    // Get the smallest t value index
    int indexOfSmallest = 0;
    double smallest_t = intersection_ts[0];

    for (int i=0; i < 4; i++) {
        if (intersection_ts[i] < smallest_t) {
            smallest_t = intersection_ts[i];
            indexOfSmallest = i;
        }
    }
    
    if (smallest_t == inf) {
        return false;
    } else {
        t = smallest_t;

        if (!ray.intersection.none && t > ray.intersection.t_hit) {
            return false;
        }

        intPoint = modelRay.origin + (t * modelRay.dir);

        if (indexOfSmallest == 0 || indexOfSmallest == 1) {
            surfaceNormal = intPoint - Point3D(0, intPoint[1], 0);
        } else if (indexOfSmallest == 2) {
            surfaceNormal = surfaceNormalTopCirc;
        } else {
            surfaceNormal = surfaceNormalBotCirc;
        }
        ray.intersection.point = modelToWorld * intPoint;
        ray.intersection.normal = transNorm(worldToModel, surfaceNormal);
        ray.intersection.normal.normalize();
        ray.intersection.t_hit = t;
        ray.intersection.none = false;
        return true;
    }
 
}
Ejemplo n.º 24
0
bool UnitSquare::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSquare, which is
	// defined on the xy-plane, with vertices (0.5, 0.5, 0), 
	// (-0.5, 0.5, 0), (-0.5, -0.5, 0), (0.5, -0.5, 0), and normal
	// (0, 0, 1).
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.

    Vector3D v_d = worldToModel*ray.dir;
    Point3D p_e = worldToModel*ray.origin;
    Point3D p_a = Point3D(-0.5, -0.5, 0.0);
    Point3D p_b = Point3D(0.5, -0.5, 0.0);
    Point3D p_c = Point3D(-0.5, 0.5, 0.0);
    Vector3D ab = p_a - p_b;
    Vector3D ac = p_a - p_c;
    Vector3D ae = p_a - p_e;
    float a = ab[0];
    float b = ab[1];
    float c = ab[2];
    float d = ac[0];
    float e = ac[1];
    float f = ac[2];
    float g = v_d[0];
    float h = v_d[1];
    float i = v_d[2];
    float j = ae[0];
    float k = ae[1];
    float l = ae[2];
    float M = a*(e*i-h*f)+b*(g*f-d*i)+c*(d*h-e*g);
    float t = -(f*(a*k-j*b)+e*(j*c-a*l)+d*(b*l-k*c))/M;
    if (!ray.intersection.none && ray.intersection.t_value < t)
    {
        return false;
    }
    if (t < 0)
    {
        return false;
    }
    float gamma = (i*(a*k-j*b)+h*(j*c-a*l)+g*(b*l-k*c))/M;
    if ((gamma < 0)||(gamma>1))
    {
        return false;
    }
    float beta = (j*(e*i-h*f)+k*(g*f-d*i)+l*(d*h-e*g))/M;
    if ((beta < 0)||(beta>1))
    {
        return false;
    }
    
    ray.intersection.point = modelToWorld * (p_e + t*v_d);
    ray.intersection.normal = transNorm(modelToWorld, Vector3D(0.0, 0.0, 1.0));  
    ray.intersection.none = false;
    ray.intersection.t_value = t;
	return true;
}
Ejemplo n.º 25
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
                           const Matrix4x4& modelToWorld ) {
    Vector3D obj_dir = worldToModel * ray.dir;
    Point3D obj_ori = worldToModel * ray.origin;
    //ray =obj_ori + t * obj_dir
    //t^2 * (obj_dir·obj_dir)+ t * (2obj_ori·obj_dir) + obj_ori·obj_ori-1
    double a = obj_dir.dot(obj_dir);
    Vector3D trans = obj_ori - Point3D(); //cast Point3D to Vector3D to use dot
    double b = 2 * trans.dot(obj_dir);
    double c = trans.dot(trans) - 1;
    double test = b*b - 4 * a * c;
    double t = 0;
    bool insideCrash=false;
    // std::cout << test <<std::endl;
    if(test < 0 || a == 0){
        return false;
    }else if(test == 0){
        t = -b/(2*a);
    }else{
        double t1 = (-b + sqrt(test))/(2*a);
        double t2 = (-b - sqrt(test))/(2*a);
        if(t1>0 && t2<0){
            insideCrash=true;
            t = t1;
        }else if(t1<=0 && t2>=0){
            insideCrash=true;
            t = t2;
        }else if(t1 > 0 && t2 > 0){
            if(t1 > t2){
                t = t2;
            }else{
                t = t1;
            }
        }else{
            return false;
        }
    }
    double inter_x = obj_ori[0] + t * obj_dir[0];
    double inter_y = obj_ori[1] + t * obj_dir[1];
    double inter_z = obj_ori[2] + t * obj_dir[2];
    
    if(t > 0 && (t < ray.intersection.t_value || ray.intersection.none)){
        ray.intersection.point = modelToWorld * Point3D(inter_x, inter_y, inter_z);
        ray.intersection.t_value = t;
        ray.intersection.none = false;
        ray.intersection.insideCrash = insideCrash;
        Point3D p_n = Point3D(inter_x, inter_y, inter_z);
        //Vector3D n = Point3D() - p_n ;
        Vector3D n = p_n - Point3D();
        n.normalize();
        Vector3D inter_norm = transNorm(worldToModel, n);
        ray.intersection.normal = inter_norm;
       
        Point3D point = worldToModel * ray.intersection.point;
        double s = acos(point[2]/1.0)/M_PI;
        double t = acos(point[0]/(1.0*sin(M_PI * s)))/(2.0*M_PI);
        ray.intersection.textcoor = Point3D(s, t, 0);
        
        return true;
    }else{
        return false;
    }
    
}