/*] 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_AABB_HH_ #define _MOOF_AABB_HH_ #include #include #include #include #include #include // FIXME this file is quite broken #include #include namespace Mf { class Script; /** * Axis-aligned Bounding Box */ template struct Aabb : public Cullable, public Drawable, public Shape { typedef cml::vector< Scalar, cml::fixed > Vector; Vector min; Vector max; Aabb() {} Aabb(const Vector& a, const Vector& b) { init(a, b); } Aabb(Scalar x1, Scalar y1, Scalar x2, Scalar y2) { Vector a(x1, y1); Vector b(x2, y2); init(a, b); } Aabb(Scalar x1, Scalar y1, Scalar z1, Scalar x2, Scalar y2, Scalar z2) { Vector a(x1, y1, z1); Vector b(x2, y2, z2); init(a, b); } void init(const Vector2& a, const Vector2& b) { if (a[0] < b[0]) { min[0] = a[0]; max[0] = b[0]; } else { min[0] = b[0]; max[0] = a[0]; } if (a[1] < b[1]) { min[1] = a[1]; max[1] = b[1]; } else { min[1] = b[1]; max[1] = a[1]; } } void init(const Vector3& a, const Vector3& b) { if (a[0] < b[0]) { min[0] = a[0]; max[0] = b[0]; } else { min[0] = b[0]; max[0] = a[0]; } if (a[1] < b[1]) { min[1] = a[1]; max[1] = b[1]; } else { min[1] = b[1]; max[1] = a[1]; } if (a[2] < b[2]) { min[2] = a[2]; max[2] = b[2]; } else { min[2] = b[2]; max[2] = a[2]; } } Vector getCenter() const { return (min + max) / 2.0; } Plane getPlaneXY() const { Plane plane; plane.normal = Vector3(0.0, 0.0, 1.0); plane.d = cml::dot(-plane.normal, getCenter()); return plane; } Plane getPlaneXZ() const { Plane plane; plane.normal = Vector3(0.0, 1.0, 0.0); plane.d = cml::dot(-plane.normal, getCenter()); return plane; } Plane getPlaneYZ() const { Plane plane; plane.normal = Vector3(1.0, 0.0, 0.0); plane.d = cml::dot(-plane.normal, getCenter()); return plane; } void getCorners(Vector2 corners[4]) const { corners[0][0] = min[0]; corners[0][1] = min[1]; corners[1][0] = max[0]; corners[1][1] = min[1]; corners[2][0] = max[0]; corners[2][1] = max[1]; corners[3][0] = min[0]; corners[3][1] = max[1]; } void getCorners(Vector3 corners[8]) const { corners[0][0] = min[0]; corners[0][1] = min[1]; corners[0][2] = max[2]; corners[1][0] = max[0]; corners[1][1] = min[1]; corners[1][2] = max[2]; corners[2][0] = max[0]; corners[2][1] = max[1]; corners[2][2] = max[2]; corners[3][0] = min[0]; corners[3][1] = max[1]; corners[3][2] = max[2]; corners[4][0] = min[0]; corners[4][1] = min[1]; corners[4][2] = min[2]; corners[5][0] = max[0]; corners[5][1] = min[1]; corners[5][2] = min[2]; corners[6][0] = max[0]; corners[6][1] = max[1]; corners[6][2] = min[2]; corners[7][0] = min[0]; corners[7][1] = max[1]; corners[7][2] = min[2]; } void encloseVertices(const Vector vertices[], unsigned count) { min.zero(); max.zero(); for (unsigned i = 1; i < count; ++i) { min.minimize(vertices[i]); max.maximize(vertices[i]); } } void draw(Scalar alpha = 0.0) const { glRect(min[0], min[1], max[0], max[1]); } bool isVisible(const Frustum& frustum) const { return true; } }; void importAabbClass(Script& script); template <> inline void Aabb<3>::draw(Scalar alpha) const { Scalar vertices[] = {min[0], min[1], min[2], min[0], max[1], min[2], max[0], max[1], min[2], max[0], min[1], min[2], min[0], max[1], max[2], min[0], min[1], max[2], max[0], min[1], max[2], max[0], max[1], max[2]}; GLubyte indices[] = {0, 1, 2, 3, 1, 2, 7, 4, 3, 0, 5, 6, 2, 3, 6, 7, 5, 0, 1, 4, 4, 5, 6, 7}; glEnableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_SCALAR, 0, vertices); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); Texture::resetBind(); glDrawElements(GL_QUADS, sizeof(indices), GL_UNSIGNED_BYTE, indices); glEnableClientState(GL_TEXTURE_COORD_ARRAY); //glDisableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } template <> inline bool Aabb<3>::isVisible(const Frustum& frustum) const { return frustum.contains(*this); } typedef Aabb<2> Aabb2; typedef Aabb2 Rectangle; typedef Aabb<3> Aabb3; } // namespace Mf #endif // _MOOF_AABB_HH_