nuclear@3: /* nuclear@3: Simple introductory ray tracer nuclear@3: Copyright (C) 2012 John Tsiombikas nuclear@3: nuclear@3: This program is free software: you can redistribute it and/or modify nuclear@3: it under the terms of the GNU General Public License as published by nuclear@3: the Free Software Foundation, either version 3 of the License, or nuclear@3: (at your option) any later version. nuclear@3: nuclear@3: This program is distributed in the hope that it will be useful, nuclear@3: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@3: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@3: GNU General Public License for more details. nuclear@3: nuclear@3: You should have received a copy of the GNU General Public License nuclear@3: along with this program. If not, see . nuclear@3: */ nuclear@0: #include nuclear@0: #include "sphere.h" nuclear@0: nuclear@0: Sphere::Sphere() nuclear@0: { nuclear@0: radius = 1.0; nuclear@0: } nuclear@0: nuclear@0: Sphere::Sphere(const Vector3 &pos, float rad) nuclear@0: { nuclear@0: radius = rad; nuclear@0: this->pos = pos; nuclear@0: } nuclear@0: nuclear@0: bool Sphere::intersect(const Ray &inray, HitPoint *pt) const nuclear@0: { nuclear@0: Ray ray = inray.transformed(inv_xform); nuclear@0: nuclear@0: float a = dot_product(ray.dir, ray.dir); nuclear@0: float b = 2.0 * ray.dir.x * (ray.origin.x - pos.x) + nuclear@0: 2.0 * ray.dir.y * (ray.origin.y - pos.y) + nuclear@0: 2.0 * ray.dir.z * (ray.origin.z - pos.z); nuclear@0: float c = dot_product(ray.origin, ray.origin) + dot_product(pos, pos) - nuclear@0: 2.0 * dot_product(ray.origin, pos) - radius * radius; nuclear@0: nuclear@0: float discr = b * b - 4.0 * a * c; nuclear@0: if(discr < 1e-4) nuclear@0: return false; nuclear@0: nuclear@0: float sqrt_discr = sqrt(discr); nuclear@0: float t0 = (-b + sqrt_discr) / (2.0 * a); nuclear@0: float t1 = (-b - sqrt_discr) / (2.0 * a); nuclear@0: nuclear@0: if(t0 < 1e-4) nuclear@0: t0 = t1; nuclear@0: if(t1 < 1e-4) nuclear@0: t1 = t0; nuclear@0: nuclear@0: float t = t0 < t1 ? t0 : t1; nuclear@0: if(t < 1e-4) nuclear@0: return false; nuclear@0: nuclear@0: // fill the HitPoint structure nuclear@0: pt->obj = this; nuclear@0: pt->dist = t; nuclear@0: pt->pos = ray.origin + ray.dir * t; nuclear@0: pt->normal = (pt->pos - pos) / radius; nuclear@0: nuclear@0: pt->pos.transform(xform); nuclear@0: pt->normal.transform(dir_xform); nuclear@0: return true; nuclear@0: }