Пример #1
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();
}
Пример #2
0
Color PointLight::calculateColor(const Scene &scene, const Ray &ray, float distance, const Vector &normal, MaterialPointer material) const {
  Vector point = ray.getPointAt(distance);

  Color ambientComponent;
  Color diffuseComponent;
  Color specularComponent;

  ambientComponent = componentwiseProduct(material->ambientColor, mAmbientIntensity);
  Color result = ambientComponent;

  Vector shadowRayDirection = mPosition - point;
  float	distanceToLight	= shadowRayDirection.length();
  float	attenuation	= 1 / (mConstantAttenutaionCoefficient + mLinearAttenutaionCoefficient * distanceToLight + mQuadraticAttenutaionCoefficient * distanceToLight * distanceToLight);
  result *= attenuation;

  shadowRayDirection.normalize(); 
  float	shadowRayDotNormal = shadowRayDirection.dotProduct(normal);

  // If the point is not illuminated
  if (shadowRayDotNormal <= 0.0) {
    return result;
  }

  Ray shadowRay(point + shadowRayDirection * EPS_FOR_SHADOW_RAYS, shadowRayDirection);	
  RayIntersection shadowRayIntersection = scene.calculateNearestIntersection(shadowRay);
  
  // If object is not in shadow
  if (!shadowRayIntersection.rayIntersectsWithShape || shadowRayIntersection.distanceFromRayOrigin > distanceToLight) {
    Color diffuseColor = material->diffuseColor;
    diffuseComponent  = componentwiseProduct(diffuseColor, mDiffuseIntensity * attenuation * shadowRayDotNormal);

    Vector lightReflect = shadowRayDirection - normal * 2 * shadowRayDirection.dotProduct(normal);
    lightReflect.normalize();

    Vector cameraDirection = ray.getOriginPosition() - point;
    cameraDirection.normalize();

    float	cosLightReflect = cameraDirection.dotProduct(lightReflect);
    if (cosLightReflect > 0.0) {
      Color specularColor = material->specularColor; 
      specularComponent	= componentwiseProduct(specularColor, mSpecularIntensity * powf(cosLightReflect, material->specularPower) * attenuation);
    }				
  }

  result += (diffuseComponent + specularComponent);
  return result;
}
Пример #3
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);
}
Пример #5
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();  
}