Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
642 строки · 22.5 Кб
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 "WorldModel.h"
19
#include "ModelInstance.h"
20
#include "VMapDefinitions.h"
21
#include "MapTree.h"
22
#include "ModelIgnoreFlags.h"
23

24
using G3D::Vector3;
25
using G3D::Ray;
26

27
template<> struct BoundsTrait<VMAP::GroupModel>
28
{
29
    static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); }
30
};
31

32
namespace VMAP
33
{
34
    bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance)
35
    {
36
        static const float EPS = 1e-5f;
37

38
        // See RTR2 ch. 13.7 for the algorithm.
39

40
        const Vector3 e1 = points[tri.idx1] - points[tri.idx0];
41
        const Vector3 e2 = points[tri.idx2] - points[tri.idx0];
42
        const Vector3 p(ray.direction().cross(e2));
43
        const float a = e1.dot(p);
44

45
        if (std::fabs(a) < EPS) {
46
            // Determinant is ill-conditioned; abort early
47
            return false;
48
        }
49

50
        const float f = 1.0f / a;
51
        const Vector3 s(ray.origin() - points[tri.idx0]);
52
        const float u = f * s.dot(p);
53

54
        if ((u < 0.0f) || (u > 1.0f)) {
55
            // We hit the plane of the m_geometry, but outside the m_geometry
56
            return false;
57
        }
58

59
        const Vector3 q(s.cross(e1));
60
        const float v = f * ray.direction().dot(q);
61

62
        if ((v < 0.0f) || ((u + v) > 1.0f)) {
63
            // We hit the plane of the triangle, but outside the triangle
64
            return false;
65
        }
66

67
        const float t = f * e2.dot(q);
68

69
        if ((t > 0.0f) && (t < distance))
70
        {
71
            // This is a new hit, closer than the previous one
72
            distance = t;
73

74
            /* baryCoord[0] = 1.0 - u - v;
75
            baryCoord[1] = u;
76
            baryCoord[2] = v; */
77

78
            return true;
79
        }
80
        // This hit is after the previous hit, so ignore it
81
        return false;
82
    }
83

84
    class TriBoundFunc
85
    {
86
        public:
87
            TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { }
88
            void operator()(const MeshTriangle &tri, G3D::AABox &out) const
89
            {
90
                G3D::Vector3 lo = vertices[tri.idx0];
91
                G3D::Vector3 hi = lo;
92

93
                lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]);
94
                hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]);
95

96
                out = G3D::AABox(lo, hi);
97
            }
98
        protected:
99
            const std::vector<Vector3>::const_iterator vertices;
100
    };
101

102
    // ===================== WmoLiquid ==================================
103

104
    WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
105
        iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
106
    {
107
        if (width && height)
108
        {
109
            iHeight = new float[(width + 1) * (height + 1)];
110
            iFlags = new uint8[width * height];
111
        }
112
        else
113
        {
114
            iHeight = new float[1];
115
            iFlags = nullptr;
116
        }
117
    }
118

119
    WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr)
120
    {
121
        *this = other; // use assignment operator...
122
    }
123

124
    WmoLiquid::~WmoLiquid()
125
    {
126
        delete[] iHeight;
127
        delete[] iFlags;
128
    }
129

130
    WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other)
131
    {
132
        if (this == &other)
133
            return *this;
134
        iTilesX = other.iTilesX;
135
        iTilesY = other.iTilesY;
136
        iCorner = other.iCorner;
137
        iType = other.iType;
138
        delete[] iHeight;
139
        delete[] iFlags;
140
        if (other.iHeight)
141
        {
142
            iHeight = new float[(iTilesX+1)*(iTilesY+1)];
143
            memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float));
144
        }
145
        else
146
            iHeight = nullptr;
147
        if (other.iFlags)
148
        {
149
            iFlags = new uint8[iTilesX * iTilesY];
150
            memcpy(iFlags, other.iFlags, iTilesX * iTilesY);
151
        }
152
        else
153
            iFlags = nullptr;
154
        return *this;
155
    }
156

157
    bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
158
    {
159
        // simple case
160
        if (!iFlags)
161
        {
162
            liqHeight = iHeight[0];
163
            return true;
164
        }
165

166
        float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
167
        uint32 tx = uint32(tx_f);
168
        if (tx_f < 0.0f || tx >= iTilesX)
169
            return false;
170
        float ty_f = (pos.y - iCorner.y)/LIQUID_TILE_SIZE;
171
        uint32 ty = uint32(ty_f);
172
        if (ty_f < 0.0f || ty >= iTilesY)
173
            return false;
174

175
        // check if tile shall be used for liquid level
176
        // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
177
        if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F)
