TrinityCore
DynamicTree.cpp
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#include "DynamicTree.h"
20#include "GameObjectModel.h"
21#include "MapTree.h"
22#include "ModelIgnoreFlags.h"
23#include "RegularGrid.h"
24#include "Timer.h"
25#include "VMapFactory.h"
26#include "VMapManager2.h"
27#include "WorldModel.h"
28#include <G3D/AABox.h>
29#include <G3D/Ray.h>
30#include <G3D/Vector3.h>
31
33
34namespace {
35
36int CHECK_TREE_PERIOD = 200;
37
38} // namespace
39
40template<> struct HashTrait< GameObjectModel>{
41 static size_t hashCode(GameObjectModel const& g) { return (size_t)(void*)&g; }
42};
43
44template<> struct PositionTrait< GameObjectModel> {
45 static void getPosition(GameObjectModel const& g, G3D::Vector3& p) { p = g.getPosition(); }
46};
47
48template<> struct BoundsTrait< GameObjectModel> {
49 static void getBounds(GameObjectModel const& g, G3D::AABox& out) { out = g.getBounds();}
50 static void getBounds2(GameObjectModel const* g, G3D::AABox& out) { out = g->getBounds();}
51};
52
53/*
54static bool operator==(GameObjectModel const& mdl, GameObjectModel const& mdl2){
55 return &mdl == &mdl2;
56}
57*/
58
60
61struct DynTreeImpl : public ParentTree/*, public Intersectable*/
62{
65
67 rebalance_timer(CHECK_TREE_PERIOD),
69 {
70 }
71
72 void insert(Model const& mdl)
73 {
74 base::insert(mdl);
76 }
77
78 void remove(Model const& mdl)
79 {
80 base::remove(mdl);
82 }
83
84 void balance()
85 {
88 }
89
90 void update(uint32 difftime)
91 {
92 if (empty())
93 return;
94
95 rebalance_timer.Update(difftime);
97 {
98 rebalance_timer.Reset(CHECK_TREE_PERIOD);
99 if (unbalanced_times > 0)
100 balance();
101 }
102 }
103
106};
107
109
111{
112 delete impl;
113}
114
116{
117 impl->insert(mdl);
118}
119
121{
122 impl->remove(mdl);
123}
124
126{
127 return impl->contains(mdl);
128}
129
131{
132 impl->balance();
133}
134
136{
137 impl->update(t_diff);
138}
139
141{
142 DynamicTreeIntersectionCallback(PhaseShift const& phaseShift) : _didHit(false), _phaseShift(phaseShift) { }
143
144 bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance)
145 {
147 return _didHit;
148 }
149
150 bool didHit() const { return _didHit; }
151
152private:
155};
156
158{
159 DynamicTreeLocationInfoCallback(PhaseShift const& phaseShift) : _phaseShift(phaseShift), _hitModel(nullptr) {}
160
161 void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
162 {
164 _hitModel = &obj;
165 }
166
168 GameObjectModel const* GetHitModel() const { return _hitModel; }
169
170private:
174};
175
176bool DynamicMapTree::getIntersectionTime(G3D::Ray const& ray, G3D::Vector3 const& endPos, PhaseShift const& phaseShift, float& maxDist) const
177{
178 float distance = maxDist;
179 DynamicTreeIntersectionCallback callback(phaseShift);
180 impl->intersectRay(ray, callback, distance, endPos);
181 if (callback.didHit())
182 maxDist = distance;
183 return callback.didHit();
184}
185
186bool DynamicMapTree::getObjectHitPos(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist, PhaseShift const& phaseShift) const
187{
188 bool result = false;
189 float maxDist = (endPos - startPos).magnitude();
190 // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
191 ASSERT(maxDist < std::numeric_limits<float>::max());
192 // prevent NaN values which can cause BIH intersection to enter infinite loop
193 if (maxDist < 1e-10f)
194 {
195 resultHitPos = endPos;
196 return false;
197 }
198 G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1
199 G3D::Ray ray(startPos, dir);
200 float dist = maxDist;
201 if (getIntersectionTime(ray, endPos, phaseShift, dist))
202 {
203 resultHitPos = startPos + dir * dist;
204 if (modifyDist < 0)
205 {
206 if ((resultHitPos - startPos).magnitude() > -modifyDist)
207 resultHitPos += dir * modifyDist;
208 else
209 resultHitPos = startPos;
210 }
211 else
212 resultHitPos += dir * modifyDist;
213
214 result = true;
215 }
216 else
217 {
218 resultHitPos = endPos;
219 result = false;
220 }
221 return result;
222}
223
224bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, PhaseShift const& phaseShift) const
225{
226 float maxDist = (endPos - startPos).magnitude();
227
228 if (!G3D::fuzzyGt(maxDist, 0) )
229 return true;
230
231 G3D::Ray r(startPos, (endPos - startPos) / maxDist);
232 DynamicTreeIntersectionCallback callback(phaseShift);
233 impl->intersectRay(r, callback, maxDist, endPos);
234
235 return !callback.didHit();
236}
237
238float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const& phaseShift) const
239{
240 G3D::Vector3 v(x, y, z);
241 G3D::Ray r(v, G3D::Vector3(0, 0, -1));
242 DynamicTreeIntersectionCallback callback(phaseShift);
243 impl->intersectZAllignedRay(r, callback, maxSearchDist);
244
245 if (callback.didHit())
246 return v.z - maxSearchDist;
247 else
248 return -G3D::finf();
249}
250
251bool DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, PhaseShift const& phaseShift, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const
252{
253 G3D::Vector3 v(x, y, z + 0.5f);
254 DynamicTreeLocationInfoCallback intersectionCallBack(phaseShift);
255 impl->intersectPoint(v, intersectionCallBack);
256 if (intersectionCallBack.GetLocationInfo().hitModel)
257 {
258 data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
259 uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
260 float liquidLevel;
261 if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & *reqLiquidType)
262 if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
263 data.liquidInfo.emplace(liquidType, liquidLevel);
264
265 data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
266 intersectionCallBack.GetHitModel()->GetNameSetId(),
267 intersectionCallBack.GetLocationInfo().rootId,
268 intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(),
269 0);
270 return true;
271 }
272 return false;
273}
uint32_t uint32
Definition: Define.h:142
RegularGrid2D< GameObjectModel, BIHWrap< GameObjectModel > > ParentTree
Definition: DynamicTree.cpp:59
#define ASSERT
Definition: Errors.h:68
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
bool contains(GameObjectModel const &) const
bool getIntersectionTime(G3D::Ray const &ray, G3D::Vector3 const &endPos, PhaseShift const &phaseShift, float &maxDist) const
bool isInLineOfSight(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos, PhaseShift const &phaseShift) const
void insert(GameObjectModel const &)
DynTreeImpl * impl
Definition: DynamicTree.h:41
bool getObjectHitPos(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos, G3D::Vector3 &resultHitPos, float modifyDist, PhaseShift const &phaseShift) const
void update(uint32 diff)
float getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const &phaseShift) const
bool getAreaAndLiquidData(float x, float y, float z, PhaseShift const &phaseShift, Optional< uint8 > reqLiquidType, VMAP::AreaAndLiquidData &data) const
void remove(GameObjectModel const &)
uint8 GetNameSetId() const
const G3D::AABox & getBounds() const
const G3D::Vector3 & getPosition() const
bool intersectRay(G3D::Ray const &ray, float &maxDist, bool stopAtFirstHit, PhaseShift const &phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const
bool GetLocationInfo(G3D::Vector3 const &point, VMAP::LocationInfo &info, PhaseShift const &phaseShift) const
bool GetLiquidLevel(G3D::Vector3 const &point, VMAP::LocationInfo &info, float &liqHeight) const
void intersectZAllignedRay(const G3D::Ray &ray, RayCallback &intersectCallback, float &max_dist)
Definition: RegularGrid.h:222
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
void intersectPoint(const G3D::Vector3 &point, IsectCallback &intersectCallback)
Definition: RegularGrid.h:211
uint32 GetLiquidType() const
Definition: WorldModel.cpp:439
uint32 GetMogpFlags() const
Definition: WorldModel.h:99
uint32 GetWmoID() const
Definition: WorldModel.h:100
static VMapManager2 * createOrGetVMapManager()
Definition: VMapFactory.cpp:27
static void getBounds2(GameObjectModel const *g, G3D::AABox &out)
Definition: DynamicTree.cpp:50
static void getBounds(GameObjectModel const &g, G3D::AABox &out)
Definition: DynamicTree.cpp:49
void insert(Model const &mdl)
Definition: DynamicTree.cpp:72
TimeTracker rebalance_timer
void balance()
Definition: DynamicTree.cpp:84
ParentTree base
Definition: DynamicTree.cpp:64
void remove(Model const &mdl)
Definition: DynamicTree.cpp:78
int unbalanced_times
void update(uint32 difftime)
Definition: DynamicTree.cpp:90
GameObjectModel Model
Definition: DynamicTree.cpp:63
bool operator()(G3D::Ray const &r, GameObjectModel const &obj, float &distance)
PhaseShift const & _phaseShift
DynamicTreeIntersectionCallback(PhaseShift const &phaseShift)
VMAP::LocationInfo _locationInfo
DynamicTreeLocationInfoCallback(PhaseShift const &phaseShift)
void operator()(G3D::Vector3 const &p, GameObjectModel const &obj)
VMAP::LocationInfo & GetLocationInfo()
GameObjectModel const * GetHitModel() const
PhaseShift const & _phaseShift
GameObjectModel const * _hitModel
static size_t hashCode(GameObjectModel const &g)
Definition: DynamicTree.cpp:41
static void getPosition(GameObjectModel const &g, G3D::Vector3 &p)
Definition: DynamicTree.cpp:45
void Update(int32 diff)
Definition: Timer.h:121
bool Passed() const
Definition: Timer.h:131
void Reset(int32 expiry)
Definition: Timer.h:136
Optional< AreaInfo > areaInfo
Definition: IVMapManager.h:68
Optional< LiquidInfo > liquidInfo
Definition: IVMapManager.h:69
GroupModel const * hitModel
Definition: MapTree.h:44