示例#1
0
// Sphere Plane Collision - returns true if collsion exists - takes Point3d params
bool Collision::SpherePlane(Vector3d& centerSphere, float radiusSphere,
                            Vector3d planeNormal, Point3d p1, Point3d p2, Point3d p3, Point3d p4){
    float dist1 = 0.0;
    float dist2 = 0.0;
    // this checks for the collsion on both sides of the plane
    if(RayPlane(planeNormal.getX(), planeNormal.getY(), planeNormal.getZ(), p1.getX(), p1.getY(), p1.getZ(),
                centerSphere.getX(), centerSphere.getY(), centerSphere.getZ(), -planeNormal.getX(), -planeNormal.getY(), -planeNormal.getZ(),
                p1, p2, p3, p4, &dist1) || RayPlane(-planeNormal.getX(), -planeNormal.getY(), -planeNormal.getZ(), p1.getX(), p1.getY(), p1.getZ(),
                centerSphere.getX(), centerSphere.getY(), centerSphere.getZ(), planeNormal.getX(), planeNormal.getY(), planeNormal.getZ(),
                p1, p2, p3, p4, &dist2)){
        if(dist1 > radiusSphere || dist2 > radiusSphere){ // if either distance is > the radiusSphere....no collision
            return false;
        }
        // indicates that we are on the side where dist1 has been determined to be > 0
        // the else is the other side of the plane. This calculates the point as well
        // as the new location of the sphere
        if(dist1 > 0 ){
            centerSphere.setX(centerSphere.getX() + planeNormal.getX() * (radiusSphere - dist1));
            centerSphere.setY(centerSphere.getY() + planeNormal.getY() * (radiusSphere - dist1));
            centerSphere.setZ(centerSphere.getZ() + planeNormal.getZ() * (radiusSphere - dist1));
        }else{
            centerSphere.setX(centerSphere.getX() + planeNormal.getX() * (radiusSphere - dist2));
            centerSphere.setY(centerSphere.getY() + planeNormal.getY() * (radiusSphere - dist2));
            centerSphere.setZ(centerSphere.getZ() + planeNormal.getZ() * (radiusSphere - dist2));
        }
        return true;
    }
    return false;
}
示例#2
0
bool RayTriangle(const Vector3& rayStart, const Vector3& rayDir,
                 const Vector3& triP0, const Vector3& triP1, const Vector3& triP2,
                 float& t, float triExpansionEpsilon)
{
  ++Application::mStatistics.mRayTriangleTests;
  Math::Vector3 normal = (triP1 - triP0).Cross(triP2 - triP0).Normalized();
  if(RayPlane(rayStart, rayDir, Math::Vector4(normal.x, normal.y, normal.z, normal.Dot(triP0)), t))
  {
    Math::Vector3 pointOnPlane = (rayDir * t) + rayStart;
    Math::Vector3 barycentric;
    return BarycentricCoordinates(pointOnPlane, triP0, triP1, triP2, barycentric.x, barycentric.y, barycentric.z, triExpansionEpsilon);
  }
  return false;
}
示例#3
0
bool RayAabb(const Vector3& rayStart, const Vector3& rayDir,
             const Vector3& aabbMin, const Vector3& aabbMax, float& t)
{
  ++Application::mStatistics.mRayAabbTests;
  
  if(PointAabb(rayStart, aabbMin, aabbMax))
  {
    t = 0.0f;
    return true;
  }

  std::vector<float> tVals;
  std::vector<Plane> planes;
  if(rayDir.x)
  {
    planes.emplace_back(Plane(Math::Vector3(aabbMin.x / Math::Abs(aabbMin.x), 0.0f, 0.0f), aabbMin));
    planes.emplace_back(Plane(Math::Vector3(aabbMax.x / Math::Abs(aabbMax.x), 0.0f, 0.0f), aabbMax));
    tVals.emplace_back(FLT_MAX);
    tVals.emplace_back(FLT_MAX);
  }
  else
  {
    if(Math::Clamp(rayStart.x, aabbMin.x, aabbMax.x) != rayStart.x)
    {
      return false;
    }
  }
  if(rayDir.y)
  {
    planes.emplace_back(Plane(Math::Vector3(0.0f, aabbMin.y / Math::Abs(aabbMin.y), 0.0f), aabbMin));
    planes.emplace_back(Plane(Math::Vector3(0.0f, aabbMax.y / Math::Abs(aabbMax.y), 0.0f), aabbMax));
    tVals.emplace_back(FLT_MAX);
    tVals.emplace_back(FLT_MAX);
  }
  else
  {
    if(Math::Clamp(rayStart.y, aabbMin.y, aabbMax.y) != rayStart.y)
    {
      return false;
    }
  }
  if(rayDir.z)
  {
    planes.emplace_back(Plane(Math::Vector3(0.0f, 0.0f, aabbMin.z / Math::Abs(aabbMin.z)), aabbMin));
    planes.emplace_back(Plane(Math::Vector3(0.0f, 0.0f, aabbMax.z / Math::Abs(aabbMax.z)), aabbMax));
    tVals.emplace_back(FLT_MAX);
    tVals.emplace_back(FLT_MAX);
  }
  else
  {
    if(Math::Clamp(rayStart.z, aabbMin.z, aabbMax.z) != rayStart.z)
    {
      return false;
    }
  }

  for(int i = 0; i < planes.size(); i += 2)
  {
    RayPlane(rayStart, rayDir, planes[i].mData, tVals[i]);
    RayPlane(rayStart, rayDir, planes[i + 1].mData, tVals[i + 1]);

    //we dot with positive plane axis to get the desired component
    if(rayDir.Dot(Math::Vector3(planes[i + 1].mData.x, planes[i + 1].mData.y, planes[i + 1].mData.z)) < 0.0f)
    {
      std::swap(tVals[i], tVals[i + 1]);
    }
  }

  float tmin = -FLT_MAX;
  float tmax = FLT_MAX;


  for(int i = 0; i < tVals.size(); i += 2)
  {
    tmin = Math::Max(tmin, tVals[i]);
    tmax = Math::Min(tmax, tVals[i + 1]);
  }
  


  //tmin should be start of our collision
  if(tmin < tmax)
  {
    if(tmin > 0.0f)
    {
      t = tmin;
      return true;
    }
  }
  
  return false;
}