TrinityCore
RegularGrid.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _REGULAR_GRID_H
19#define _REGULAR_GRID_H
20
21#include "Errors.h"
22#include "IteratorPair.h"
23#include <G3D/Ray.h>
24#include <G3D/BoundsTrait.h>
25#include <G3D/PositionTrait.h>
26#include <unordered_map>
27
28template<class Node>
30 static Node * makeNode(int /*x*/, int /*y*/) { return new Node();}
31};
32
33template<class T,
34class Node,
35class NodeCreatorFunc = NodeCreator<Node>,
36class BoundsFunc = BoundsTrait<T>,
37class PositionFunc = PositionTrait<T>
38>
40{
41public:
42
43 enum{
44 CELL_NUMBER = 64,
45 };
46
47 #define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed
48 #define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER)
49
50 typedef std::unordered_multimap<const T*, Node*> MemberTable;
51
53 Node* nodes[CELL_NUMBER][CELL_NUMBER];
54
56 {
57 memset(nodes, 0, sizeof(nodes));
58 }
59
61 {
62 for (int x = 0; x < CELL_NUMBER; ++x)
63 for (int y = 0; y < CELL_NUMBER; ++y)
64 delete nodes[x][y];
65 }
66
67 void insert(const T& value)
68 {
69 G3D::AABox bounds;
70 BoundsFunc::getBounds(value, bounds);
71 Cell low = Cell::ComputeCell(bounds.low().x, bounds.low().y);
72 Cell high = Cell::ComputeCell(bounds.high().x, bounds.high().y);
73 for (int x = low.x; x <= high.x; ++x)
74 {
75 for (int y = low.y; y <= high.y; ++y)
76 {
77 Node& node = getGrid(x, y);
78 node.insert(value);
79 memberTable.emplace(&value, &node);
80 }
81 }
82 }
83
84 void remove(const T& value)
85 {
86 for (auto& p : Trinity::Containers::MapEqualRange(memberTable, &value))
87 p.second->remove(value);
88 // Remove the member
89 memberTable.erase(&value);
90 }
91
92 void balance()
93 {
94 for (int x = 0; x < CELL_NUMBER; ++x)
95 for (int y = 0; y < CELL_NUMBER; ++y)
96 if (Node* n = nodes[x][y])
97 n->balance();
98 }
99
100 bool contains(const T& value) const { return memberTable.count(&value) > 0; }
101 bool empty() const { return memberTable.empty(); }
102
103 struct Cell
104 {
105 int x, y;
106 bool operator==(Cell const& c2) const
107 {
108 return x == c2.x && y == c2.y;
109 }
110
111 static Cell ComputeCell(float fx, float fy)
112 {
113 Cell c = { int(fx * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)), int(fy * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)) };
114 return c;
115 }
116
117 bool isValid() const { return x >= 0 && x < CELL_NUMBER && y >= 0 && y < CELL_NUMBER; }
118 };
119
120 Node& getGrid(int x, int y)
121 {
122 ASSERT(x < CELL_NUMBER && y < CELL_NUMBER);
123 if (!nodes[x][y])
124 nodes[x][y] = NodeCreatorFunc::makeNode(x, y);
125 return *nodes[x][y];
126 }
127
128 template<typename RayCallback>
129 void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float max_dist)
130 {
131 intersectRay(ray, intersectCallback, max_dist, ray.origin() + ray.direction() * max_dist);
132 }
133
134 template<typename RayCallback>
135 void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist, const G3D::Vector3& end)
136 {
137 Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
138 if (!cell.isValid())
139 return;
140
141 Cell last_cell = Cell::ComputeCell(end.x, end.y);
142
143 if (cell == last_cell)
144 {
145 if (Node* node = nodes[cell.x][cell.y])
146 node->intersectRay(ray, intersectCallback, max_dist);
147 return;
148 }
149
150 float voxel = (float)CELL_SIZE;
151 float kx_inv = ray.invDirection().x, bx = ray.origin().x;
152 float ky_inv = ray.invDirection().y, by = ray.origin().y;
153
154 int stepX, stepY;
155 float tMaxX, tMaxY;
156 if (kx_inv >= 0)
157 {
158 stepX = 1;
159 float x_border = (cell.x+1) * voxel;
160 tMaxX = (x_border - bx) * kx_inv;
161 }
162 else
163 {
164 stepX = -1;
165 float x_border = (cell.x-1) * voxel;
166 tMaxX = (x_border - bx) * kx_inv;
167 }
168
169 if (ky_inv >= 0)
170 {
171 stepY = 1;
172 float y_border = (cell.y+1) * voxel;
173 tMaxY = (y_border - by) * ky_inv;
174 }
175 else
176 {
177 stepY = -1;
178 float y_border = (cell.y-1) * voxel;
179 tMaxY = (y_border - by) * ky_inv;
180 }
181
182 //int Cycles = std::max((int)ceilf(max_dist/tMaxX),(int)ceilf(max_dist/tMaxY));
183 //int i = 0;
184
185 float tDeltaX = voxel * std::fabs(kx_inv);
186 float tDeltaY = voxel * std::fabs(ky_inv);
187 do
188 {
189 if (Node* node = nodes[cell.x][cell.y])
190 {
191 //float enterdist = max_dist;
192 node->intersectRay(ray, intersectCallback, max_dist);
193 }
194 if (cell == last_cell)
195 break;
196 if (tMaxX < tMaxY)
197 {
198 tMaxX += tDeltaX;
199 cell.x += stepX;
200 }
201 else
202 {
203 tMaxY += tDeltaY;
204 cell.y += stepY;
205 }
206 //++i;
207 } while (cell.isValid());
208 }
209
210 template<typename IsectCallback>
211 void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback)
212 {
213 Cell cell = Cell::ComputeCell(point.x, point.y);
214 if (!cell.isValid())
215 return;
216 if (Node* node = nodes[cell.x][cell.y])
217 node->intersectPoint(point, intersectCallback);
218 }
219
220 // Optimized verson of intersectRay function for rays with vertical directions
221 template<typename RayCallback>
222 void intersectZAllignedRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist)
223 {
224 Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
225 if (!cell.isValid())
226 return;
227 if (Node* node = nodes[cell.x][cell.y])
228 node->intersectRay(ray, intersectCallback, max_dist);
229 }
230};
231
232#undef CELL_SIZE
233#undef HGRID_MAP_SIZE
234
235#endif
#define TC_COMMON_API
Definition: Define.h:99
#define ASSERT
Definition: Errors.h:68
#define CELL_SIZE
Definition: RegularGrid.h:48
Node & getGrid(int x, int y)
Definition: RegularGrid.h:120
void intersectZAllignedRay(const G3D::Ray &ray, RayCallback &intersectCallback, float &max_dist)
Definition: RegularGrid.h:222
MemberTable memberTable
Definition: RegularGrid.h:52
void intersectRay(const G3D::Ray &ray, RayCallback &intersectCallback, float &max_dist, const G3D::Vector3 &end)
Definition: RegularGrid.h:135
bool empty() const
Definition: RegularGrid.h:101
void balance()
Definition: RegularGrid.h:92
void insert(const T &value)
Definition: RegularGrid.h:67
bool contains(const T &value) const
Definition: RegularGrid.h:100
void intersectRay(const G3D::Ray &ray, RayCallback &intersectCallback, float max_dist)
Definition: RegularGrid.h:129
void remove(const T &value)
Definition: RegularGrid.h:84
std::unordered_multimap< const T *, Node * > MemberTable
Definition: RegularGrid.h:50
void intersectPoint(const G3D::Vector3 &point, IsectCallback &intersectCallback)
Definition: RegularGrid.h:211
auto MapEqualRange(M &map, typename M::key_type const &key)
Definition: IteratorPair.h:60
static Node * makeNode(int, int)
Definition: RegularGrid.h:30
bool isValid() const
Definition: RegularGrid.h:117
bool operator==(Cell const &c2) const
Definition: RegularGrid.h:106
static Cell ComputeCell(float fx, float fy)
Definition: RegularGrid.h:111