/*] Copyright (c) 2009-2010, Charles McGarvey [************************** **] All rights reserved. * * vi:ts=4 sw=4 tw=75 * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * **************************************************************************/ #ifndef _MOOF_SPHERE_HH_ #define _MOOF_SPHERE_HH_ #include #include #include #include #include #include // TODO this needs work namespace Mf { /** * A round object. */ template struct Sphere : public Cullable, public Drawable, public Shape { typedef cml::vector< Scalar, cml::fixed > Vector; // (solution - point)^2 - radius^2 = 0 Vector point; Scalar radius; Sphere() {} Sphere(const Vector& p, Scalar r) : point(p), radius(r) {} //Sphere(Scalar x, Scalar y, Scalar z, Scalar r) : //point(x, y, z), //radius(r) {} void init(const Vector& p, Scalar r) { point = p; radius = r; } void init(const Vector& p, const Vector& o) { point = p; radius = (o - p).length(); } // a ray inside the sphere will not intersect on its way out bool intersectRay(const Ray& ray, typename Ray::Contact& hit) { Vector b = point - ray.point; Scalar z = cml::dot(b, ray.direction); // check if the ball is behind the ray if (z < SCALAR(0.0)) return false; Scalar d2 = cml::dot(b, b) - z*z; Scalar r2 = radius * radius; // check for an intersection if (d2 > r2) return false; hit.distance = z - std::sqrt(r2 - d2); if (hit.distance < SCALAR(0.0)) return false; Vector surfacePoint; ray.solve(surfacePoint, hit.distance); hit.normal = surfacePoint - point; return true; } //void encloseVertices(const Vector vertices[], unsigned count); //void draw(Scalar alpha = 0.0) const; //bool isVisible(const Frustum& frustum) const; void encloseVertices(const Vector vertices[], unsigned count) { // TODO } void draw(Scalar alpha = 0.0) const; //{ //GLUquadricObj* sphereObj = gluNewQuadric(); //gluQuadricDrawStyle(sphereObj, GLU_LINE); //glPushMatrix(); //glTranslate(point); //gluSphere(sphereObj, GLdouble(radius), 16, 16); //glPopMatrix(); //gluDeleteQuadric(sphereObj); //} bool isVisible(const Frustum& frustum) const { return true; } }; template <> inline bool Sphere<3>::isVisible(const Frustum& frustum) const { return frustum.contains(*this); } template <> inline void Sphere<2>::draw(Scalar alpha) const { GLUquadricObj* sphereObj = gluNewQuadric(); gluQuadricDrawStyle(sphereObj, GLU_LINE); glPushMatrix(); glTranslate(promote(point)); gluSphere(sphereObj, GLdouble(radius), 16, 16); glPopMatrix(); gluDeleteQuadric(sphereObj); } template <> inline void Sphere<3>::draw(Scalar alpha) const { GLUquadricObj* sphereObj = gluNewQuadric(); gluQuadricDrawStyle(sphereObj, GLU_LINE); glPushMatrix(); glTranslate(point); gluSphere(sphereObj, GLdouble(radius), 16, 16); glPopMatrix(); gluDeleteQuadric(sphereObj); } template inline bool checkCollision(const Sphere& a, const Sphere& b) { Scalar d = (a.point - b.point).length(); return d < (a.radius + b.radius); } typedef Sphere<2> Sphere2; typedef Sphere2 Circle; typedef Sphere<3> Sphere3; } // namespace Mf #endif // _MOOF_SPHERE_HH_