示例#1
0
RayIntersection SpatialList::rayIntersection(Ray ray) const {
	if (objectsVector.empty() || (boundingBox && !boundingBox->rayIntersection(ray).intersects))
		return RayIntersection();

	RayIntersection first_intersection = RayIntersection();

	for (unsigned int i = 0; i < objectsVector.size(); i++) {
		RayIntersection intersection = objectsVector[i]->rayIntersection(ray);
		if (intersection.intersects && (!first_intersection.intersects || intersection < first_intersection)) {
			first_intersection = intersection;
		}
	}

	return first_intersection;
}
示例#2
0
RayIntersection Sphere::intersectWithRay(const Ray &ray) const {
  // Solve square equation x^2 + b * x + c = 0
  Vector cameraToRayOrigin = ray.getOriginPosition() - mCenter;
  float b = ray.getDirection().dotProduct(cameraToRayOrigin);
  float c = cameraToRayOrigin.dotProduct(cameraToRayOrigin) - mRadius * mRadius;
  float descriminant = b * b - c;

  if (descriminant < 0) {
    return RayIntersection();
  }

  descriminant = sqrt(descriminant);

  std::vector<float> intersectionDistances;
  float	closestRoot = -1.f;

  // Get closest root
  float root = -b - descriminant;
  float rayExit = -1.f;
  if (root >= 0.f) {
    closestRoot = root;
    intersectionDistances.push_back(root);
  }

  root = -b + descriminant;
  if (root >= 0.f) {
    intersectionDistances.push_back(root);
    if (closestRoot < 0.f) {
      closestRoot = root;
    } else if (root < closestRoot) {
      rayExit = closestRoot;
      closestRoot = root;
    } else {
      rayExit = root;
    }
  }

  if (closestRoot > 0.f) {
    if (rayExit < 0.f) {
      intersectionDistances.insert(intersectionDistances.begin(), 0.f);
    }
    SpherePointer pointer = SpherePointer(new Sphere(*this));
    return RayIntersection(true, pointer, closestRoot, getNormal(ray, closestRoot), intersectionDistances);
  }

  return RayIntersection();
}
示例#3
0
std::vector<RayIntersection> FastArc::RayIntersects(gp_Pnt p)
{
	std::vector<RayIntersection> ret;

	double y = p.Y() - C.Y();
	if(fabs(y) > rad)
		return ret;

	double x1 = sqrt(rad*rad - y*y);
	double x2 = x1+C.X();
	x1 = C.X()-x1;

	if(x1 < p.X())
		ret.push_back(RayIntersection(GetU(x1,p.Y()),gp_Pnt(x1,p.Y(),0),false,false));
	if(x2 < p.X())
		ret.push_back(RayIntersection(GetU(x2,p.Y()),gp_Pnt(x2,p.Y(),0),false,false));
	return ret;
}
示例#4
0
RayIntersection Plane::intersectWithRay(const Ray &ray) const {
  float cosineRayNormal = mNormal.dotProduct(ray.getDirection());
  if (fabs(cosineRayNormal) < FLOAT_ZERO) 
  {
    return RayIntersection();
  }
  
  float distance = -(ray.getOriginPosition().dotProduct(mNormal) + mDistance) / cosineRayNormal;
  if (distance > 0.0)
  {    
    PlanePointer pointer = PlanePointer(new Plane(*this));
    std::vector<float> intersectionDistances;
    intersectionDistances.push_back(distance);
    return RayIntersection(true, pointer, distance, getNormal(ray, distance), intersectionDistances);
  }

  return RayIntersection();
}
RayIntersection TrianglePatch::intersectWithRay(const Ray &ray) const {
  Vector rayOrigin	= ray.getOriginPosition();
  Vector rayDirection = ray.getDirection();

  Vector e1 = mVertex1->getCoordinates() - mVertex0->getCoordinates();
  Vector e2 = mVertex2->getCoordinates() - mVertex0->getCoordinates();

  Vector pvector = rayDirection.crossProduct(e2);
  float	determinant = e1.dotProduct(pvector);

  if (fabs(determinant) < FLOAT_ZERO) {
    return RayIntersection();
  }

  const float invertedDeterminant = 1.0f / determinant;

  Vector tvec	= rayOrigin - mVertex0->getCoordinates();
  float	lambda = tvec.dotProduct(pvector);

  lambda *= invertedDeterminant;

  if (lambda < 0.0f || lambda > 1.0f) {
    return RayIntersection();
  }

  Vector qvec = tvec.crossProduct(e1);
  float	mue	= rayDirection.dotProduct(qvec);

  mue *= invertedDeterminant;

  if (mue < 0.0f || mue + lambda > 1.0f) {
    return RayIntersection();
  }

  float f = e2.dotProduct(qvec);

  f = f * invertedDeterminant - FLOAT_ZERO;
  if (f < FLOAT_ZERO) {
    return RayIntersection();
  }
  
  TrianglePatchPointer pointer = TrianglePatchPointer(new TrianglePatch(*this));
  return RayIntersection(true, pointer, f, lambda, mue);
}
示例#6
0
文件: Sphere.cpp 项目: enra64/CG
bool
Sphere::closestIntersectionModel(const Ray &ray, double maxLambda, RayIntersection& intersection) const
{
  // Implicit sphere: (x-c)^2-r^2 = 0
  // r = 1, c=0
  // x^2 = 1
  // Ray: x = o+t*d
  
  // Solve: 0=(o+t*d)^2 -1
  // 0 = t^2*(d*d) + t*(2*o*d) + (o*o-1)

  // Then, these are the 2 possible solutions
  // t0 = 0.5*(-b-sqrt(b*b - 4*a))

  // simplify
  // t01 = -o.d +- sqrt( (o.d)^2 - o.o + 1)

  const Vec3d &d = ray.direction();
  const Vec3d &o = ray.origin();

  double b = dot(o,d);
  double c = o.lengthSquared() - 1;

  double ds = b*b - c;

  //discriminant is negative, no intersection
  if(ds < 0)
    return false;

  double dssqr = sqrt(ds);

  double t0 = -b-dssqr;
  double t1 = -b+dssqr;

  double lambda = t0;

  //ray starts inside sphere, discard first hit
  if(t0 < 0)
    lambda = t1;

  if(lambda < 0 || lambda > maxLambda)
    return false;

  // Compute intersection point
  const Vec3d p = ray.pointOnRay(lambda);

  // Compute parameterization of intersection point
  const double theta = std::atan2(p[1], p[0]);
  const double phi   = std::acos (p[2]);
  const Vec3d uvw(theta,phi,double(0));

  intersection = RayIntersection(ray,shared_from_this(),lambda,ray.pointOnRay(lambda),uvw);
  return true;
}
示例#7
0
bool IndexedTriangleMesh::closestIntersectionModel(const Ray &ray, double maxLambda, RayIntersection& intersection) const
{

  double closestLambda = maxLambda;
  Vec3d closestbary;
  int  closestTri = -1;

  Vec3d bary;
  double lambda;

  // Loop over all stored triangles to find a possible intersection between ray 
  // and any triangle
  for (size_t i=0;i<mIndices.size();i+=3)
  {
    const int i0 = mIndices[i+0];
    const int i1 = mIndices[i+1];
    const int i2 = mIndices[i+2];
    if (Intersection::lineTriangle(ray,mVertexPosition[i0],mVertexPosition[i1],mVertexPosition[i2],bary,lambda) &&
      lambda > 0 && lambda < closestLambda)
    {
      closestLambda = lambda;
      closestbary = bary;
      closestTri = (int)i;
    }
  }

  // If an intersection occurred, compute the normal and the uv coordinates based
  // on the barycentric coordinates of the hit point
  if (closestTri >= 0)
  {
    const int i0 = mIndices[closestTri+0];
    const int i1 = mIndices[closestTri+1];
    const int i2 = mIndices[closestTri+2];

    Vec3d n;
    if(mVertexNormal.empty())
      n = cross(mVertexPosition[i1]-mVertexPosition[i0],mVertexPosition[i2]-mVertexPosition[i0]).normalize();
    else
      n = (mVertexNormal[i0]*closestbary[0]+
           mVertexNormal[i1]*closestbary[1]+
           mVertexNormal[i2]*closestbary[2]).normalize();

    Vec3d uvw(0,0,0);
    if(!mVertexTextureCoordinate.empty())
      uvw = (mVertexTextureCoordinate[i0]*closestbary[0]+
             mVertexTextureCoordinate[i1]*closestbary[1]+
             mVertexTextureCoordinate[i2]*closestbary[2]);
    intersection=RayIntersection(ray,shared_from_this(),closestLambda,n,uvw);
    return true;
  }

  return false;
}
bool
  CollisionGeometry::closestIntersectionModel(const Ray &ray, float maxLambda, RayIntersection& intersection) const
{
  const BVTree &collisionTree = mInstance ? mInstance->mCollisionTree : mCollisionTree;
  const std::vector<Vec3f> &collisionPositions = mInstance ? mInstance->mCollisionPositions : mCollisionPositions;
  const std::vector<Vec3f> &collisionNormals = mInstance ? mInstance->mCollisionNormals : mCollisionNormals;
  const std::vector<Vec3i> &collisionIndices = mInstance ? mInstance->mCollisionIndices : mCollisionIndices;
  const std::vector<int> &intersectionCandidates = collisionTree.intersectBoundingBoxes(ray,maxLambda);

  float closestLambda = maxLambda;
  Vec3f closestbary;
  int  closestTri = -1;

  Vec3f bary;
  float lambda;

  for(size_t i=0;i<intersectionCandidates.size();++i)
  {
    const int triangleIndex = intersectionCandidates[i];
    const int idx0 = collisionIndices[triangleIndex][0];
    const int idx1 = collisionIndices[triangleIndex][1];
    const int idx2 = collisionIndices[triangleIndex][2];

    const Vec3f &p0 = collisionPositions[idx0];
    const Vec3f &p1 = collisionPositions[idx1];
    const Vec3f &p2 = collisionPositions[idx2];

    if (Intersection::lineTriangle(ray,p0,p1,p2,bary,lambda) &&
      lambda > 0 && lambda < closestLambda)
    {
      closestLambda = lambda;
      closestbary = bary;
      closestTri = triangleIndex;
    }
  }

  if (closestTri >= 0)
  {
    const int i0 = collisionIndices[closestTri][0];
    const int i1 = collisionIndices[closestTri][1];
    const int i2 = collisionIndices[closestTri][2];

    Vec3f n = collisionNormals[i0]*closestbary[0]+
              collisionNormals[i1]*closestbary[1]+
              collisionNormals[i2]*closestbary[2];

    intersection = RayIntersection(ray,closestLambda,n);
    return true;
  }
  return false;
}
示例#9
0
bool
Sphere::closestIntersectionModel(const Ray &ray, double maxLambda, RayIntersection& intersection) const
{
  /*
    A ray and a sphere intersect if and only if
      (o + lambda * d - c)^2 = r^2

    where
      o is the origin of the ray
      d is the direction vector of the ray
      c is the center of the sphere
      r is the radius of the sphere

    Since o and d are known, c = O and r = 1, we have
    a quadratic equation in lambda. We solve it using calcRoots()
    which is a slightly modified version of the classical
    quadratic formula (as described in [1]).

    [1] http://wiki.delphigl.com/index.php/Tutorial_Raytracing_-_Grundlagen_I#Quadratische_Gleichungen
  */

  // a, b and c are the constants in
  // a * lambda^2 + b * lambda + c = 0.
  double a = dot(ray.direction(), ray.direction());
  double b = 2 * dot(ray.direction(), ray.origin());
  double c = dot(ray.origin(), ray.origin()) - 1;

  // t1 and t2 are the solutions of our quadratic equation.
  // W.l.o.g. t1 <= t2 (calcRoots takes care of that)
  // calcRoots return the number of roots it found (zero, one or two).
  double t1, t2;
  int roots = calcRoots(a, b, c, t1, t2);

  bool doIntersect = false;
  if (roots > 0) {
    // There is a solution, we just need the (smallest) positve one.
    double lambda = t1 >= 0 ? t1 : t2;
    if (lambda >= 0.0 && lambda < maxLambda) {
      doIntersect = true;
      intersection = RayIntersection(ray, shared_from_this(), lambda, ray.pointOnRay(lambda), Vec3d(0,0,0));
    }
  }

  return doIntersect;
}
示例#10
0
文件: Triangle.cpp 项目: enra64/CG
bool
Triangle::closestIntersectionModel(const Ray &ray, double maxLambda, RayIntersection& intersection) const
{
  Vec3d bary;
  double lambda;

  if(!Intersection::lineTriangle(ray,mVertices[0],mVertices[1],mVertices[2],bary,lambda))
    return false;

  // Intersection is inside triangle if 0<=u,v,w<=1
  if(lambda<0 || lambda>maxLambda)
    return false;

  const Vec3d normal = cross(mVertices[1]-mVertices[0],mVertices[2]-mVertices[0]).normalize();
  const Vec3d uvw = mUVW[0]*bary[0]+mUVW[1]*bary[1]+mUVW[2]*bary[2];

  intersection = RayIntersection(ray,shared_from_this(),lambda,normal,uvw);
  return true;                      
}
示例#11
0
std::vector<RayIntersection> FastLine::RayIntersects(gp_Pnt pnt)
{
	std::vector<RayIntersection> ret;
	//If this line is significantly horizontal, there is nothing good
	//we can do here
	if(B.Y() < A.Y() + TOLERANCE/4 && B.Y() > A.Y() - TOLERANCE/4)
		return ret;

	if((pnt.Y() < B.Y() + TOLERANCE && pnt.Y() > A.Y() - TOLERANCE)||
		(pnt.Y() > B.Y() - TOLERANCE && pnt.Y() < A.Y() + TOLERANCE))
	{
		if(fabs(A.Y() - B.Y()) < TOLERANCE)
			return ret;
		double u = (pnt.Y() - A.Y())/(B.Y()-A.Y());
		double x = GetXatU(u);
		if(x < pnt.X())
			ret.push_back(RayIntersection(u,gp_Pnt(x,pnt.Y(),0),false,false));
	}
	return ret;
}
示例#12
0
    bool
    Plane::closestIntersectionModel(const Ray &ray, double maxLambda, RayIntersection &intersection) const {
        // Solve linear equation for lambda
        // see also http://en.wikipedia.org/wiki/Line-plane_intersection
        double a = dot((-ray.origin()), (mNormal));
        double d = dot(ray.direction(), (mNormal));

        // No intersection if ray is (almost) parallel to plane
        if (fabs(d) < Math::safetyEps())
            return false;

        double lambda = a / d;

        // Only intersections in [0,1] range are valid.
        if (lambda < 0.0 || lambda > maxLambda)
            return false;

        const Vec3d p = ray.pointOnRay(lambda);
        const Vec3d uvw(dot(p, mTangent), dot(p, mBitangent), double(0));

        intersection = RayIntersection(ray, shared_from_this(), lambda, mNormal, uvw);
        return true;
    }
