Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
wmo.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "vmapexport.h"
7#include "wmo.h"
8#include "vec3d.h"
9#include <cstdio>
10#include <cstdlib>
11#include <cassert>
12#include <map>
13#include <fstream>
14#undef min
15#undef max
16#include "mpqfile.h"
17
18using namespace std;
19extern uint16 *LiqType;
20
22 : filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0),
24{
25 memset(bbcorn1, 0, sizeof(bbcorn1));
26 memset(bbcorn2, 0, sizeof(bbcorn2));
27}
28
29extern HANDLE WorldMpq;
30
32{
33 MPQFile f(WorldMpq, filename.c_str());
34 if(f.isEof ())
35 {
36 printf("No such file.\n");
37 return false;
38 }
39
40 uint32 size;
41 char fourcc[5];
42
43 while (!f.isEof())
44 {
45 f.read(fourcc,4);
46 f.read(&size, 4);
47
48 flipcc(fourcc);
49 fourcc[4] = 0;
50
51 size_t nextpos = f.getPos() + size;
52
53 if (!strcmp(fourcc,"MOHD")) // header
54 {
55 f.read(&nTextures, 4);
56 f.read(&nGroups, 4);
57 f.read(&nP, 4);
58 f.read(&nLights, 4);
59 f.read(&nModels, 4);
60 f.read(&nDoodads, 4);
61 f.read(&nDoodadSets, 4);
62 f.read(&col, 4);
63 f.read(&RootWMOID, 4);
64 f.read(bbcorn1, 12);
65 f.read(bbcorn2, 12);
66 f.read(&liquidType, 4);
67 break;
68 }
69 /*
70 else if (!strcmp(fourcc,"MOTX"))
71 {
72 }
73 else if (!strcmp(fourcc,"MOMT"))
74 {
75 }
76 else if (!strcmp(fourcc,"MOGN"))
77 {
78 }
79 else if (!strcmp(fourcc,"MOGI"))
80 {
81 }
82 else if (!strcmp(fourcc,"MOLT"))
83 {
84 }
85 else if (!strcmp(fourcc,"MODN"))
86 {
87 }
88 else if (!strcmp(fourcc,"MODS"))
89 {
90 }
91 else if (!strcmp(fourcc,"MODD"))
92 {
93 }
94 else if (!strcmp(fourcc,"MOSB"))
95 {
96 }
97 else if (!strcmp(fourcc,"MOPV"))
98 {
99 }
100 else if (!strcmp(fourcc,"MOPT"))
101 {
102 }
103 else if (!strcmp(fourcc,"MOPR"))
104 {
105 }
106 else if (!strcmp(fourcc,"MFOG"))
107 {
108 }
109 */
110 f.seek((int)nextpos);
111 }
112 f.close ();
113 return true;
114}
115
117{
118 //printf("Convert RootWmo...\n");
119
120 fwrite(szRawVMAPMagic, 1, 8, pOutfile);
121 unsigned int nVectors = 0;
122 fwrite(&nVectors,sizeof(nVectors), 1, pOutfile); // will be filled later
123 fwrite(&nGroups, 4, 1, pOutfile);
124 fwrite(&RootWMOID, 4, 1, pOutfile);
125 return true;
126}
127
131
132WMOGroup::WMOGroup(const std::string &filename) :
133 filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0),
134 hlq(0), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0),
135 moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
138{
139 memset(bbcorn1, 0, sizeof(bbcorn1));
140 memset(bbcorn2, 0, sizeof(bbcorn2));
141}
142
144{
145 MPQFile f(WorldMpq, filename.c_str());
146 if(f.isEof ())
147 {
148 printf("No such file.\n");
149 return false;
150 }
151 uint32 size;
152 char fourcc[5];
153 while (!f.isEof())
154 {
155 f.read(fourcc,4);
156 f.read(&size, 4);
157 flipcc(fourcc);
158 if (!strcmp(fourcc,"MOGP"))//Fix sizeoff = Data size.
159 {
160 size = 68;
161 }
162 fourcc[4] = 0;
163 size_t nextpos = f.getPos() + size;
164 LiquEx_size = 0;
165 liquflags = 0;
166
167 if (!strcmp(fourcc,"MOGP"))//header
168 {
169 f.read(&groupName, 4);
170 f.read(&descGroupName, 4);
171 f.read(&mogpFlags, 4);
172 f.read(bbcorn1, 12);
173 f.read(bbcorn2, 12);
174 f.read(&moprIdx, 2);
175 f.read(&moprNItems, 2);
176 f.read(&nBatchA, 2);
177 f.read(&nBatchB, 2);
178 f.read(&nBatchC, 4);
179 f.read(&fogIdx, 4);
180 f.read(&liquidType, 4);
181 f.read(&groupWMOID,4);
182 }
183 else if (!strcmp(fourcc,"MOPY"))
184 {
185 MOPY = new char[size];
186 mopy_size = size;
187 nTriangles = (int)size / 2;
188 f.read(MOPY, size);
189 }
190 else if (!strcmp(fourcc,"MOVI"))
191 {
192 MOVI = new uint16[size/2];
193 f.read(MOVI, size);
194 }
195 else if (!strcmp(fourcc,"MOVT"))
196 {
197 MOVT = new float[size/4];
198 f.read(MOVT, size);
199 nVertices = (int)size / 12;
200 }
201 else if (!strcmp(fourcc,"MONR"))
202 {
203 }
204 else if (!strcmp(fourcc,"MOTV"))
205 {
206 }
207 else if (!strcmp(fourcc,"MOBA"))
208 {
209 MOBA = new uint16[size/2];
210 moba_size = size/2;
211 f.read(MOBA, size);
212 }
213 else if (!strcmp(fourcc,"MLIQ"))
214 {
215 liquflags |= 1;
216 hlq = new WMOLiquidHeader;
217 f.read(hlq, 0x1E);
218 LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
219 LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
221 int nLiquBytes = hlq->xtiles * hlq->ytiles;
222 LiquBytes = new char[nLiquBytes];
223 f.read(LiquBytes, nLiquBytes);
224
225 /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
226 llog << filename;
227 llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
228 llog << "\nlpos: " << hlq->pos_x << ", " << hlq->pos_y << ", " << hlq->pos_z;
229 llog << "\nx-/yvert: " << hlq->xverts << "/" << hlq->yverts << " size: " << size << " expected size: " << 30 + hlq->xverts*hlq->yverts*8 + hlq->xtiles*hlq->ytiles << std::endl;
230 llog.close(); */
231 }
232 f.seek((int)nextpos);
233 }
234 f.close();
235 return true;
236}
237
239{
240 fwrite(&mogpFlags,sizeof(uint32),1,output);
241 fwrite(&groupWMOID,sizeof(uint32),1,output);
242 // group bound
243 fwrite(bbcorn1, sizeof(float), 3, output);
244 fwrite(bbcorn2, sizeof(float), 3, output);
245 fwrite(&liquflags,sizeof(uint32),1,output);
246 int nColTriangles = 0;
248 {
249 char GRP[] = "GRP ";
250 fwrite(GRP,1,4,output);
251
252 int k = 0;
253 int moba_batch = moba_size/12;
254 MobaEx = new int[moba_batch*4];
255 for(int i=8; i<moba_size; i+=12)
256 {
257 MobaEx[k++] = MOBA[i];
258 }
259 int moba_size_grp = moba_batch*4+4;
260 fwrite(&moba_size_grp,4,1,output);
261 fwrite(&moba_batch,4,1,output);
262 fwrite(MobaEx,4,k,output);
263 delete [] MobaEx;
264
265 uint32 nIdexes = nTriangles * 3;
266
267 if(fwrite("INDX",4, 1, output) != 1)
268 {
269 printf("Error while writing file nbraches ID");
270 exit(0);
271 }
272 int wsize = sizeof(uint32) + sizeof(unsigned short) * nIdexes;
273 if(fwrite(&wsize, sizeof(int), 1, output) != 1)
274 {
275 printf("Error while writing file wsize");
276 // no need to exit?
277 }
278 if(fwrite(&nIdexes, sizeof(uint32), 1, output) != 1)
279 {
280 printf("Error while writing file nIndexes");
281 exit(0);
282 }
283 if(nIdexes >0)
284 {
285 if(fwrite(MOVI, sizeof(unsigned short), nIdexes, output) != nIdexes)
286 {
287 printf("Error while writing file indexarray");
288 exit(0);
289 }
290 }
291
292 if(fwrite("VERT",4, 1, output) != 1)
293 {
294 printf("Error while writing file nbraches ID");
295 exit(0);
296 }
297 wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
298 if(fwrite(&wsize, sizeof(int), 1, output) != 1)
299 {
300 printf("Error while writing file wsize");
301 // no need to exit?
302 }
303 if(fwrite(&nVertices, sizeof(int), 1, output) != 1)
304 {
305 printf("Error while writing file nVertices");
306 exit(0);
307 }
308 if(nVertices >0)
309 {
310 if(fwrite(MOVT, sizeof(float)*3, nVertices, output) != nVertices)
311 {
312 printf("Error while writing file vectors");
313 exit(0);
314 }
315 }
316
317 nColTriangles = nTriangles;
318 }
319 else
320 {
321 char GRP[] = "GRP ";
322 fwrite(GRP,1,4,output);
323 int k = 0;
324 int moba_batch = moba_size/12;
325 MobaEx = new int[moba_batch*4];
326 for(int i=8; i<moba_size; i+=12)
327 {
328 MobaEx[k++] = MOBA[i];
329 }
330
331 int moba_size_grp = moba_batch*4+4;
332 fwrite(&moba_size_grp,4,1,output);
333 fwrite(&moba_batch,4,1,output);
334 fwrite(MobaEx,4,k,output);
335 delete [] MobaEx;
336
337 //-------INDX------------------------------------
338 //-------MOPY--------
339 MoviEx = new uint16[nTriangles*3]; // "worst case" size...
340 int *IndexRenum = new int[nVertices];
341 memset(IndexRenum, 0xFF, nVertices*sizeof(int));
342 for (int i=0; i<nTriangles; ++i)
343 {
344 // Skip no collision triangles
347 continue;
348 // Use this triangle
349 for (int j=0; j<3; ++j)
350 {
351 IndexRenum[MOVI[3*i + j]] = 1;
352 MoviEx[3*nColTriangles + j] = MOVI[3*i + j];
353 }
354 ++nColTriangles;
355 }
356
357 // assign new vertex index numbers
358 int nColVertices = 0;
359 for (uint32 i=0; i<nVertices; ++i)
360 {
361 if (IndexRenum[i] == 1)
362 {
363 IndexRenum[i] = nColVertices;
364 ++nColVertices;
365 }
366 }
367
368 // translate triangle indices to new numbers
369 for (int i=0; i<3*nColTriangles; ++i)
370 {
371 assert(MoviEx[i] < nVertices);
372 MoviEx[i] = IndexRenum[MoviEx[i]];
373 }
374
375 // write triangle indices
376 int INDX[] = {0x58444E49, nColTriangles*6+4, nColTriangles*3};
377 fwrite(INDX,4,3,output);
378 fwrite(MoviEx,2,nColTriangles*3,output);
379
380 // write vertices
381 int VERT[] = {0x54524556, nColVertices*3*static_cast<int>(sizeof(float))+4, nColVertices};// "VERT"
382 int check = 3*nColVertices;
383 fwrite(VERT,4,3,output);
384 for (uint32 i=0; i<nVertices; ++i)
385 if(IndexRenum[i] >= 0)
386 check -= fwrite(MOVT+3*i, sizeof(float), 3, output);
387
388 assert(check==0);
389
390 delete [] MoviEx;
391 delete [] IndexRenum;
392 }
393
394 //------LIQU------------------------
395 if(LiquEx_size != 0)
396 {
397 int LIQU_h[] = {0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader)+LiquEx_size)+hlq->xtiles*hlq->ytiles};// "LIQU"
398 fwrite(LIQU_h, 4, 2, output);
399
400 // according to WoW.Dev Wiki:
401 uint32 liquidEntry;
402 if (rootWMO->liquidType & 4)
403 liquidEntry = liquidType;
404 else if (liquidType == 15)
405 liquidEntry = 0;
406 else
407 liquidEntry = liquidType + 1;
408
409 if (!liquidEntry)
410 {
411 int v1; // edx@1
412 int v2; // eax@1
413
414 v1 = hlq->xtiles * hlq->ytiles;
415 v2 = 0;
416 if (v1 > 0)
417 {
418 while ((LiquBytes[v2] & 0xF) == 15)
419 {
420 ++v2;
421 if (v2 >= v1)
422 break;
423 }
424
425 if (v2 < v1 && (LiquBytes[v2] & 0xF) != 15)
426 liquidEntry = (LiquBytes[v2] & 0xF) + 1;
427 }
428 }
429
430 if (liquidEntry && liquidEntry < 21)
431 {
432 switch (((uint8)liquidEntry - 1) & 3)
433 {
434 case 0:
435 liquidEntry = ((mogpFlags & 0x80000) != 0) + 13;
436 break;
437 case 1:
438 liquidEntry = 14;
439 break;
440 case 2:
441 liquidEntry = 19;
442 break;
443 case 3:
444 liquidEntry = 20;
445 break;
446 default:
447 break;
448 }
449 }
450
451 hlq->type = liquidEntry;
452
453 /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
454 llog << filename;
455 llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n";
456 llog.close(); */
457
458 fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
459 // only need height values, the other values are unknown anyway
460 for (uint32 i = 0; i<LiquEx_size/sizeof(WMOLiquidVert); ++i)
461 fwrite(&LiquEx[i].height, sizeof(float), 1, output);
462 // todo: compress to bit field
463 fwrite(LiquBytes, 1, hlq->xtiles*hlq->ytiles, output);
464 }
465
466 return nColTriangles;
467}
468
470{
471 delete [] MOPY;
472 delete [] MOVI;
473 delete [] MOVT;
474 delete [] MOBA;
475 delete hlq;
476 delete [] LiquEx;
477 delete [] LiquBytes;
478}
479
480WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
481 : currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), d3(0)
482{
483 float ff[3];
484 f.read(&id, 4);
485 f.read(ff,12);
486 pos = Vec3D(ff[0],ff[1],ff[2]);
487 f.read(ff,12);
488 rot = Vec3D(ff[0],ff[1],ff[2]);
489 f.read(ff,12);
490 pos2 = Vec3D(ff[0],ff[1],ff[2]);
491 f.read(ff,12);
492 pos3 = Vec3D(ff[0],ff[1],ff[2]);
493 f.read(&d2,4);
494
495 uint16 trash,adtId;
496 f.read(&adtId,2);
497 f.read(&trash,2);
498
499 //-----------add_in _dir_file----------------
500
501 char tempname[512];
502 snprintf(tempname, sizeof(tempname), "%s/%s", szWorkDirWmo, WmoInstName);
503 FILE *input;
504 input = fopen(tempname, "r+b");
505
506 if(!input)
507 {
508 printf("WMOInstance::WMOInstance: couldn't open %s\n", tempname);
509 return;
510 }
511
512 fseek(input, 8, SEEK_SET); // get the correct no of vertices
513 int nVertices;
514 int count = fread(&nVertices, sizeof (int), 1, input);
515 fclose(input);
516
517 if (count != 1 || nVertices == 0)
518 return;
519
520 float x,z;
521 x = pos.x;
522 z = pos.z;
523 if(x==0 && z == 0)
524 {
525 pos.x = 533.33333f*32;
526 pos.z = 533.33333f*32;
527 }
528 pos = fixCoords(pos);
531
532 float scale = 1.0f;
533 uint32 flags = MOD_HAS_BOUND;
534 if(tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN;
535 //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
536 fwrite(&mapID, sizeof(uint32), 1, pDirfile);
537 fwrite(&tileX, sizeof(uint32), 1, pDirfile);
538 fwrite(&tileY, sizeof(uint32), 1, pDirfile);
539 fwrite(&flags, sizeof(uint32), 1, pDirfile);
540 fwrite(&adtId, sizeof(uint16), 1, pDirfile);
541 fwrite(&id, sizeof(uint32), 1, pDirfile);
542 fwrite(&pos, sizeof(float), 3, pDirfile);
543 fwrite(&rot, sizeof(float), 3, pDirfile);
544 fwrite(&scale, sizeof(float), 1, pDirfile);
545 fwrite(&pos2, sizeof(float), 3, pDirfile);
546 fwrite(&pos3, sizeof(float), 3, pDirfile);
547 uint32 nlen=strlen(WmoInstName);
548 fwrite(&nlen, sizeof(uint32), 1, pDirfile);
549 fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
550
551 /* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n",
552 MapName,
553 WmoInstName,
554 (float) x, (float) pos.y, (float) z,
555 (float) rot.x, (float) rot.y, (float) rot.z,
556 nVertices,
557 realx1, realy1,
558 realx2, realy2
559 ); */
560
561 // fclose(dirfile);
562}
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint16_t uint16
Definition Define.h:78
HANDLE WorldMpq
Definition System.cpp:49
uint16 * LiqType
Definition System.cpp:60
size_t read(void *dest, size_t bytes)
Definition mpqfile.cpp:58
bool isEof()
Definition mpqfile.h:69
void close()
Definition mpqfile.cpp:87
size_t getPos()
Definition mpqfile.h:66
void seek(int offset)
Definition mpqfile.cpp:75
Definition vec3d.h:13
uint32 nBatchC
Definition wmo.h:89
float * MOVT
Definition wmo.h:75
int moba_size
Definition wmo.h:91
WMOGroup(std::string const &filename)
Definition wmo.cpp:132
uint32 liquidType
Definition wmo.h:89
uint16 * MOVI
Definition wmo.h:73
uint16 nBatchA
Definition wmo.h:87
uint32 fogIdx
Definition wmo.h:89
uint16 moprIdx
Definition wmo.h:85
std::string filename
Definition wmo.h:68
int groupName
Definition wmo.h:81
int descGroupName
Definition wmo.h:81
int LiquEx_size
Definition wmo.h:92
uint32 groupWMOID
Definition wmo.h:89
uint16 nBatchB
Definition wmo.h:88
float bbcorn2[3]
Definition wmo.h:84
int mogpFlags
Definition wmo.h:82
int ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool preciseVectorData)
Definition wmo.cpp:238
unsigned int nVertices
Definition wmo.h:93
WMOLiquidVert * LiquEx
Definition wmo.h:79
uint16 * MOBA
Definition wmo.h:76
uint32 liquflags
Definition wmo.h:95
char * MOPY
Definition wmo.h:72
int nTriangles
Definition wmo.h:94
bool open()
Definition wmo.cpp:143
char * LiquBytes
Definition wmo.h:80
int mopy_size
Definition wmo.h:91
~WMOGroup()
Definition wmo.cpp:469
int * MobaEx
Definition wmo.h:77
WMOLiquidHeader * hlq
Definition wmo.h:78
uint16 * MoviEx
Definition wmo.h:74
uint16 moprNItems
Definition wmo.h:86
float bbcorn1[3]
Definition wmo.h:83
uint32 d2
Definition wmo.h:115
Vec3D rot
Definition wmo.h:114
uint32 indx
Definition wmo.h:115
int doodadset
Definition wmo.h:112
Vec3D pos
Definition wmo.h:113
WMOGroup * wmo
Definition wmo.h:111
int curry
Definition wmo.h:110
Vec3D pos3
Definition wmo.h:114
uint32 d3
Definition wmo.h:115
Vec3D pos2
Definition wmo.h:114
WMOInstance(MPQFile &f, char const *WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile)
Definition wmo.cpp:480
int currx
Definition wmo.h:109
Definition wmo.h:33
uint32 liquidType
Definition wmo.h:38
float bbcorn1[3]
Definition wmo.h:39
uint32 nDoodadSets
Definition wmo.h:38
uint32 nLights
Definition wmo.h:38
uint32 nModels
Definition wmo.h:38
bool open()
Definition wmo.cpp:31
uint32 nDoodads
Definition wmo.h:38
~WMORoot()
Definition wmo.cpp:128
float bbcorn2[3]
Definition wmo.h:40
unsigned int col
Definition wmo.h:37
uint32 nGroups
Definition wmo.h:38
std::string filename
Definition wmo.h:35
bool ConvertToVMAPRootWmo(FILE *output)
Definition wmo.cpp:116
uint32 nP
Definition wmo.h:38
uint32 nTextures
Definition wmo.h:38
uint32 RootWMOID
Definition wmo.h:38
WMORoot(std::string &filename)
Definition wmo.cpp:21
void flipcc(char *fcc)
Definition mpqfile.h:75
bool preciseVectorData
const char * szWorkDirWmo
const char * szRawVMAPMagic
@ MOD_WORLDSPAWN
Definition vmapexport.h:14
@ MOD_HAS_BOUND
Definition vmapexport.h:15
#define WMO_MATERIAL_HINT
Definition wmo.h:20
#define WMO_MATERIAL_COLLIDE_HIT
Definition wmo.h:22
static Vec3D fixCoords(const Vec3D &v)
Definition wmo.h:30
#define WMO_MATERIAL_NO_COLLISION
Definition wmo.h:19