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 "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{
144 DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { }
145 bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance)
146 {
148 return did_hit;
149 }
150 bool didHit() const { return did_hit;}
151};
152
154{
155 DynamicTreeLocationInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask), _hitModel(nullptr) {}
156
157 void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
158 {
160 _hitModel = &obj;
161 }
162
164 GameObjectModel const* GetHitModel() const { return _hitModel; }
165
166private:
170};
171
172bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
173 const G3D::Vector3& endPos, float& maxDist) const
174{
175 float distance = maxDist;
176 DynamicTreeIntersectionCallback callback(phasemask);
177 impl->intersectRay(ray, callback, distance, endPos);
178 if (callback.didHit())
179 maxDist = distance;
180 return callback.didHit();
181}
182
183bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3& startPos,
184 const G3D::Vector3& endPos, G3D::Vector3& resultHit,
185 float modifyDist) const
186{
187 bool result = false;
188 float maxDist = (endPos - startPos).magnitude();
189 // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
190 ASSERT(maxDist < std::numeric_limits<float>::max());
191 // prevent NaN values which can cause BIH intersection to enter infinite loop
192 if (maxDist < 1e-10f)
193 {
194 resultHit = endPos;
195 return false;
196 }
197 G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1
198 G3D::Ray ray(startPos, dir);
199 float dist = maxDist;
200 if (getIntersectionTime(phasemask, ray, endPos, dist))
201 {
202 resultHit = startPos + dir * dist;
203 if (modifyDist < 0)
204 {
205 if ((resultHit - startPos).magnitude() > -modifyDist)
206 resultHit = resultHit + dir*modifyDist;
207 else
208 resultHit = startPos;
209 }
210 else
211 resultHit = resultHit + dir*modifyDist;
212
213 result = true;
214 }
215 else
216 {
217 resultHit = endPos;
218 result = false;
219 }
220 return result;
221}
222
223bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
224{
225 G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2);
226
227 float maxDist = (v2 - v1).magnitude();
228
229 if (!G3D::fuzzyGt(maxDist, 0) )
230 return true;
231
232 G3D::Ray r(v1, (v2-v1) / maxDist);
233 DynamicTreeIntersectionCallback callback(phasemask);
234 impl->intersectRay(r, callback, maxDist, v2);
235
236 return !callback.did_hit;
237}
238
239float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const
240{
241 G3D::Vector3 v(x, y, z);
242 G3D::Ray r(v, G3D::Vector3(0, 0, -1));
243 DynamicTreeIntersectionCallback callback(phasemask);
244 impl->intersectZAllignedRay(r, callback, maxSearchDist);
245
246 if (callback.didHit())
247 return v.z - maxSearchDist;
248 else
249 return -G3D::finf();
250}
251
252bool DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const
253{
254 G3D::Vector3 v(x, y, z + 0.5f);
255 DynamicTreeLocationInfoCallback intersectionCallBack(phasemask);
256 impl->intersectPoint(v, intersectionCallBack);
257 if (intersectionCallBack.GetLocationInfo().hitModel)
258 {
259 data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
260 uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
261 float liquidLevel;
262 if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & *reqLiquidType)
263 if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
264 data.liquidInfo.emplace(liquidType, liquidLevel);
265
266 data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
267 0,
268 intersectionCallBack.GetLocationInfo().rootId,
269 intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(),
270 0);
271 return true;
272 }
273 return false;
274}
uint32_t uint32
Definition Define.h:133
RegularGrid2D< GameObjectModel, BIHWrap< GameObjectModel > > ParentTree
#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 getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional< uint8 > reqLiquidType, VMAP::AreaAndLiquidData &data) const
bool getIntersectionTime(uint32 phasemask, const G3D::Ray &ray, const G3D::Vector3 &endPos, float &maxDist) const
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
void insert(GameObjectModel const &)
DynTreeImpl * impl
Definition DynamicTree.h:40
void update(uint32 diff)
float getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const
bool getObjectHitPos(uint32 phasemask, const G3D::Vector3 &pPos1, const G3D::Vector3 &pPos2, G3D::Vector3 &pResultHitPos, float pModifyDist) const
void remove(GameObjectModel const &)
bool GetLocationInfo(G3D::Vector3 const &point, VMAP::LocationInfo &info, uint32 ph_mask) const
const G3D::AABox & getBounds() const
const G3D::Vector3 & getPosition() const
bool GetLiquidLevel(G3D::Vector3 const &point, VMAP::LocationInfo &info, float &liqHeight) const
bool intersectRay(const G3D::Ray &Ray, float &MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const
void intersectZAllignedRay(const G3D::Ray &ray, RayCallback &intersectCallback, float &max_dist)
bool empty() const
void insert(const T &value)
Definition RegularGrid.h:67
bool contains(const T &value) const
void intersectRay(const G3D::Ray &ray, RayCallback &intersectCallback, float max_dist)
void remove(const T &value)
Definition RegularGrid.h:84
void intersectPoint(const G3D::Vector3 &point, IsectCallback &intersectCallback)
uint32 GetLiquidType() const
uint32 GetMogpFlags() const
Definition WorldModel.h:95
uint32 GetWmoID() const
Definition WorldModel.h:96
static VMapManager2 * createOrGetVMapManager()
static void getBounds2(GameObjectModel const *g, G3D::AABox &out)
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(uint32 phasemask)
DynamicTreeLocationInfoCallback(uint32 phaseMask)
void operator()(G3D::Vector3 const &p, GameObjectModel const &obj)
VMAP::LocationInfo & GetLocationInfo()
GameObjectModel const * GetHitModel() const
GameObjectModel const * _hitModel
static size_t hashCode(GameObjectModel const &g)
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
Optional< LiquidInfo > liquidInfo
GroupModel const * hitModel
Definition MapTree.h:44