// // Created by LEI XU on 5/13/19. // #ifndef RAYTRACING_SPHERE_H #define RAYTRACING_SPHERE_H #include "Object.hpp" #include "Vector.hpp" #include "Bounds3.hpp" #include "Material.hpp" class Sphere : public Object{ public: Vector3f center; float radius, radius2; Material *m; float area; Sphere(const Vector3f &c, const float &r, Material* mt = new Material()) : center(c), radius(r), radius2(r * r), m(mt), area(4 * M_PI *r *r) {} bool intersect(const Ray& ray) { // analytic solution Vector3f L = ray.origin - center; float a = dotProduct(ray.direction, ray.direction); float b = 2 * dotProduct(ray.direction, L); float c = dotProduct(L, L) - radius2; float t0, t1; float area = 4 * M_PI * radius2; if (!solveQuadratic(a, b, c, t0, t1)) return false; if (t0 < 0) t0 = t1; if (t0 < 0) return false; return true; } bool intersect(const Ray& ray, float &tnear, uint32_t &index) const { // analytic solution Vector3f L = ray.origin - center; float a = dotProduct(ray.direction, ray.direction); float b = 2 * dotProduct(ray.direction, L); float c = dotProduct(L, L) - radius2; float t0, t1; if (! solveQuadratic(a, b, c, t0, t1)) return false; if (t0 < 0) t0 = t1; if (t0 < 0) return false; tnear = t0; return true; } Intersection getIntersection(Ray ray){ Intersection result; result.happened = false; Vector3f L = ray.origin - center; float a = dotProduct(ray.direction, ray.direction); float b = 2 * dotProduct(ray.direction, L); float c = dotProduct(L, L) - radius2; float t0, t1; if (!solveQuadratic(a, b, c, t0, t1)) return result; if (t0 < 0) t0 = t1; if (t0 < 0) return result; result.happened=true; result.coords = Vector3f(ray.origin + ray.direction * t0); result.normal = normalize(Vector3f(result.coords - center)); result.m = this->m; result.obj = this; result.distance = t0; return result; } void getSurfaceProperties(const Vector3f &P, const Vector3f &I, const uint32_t &index, const Vector2f &uv, Vector3f &N, Vector2f &st) const { N = normalize(P - center); } Vector3f evalDiffuseColor(const Vector2f &st)const { //return m->getColor(); } Bounds3 getBounds(){ return Bounds3(Vector3f(center.x-radius, center.y-radius, center.z-radius), Vector3f(center.x+radius, center.y+radius, center.z+radius)); } void Sample(Intersection &pos, float &pdf){ float theta = 2.0 * M_PI * get_random_float(), phi = M_PI * get_random_float(); Vector3f dir(std::cos(phi), std::sin(phi)*std::cos(theta), std::sin(phi)*std::sin(theta)); pos.coords = center + radius * dir; pos.normal = dir; pos.emit = m->getEmission(); pdf = 1.0f / area; } float getArea(){ return area; } bool hasEmit(){ return m->hasEmission(); } }; #endif //RAYTRACING_SPHERE_H