Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
598 строк · 17.8 Кб
1
/*
2
 * Copyright (C) 2011-2016 Project SkyFire <http://www.projectskyfire.org/>
3
 * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
4
 * Copyright (C) 2005-2016 MaNGOS <http://getmangos.com/>
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 3 of the License, or (at your
9
 * option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
 * more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with this program. If not, see <http://www.gnu.org/licenses/>.
18
 */
19

20
#include "vmapexport.h"
21
#include "adtfile.h"
22
#include "vec3d.h"
23

24
#include "VMapDefinitions.h"
25
#include "wmo.h"
26
#include <cstdio>
27
#include <cstdlib>
28
#include <cassert>
29
#include <map>
30
#include <fstream>
31
#include "Errors.h"
32
#include "mpqfile.h"
33
#undef min
34
#undef max
35

36
using namespace std;
37
extern uint16 *LiqType;
38

39
WMORoot::WMORoot(std::string const& filename)
40
    : filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0),
41
    nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), flags(0)
42
{
43
    memset(bbcorn1, 0, sizeof(bbcorn1));
44
    memset(bbcorn2, 0, sizeof(bbcorn2));
45
}
46

47
extern HANDLE WorldMpq;
48

49
bool WMORoot::open()
50
{
51
    MPQFile f(WorldMpq, filename.c_str());
52
    if(f.isEof ())
53
    {
54
        printf("No such file.\n");
55
        return false;
56
    }
57

58
    uint32 size;
59
    char fourcc[5];
60

61
    while (!f.isEof())
62
    {
63
        f.read(fourcc,4);
64
        f.read(&size, 4);
65

66
        flipcc(fourcc);
67
        fourcc[4] = 0;
68

69
        size_t nextpos = f.getPos() + size;
70

71
        if (!strcmp(fourcc,"MOHD")) // header
72
        {
73
            f.read(&nTextures, 4);
74
            f.read(&nGroups, 4);
75
            f.read(&nPortals, 4);
76
            f.read(&nLights, 4);
77
            f.read(&nDoodadNames, 4);
78
            f.read(&nDoodadDefs, 4);
79
            f.read(&nDoodadSets, 4);
80
            f.read(&color, 4);
81
            f.read(&RootWMOID, 4);
82
            f.read(bbcorn1, 12);
83
            f.read(bbcorn2, 12);
84
            f.read(&flags, 4);
85
        }
86
        else if (!strcmp(fourcc, "MODS"))
87
        {
88
            DoodadData.Sets.resize(size / sizeof(WMO::MODS));
89
            f.read(DoodadData.Sets.data(), size);
90
        } 
91
        else if (!strcmp(fourcc,"MODN"))
92
        {
93
            char* ptr = f.getPointer();
94
            char* end = ptr + size;
95
            DoodadData.Paths = std::make_unique<char[]>(size);
96
            memcpy(DoodadData.Paths.get(), ptr, size);
97
            while (ptr < end)
98
            {
99
                std::string path = ptr;
100

101
                char* s = GetPlainName(ptr);
102
                fixnamen(s, strlen(s));
103
                fixname2(s, strlen(s));
104

105
                uint32 doodadNameIndex = ptr - f.getPointer();
106
                ptr += path.length() + 1;
107

108
                if (ExtractSingleModel(path))
109
                    ValidDoodadNames.insert(doodadNameIndex);
110
            }
111
        } 
112
        else if (!strcmp(fourcc,"MODD"))
113
        {
114
            DoodadData.Spawns.resize(size / sizeof(WMO::MODD));
115
            f.read(DoodadData.Spawns.data(), size);
116
        }
117
        else if (!strcmp(fourcc, "MOGN"))
118
        {
119
            GroupNames.resize(size);
120
            f.read(GroupNames.data(), size);
121
        }                      
122
        /*
123
        else if (!strcmp(fourcc,"MOTX"))
124
        {
125
        }
126
        else if (!strcmp(fourcc,"MOMT"))
127
        {
128
        }
129
        else if (!strcmp(fourcc,"MOGI"))
130
        {
131
        }
132
        else if (!strcmp(fourcc,"MOLT"))
133
        {
134
        }
135
        else if (!strcmp(fourcc,"MOSB"))
136
        {
137
        }
138
        else if (!strcmp(fourcc,"MOPV"))
139
        {
140
        }
141
        else if (!strcmp(fourcc,"MOPT"))
142
        {
143
        }
144
        else if (!strcmp(fourcc,"MOPR"))
145
        {
146
        }
147
        else if (!strcmp(fourcc,"MFOG"))
148
        {
149
        }
150
        */
151
        f.seek((int)nextpos);
152
    }
153
    f.close ();
154
    return true;
155
}
156

