| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- Copyright (c) 2013 Daniele Bartolini, Michele Rossi
- Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
- #pragma once
- #include "assert.h"
- #include "math_types.h"
- #include "matrix4x4.h"
- #include "sphere.h"
- #include "types.h"
- #include "vector3.h"
- namespace crown
- {
- /// Functions to manipulate AABB.
- ///
- /// @ingroup Math
- namespace aabb
- {
- void reset(AABB& b);
- /// Returns the center of the box @a b.
- Vector3 center(const AABB& b);
- /// Returns the radius of the box @a b.
- float radius(const AABB& b);
- /// Returns the volume of the box @a b.
- float volume(const AABB& b);
- /// Adds @a num @a points to the box @a b, expanding its bounds if necessary.
- void add_points(AABB& b, uint32_t num, const Vector3* points);
- /// Adds @a num @a boxes to the box @a b, expanding its bounds if necessary.
- void add_boxes(AABB& b, uint32_t num, const AABB* boxes);
- /// Returns whether point @a p is contained in the box @a b.
- bool contains_point(const AABB& b, const Vector3& p);
- /// Returns the @a index -th vertex of the box.
- Vector3 vertex(const AABB& b, uint32_t index);
- /// Returns the box enclosing @a b transformed by @a m.
- AABB transformed(const AABB& b, const Matrix4x4& m);
- /// Returns the eight vertices of the box @a b.
- void to_vertices(const AABB& b, Vector3 v[8]);
- /// Returns the sphere enclosing the box @a b.
- Sphere to_sphere(const AABB& b);
- }
- namespace aabb
- {
- //-----------------------------------------------------------------------------
- inline void reset(AABB& b)
- {
- b.min = vector3::ZERO;
- b.max = vector3::ZERO;
- }
- //-----------------------------------------------------------------------------
- inline Vector3 center(const AABB& b)
- {
- return (b.min + b.max) * 0.5;
- }
- //-----------------------------------------------------------------------------
- inline float radius(const AABB& b)
- {
- return vector3::length(b.max - (b.min + b.max) * 0.5);
- }
- //-----------------------------------------------------------------------------
- inline float volume(const AABB& b)
- {
- return (b.max.x - b.min.x) * (b.max.y - b.min.y) * (b.max.z - b.min.z);
- }
- //-----------------------------------------------------------------------------
- inline void add_points(AABB& b, uint32_t num, const Vector3* points)
- {
- for (uint32_t i = 0; i < num; i++)
- {
- const Vector3& p = points[i];
- if (p.x < b.min.x) b.min.x = p.x;
- if (p.y < b.min.y) b.min.y = p.y;
- if (p.z < b.min.z) b.min.z = p.z;
- if (p.x > b.max.x) b.max.x = p.x;
- if (p.y > b.max.y) b.max.y = p.y;
- if (p.z > b.max.z) b.max.z = p.z;
- }
- }
- //-----------------------------------------------------------------------------
- inline void add_boxes(AABB& b, uint32_t num, const AABB* boxes)
- {
- for (uint32_t i = 0; i < num; i++)
- {
- const AABB& box = boxes[i];
- if (box.min.x < b.min.x) b.min.x = box.min.x;
- if (box.min.y < b.min.y) b.min.y = box.min.y;
- if (box.min.z < b.min.z) b.min.z = box.min.z;
- if (box.max.x > b.max.x) b.max.x = box.max.x;
- if (box.max.y > b.max.y) b.max.y = box.max.y;
- if (box.max.z > b.max.z) b.max.z = box.max.z;
- }
- }
- //-----------------------------------------------------------------------------
- inline bool contains_point(const AABB& b, const Vector3& p)
- {
- return (p.x > b.min.x &&
- p.y > b.min.y &&
- p.z > b.min.z &&
- p.x < b.max.x &&
- p.y < b.max.y &&
- p.z < b.max.z);
- }
- //-----------------------------------------------------------------------------
- inline Vector3 vertex(const AABB& b, uint32_t index)
- {
- CE_ASSERT(index < 8, "Index must be < 8");
- switch (index)
- {
- case 0: return Vector3(b.min.x, b.min.y, b.min.z);
- case 1: return Vector3(b.max.x, b.min.y, b.min.z);
- case 2: return Vector3(b.max.x, b.min.y, b.max.z);
- case 3: return Vector3(b.min.x, b.min.y, b.max.z);
- case 4: return Vector3(b.min.x, b.max.y, b.min.z);
- case 5: return Vector3(b.max.x, b.max.y, b.min.z);
- case 6: return Vector3(b.max.x, b.max.y, b.max.z);
- case 7: return Vector3(b.min.x, b.max.y, b.max.z);
- }
- }
- //-----------------------------------------------------------------------------
- inline AABB transformed(const AABB& b, const Matrix4x4& m)
- {
- Vector3 vertices[8];
- to_vertices(b, vertices);
- vertices[0] = m * vertices[0];
- vertices[1] = m * vertices[1];
- vertices[2] = m * vertices[2];
- vertices[3] = m * vertices[3];
- vertices[4] = m * vertices[4];
- vertices[5] = m * vertices[5];
- vertices[6] = m * vertices[6];
- vertices[7] = m * vertices[7];
- AABB res;
- reset(res);
- add_points(res, 8, vertices);
- return res;
- }
- //-----------------------------------------------------------------------------
- inline void to_vertices(const AABB& b, Vector3 v[8])
- {
- // 7 ---- 6
- // | |
- // | | <--- Top face
- // 4 ---- 5
- //
- // 3 ---- 2
- // | |
- // | | <--- Bottom face
- // 0 ---- 1
- v[0].x = b.min.x;
- v[0].y = b.min.y;
- v[0].z = b.max.z;
- v[1].x = b.max.x;
- v[1].y = b.min.y;
- v[1].z = b.max.z;
- v[2].x = b.max.x;
- v[2].y = b.min.y;
- v[2].z = b.min.z;
- v[3].x = b.min.x;
- v[3].y = b.min.y;
- v[3].z = b.min.z;
- v[4].x = b.min.x;
- v[4].y = b.max.y;
- v[4].z = b.max.z;
- v[5].x = b.max.x;
- v[5].y = b.max.y;
- v[5].z = b.max.z;
- v[6].x = b.max.x;
- v[6].y = b.max.y;
- v[6].z = b.min.z;
- v[7].x = b.min.x;
- v[7].y = b.max.y;
- v[7].z = b.min.z;
- }
- //-----------------------------------------------------------------------------
- inline Sphere to_sphere(const AABB& b)
- {
- return Sphere(center(b), radius(b));
- }
- } // namespace aabb
- //-----------------------------------------------------------------------------
- inline AABB::AABB()
- {
- // Do not initialize
- }
- //-----------------------------------------------------------------------------
- inline AABB::AABB(const Vector3& min, const Vector3& max)
- : min(min), max(max)
- {
- }
- } // namespace crown
|