From 2fa398926dfc759655050ab41aebc9ae43b5b1a1 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Wed, 22 Apr 2015 23:44:56 +0000 Subject: [PATCH] math: improve the 2D and 3D box classes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Box objects (AABB) now have the long awaited extent() and center() methods. Corners are now called “aa” and “bb” for convenience. The WorldEntity class uses a box3 for its AABB instead of two vec3s. This allows us to simplify a lot of verbose code. --- doc/samples/meshviewer/meshviewer.cpp | 4 +- doc/tutorial/11_fractal.cpp | 4 +- src/debug/lines.cpp | 16 ++--- src/gpu/renderer.cpp | 14 ++-- src/gradient.cpp | 16 ++--- src/image/crop.cpp | 16 ++--- src/lol/algorithm/aabb_tree.h | 24 +++---- src/lol/math/geometry.h | 96 +++++++++++++++++---------- src/tileset.cpp | 23 +++---- src/video.cpp | 4 +- src/worldentity.cpp | 6 +- src/worldentity.h | 2 +- 12 files changed, 125 insertions(+), 100 deletions(-) diff --git a/doc/samples/meshviewer/meshviewer.cpp b/doc/samples/meshviewer/meshviewer.cpp index 591c1bf8..66f48e89 100644 --- a/doc/samples/meshviewer/meshviewer.cpp +++ b/doc/samples/meshviewer/meshviewer.cpp @@ -75,8 +75,8 @@ public: //This considers the box usage A to B as top-left to bottom-right void AddTarget(box3 new_target) { - vec3 base_off = .5f * (new_target.B - new_target.A); - vec3 base_pos = new_target.A + base_off; + vec3 base_off = .5f * new_target.extent(); + vec3 base_pos = new_target.center(); int pass = 0; while (pass < 3) { diff --git a/doc/tutorial/11_fractal.cpp b/doc/tutorial/11_fractal.cpp index 85ead843..1a5c180e 100644 --- a/doc/tutorial/11_fractal.cpp +++ b/doc/tutorial/11_fractal.cpp @@ -120,8 +120,8 @@ public: #endif m_position = vec3::zero; - m_bbox[0] = m_position; - m_bbox[1] = vec3((vec2)m_window_size, 0); + m_aabb.aa = m_position; + m_aabb.bb = vec3((vec2)m_window_size, 0); //Input::TrackMouse(this); #if LOL_FEATURE_THREADS diff --git a/src/debug/lines.cpp b/src/debug/lines.cpp index 60e1ceee..c46f0056 100644 --- a/src/debug/lines.cpp +++ b/src/debug/lines.cpp @@ -212,20 +212,20 @@ void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, vec4 color, float az, float bz) } //-- BOX: 3D -2D - 3D_to_2D --------------------------------------------------- -void Debug::DrawBox(box3 a) { Debug::DrawBox(a.A, a.B, Scene::GetLineColor()); } -void Debug::DrawBox(box2 a) { Debug::DrawBox(a.A, a.B, Scene::GetLineColor()); } -void Debug::DrawBox(box3 a, vec4 color) { Debug::DrawBox(a.A, a.B, color); } -void Debug::DrawBox(box2 a, vec4 color) { Debug::DrawBox(a.A, a.B, color); } +void Debug::DrawBox(box3 a) { Debug::DrawBox(a.aa, a.bb, Scene::GetLineColor()); } +void Debug::DrawBox(box2 a) { Debug::DrawBox(a.aa, a.bb, Scene::GetLineColor()); } +void Debug::DrawBox(box3 a, vec4 color) { Debug::DrawBox(a.aa, a.bb, color); } +void Debug::DrawBox(box2 a, vec4 color) { Debug::DrawBox(a.aa, a.bb, color); } void Debug::DrawBox(vec3 a, vec3 b) { Debug::DrawBox(a, b, Scene::GetLineColor()); } void Debug::DrawBox(vec2 a, vec2 b) { Debug::DrawBox(a, b, Scene::GetLineColor()); } void Debug::DrawBox(vec2 a, float s) { Debug::DrawBox(a, s, Scene::GetLineColor()); } void Debug::DrawBox(vec3 a, vec3 b, vec4 color) { Debug::DrawBox(a, b, mat4::identity, color); } void Debug::DrawBox(vec2 a, vec2 b, vec4 color) { Debug::DrawBox(a, b, mat2::identity, color); } void Debug::DrawBox(vec2 a, float s, vec4 color) { Debug::DrawBox(a, s, mat2::identity, color); } -void Debug::DrawBox(box3 a, mat4 transform) { Debug::DrawBox(a.A, a.B, transform, Scene::GetLineColor()); } -void Debug::DrawBox(box2 a, mat2 transform) { Debug::DrawBox(a.A, a.B, transform, Scene::GetLineColor()); } -void Debug::DrawBox(box3 a, mat4 transform, vec4 color) { Debug::DrawBox(a.A, a.B, transform, color); } -void Debug::DrawBox(box2 a, mat2 transform, vec4 color) { Debug::DrawBox(a.A, a.B, transform, color); } +void Debug::DrawBox(box3 a, mat4 transform) { Debug::DrawBox(a.aa, a.bb, transform, Scene::GetLineColor()); } +void Debug::DrawBox(box2 a, mat2 transform) { Debug::DrawBox(a.aa, a.bb, transform, Scene::GetLineColor()); } +void Debug::DrawBox(box3 a, mat4 transform, vec4 color) { Debug::DrawBox(a.aa, a.bb, transform, color); } +void Debug::DrawBox(box2 a, mat2 transform, vec4 color) { Debug::DrawBox(a.aa, a.bb, transform, color); } void Debug::DrawBox(vec3 a, vec3 b, mat4 transform) { Debug::DrawBox(a, b, transform, Scene::GetLineColor()); } void Debug::DrawBox(vec2 a, vec2 b, mat2 transform) { Debug::DrawBox(a, b, transform, Scene::GetLineColor()); } void Debug::DrawBox(vec2 a, float s, mat2 transform) { Debug::DrawBox(a, s, transform, Scene::GetLineColor()); } diff --git a/src/gpu/renderer.cpp b/src/gpu/renderer.cpp index 799507ce..53bae2a5 100644 --- a/src/gpu/renderer.cpp +++ b/src/gpu/renderer.cpp @@ -235,12 +235,12 @@ void Renderer::SetViewport(ibox2 viewport) return; #if defined USE_D3D9 || defined _XBOX - D3DVIEWPORT9 vp = { viewport.A.x, viewport.A.y, - viewport.B.x, viewport.B.y, + D3DVIEWPORT9 vp = { viewport.aa.x, viewport.aa.y, + viewport.bb.x, viewport.bb.y, 0.0f, 1.0f }; m_data->m_d3d_dev->SetViewport(&vp); #else - glViewport(viewport.A.x, viewport.A.y, viewport.B.x, viewport.B.y); + glViewport(viewport.aa.x, viewport.aa.y, viewport.bb.x, viewport.bb.y); #endif m_data->m_viewport = viewport; @@ -253,17 +253,13 @@ ibox2 Renderer::GetViewport() const float Renderer::GetXYRatio() const { - ibox2 a = GetViewport(); - ibox2 b(a.A, a.B); - ivec2 s = b.B - b.A; + ivec2 s = GetViewport().extent(); return (float)s.x / s.y; } float Renderer::GetYXRatio() const { - ibox2 a = GetViewport(); - ibox2 b(a.A, a.B); - ivec2 s = b.B - b.A; + ivec2 s = GetViewport().extent(); return (float)s.y / s.x; } diff --git a/src/gradient.cpp b/src/gradient.cpp index 80e7104d..b35e32a8 100644 --- a/src/gradient.cpp +++ b/src/gradient.cpp @@ -38,8 +38,8 @@ Gradient::Gradient(vec3 aa, vec3 bb) { /* FIXME: this should not be hardcoded */ m_position = aa; - m_bbox[0] = aa; - m_bbox[1] = bb; + m_aabb.aa = aa; + m_aabb.bb = bb; data->shader = nullptr; } @@ -53,12 +53,12 @@ void Gradient::TickDraw(float seconds, Scene &scene) { Entity::TickDraw(seconds, scene); - float const vertex[] = { m_bbox[0].x, m_bbox[0].y, 0.0f, - m_bbox[1].x, m_bbox[0].y, 0.0f, - m_bbox[0].x, m_bbox[1].y, 0.0f, - m_bbox[1].x, m_bbox[1].y, 0.0f, - m_bbox[0].x, m_bbox[1].y, 0.0f, - m_bbox[1].x, m_bbox[0].y, 0.0f, }; + float const vertex[] = { m_aabb.aa.x, m_aabb.aa.y, 0.0f, + m_aabb.bb.x, m_aabb.aa.y, 0.0f, + m_aabb.aa.x, m_aabb.bb.y, 0.0f, + m_aabb.bb.x, m_aabb.bb.y, 0.0f, + m_aabb.aa.x, m_aabb.bb.y, 0.0f, + m_aabb.bb.x, m_aabb.aa.y, 0.0f, }; float const color[] = { 0.73f, 0.85f, 0.85f, 1.0f, 0.73f, 0.85f, 0.85f, 1.0f, diff --git a/src/image/crop.cpp b/src/image/crop.cpp index ab3afeed..9709d5b7 100644 --- a/src/image/crop.cpp +++ b/src/image/crop.cpp @@ -22,7 +22,7 @@ namespace lol Image Image::Crop(ibox2 box) const { ivec2 const srcsize = GetSize(); - ivec2 const dstsize = box.B - box.A; + ivec2 const dstsize = box.extent(); Image dst(dstsize); PixelFormat format = GetFormat(); @@ -36,24 +36,24 @@ Image Image::Crop(ibox2 box) const int len = dstsize.x; - if (box.A.x < 0) + if (box.aa.x < 0) { - len += box.A.x; - box.A.x = 0; + len += box.aa.x; + box.aa.x = 0; } - if (box.A.x + len > srcsize.x) - len = srcsize.x - box.A.x; + if (box.aa.x + len > srcsize.x) + len = srcsize.x - box.aa.x; if (len > 0) { for (int y = 0; y < dstsize.y; y++) { - if (y + box.A.y < 0 || y + box.A.y >= srcsize.y) + if (y + box.aa.y < 0 || y + box.aa.y >= srcsize.y) continue; memcpy(dstp + y * dstsize.x * bpp, - srcp + ((y + box.A.y) * srcsize.x + box.A.x) * bpp, + srcp + ((y + box.aa.y) * srcsize.x + box.aa.x) * bpp, len * bpp); } } diff --git a/src/lol/algorithm/aabb_tree.h b/src/lol/algorithm/aabb_tree.h index cf5291fc..1f681f91 100644 --- a/src/lol/algorithm/aabb_tree.h +++ b/src/lol/algorithm/aabb_tree.h @@ -81,8 +81,8 @@ void Draw(Quadtree* tree, vec4 color) //vec3 add = vec3(0.0f, 0.1f, 0.0f); while (boxes.Count() > 0) { - Debug::DrawBox(vec3(boxes[0].m1.A.x, tree->m_debug_y_offset, boxes[0].m1.A.y), - vec3(boxes[0].m1.B.x, tree->m_debug_y_offset, boxes[0].m1.B.y), + Debug::DrawBox(vec3(boxes[0].m1.aa.x, tree->m_debug_y_offset, boxes[0].m1.aa.y), + vec3(boxes[0].m1.bb.x, tree->m_debug_y_offset, boxes[0].m1.bb.y), boxes[0].m2); boxes.Remove(0); } @@ -90,8 +90,8 @@ void Draw(Quadtree* tree, vec4 color) { while (elements[0].m2 > 0) { - Debug::DrawBox(vec3(elements[0].m1->GetAABB().A.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().A.y) + off * (float)elements[0].m2, - vec3(elements[0].m1->GetAABB().B.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().B.y) + off * (float)elements[0].m2, + Debug::DrawBox(vec3(elements[0].m1->GetAABB().aa.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().aa.y) + off * (float)elements[0].m2, + vec3(elements[0].m1->GetAABB().bb.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().bb.y) + off * (float)elements[0].m2, elements[0].m3); elements[0].m2--; } @@ -112,9 +112,9 @@ void Draw(Octree* tree, vec4 color) //vec3 add = vec3(0.0f, 0.1f, 0.0f); while (boxes.Count() > 0) { - //float size = boxes[0].m1.B.x - boxes[0].m1.A.x; - Debug::DrawBox(vec3(boxes[0].m1.A.x, boxes[0].m1.A.y, boxes[0].m1.A.z) /* + off * (m_size.x / size) */, - vec3(boxes[0].m1.B.x, boxes[0].m1.B.y, boxes[0].m1.B.z) /* + off * (m_size.x / size) */, + //float size = boxes[0].m1.bb.x - boxes[0].m1.aa.x; + Debug::DrawBox(vec3(boxes[0].m1.aa.x, boxes[0].m1.aa.y, boxes[0].m1.aa.z) /* + off * (m_size.x / size) */, + vec3(boxes[0].m1.bb.x, boxes[0].m1.bb.y, boxes[0].m1.bb.z) /* + off * (m_size.x / size) */, boxes[0].m2); //off += add; boxes.Remove(0); @@ -123,8 +123,8 @@ void Draw(Octree* tree, vec4 color) { while (elements[0].m2 > 0) { - Debug::DrawBox(vec3(elements[0].m1->GetAABB().A.x, elements[0].m1->GetAABB().A.y, elements[0].m1->GetAABB().A.z) + off * (float)elements[0].m2, - vec3(elements[0].m1->GetAABB().B.x, elements[0].m1->GetAABB().B.y, elements[0].m1->GetAABB().B.z) + off * (float)elements[0].m2, + Debug::DrawBox(vec3(elements[0].m1->GetAABB().aa.x, elements[0].m1->GetAABB().aa.y, elements[0].m1->GetAABB().aa.z) + off * (float)elements[0].m2, + vec3(elements[0].m1->GetAABB().bb.x, elements[0].m1->GetAABB().bb.y, elements[0].m1->GetAABB().bb.z) + off * (float)elements[0].m2, elements[0].m3); elements[0].m2--; } @@ -341,9 +341,9 @@ public: virtual TB GetSubAABB(const TB& bbox, int sub) { TV v(GetSubOffset(sub)); - TV half_vec = (bbox.B - bbox.A) * .5f; - return TB(bbox.A + half_vec * v, - bbox.A + half_vec * (v + TV(1.f))); + TV half_vec = bbox.extent() * .5f; + return TB(bbox.aa + half_vec * v, + bbox.aa + half_vec * (v + TV(1.f))); } //-- diff --git a/src/lol/math/geometry.h b/src/lol/math/geometry.h index 2cd2732a..32484588 100644 --- a/src/lol/math/geometry.h +++ b/src/lol/math/geometry.h @@ -87,23 +87,23 @@ LOL_BOX_TYPEDEFS(Box3, box3) template struct Box2 { inline Box2() - : A(T(0)), - B(T(0)) + : aa(T(0)), + bb(T(0)) {} inline Box2(vec_t const &a, vec_t const &b) - : A(a), - B(b) + : aa(a), + bb(b) {} inline Box2(T const &ax, T const &ay, T const &bx, T const &by) - : A(ax, ay), - B(bx, by) + : aa(ax, ay), + bb(bx, by) {} Box2 operator +(vec_t const &v) const { - return Box2(A + v, B + v); + return Box2(aa + v, bb + v); } Box2 &operator +=(vec_t const &v) @@ -113,7 +113,7 @@ template struct Box2 Box2 operator -(vec_t const &v) const { - return Box2(A - v, B - v); + return Box2(aa - v, bb - v); } Box2 &operator -=(vec_t const &v) @@ -123,7 +123,7 @@ template struct Box2 Box2 operator *(vec_t const &v) const { - return Box2(A * v, B * v); + return Box2(aa * v, bb * v); } Box2 &operator *=(vec_t const &v) @@ -131,17 +131,31 @@ template struct Box2 return *this = *this * v; } - bool operator ==(Box2 const &box) + Box2 operator *(T const &s) const { - return A == box.A && B == box.B; + return Box2(aa * s, bb * s); } - bool operator !=(Box2 const &box) + Box2 &operator *=(T const &s) { - return A != box.A || B != box.B; + return *this = *this * s; } - vec_t A, B; + bool operator ==(Box2 const &box) const + { + return aa == box.aa && bb == box.bb; + } + + bool operator !=(Box2 const &box) const + { + return aa != box.aa || bb != box.bb; + } + + inline vec_t center() const { return (bb + aa) / 2; } + + inline vec_t extent() const { return bb - aa; } + + vec_t aa, bb; }; /* @@ -151,24 +165,24 @@ template struct Box2 template struct Box3 { inline Box3() - : A(T(0)), - B(T(0)) + : aa(T(0)), + bb(T(0)) {} inline Box3(vec_t const &a, vec_t const &b) - : A(a), - B(b) + : aa(a), + bb(b) {} inline Box3(T const &ax, T const &ay, T const &az, T const &bx, T const &by, T const &bz) - : A(ax, ay, az), - B(bx, by, bz) + : aa(ax, ay, az), + bb(bx, by, bz) {} Box3 operator +(vec_t const &v) const { - return Box3(A + v, B + v); + return Box3(aa + v, bb + v); } Box3 &operator +=(vec_t const &v) @@ -178,7 +192,7 @@ template struct Box3 Box3 operator -(vec_t const &v) const { - return Box3(A - v, B - v); + return Box3(aa - v, bb - v); } Box3 &operator -=(vec_t const &v) @@ -188,7 +202,7 @@ template struct Box3 Box3 operator *(vec_t const &v) const { - return Box3(A * v, B * v); + return Box3(aa * v, bb * v); } Box3 &operator *=(vec_t const &v) @@ -196,17 +210,31 @@ template struct Box3 return *this = *this * v; } - bool operator ==(Box3 const &box) + Box3 operator *(T const &s) const { - return A == box.A && B == box.B; + return Box3(aa * s, bb * s); } - bool operator !=(Box3 const &box) + Box3 &operator *=(T const &s) { - return A != box.A || B != box.B; + return *this = *this * s; } - vec_t A, B; + bool operator ==(Box3 const &box) const + { + return aa == box.aa && bb == box.bb; + } + + bool operator !=(Box3 const &box) const + { + return aa != box.aa || bb != box.bb; + } + + inline vec_t center() const { return (bb + aa) / 2; } + + inline vec_t extent() const { return bb - aa; } + + vec_t aa, bb; }; /* @@ -243,9 +271,9 @@ bool operator>=(float value, const TestEpsilon& epsilon); //-- static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) { - vec2 c = 0.5f * ((b1.A + b1.B) - (b2.A + b2.B)); - vec2 e1 = 0.5f * (b1.B - b1.A); - vec2 e2 = 0.5f * (b2.B - b2.A); + vec2 c = b1.center() - b2.center(); + vec2 e1 = 0.5f * b1.extent(); + vec2 e2 = 0.5f * b2.extent(); return abs(c.x) <= e1.x + e2.x && abs(c.y) <= e1.y + e2.y; @@ -257,9 +285,9 @@ static inline bool TestAABBVsPoint(box2 const &b1, vec2 const &p) static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) { - vec3 c = 0.5f * ((b1.A + b1.B) - (b2.A + b2.B)); - vec3 e1 = 0.5f * (b1.B - b1.A); - vec3 e2 = 0.5f * (b2.B - b2.A); + vec3 c = b1.center() - b2.center(); + vec3 e1 = 0.5f * b1.extent(); + vec3 e2 = 0.5f * b2.extent(); return abs(c.x) <= e1.x + e2.x && abs(c.y) <= e1.y + e2.y diff --git a/src/tileset.cpp b/src/tileset.cpp index 90cabc91..ff554a3b 100644 --- a/src/tileset.cpp +++ b/src/tileset.cpp @@ -137,8 +137,8 @@ char const *TileSet::GetName() ptrdiff_t TileSet::AddTile(ibox2 rect) { m_tileset_data->m_tiles.Push(rect, - box2((vec2)rect.A / (vec2)m_data->m_texture_size, - (vec2)rect.B / (vec2)m_data->m_texture_size)); + box2((vec2)rect.aa / (vec2)m_data->m_texture_size, + (vec2)rect.bb / (vec2)m_data->m_texture_size)); return m_tileset_data->m_tiles.Count() - 1; } @@ -161,8 +161,7 @@ ptrdiff_t TileSet::GetTileCount() const ivec2 TileSet::GetTileSize(ptrdiff_t tileid) const { - ibox2 const &box = m_tileset_data->m_tiles[tileid].m1; - return box.B - box.A; + return m_tileset_data->m_tiles[tileid].m1.extent(); } //Palette --------------------------------------------------------------------- @@ -186,14 +185,14 @@ void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, float angle, { ibox2 pixels = m_tileset_data->m_tiles[id].m1; box2 texels = m_tileset_data->m_tiles[id].m2; - float dtx = texels.B.x - texels.A.x; - float dty = texels.B.y - texels.A.y; - float tx = texels.A.x; - float ty = texels.A.y; - - int dx = (int)((float)(pixels.B.x - pixels.A.x) * scale.x); - int dy = o ? 0 : (int)((float)(pixels.B.y - pixels.A.y) * scale.y); - int dz = o ? (int)((float)(pixels.B.y - pixels.A.y) * scale.y) : 0; + float dtx = texels.extent().x; + float dty = texels.extent().y; + float tx = texels.aa.x; + float ty = texels.aa.y; + + int dx = (int)(pixels.extent().x * scale.x); + int dy = o ? 0 : (int)(pixels.extent().y * scale.y); + int dz = o ? (int)(pixels.extent().y * scale.y) : 0; /* If scaling is negative, switch triangle winding */ if (scale.x * scale.y < 0.0f) diff --git a/src/video.cpp b/src/video.cpp index e679763e..a5d1c504 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -132,9 +132,7 @@ void Video::Capture(uint32_t *buffer) ivec2 Video::GetSize() { - ibox2 viewport = g_renderer->GetViewport(); - - return viewport.B - viewport.A; + return g_renderer->GetViewport().extent(); } } /* namespace lol */ diff --git a/src/worldentity.cpp b/src/worldentity.cpp index 55cb56e6..81359d40 100644 --- a/src/worldentity.cpp +++ b/src/worldentity.cpp @@ -20,8 +20,12 @@ namespace lol */ WorldEntity::WorldEntity() + : m_aabb(vec3(0.f), vec3(0.f)), + m_position(0.f), + m_velocity(0.f), + m_rotation(1.f), + m_rotation_velocity(0.f) { - m_bbox[0] = m_bbox[1] = vec3::zero; } WorldEntity::~WorldEntity() diff --git a/src/worldentity.h b/src/worldentity.h index f3990918..33e4580e 100644 --- a/src/worldentity.h +++ b/src/worldentity.h @@ -28,11 +28,11 @@ public: virtual char const *GetName(); public: + box3 m_aabb; vec3 m_position = vec3::zero; vec3 m_velocity = vec3::zero; quat m_rotation = quat(1); vec3 m_rotation_velocity = vec3::zero; - vec3 m_bbox[2]; protected: WorldEntity();