49 lines
1.8 KiB
C++
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
|