178
            return false;
179

180
        // (dx, dy) coordinates inside tile, in [0, 1]^2
181
        float dx = tx_f - (float)tx;
182
        float dy = ty_f - (float)ty;
183

184
        /* Tesselate tile to two triangles (not sure if client does it exactly like this)
185

186
            ^ dy
187
            |
188
          1 x---------x (1, 1)
189
            | (b)   / |
190
            |     /   |
191
            |   /     |
192
            | /   (a) |
193
            x---------x---> dx
194
          0           1
195
        */
196

197
        const uint32 rowOffset = iTilesX + 1;
198
        if (dx > dy) // case (a)
199
        {
200
            float sx = iHeight[tx+1 +  ty    * rowOffset] - iHeight[tx   + ty * rowOffset];
201
            float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset];
202
            liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
203
        }
204
        else // case (b)
205
        {
206
            float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset];
207
            float sy = iHeight[tx   + (ty+1) * rowOffset] - iHeight[tx +  ty    * rowOffset];
208
            liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
209
        }
210
        return true;
211
    }
212

213
    uint32 WmoLiquid::GetFileSize()
214
    {
215
        return 2 * sizeof(uint32) +
216
                sizeof(Vector3) +
217
                sizeof(uint32) +
218
                (iFlags ? ((iTilesX + 1) * (iTilesY + 1) * sizeof(float) + iTilesX * iTilesY) : sizeof(float));
219
    }
220

221
    bool WmoLiquid::writeToFile(FILE* wf)
222
    {
223
        bool result = false;
224
        if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 &&
225
            fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 &&
226
            fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
227
            fwrite(&iType, sizeof(uint32), 1, wf) == 1)
228
        {
229
            if (iTilesX && iTilesY)
230
            {
231
                uint32 size = (iTilesX + 1) * (iTilesY + 1);
232
                if (fwrite(iHeight, sizeof(float), size, wf) == size)
233
                {
234
                    size = iTilesX * iTilesY;
235
                    result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
236
                }
237
            }
238
            else
239
                result = fwrite(iHeight, sizeof(float), 1, wf) == 1;
240
        }
241

242
        return result;
243
    }
244

245
    bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out)
246
    {
247
        bool result = false;
248
        WmoLiquid* liquid = new WmoLiquid();
249

250
        if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 &&
251
            fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 &&
252
            fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
253
            fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
254
        {
255
            if (liquid->iTilesX && liquid->iTilesY)
256
            {
257
                uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
258
                liquid->iHeight = new float[size];
259
                if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
260
                {
261
                    size = liquid->iTilesX * liquid->iTilesY;
262
                    liquid->iFlags = new uint8[size];
263
                    result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
264
                }
265
            }
266
            else
267
            {
268
                liquid->iHeight = new float[1];
269
                result = fread(liquid->iHeight, sizeof(float), 1, rf) == 1;
270
            }
271
        }
272

273
        if (!result)
274
            delete liquid;
275
        else
276
            out = liquid;
277

278
        return result;
279
    }
280

281
    void WmoLiquid::getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const
282
    {
283
        tilesX = iTilesX;
284
        tilesY = iTilesY;
285
        corner = iCorner;
286
    }
287

288
    // ===================== GroupModel ==================================
289

290
    GroupModel::GroupModel(const GroupModel &other):
291
        iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
292
        vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr)
293
    {
294
        if (other.iLiquid)
295
            iLiquid = new WmoLiquid(*other.iLiquid);
296
    }
297

298
    void GroupModel::setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri)
299
    {
300
        vertices.swap(vert);
301
        triangles.swap(tri);
302
        TriBoundFunc bFunc(vertices);
303
        meshTree.build(triangles, bFunc);
304
    }
305

306
    bool GroupModel::writeToFile(FILE* wf)
307
    {
308
        bool result = true;
309
        uint32 chunkSize, count;
310

311
        if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false;
312
        if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false;
313
        if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false;
314

315
        // write vertices
316
        if (result && fwrite("VERT", 1, 4, wf) != 4) result = false;
317
        count = vertices.size();
318
        chunkSize = sizeof(uint32)+ sizeof(Vector3)*count;
319
        if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
320
        if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
321
        if (!count) // models without (collision) geometry end here, unsure if they are useful
322
            return result;
323
        if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false;
324

325
        // write triangle mesh
326
        if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false;
327
        count = triangles.size();
328
        chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count;
329
        if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
330
        if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
331
        if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false;
332

333
        // write mesh BIH
334
        if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false;
335
        if (result) result = meshTree.writeToFile(wf);
336

337
        // write liquid data
338
        if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false;
339
        if (!iLiquid)
340
        {
341
            chunkSize = 0;
342
            if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
343
            return result;
344
        }
345
        chunkSize = iLiquid->GetFileSize();
346
        if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
347
        if (result) result = iLiquid->writeToFile(wf);
348

349
        return result;
350
    }
