#include <Moof/Cullable.hh>
#include <Moof/Drawable.hh>
+#include <Moof/Frustum.hh>
#include <Moof/Math.hh>
+#include <Moof/OpenGL.hh>
+#include <Moof/Shape.hh>
namespace Mf {
* A round object.
*/
-struct Sphere : public Cullable, public Drawable
+template <int D = 3>
+struct Sphere : public Cullable, public Drawable, public Shape<D>
{
- Vector3 point;
+ typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+
+ // (solution - point)^2 - radius^2 = 0
+ Vector point;
Scalar radius;
Sphere() {}
- Sphere(const Vector3& p, Scalar r) :
+ 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) {}
+ //Sphere(Scalar x, Scalar y, Scalar z, Scalar r) :
+ //point(x, y, z),
+ //radius(r) {}
- inline void init(const Vector3& p, Scalar r)
+ void init(const Vector& p, Scalar r)
{
point = p;
radius = r;
}
- void encloseVertices(const Vector3 vertices[], unsigned count);
+ 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<D>& ray, typename Ray<D>::Intersection& 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();
- void draw(Scalar alpha = 0.0) const;
- bool isVisible(const Camera& cam) const;
+ //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 <int D>
+inline bool checkCollision(const Sphere<D>& a, const Sphere<D>& b)
+{
+ Scalar d = (a.point - b.point).length();
+ return d < (a.radius + b.radius);
+}
+
+
} // namespace Mf
#endif // _MOOF_SPHERE_HH_