accelerated-raytracer/src/Sphere.cpp

49 lines
1.8 KiB
C++

#include "Sphere.h"
namespace raytry {
Sphere::Sphere(QVector3D position, float radius) : position{position}, radius{radius}, mat{RenderObject::material()} {}
Sphere::Sphere(QVector3D position, float radius, RenderMaterial material) : position{position}, radius{radius}, mat{material} {}
Sphere::Sphere() : position(), radius{1.0f}, mat{RenderObject::material()} {}
float inline squared(const float& a) {
return a * a;
}
std::optional<float> Sphere::intersects(const Ray &ray) const {
float b = 2 * ((ray.originVec.x() - position.x()) * ray.directionVec.x() +
(ray.originVec.y() - position.y()) * ray.directionVec.y() +
(ray.originVec.z() - position.z()) * ray.directionVec.z());
float c = (squared(ray.originVec.x() - position.x()) +
squared(ray.originVec.y() - position.y()) +
squared(ray.originVec.z() - position.z()) -
squared(radius));
float b2m4c = (b * b) - 4 * c;
if (b2m4c < RenderObject::nearCrop) {
return std::nullopt;
}
float t0 = (-b - std::sqrt(b2m4c)) / 2;
float t1 = (-b + std::sqrt(b2m4c)) / 2;
if (t0 < RenderObject::nearCrop && t1 < RenderObject::nearCrop) {
return std::nullopt;
} else if (t0 < RenderObject::nearCrop) {
return std::make_optional<float>(t1);
} else if (t1 < RenderObject::nearCrop) {
return std::make_optional<float>(t0);
} else {
return std::make_optional<float>(std::min(t0, t1));
}
}
RenderMaterial Sphere::material() const {
return mat;
}
QVector3D Sphere::calculateNormal(QVector3D hitpoint) const {
hitpoint -= position;
hitpoint.normalize();
return hitpoint;
}
}// namespace raytry