Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
332 строки · 9.7 Кб
1
/*
2
* This file is part of the Pandaria 5.4.8 Project. See THANKS 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"
19
#include "BoundingIntervalHierarchyWrapper.h"
20
#include "GameObjectModel.h"
21
#include "Log.h"
22
#include "MapTree.h"
23
#include "ModelIgnoreFlags.h"
24
#include "ModelInstance.h"
25
#include "RegularGrid.h"
26
#include "Timer.h"
27
#include "VMapFactory.h"
28
#include "VMapManager2.h"
29
#include "WorldModel.h"
30
#include <G3D/AABox.h>
31
#include <G3D/Ray.h>
32
#include <G3D/Vector3.h>
33

34
#include <G3D/AABox.h>
35
#include <G3D/Ray.h>
36
#include <G3D/Vector3.h>
37

38
using VMAP::ModelInstance;
39

40
namespace {
41

42
int CHECK_TREE_PERIOD = 200;
43

44
} // namespace
45

46
template<> struct HashTrait< GameObjectModel>{
47
    static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; }
48
};
49

50
template<> struct PositionTrait< GameObjectModel> {
51
    static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); }
52
};
53

54
template<> struct BoundsTrait< GameObjectModel> {
55
    static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();}
56
    static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();}
57
};
58

59
/*
60
static bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2){
61
    return &mdl == &mdl2;
62
}
63
*/
64

65
typedef RegularGrid2D<GameObjectModel, BIHWrap<GameObjectModel> > ParentTree;
66

67
struct DynTreeImpl : public ParentTree/*, public Intersectable*/
68
{
69
    typedef GameObjectModel Model;
70
    typedef ParentTree base;
71

72
    DynTreeImpl() :
73
        rebalance_timer(CHECK_TREE_PERIOD),
74
        unbalanced_times(0)
75
    {
76
    }
77

78
    void insert(const Model& mdl)
79
    {
80
        base::insert(mdl);
81
        ++unbalanced_times;
82
    }
83

84
    void remove(const Model& mdl)
85
    {
86
        base::remove(mdl);
87
        ++unbalanced_times;
88
    }
89

90
    void balance()
91
    {
92
        base::balance();
93
        unbalanced_times = 0;
94
    }
95

96
    void update(uint32 difftime)
97
    {
98
        if (empty())
99
            return;
100

101
        rebalance_timer.Update(difftime);
102
        if (rebalance_timer.Passed())
103
        {
104
            rebalance_timer.Reset(CHECK_TREE_PERIOD);
105
            if (unbalanced_times > 0)
106
                balance();
107
        }
108
    }
109

110
    TimeTrackerSmall rebalance_timer;
111
    int unbalanced_times;
112
};
113

114
DynamicMapTree::DynamicMapTree() : impl(new DynTreeImpl()) { }
115

116
DynamicMapTree::~DynamicMapTree()
117
{
118
    delete impl;
119
}
120

121
void DynamicMapTree::insert(const GameObjectModel& mdl)
122
{
123
    impl->insert(mdl);
124
}
125

126
void DynamicMapTree::remove(const GameObjectModel& mdl)
127
{
128
    impl->remove(mdl);
129
}
130

131
bool DynamicMapTree::contains(const GameObjectModel& mdl) const
132
{
133
    return impl->contains(mdl);
134
}
135

136
void DynamicMapTree::balance()
137
{
138
    impl->balance();
139
}
140

141
void DynamicMapTree::update(uint32 t_diff)
142
{
143
    impl->update(t_diff);
144
}
145

146
struct DynamicTreeIntersectionCallback
147
{
148
    bool did_hit;
149
    uint32 phase_mask;
150
    DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { }
151
    bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
152
    {
153
        did_hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
154
        return did_hit;
155
    }
156
    bool didHit() const { return did_hit;}
157
};
158

159
struct DynamicTreeIntersectionCallback_WithLogger
160
{
161
    bool did_hit;
162
    uint32 phase_mask;
163
    DynamicTreeIntersectionCallback_WithLogger(uint32 phasemask) : did_hit(false), phase_mask(phasemask)
164
    {
165
        TC_LOG_DEBUG("maps", "Dynamic Intersection log");
166
    }
167
    bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
168
    {
169
        TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str());
170
        bool hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
171
        if (hit)
172
        {
173
            did_hit = true;
174
            TC_LOG_DEBUG("maps", "result: intersects");
175
        }
176
        return hit;
177
    }
178
    bool didHit() const { return did_hit;}
179
};
180

181
struct DynamicTreeAreaInfoCallback
182
{
183
    DynamicTreeAreaInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask) {}
184

185
    void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
186
    {
187
        obj.intersectPoint(p, _areaInfo, _phaseMask);
188
    }
189

190
    VMAP::AreaInfo const& GetAreaInfo() const { return _areaInfo; }
191