157
bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile)
158
{
159
    //printf("Convert RootWmo...\n");
160

161
    fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, pOutfile);
162
    unsigned int nVectors = 0;
163
    fwrite(&nVectors, sizeof(nVectors), 1, pOutfile); // will be filled later
164
    fwrite(&nGroups, 4, 1, pOutfile);
165
    fwrite(&RootWMOID, 4, 1, pOutfile);
166
    return true;
167
}
168

169
WMOGroup::WMOGroup(const std::string &filename) :
170
    filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0),
171
    hlq(nullptr), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0),
172
    mopy_size(0), moba_size(0), LiquEx_size(0), nVertices(0), nTriangles(0), liquflags(0)
173
{
174
    memset(bbcorn1, 0, sizeof(bbcorn1));
175
    memset(bbcorn2, 0, sizeof(bbcorn2));
176
}
177

178
bool WMOGroup::open(WMORoot* rootWMO)
179
{
180
    MPQFile f(WorldMpq, filename.c_str());
181
    if(f.isEof ())
182
    {
183
        printf("No such file.\n");
184
        return false;
185
    }
186
    uint32 size;
187
    char fourcc[5];
188
    while (!f.isEof())
189
    {
190
        f.read(fourcc,4);
191
        f.read(&size, 4);
192
        flipcc(fourcc);
193
        if (!strcmp(fourcc,"MOGP"))//Fix sizeoff = Data size.
194
        {
195
            size = 68;
196
        }
197
        fourcc[4] = 0;
198
        size_t nextpos = f.getPos() + size;
199
        LiquEx_size = 0;
200
        liquflags = 0;
201

202
        if (!strcmp(fourcc,"MOGP"))//header
203
        {
204
            f.read(&groupName, 4);
205
            f.read(&descGroupName, 4);
206
            f.read(&mogpFlags, 4);
207
            f.read(bbcorn1, 12);
208
            f.read(bbcorn2, 12);
209
            f.read(&moprIdx, 2);
210
            f.read(&moprNItems, 2);
211
            f.read(&nBatchA, 2);
212
            f.read(&nBatchB, 2);
213
            f.read(&nBatchC, 4);
214
            f.read(&fogIdx, 4);
215
            f.read(&groupLiquid, 4);
216
            f.read(&groupWMOID,4);
217

218
            // according to WoW.Dev Wiki:
219
            if (rootWMO->flags & 4)
220
                groupLiquid = GetLiquidTypeId(groupLiquid);
221
            else if (groupLiquid == 15)
222
                groupLiquid = 0;
223
            else
224
                groupLiquid = GetLiquidTypeId(groupLiquid + 1);
225

226
            if (groupLiquid)
227
                liquflags |= 2;
228
        }
229
        else if (!strcmp(fourcc,"MOPY"))
230
        {
231
            MOPY = new char[size];
232
            mopy_size = size;
233
            nTriangles = (int)size / 2;
234
            f.read(MOPY, size);
235
        }
236
        else if (!strcmp(fourcc,"MOVI"))
237
        {
238
            MOVI = new uint16[size/2];
239
            f.read(MOVI, size);
240
        }
241
        else if (!strcmp(fourcc,"MOVT"))
242
        {
243
            MOVT = new float[size/4];
244
            f.read(MOVT, size);
245
            nVertices = (int)size / 12;
246
        }
247
        else if (!strcmp(fourcc, "MONR"))
248
        {
249
        }
250
        else if (!strcmp(fourcc, "MOTV"))
251
        {
252
        }
253
        else if (!strcmp(fourcc, "MOBA"))
254
        {
255
            MOBA = new uint16[size/2];
256
            moba_size = size/2;
257
            f.read(MOBA, size);
258
        }
259
        else if (!strcmp(fourcc, "MODR"))
260
        {
261
            DoodadReferences.resize(size / sizeof(uint16));
262
            f.read(DoodadReferences.data(), size);
263
        }        
264
        else if (!strcmp(fourcc, "MLIQ"))
265
        {
266
            liquflags |= 1;
267
            hlq = new WMOLiquidHeader();
268
            f.read(hlq, sizeof(WMOLiquidHeader));
269
            LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
270
            LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
271
            f.read(LiquEx, LiquEx_size);
272
            int nLiquBytes = hlq->xtiles * hlq->ytiles;
273
            LiquBytes = new char[nLiquBytes];
274
            f.read(LiquBytes, nLiquBytes);
275

276
            // Determine legacy liquid type
277
            if (!groupLiquid)
278
            {
279
                for (int i = 0; i < hlq->xtiles * hlq->ytiles; ++i)
280
                {
281
                    if ((LiquBytes[i] & 0xF) != 15)
282
                    {
283
                        groupLiquid = GetLiquidTypeId((LiquBytes[i] & 0xF) + 1);
284
                        break;
285
                    }
286
                }
287
            }
288

289
            /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
290
            llog << filename;
291
            llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
292
            llog << "\nlpos: " << hlq->pos_x << ", " << hlq->pos_y << ", " << hlq->pos_z;
293
            llog << "\nx-/yvert: " << hlq->xverts << "/" << hlq->yverts << " size: " << size << " expected size: " << 30 + hlq->xverts*hlq->yverts*8 + hlq->xtiles*hlq->ytiles << std::endl;
294
            llog.close(); */
295
        }
296
        f.seek((int)nextpos);
297
    }
298
    f.close();
299
    return true;
300
}
301

