TrinityCore
Loading...
Searching...
No Matches
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 "VMapManager.h"
27#include "WorldModel.h"
28#include <G3D/AABox.h>
29#include <G3D/Ray.h>
30#include <G3D/Vector3.h>
31
32namespace {
33
34int CHECK_TREE_PERIOD = 200;
35
36} // namespace
37
38template<> struct PositionTrait< GameObjectModel> {
39 static void getPosition(GameObjectModel const& g, G3D::Vector3& p) { p = g.GetPosition(); }
40};
41
42template<> struct BoundsTrait< GameObjectModel> {
43 static void getBounds(GameObjectModel const& g, G3D::AABox& out) { out = g.getBounds();}
44 void operator()(GameObjectModel const* g, G3D::AABox& out) const { getBounds(*g, out); }
45};
46
47/*
48static bool operator==(GameObjectModel const& mdl, GameObjectModel const& mdl2){
49 return &mdl == &mdl2;
50}
51*/
52
54
55struct DynTreeImpl : public ParentTree/*, public Intersectable*/
56{
59
61 rebalance_timer(CHECK_TREE_PERIOD),
63 {
64 }
65
66 void insert(Model const& mdl)
67 {
68 base::insert(mdl);
70 }
71
72 void remove(Model const& mdl)
73 {
74 base::remove(mdl);
76 }
77
78 void balance()
79 {
82 }
83
84 void update(uint32 difftime)
85 {
86 if (empty())
87 return;
88
89 rebalance_timer.Update(difftime);
91 {
92 rebalance_timer.Reset(CHECK_TREE_PERIOD);
93 if (unbalanced_times > 0)
94 balance();
95 }
96 }
97
100};
101
103
105
107{
108 impl->insert(mdl);
109}
110
112{
113 impl->remove(mdl);
114}
115
117{
118 return impl->contains(mdl);
119}
120
122{
123 impl->balance();
124}
125
127{
128 impl->update(t_diff);
129}
130
132{
133 DynamicTreeIntersectionCallback(PhaseShift const& phaseShift) : _didHit(false), _phaseShift(phaseShift) { }
134
135 bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance)
136 {
138 return _didHit;
139 }
140
141 bool didHit() const { return _didHit; }
142
143private:
146};
147
149{
150 DynamicTreeLosCallback(PhaseShift const& phaseShift) : _didHit(false), _phaseShift(phaseShift) { }
151
152 bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance)
153 {
154 if (!obj.IsLosBlockingDisabled())
156 return _didHit;
157 }
158
159 bool didHit() const { return _didHit; }
160
161private:
164};
165
167{
168 DynamicTreeLocationInfoCallback(PhaseShift const& phaseShift) : _phaseShift(phaseShift), _hitModel(nullptr) {}
169
170 void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
171 {
173 _hitModel = &obj;
174 }
175
177 GameObjectModel const* GetHitModel() const { return _hitModel; }
178
179private:
183};
184
185bool DynamicMapTree::getIntersectionTime(G3D::Ray const& ray, G3D::Vector3 const& endPos, PhaseShift const& phaseShift, float& maxDist) const
186{
187 float distance = maxDist;
188 DynamicTreeIntersectionCallback callback(phaseShift);
189 impl->intersectRay(ray, callback, distance, endPos);
190 if (callback.didHit())
191 maxDist = distance;
192 return callback.didHit();
193}
194
195bool DynamicMapTree::getObjectHitPos(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist, PhaseShift const& phaseShift) const
196{
197 bool result = false;
198 float maxDist = (endPos - startPos).magnitude();
199 // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
200 ASSERT(maxDist < std::numeric_limits<float>::max());
201 // prevent NaN values which can cause BIH intersection to enter infinite loop
202 if (maxDist < 1e-10f)
203 {
204 resultHitPos = endPos;
205 return false;
206 }
207 G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1
208 G3D::Ray ray(startPos, dir);
209 float dist = maxDist;
210 if (getIntersectionTime(ray, endPos, phaseShift, dist))
211 {
212 resultHitPos = startPos + dir * dist;
213 if (modifyDist < 0)
214 {
215 if ((resultHitPos - startPos).magnitude() > -modifyDist)
216 resultHitPos += dir * modifyDist;
217 else
218 resultHitPos = startPos;
219 }
220 else
221 resultHitPos += dir * modifyDist;
222
223 result = true;
224 }
225 else
226 {
227 resultHitPos = endPos;
228 result = false;
229 }
230 return result;
231}
232
233bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, PhaseShift const& phaseShift) const
234{
235 float maxDist = (endPos - startPos).magnitude();
236
237 if (!G3D::fuzzyGt(maxDist, 0) )
238 return true;
239
240 G3D::Ray r(startPos, (endPos - startPos) / maxDist);
241 DynamicTreeLosCallback callback(phaseShift);
242 impl->intersectRay(r, callback, maxDist, endPos);
243
244 return !callback.didHit();
245}
246
247float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const& phaseShift) const
248{
249 G3D::Vector3 v(x, y, z);
250 G3D::Ray r(v, G3D::Vector3(0, 0, -1));
251 DynamicTreeIntersectionCallback callback(phaseShift);
252 impl->intersectZAllignedRay(r, callback, maxSearchDist);
253
254 if (callback.didHit())
255 return v.z - maxSearchDist;
256 else
257 return -G3D::finf();
258}
259
260bool DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, PhaseShift const& phaseShift, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const
261{
262 G3D::Vector3 v(x, y, z + 0.5f);
263 DynamicTreeLocationInfoCallback intersectionCallBack(phaseShift);
264 impl->intersectPoint(v, intersectionCallBack);
265 if (intersectionCallBack.GetLocationInfo().hitModel)
266 {
267 data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
268 uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
269 float liquidLevel;
270 if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & *reqLiquidType)
271 if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
272 data.liquidInfo.emplace(liquidType, liquidLevel);
273
274 data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
275 intersectionCallBack.GetHitModel()->GetNameSetId(),
276 intersectionCallBack.GetLocationInfo().rootId,
277 intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(),
278 0);
279 return true;
280 }
281 return false;
282}
283
284std::span<GameObjectModel const* const> DynamicMapTree::getModelsInGrid(uint32 gx, uint32 gy) const
285{
286 // convert from map tile X/Y to RegularGrid internal representation
287 return impl->getObjects(63 - int32(gx), 63 - int32(gy));
288}
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
RegularGrid2D< GameObjectModel, BIHWrap< GameObjectModel > > ParentTree
#define ASSERT
Definition Errors.h:80
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 &)
bool getObjectHitPos(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos, G3D::Vector3 &resultHitPos, float modifyDist, PhaseShift const &phaseShift) const
std::unique_ptr< DynTreeImpl > impl
Definition DynamicTree.h:43
void update(uint32 diff)
std::span< GameObjectModel const *const > getModelsInGrid(uint32 gx, uint32 gy) const
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
G3D::Vector3 const & GetPosition() 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
bool IsLosBlockingDisabled() const
bool IntersectRay(G3D::Ray const &ray, float &maxDist, bool stopAtFirstHit, PhaseShift const &phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const
void remove(T const &value)
Definition RegularGrid.h:71
void insert(T const &value)
Definition RegularGrid.h:54
bool empty() const
Definition RegularGrid.h:88
uint32 GetLiquidType() const
uint32 GetMogpFlags() const
Definition WorldModel.h:101
uint32 GetWmoID() const
Definition WorldModel.h:102
static VMapManager * createOrGetVMapManager()
void operator()(GameObjectModel const *g, G3D::AABox &out) const
static void getBounds(GameObjectModel const &g, G3D::AABox &out)
void insert(Model const &mdl)
TimeTracker rebalance_timer
ParentTree base
void remove(Model const &mdl)
void update(uint32 difftime)
GameObjectModel Model
bool operator()(G3D::Ray const &r, GameObjectModel const &obj, float &distance)
DynamicTreeIntersectionCallback(PhaseShift const &phaseShift)
DynamicTreeLocationInfoCallback(PhaseShift const &phaseShift)
void operator()(G3D::Vector3 const &p, GameObjectModel const &obj)
VMAP::LocationInfo & GetLocationInfo()
GameObjectModel const * GetHitModel() const
GameObjectModel const * _hitModel
PhaseShift const & _phaseShift
DynamicTreeLosCallback(PhaseShift const &phaseShift)
bool operator()(G3D::Ray const &r, GameObjectModel const &obj, float &distance)
static void getPosition(GameObjectModel const &g, G3D::Vector3 &p)
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 VMapManager.h:95
Optional< LiquidInfo > liquidInfo
Definition VMapManager.h:96
GroupModel const * hitModel
Definition MapTree.h:45