192
private:
193
    uint32 _phaseMask;
194
    VMAP::AreaInfo _areaInfo;
195
};
196

197
struct DynamicTreeLocationInfoCallback
198
{
199
    DynamicTreeLocationInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask), _hitModel(nullptr) {}
200

201
    void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
202
    {
203
        if (obj.GetLocationInfo(p, _locationInfo, _phaseMask))
204
            _hitModel = &obj;
205
    }
206

207
    VMAP::LocationInfo& GetLocationInfo() { return _locationInfo; }
208
    GameObjectModel const* GetHitModel() const { return _hitModel; }
209

210
private:
211
    uint32 _phaseMask;
212
    VMAP::LocationInfo _locationInfo;
213
    GameObjectModel const* _hitModel;
214
};
215

216
bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
217
                                         const G3D::Vector3& endPos, float& maxDist) const
218
{
219
    float distance = maxDist;
220
    DynamicTreeIntersectionCallback callback(phasemask);
221
    impl->intersectRay(ray, callback, distance, endPos);
222
    if (callback.didHit())
223
        maxDist = distance;
224
    return callback.didHit();
225
}
226

227
bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3& startPos,
228
                                     const G3D::Vector3& endPos, G3D::Vector3& resultHit,
229
                                     float modifyDist) const
230
{
231
    bool result = false;
232
    float maxDist = (endPos - startPos).magnitude();
233
    // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
234
    ASSERT(maxDist < std::numeric_limits<float>::max());
235
    // prevent NaN values which can cause BIH intersection to enter infinite loop
236
    if (maxDist < 1e-10f)
237
    {
238
        resultHit = endPos;
239
        return false;
240
    }
241
    G3D::Vector3 dir = (endPos - startPos)/maxDist;              // direction with length of 1
242
    G3D::Ray ray(startPos, dir);
243
    float dist = maxDist;
244
    if (getIntersectionTime(phasemask, ray, endPos, dist))
245
    {
246
        resultHit = startPos + dir * dist;
247
        if (modifyDist < 0)
248
        {
249
            if ((resultHit - startPos).magnitude() > -modifyDist)
250
                resultHit = resultHit + dir*modifyDist;
251
            else
252
                resultHit = startPos;
253
        }
254
        else
255
            resultHit = resultHit + dir*modifyDist;
256

257
        result = true;
258
    }
259
    else
260
    {
261
        resultHit = endPos;
262
        result = false;
263
    }
264
    return result;
265
}
266

267
bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
268
{
269
    G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2);
270

271
    float maxDist = (v2 - v1).magnitude();
272

273
    if (!G3D::fuzzyGt(maxDist, 0) )
274
        return true;
275

276
    G3D::Ray r(v1, (v2-v1) / maxDist);
277
    DynamicTreeIntersectionCallback callback(phasemask);
278
    impl->intersectRay(r, callback, maxDist, v2);
279

280
    return !callback.did_hit;
281
}
282

283
float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const
284
{
285
    G3D::Vector3 v(x, y, z);
286
    G3D::Ray r(v, G3D::Vector3(0, 0, -1));
287
    DynamicTreeIntersectionCallback callback(phasemask);
288
    impl->intersectZAllignedRay(r, callback, maxSearchDist);
289

290
    if (callback.didHit())
291
        return v.z - maxSearchDist;
292
    else
293
        return -G3D::finf();
294
}
295

296
bool DynamicMapTree::getAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
297
{
298
    G3D::Vector3 v(x, y, z + 0.5f);
299
    DynamicTreeAreaInfoCallback intersectionCallBack(phasemask);
300
    impl->intersectPoint(v, intersectionCallBack);
301
    if (intersectionCallBack.GetAreaInfo().result)
302
    {
303
        flags = intersectionCallBack.GetAreaInfo().flags;
304
        adtId = intersectionCallBack.GetAreaInfo().adtId;
305
        rootId = intersectionCallBack.GetAreaInfo().rootId;
306
        groupId = intersectionCallBack.GetAreaInfo().groupId;
307
        z = intersectionCallBack.GetAreaInfo().ground_Z;
308
        return true;
309
    }
310
    return false;
311
}
312

313
void DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const
314
{
315
    G3D::Vector3 v(x, y, z + 0.5f);
316
    DynamicTreeLocationInfoCallback intersectionCallBack(phasemask);
317
    impl->intersectPoint(v, intersectionCallBack);
318
    if (intersectionCallBack.GetLocationInfo().hitModel)
319
    {
320
        data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
321
        uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
322
        float liquidLevel;
323
        if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & reqLiquidType)
324
            if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
325
                data.liquidInfo.emplace(liquidType, liquidLevel);
326

327
        data.areaInfo.emplace(0,
328
            intersectionCallBack.GetLocationInfo().rootId,
329
            intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
330
            intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags());
331
    }
332
}
333

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.