302
int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, bool preciseVectorData)
303
{
304
    fwrite(&mogpFlags,sizeof(uint32),1,output);
305
    fwrite(&groupWMOID,sizeof(uint32),1,output);
306
    // group bound
307
    fwrite(bbcorn1, sizeof(float), 3, output);
308
    fwrite(bbcorn2, sizeof(float), 3, output);
309
    fwrite(&liquflags,sizeof(uint32),1,output);
310
    int nColTriangles = 0;
311
    if (preciseVectorData)
312
    {
313
        char GRP[] = "GRP ";
314
        fwrite(GRP,1,4,output);
315

316
        int k = 0;
317
        int moba_batch = moba_size / 12;
318
        MobaEx = new int[moba_batch * 4];
319
        for (int i = 8; i < moba_size; i += 12)
320
        {
321
            MobaEx[k++] = MOBA[i];
322
        }
323
        int moba_size_grp = moba_batch * 4 + 4;
324
        fwrite(&moba_size_grp, 4, 1, output);
325
        fwrite(&moba_batch, 4, 1, output);
326
        fwrite(MobaEx, 4, k, output);
327
        delete[] MobaEx;
328

329
        uint32 nIdexes = nTriangles * 3;
330

331
        if (fwrite("INDX", 4, 1, output) != 1)
332
        {
333
            printf("Error while writing file nbraches ID");
334
            exit(0);
335
        }
336
        int wsize = sizeof(uint32) + sizeof(unsigned short) * nIdexes;
337
        if(fwrite(&wsize, sizeof(int), 1, output) != 1)
338
        {
339
            printf("Error while writing file wsize");
340
            // no need to exit?
341
        }
342
        if(fwrite(&nIdexes, sizeof(uint32), 1, output) != 1)
343
        {
344
            printf("Error while writing file nIndexes");
345
            exit(0);
346
        }
347
        if(nIdexes >0)
348
        {
349
            if(fwrite(MOVI, sizeof(unsigned short), nIdexes, output) != nIdexes)
350
            {
351
                printf("Error while writing file indexarray");
352
                exit(0);
353
            }
354
        }
355

356
        if (fwrite("VERT", 4, 1, output) != 1)
357
        {
358
            printf("Error while writing file nbraches ID");
359
            exit(0);
360
        }
361
        wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
362
        if(fwrite(&wsize, sizeof(int), 1, output) != 1)
363
        {
364
            printf("Error while writing file wsize");
365
            // no need to exit?
366
        }
367
        if(fwrite(&nVertices, sizeof(int), 1, output) != 1)
368
        {
369
            printf("Error while writing file nVertices");
370
            exit(0);
371
        }
372
        if(nVertices >0)
373
        {
374
            if(fwrite(MOVT, sizeof(float)*3, nVertices, output) != nVertices)
375
            {
376
                printf("Error while writing file vectors");
377
                exit(0);
378
            }
379
        }
380

381
        nColTriangles = nTriangles;
382
    }
383
    else
384
    {
385
        char GRP[] = "GRP ";
386
        fwrite(GRP, 1, 4, output);
387
        int k = 0;
388
        int moba_batch = moba_size / 12;
389
        MobaEx = new int[moba_batch * 4];
390
        for (int i = 8; i < moba_size; i += 12)
391
        {
392
            MobaEx[k++] = MOBA[i];
393
        }
394

395
        int moba_size_grp = moba_batch * 4 + 4;
396
        fwrite(&moba_size_grp, 4, 1, output);
397
        fwrite(&moba_batch, 4, 1, output);
398
        fwrite(MobaEx, 4, k, output);
399
        delete[] MobaEx;
400

401
        //-------INDX------------------------------------
402
        //-------MOPY--------
403
        MoviEx = new uint16[nTriangles*3]; // "worst case" size...
404
        int *IndexRenum = new int[nVertices];
405
        memset(IndexRenum, 0xFF, nVertices*sizeof(int));
406
        for (int i=0; i<nTriangles; ++i)
407
        {
408
            // Skip no collision triangles
409
            bool isRenderFace = (MOPY[2 * i] & WMO_MATERIAL_RENDER) && !(MOPY[2 * i] & WMO_MATERIAL_DETAIL);
410
            bool isCollision = MOPY[2 * i] & WMO_MATERIAL_COLLISION || isRenderFace;
411
            if (!isCollision)
412
                continue;
413
            
414
            // Use this triangle
415
            for (int j = 0; j < 3; ++j)
416
            {
417
                IndexRenum[MOVI[3 * i + j]] = 1;
418
                MoviEx[3 * nColTriangles + j] = MOVI[3 * i + j];
419
            }
420
            ++nColTriangles;
421
        }
422

423
        // assign new vertex index numbers
424
        int nColVertices = 0;
425
        for (uint32 i=0; i<nVertices; ++i)
426
        {
427
            if (IndexRenum[i] == 1)
428
            {
429
                IndexRenum[i] = nColVertices;
430
                ++nColVertices;
431
            }
432
        }
433

434
        // translate triangle indices to new numbers
435
        for (int i = 0; i < 3 * nColTriangles; ++i)
436
        {
437
            ASSERT(MoviEx[i] < nVertices);
438
            MoviEx[i] = IndexRenum[MoviEx[i]];
439
        }
440

441
        // write triangle indices
442
        int INDX[] = { 0x58444E49, nColTriangles * 6 + 4, nColTriangles * 3 };
443
        fwrite(INDX, 4, 3, output);
444
        fwrite(MoviEx, 2, nColTriangles * 3, output);
445

446
        // write vertices
447
        int VERT[] = { 0x54524556, nColVertices * 3 * static_cast<int>(sizeof(float)) + 4, nColVertices };// "VERT"
448
        int check = 3 * nColVertices;
449
        fwrite(VERT, 4, 3, output);
450
        for (uint32 i = 0; i < nVertices; ++i)
451
            if (IndexRenum[i] >= 0)
452
                check -= fwrite(MOVT + 3 * i, sizeof(float), 3, output);
453

454
        ASSERT(check == 0);
455

456
        delete [] MoviEx;
457
        delete [] IndexRenum;
458
    }
459

460
    //------LIQU------------------------
461
    if (liquflags & 3)
462
    {
463
        int LIQU_totalSize = sizeof(uint32);
464
        if (liquflags & 1)
465
        {
466
            LIQU_totalSize += sizeof(WMOLiquidHeader);
467
            LIQU_totalSize += LiquEx_size / sizeof(WMOLiquidVert) * sizeof(float);
468
            LIQU_totalSize += hlq->xtiles * hlq->ytiles;
469
        }
470
        int LIQU_h[] = { 0x5551494C, LIQU_totalSize };// "LIQU"
471
        fwrite(LIQU_h, 4, 2, output);
472

473
        /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
474
        llog << filename;
475
        llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n";
476
        llog.close(); */
477

478
        fwrite(&groupLiquid, sizeof(uint32), 1, output);
479
        if (liquflags & 1)
480
        {
481
            fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
482
            // only need height values, the other values are unknown anyway
483
            for (uint32 i = 0; i < LiquEx_size / sizeof(WMOLiquidVert); ++i)
484
                fwrite(&LiquEx[i].height, sizeof(float), 1, output);
485
            // todo: compress to bit field
486
            fwrite(LiquBytes, 1, hlq->xtiles * hlq->ytiles, output);
487
        }
488
    }
489

490
    return nColTriangles;
491
}
492