示例#13
0
RayIntersection Cone::intersectWithRay(const Ray &ray) const {
  Vector coneAxis	= (mBottomCenter - mTop);
  coneAxis.normalize();

  Vector rayOriginPosition = ray.getOriginPosition();
  Vector rayDirection = ray.getDirection();

  Vector bottomCenterToRayOrigin = rayOriginPosition - mTop;

  float rayDirectionDotAxis = rayDirection.dotProduct(coneAxis);
  float bottomCenterToRayOriginDotAxis = bottomCenterToRayOrigin.dotProduct(coneAxis);
  float radiansPerHeight = mRadius / (mBottomCenter - mTop).length();

  Vector u = rayDirection + coneAxis * (-rayDirectionDotAxis);
  Vector v = bottomCenterToRayOrigin + coneAxis * (-bottomCenterToRayOriginDotAxis);
  float  w = bottomCenterToRayOriginDotAxis * radiansPerHeight;

  float	radiansPerDirection = rayDirectionDotAxis * radiansPerHeight;


  // Solve square equation a * x^2 + b * x + c = 0
  float a = u.dotProduct(u) - radiansPerDirection * radiansPerDirection;
  float closestRoot = -1.f;
  float rayExit = -1.f;
  float root		= 0.f;
  std::vector<float> intersectionDistances;
  
  if (fabs(a) > FLOAT_ZERO) {
    float b = 2 * (u.dotProduct(v) - w * radiansPerDirection);
    float c = v.dotProduct(v) - w * w;
    float discriminant = b * b - 4 * a * c;

    if (discriminant < 0.0) {
      return RayIntersection();
    }

    discriminant = sqrtf(discriminant);
    float denominator = 1.0 / (2.0 * a);

    root = (-b - discriminant) * denominator;
    if (root > 0.0) {
      Vector point = ray.getPointAt(root);
      Vector bottomCenterToPoint = point - mTop;
      Vector topToPoint = point - mBottomCenter;
      if (coneAxis.dotProduct(bottomCenterToPoint) > 0.0 && (-coneAxis).dotProduct(topToPoint) > 0.0) {
        intersectionDistances.push_back(root);
        closestRoot = root;
      }
    }
    
    root = (-b + discriminant) * denominator;
    if (root > 0.0) {
      Vector point = ray.getPointAt(root);
      Vector bottomCenterToPoint = point - mTop;
      Vector topToPoint = point - mBottomCenter;
      if (coneAxis.dotProduct(bottomCenterToPoint) > 0.0 && (-coneAxis).dotProduct(topToPoint) > 0.0) {
        intersectionDistances.push_back(root);
        if (closestRoot < 0.0) {
          closestRoot = root;
        } else if (root < closestRoot) {
          rayExit = closestRoot;
          closestRoot = root;
        } else {
          rayExit = root;
        }
      }
    }
  }

  // Intersection with bottom
  if (fabs(rayDirectionDotAxis) < FLOAT_ZERO) {
    if (closestRoot > 0.0) {
      if (rayExit < 0.f) {
        intersectionDistances.insert(intersectionDistances.begin(), 0.f);
      }
      ConePointer pointer = ConePointer(new Cone(*this));
      return RayIntersection(true, pointer, closestRoot, getNormal(ray, closestRoot), intersectionDistances);
    }

    return RayIntersection();
  }

  // Intersection with top and bottom points
  root = (-coneAxis).dotProduct(rayOriginPosition - mBottomCenter) / rayDirectionDotAxis;
  if (root > 0.0)
  {
    Vector topToPoint = ray.getPointAt(root) - mBottomCenter;
    if (topToPoint.dotProduct(topToPoint) < mRadius * mRadius)
    {
      intersectionDistances.push_back(root);
      if (closestRoot < 0.0) {
        closestRoot = root;
        rayExit = root;
      } else if (root < closestRoot) {
        rayExit = closestRoot;
        closestRoot = root;
      } else {
        rayExit = root;
      }
    }
  }

  if (closestRoot > 0.0) {
    if (rayExit < 0.0) {
      intersectionDistances.insert(intersectionDistances.begin(), 0.f);
    }
    ConePointer pointer = ConePointer(new Cone(*this));
    return RayIntersection(true, pointer, closestRoot, getNormal(ray, closestRoot), intersectionDistances);
  }

  return RayIntersection();  
}