351

352
    bool GroupModel::readFromFile(FILE* rf)
353
    {
354
        char chunk[8];
355
        bool result = true;
356
        uint32 chunkSize = 0;
357
        uint32 count = 0;
358
        triangles.clear();
359
        vertices.clear();
360
        delete iLiquid;
361
        iLiquid = nullptr;
362

363
        if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false;
364
        if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false;
365
        if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false;
366

367
        // read vertices
368
        if (result && !readChunk(rf, chunk, "VERT", 4)) result = false;
369
        if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
370
        if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
371
        if (!count) // models without (collision) geometry end here, unsure if they are useful
372
            return result;
373
        if (result) vertices.resize(count);
374
        if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false;
375

376
        // read triangle mesh
377
        if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false;
378
        if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
379
        if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
380
        if (result) triangles.resize(count);
381
        if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false;
382

383
        // read mesh BIH
384
        if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false;
385
        if (result) result = meshTree.readFromFile(rf);
386

387
        // write liquid data
388
        if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false;
389
        if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
390
        if (result && chunkSize > 0)
391
            result = WmoLiquid::readFromFile(rf, iLiquid);
392
        return result;
393
    }
394

395
    struct GModelRayCallback
396
    {
397
        GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert):
398
            vertices(vert.begin()), triangles(tris.begin()), hit(false) { }
399
        bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*pStopAtFirstHit*/)
400
        {
401
            hit = IntersectTriangle(triangles[entry], vertices, ray, distance) || hit;
402
            return hit;
403
        }
404
        std::vector<Vector3>::const_iterator vertices;
405
        std::vector<MeshTriangle>::const_iterator triangles;
406
        bool hit;
407
    };
408

409
    bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
410
    {
411
        if (triangles.empty())
412
            return false;
413

414
        GModelRayCallback callback(triangles, vertices);
415
        meshTree.intersectRay(ray, callback, distance, stopAtFirstHit);
416
        return callback.hit;
417
    }
418

419
    bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const
420
    {
421
        if (triangles.empty() || !iBound.contains(pos))
422
            return false;
423
        Vector3 rPos = pos - 0.1f * down;
424
        float dist = G3D::finf();
425
        G3D::Ray ray(rPos, down);
426
        bool hit = IntersectRay(ray, dist, false);
427
        if (hit)
428
            z_dist = dist - 0.1f;
429
        return hit;
430
    }
431

432
    bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const
433
    {
434
        if (iLiquid)
435
            return iLiquid->GetLiquidHeight(pos, liqHeight);
436
        return false;
437
    }
438

439
    uint32 GroupModel::GetLiquidType() const
440
    {
441
        if (iLiquid)
442
            return iLiquid->GetType();
443
        return 0;
444
    }
445

446
    void GroupModel::getMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid)
447
    {
448
        outVertices = vertices;
449
        outTriangles = triangles;
450
        liquid = iLiquid;
451
    }
452

453
    // ===================== WorldModel ==================================
454

455
    void WorldModel::setGroupModels(std::vector<GroupModel> &models)
456
    {
457
        groupModels.swap(models);
458
        groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1);
459
    }
460

461
    struct WModelRayCallBack
462
    {
463
        WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) { }
464
        bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit)
465
        {
466
            bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit);
467
            if (result)
468
                hit = true;
469
            return hit;
470
        }
471
        std::vector<GroupModel>::const_iterator models;
472
        bool hit;
473
    };
474

475
    bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
476
    {
477
        // If the caller asked us to ignore certain objects we should check flags
478
        if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing)
479
        {
480
            // M2 models are not taken into account for LoS calculation if caller requested their ignoring.
481
            if (Flags & MOD_M2)
482
                return false;
483
        }        
484

485
        // small M2 workaround, maybe better make separate class with virtual intersection funcs
486
        // in any case, there's no need to use a bound tree if we only have one submodel
487
        if (groupModels.size() == 1)
488
            return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
489

490
        WModelRayCallBack isc(groupModels);