493
uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId)
494
{
495
    if (liquidTypeId < 21 && liquidTypeId)
496
    {
497
        switch (((static_cast<uint8>(liquidTypeId) - 1) & 3))
498
        {
499
            case 0: return ((mogpFlags & 0x80000) != 0) + 13;
500
            case 1: return 14;
501
            case 2: return 19;
502
            case 3: return 20;
503
            default: break;
504
        }
505
    }
506
    return liquidTypeId;
507
}
508

509
bool WMOGroup::ShouldSkip(WMORoot const* root) const
510
{
511
    // skip unreachable
512
    if (mogpFlags & 0x80)
513
        return true;
514

515
    // skip antiportals
516
    if (mogpFlags & 0x4000000)
517
        return true;
518

519
    if (groupName < int32(root->GroupNames.size()) && !strcmp(&root->GroupNames[groupName], "antiportal"))
520
        return true;
521

522
    return false;
523
}
524

525
WMOGroup::~WMOGroup()
526
{
527
    delete [] MOPY;
528
    delete [] MOVI;
529
    delete [] MOVT;
530
    delete [] MOBA;
531
    delete hlq;
532
    delete [] LiquEx;
533
    delete [] LiquBytes;
534
}
535

536
void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
537
{
538
    // destructible wmo, do not dump. we can handle the vmap for these
539
    // in dynamic tree (gameobject vmaps)
540
    if ((mapObjDef.Flags & 0x1) != 0)
541
        return;
542

543
    //-----------add_in _dir_file----------------
544

545
    char tempname[512];
546
    sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName);
547
    FILE *input;
548
    input = fopen(tempname, "r+b");
549

550
    if (!input)
551
    {
552
        printf("WMOInstance::WMOInstance: couldn't open %s\n", tempname);
553
        return;
554
    }
555

556
    fseek(input, 8, SEEK_SET); // get the correct no of vertices
557
    int nVertices;
558
    int count = fread(&nVertices, sizeof(int), 1, input);
559
    fclose(input);
560

561
    if (count != 1 || nVertices == 0)
562
        return;
563

564
    Vec3D position = mapObjDef.Position;
565

566
    float x, z;
567
    x = position.x;
568
    z = position.z;
569
    if (x == 0 && z == 0)
570
    {
571
        position.x = 533.33333f * 32;
572
        position.z = 533.33333f * 32;
573
    }
574
    position = fixCoords(position);
575
    AaBox3D bounds;
576
    bounds.min = fixCoords(mapObjDef.Bounds.min);
577
    bounds.max = fixCoords(mapObjDef.Bounds.max);
578

579
    float scale = 1.0f;
580
    uint32 uniqueId = GenerateUniqueObjectId(mapObjDef.UniqueId, 0);
581
    uint32 flags = MOD_HAS_BOUND;
582
    if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN;
583
    //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
584
    fwrite(&mapID, sizeof(uint32), 1, pDirfile);
585
    fwrite(&tileX, sizeof(uint32), 1, pDirfile);
586
    fwrite(&tileY, sizeof(uint32), 1, pDirfile);
587
    fwrite(&flags, sizeof(uint32), 1, pDirfile);
588
    fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile);
589
    fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
590
    fwrite(&position, sizeof(Vec3D), 1, pDirfile);
591
    fwrite(&mapObjDef.Rotation, sizeof(Vec3D), 1, pDirfile);
592
    fwrite(&scale, sizeof(float), 1, pDirfile);
593
    fwrite(&bounds, sizeof(AaBox3D), 1, pDirfile);
594
    uint32 nlen = strlen(WmoInstName);
595
    fwrite(&nlen, sizeof(uint32), 1, pDirfile);
596
    fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
597

598
}

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

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

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

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