491
        groupTree.intersectRay(ray, isc, distance, stopAtFirstHit);
492
        return isc.hit;
493
    }
494

495
    class WModelAreaCallback {
496
        public:
497
            WModelAreaCallback(std::vector<GroupModel> const& vals, Vector3 const& down) :
498
                prims(vals.begin()), hit(vals.end()), minVol(G3D::finf()), zDist(G3D::finf()), zVec(down) { }
499
            std::vector<GroupModel>::const_iterator prims;
500
            std::vector<GroupModel>::const_iterator hit;
501
            float minVol;
502
            float zDist;
503
            Vector3 zVec;
504
            void operator()(Vector3 const& point, uint32 entry)
505
            {
506
                float group_Z;
507
                //float pVol = prims[entry].GetBound().volume();
508
                //if (pVol < minVol)
509
                //{
510
                    /* if (prims[entry].iBound.contains(point)) */
511
                    if (prims[entry].IsInsideObject(point, zVec, group_Z))
512
                    {
513
                        //minVol = pVol;
514
                        //hit = prims + entry;
515
                        if (group_Z < zDist)
516
                        {
517
                            zDist = group_Z;
518
                            hit = prims + entry;
519
                        }
520
#ifdef VMAP_DEBUG
521
                        GroupModel const& gm = prims[entry];
522
                        printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
523
                        gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
524
                        gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
525
#endif
526
                    }
527
                //}
528
                //std::cout << "trying to intersect '" << prims[entry].name << "'\n";
529
            }
530
    };
531

532
    bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const
533
    {
534
        if (groupModels.empty())
535
            return false;
536

537
        WModelAreaCallback callback(groupModels, down);
538
        groupTree.intersectPoint(p, callback);
539
        if (callback.hit != groupModels.end())
540
        {
541
            info.rootId = RootWMOID;
542
            info.groupId = callback.hit->GetWmoID();
543
            info.flags = callback.hit->GetMogpFlags();
544
            info.result = true;
545
            dist = callback.zDist;
546
            return true;
547
        }
548
        return false;
549
    }
550

551
    bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const
552
    {
553
        if (groupModels.empty())
554
            return false;
555

556
        WModelAreaCallback callback(groupModels, down);
557
        groupTree.intersectPoint(p, callback);
558
        if (callback.hit != groupModels.end())
559
        {
560
            info.rootId = RootWMOID;
561
            info.hitModel = &(*callback.hit);
562
            dist = callback.zDist;
563
            return true;
564
        }
565
        return false;
566
    }
567

568
    bool WorldModel::writeFile(const std::string &filename)
569
    {
570
        FILE* wf = fopen(filename.c_str(), "wb");
571
        if (!wf)
572
            return false;
573

574
        uint32 chunkSize, count;
575
        bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8;
576
        if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false;
577
        chunkSize = sizeof(uint32) + sizeof(uint32);
578
        if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
579
        if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false;
580

581
        // write group models
582
        count = groupModels.size();
583
        if (count)
584
        {
585
            if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false;
586
            //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
587
            //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
588
            if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
589
            for (uint32 i=0; i<groupModels.size() && result; ++i)
590
                result = groupModels[i].writeToFile(wf);
591

592
            // write group BIH
593
            if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false;
594
            if (result) result = groupTree.writeToFile(wf);
595
        }
596

597
        fclose(wf);
598
        return result;
599
    }
600

601
    bool WorldModel::readFile(const std::string &filename)
602
    {
603
        FILE* rf = fopen(filename.c_str(), "rb");
604
        if (!rf)
605
            return false;
606

607
        bool result = true;
608
        uint32 chunkSize = 0;
609
        uint32 count = 0;
610
        char chunk[8];                          // Ignore the added magic header
611
        if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false;
612

613
        if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false;
614
        if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
615
        if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false;
616

617
        // read group models
618
        if (result && readChunk(rf, chunk, "GMOD", 4))
619
        {
620
            //if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
621

622
            if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
623
            if (result) groupModels.resize(count);
624
            //if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
625
            for (uint32 i=0; i<count && result; ++i)
626
                result = groupModels[i].readFromFile(rf);
627

628
            // read group BIH
629
            if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false;
630
            if (result) result = groupTree.readFromFile(rf);
631
        }
632

633
        fclose(rf);
634
        return result;
635
    }
636

637
    void WorldModel::getGroupModels(std::vector<GroupModel>& outGroupModels)
638
    {
639
        outGroupModels = groupModels;
640
    }
641

642
}
643

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

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

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

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