AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
WMOGroup Class Reference

#include "wmo.h"

Public Member Functions

 WMOGroup (std::string const &filename)
 
 ~WMOGroup ()
 
bool open (WMORoot *rootWMO)
 
int ConvertToVMAPGroupWmo (FILE *output, bool preciseVectorData)
 
uint32 GetLiquidTypeId (uint32 liquidTypeId)
 

Public Attributes

char * MOPY
 
uint16MOVI
 
uint16MoviEx
 
float * MOVT
 
uint16MOBA
 
int * MobaEx
 
WMOLiquidHeaderhlq
 
WMOLiquidVertLiquEx
 
char * LiquBytes
 
int groupName
 
int descGroupName
 
int mogpFlags
 
float bbcorn1 [3]
 
float bbcorn2 [3]
 
uint16 moprIdx
 
uint16 moprNItems
 
uint16 nBatchA
 
uint16 nBatchB
 
uint32 nBatchC
 
uint32 fogIdx
 
uint32 groupLiquid
 
uint32 groupWMOID
 
int mopy_size
 
int moba_size
 
int LiquEx_size
 
unsigned int nVertices
 
int nTriangles
 
uint32 liquflags
 
std::vector< uint16DoodadReferences
 

Private Attributes

std::string filename
 

Detailed Description

Constructor & Destructor Documentation

◆ WMOGroup()

WMOGroup::WMOGroup ( std::string const &  filename)
156 :
157 filename(std::move(filename)), MOPY(nullptr), MOVI(nullptr), MoviEx(nullptr), MOVT(nullptr), MOBA(nullptr), MobaEx(nullptr),
158 hlq(nullptr), LiquEx(nullptr), LiquBytes(nullptr), groupName(0), descGroupName(0), mogpFlags(0),
159 moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
162{
163 memset(bbcorn1, 0, sizeof(bbcorn1));
164 memset(bbcorn2, 0, sizeof(bbcorn2));
165}
uint32 nBatchC
Definition: wmo.h:141
float * MOVT
Definition: wmo.h:127
int moba_size
Definition: wmo.h:143
uint16 * MOVI
Definition: wmo.h:125
uint16 nBatchA
Definition: wmo.h:139
uint32 fogIdx
Definition: wmo.h:141
uint32 groupLiquid
Definition: wmo.h:141
uint16 moprIdx
Definition: wmo.h:137
std::string filename
Definition: wmo.h:120
int groupName
Definition: wmo.h:133
int descGroupName
Definition: wmo.h:133
int LiquEx_size
Definition: wmo.h:144
uint32 groupWMOID
Definition: wmo.h:141
uint16 nBatchB
Definition: wmo.h:140
float bbcorn2[3]
Definition: wmo.h:136
int mogpFlags
Definition: wmo.h:134
unsigned int nVertices
Definition: wmo.h:145
WMOLiquidVert * LiquEx
Definition: wmo.h:131
uint16 * MOBA
Definition: wmo.h:128
uint32 liquflags
Definition: wmo.h:147
char * MOPY
Definition: wmo.h:124
int nTriangles
Definition: wmo.h:146
char * LiquBytes
Definition: wmo.h:132
int mopy_size
Definition: wmo.h:143
int * MobaEx
Definition: wmo.h:129
WMOLiquidHeader * hlq
Definition: wmo.h:130
uint16 * MoviEx
Definition: wmo.h:126
uint16 moprNItems
Definition: wmo.h:138
float bbcorn1[3]
Definition: wmo.h:135

References bbcorn1, and bbcorn2.

◆ ~WMOGroup()

WMOGroup::~WMOGroup ( )
501{
502 delete [] MOPY;
503 delete [] MOVI;
504 delete [] MOVT;
505 delete [] MOBA;
506 delete hlq;
507 delete [] LiquEx;
508 delete [] LiquBytes;
509}

References hlq, LiquBytes, LiquEx, MOBA, MOPY, MOVI, and MOVT.

Member Function Documentation

◆ ConvertToVMAPGroupWmo()

int WMOGroup::ConvertToVMAPGroupWmo ( FILE *  output,
bool  preciseVectorData 
)
Todo:
: compress to bit field
292{
293 fwrite(&mogpFlags, sizeof(uint32), 1, output);
294 fwrite(&groupWMOID, sizeof(uint32), 1, output);
295 // group bound
296 fwrite(bbcorn1, sizeof(float), 3, output);
297 fwrite(bbcorn2, sizeof(float), 3, output);
298 fwrite(&liquflags, sizeof(uint32), 1, output);
299 int nColTriangles = 0;
301 {
302 char GRP[] = "GRP ";
303 fwrite(GRP, 1, 4, output);
304
305 int k = 0;
306 int moba_batch = moba_size / 12;
307 MobaEx = new int[moba_batch * 4];
308 for (int i = 8; i < moba_size; i += 12)
309 {
310 MobaEx[k++] = MOBA[i];
311 }
312 int moba_size_grp = moba_batch * 4 + 4;
313 fwrite(&moba_size_grp, 4, 1, output);
314 fwrite(&moba_batch, 4, 1, output);
315 fwrite(MobaEx, 4, k, output);
316 delete [] MobaEx;
317
318 uint32 nIdexes = nTriangles * 3;
319
320 if (fwrite("INDX", 4, 1, output) != 1)
321 {
322 printf("Error while writing file nbraches ID");
323 exit(0);
324 }
325 int wsize = sizeof(uint32) + sizeof(unsigned short) * nIdexes;
326 if (fwrite(&wsize, sizeof(int), 1, output) != 1)
327 {
328 printf("Error while writing file wsize");
329 // no need to exit?
330 }
331 if (fwrite(&nIdexes, sizeof(uint32), 1, output) != 1)
332 {
333 printf("Error while writing file nIndexes");
334 exit(0);
335 }
336 if (nIdexes > 0)
337 {
338 if (fwrite(MOVI, sizeof(unsigned short), nIdexes, output) != nIdexes)
339 {
340 printf("Error while writing file indexarray");
341 exit(0);
342 }
343 }
344
345 if (fwrite("VERT", 4, 1, output) != 1)
346 {
347 printf("Error while writing file nbraches ID");
348 exit(0);
349 }
350 wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
351 if (fwrite(&wsize, sizeof(int), 1, output) != 1)
352 {
353 printf("Error while writing file wsize");
354 // no need to exit?
355 }
356 if (fwrite(&nVertices, sizeof(int), 1, output) != 1)
357 {
358 printf("Error while writing file nVertices");
359 exit(0);
360 }
361 if (nVertices > 0)
362 {
363 if (fwrite(MOVT, sizeof(float) * 3, nVertices, output) != nVertices)
364 {
365 printf("Error while writing file vectors");
366 exit(0);
367 }
368 }
369
370 nColTriangles = nTriangles;
371 }
372 else
373 {
374 char GRP[] = "GRP ";
375 fwrite(GRP, 1, 4, output);
376 int k = 0;
377 int moba_batch = moba_size / 12;
378 MobaEx = new int[moba_batch * 4];
379 for (int i = 8; i < moba_size; i += 12)
380 {
381 MobaEx[k++] = MOBA[i];
382 }
383
384 int moba_size_grp = moba_batch * 4 + 4;
385 fwrite(&moba_size_grp, 4, 1, output);
386 fwrite(&moba_batch, 4, 1, output);
387 fwrite(MobaEx, 4, k, output);
388 delete [] MobaEx;
389
390 //-------INDX------------------------------------
391 //-------MOPY--------
392 MoviEx = new uint16[nTriangles * 3]; // "worst case" size...
393 int* IndexRenum = new int[nVertices];
394 memset(IndexRenum, 0xFF, nVertices * sizeof(int));
395 for (int i = 0; i < nTriangles; ++i)
396 {
397 // Skip no collision triangles
398 // TODO: Update to use MOBR in the future to catch any possibly missed edge cases
399 bool isRenderFace = (MOPY[2 * i] & WMO_MATERIAL_RENDER) && !(MOPY[2 * i] & WMO_MATERIAL_DETAIL);
400 bool isCollisionOnlyFace = static_cast<unsigned char>(MOPY[(2 * i) + 1]) == 0xFF; // 255 is a collision-only material id
401 bool isCollision = MOPY[2 * i] & WMO_MATERIAL_COLLISION || isRenderFace || isCollisionOnlyFace;
402 if (!isCollision)
403 continue;
404 // Use this triangle
405 for (int j = 0; j < 3; ++j)
406 {
407 IndexRenum[MOVI[3 * i + j]] = 1;
408 MoviEx[3 * nColTriangles + j] = MOVI[3 * i + j];
409 }
410 ++nColTriangles;
411 }
412
413 // assign new vertex index numbers
414 int nColVertices = 0;
415 for (uint32 i = 0; i < nVertices; ++i)
416 {
417 if (IndexRenum[i] == 1)
418 {
419 IndexRenum[i] = nColVertices;
420 ++nColVertices;
421 }
422 }
423
424 // translate triangle indices to new numbers
425 for (int i = 0; i < 3 * nColTriangles; ++i)
426 {
427 assert(MoviEx[i] < nVertices);
428 MoviEx[i] = IndexRenum[MoviEx[i]];
429 }
430
431 // write triangle indices
432 int INDX[] = {0x58444E49, nColTriangles * 6 + 4, nColTriangles * 3};
433 fwrite(INDX, 4, 3, output);
434 fwrite(MoviEx, 2, nColTriangles * 3, output);
435
436 // write vertices
437 int VERT[] = {0x54524556, nColVertices * 3 * static_cast<int>(sizeof(float)) + 4, nColVertices}; // "VERT"
438 int check = 3 * nColVertices;
439 fwrite(VERT, 4, 3, output);
440 for (uint32 i = 0; i < nVertices; ++i)
441 if (IndexRenum[i] >= 0)
442 check -= fwrite(MOVT + 3 * i, sizeof(float), 3, output);
443
444 assert(check == 0);
445
446 delete [] MoviEx;
447 delete [] IndexRenum;
448 }
449
450 //------LIQU------------------------
451 if (liquflags & 3)
452 {
453 int LIQU_totalSize = sizeof(uint32);
454 if (liquflags & 1)
455 {
456 LIQU_totalSize += sizeof(WMOLiquidHeader);
457 LIQU_totalSize += LiquEx_size / sizeof(WMOLiquidVert) * sizeof(float);
458 LIQU_totalSize += hlq->xtiles * hlq->ytiles;
459 }
460
461 int LIQU_h[] = { 0x5551494C, LIQU_totalSize };// "LIQU"
462 fwrite(LIQU_h, 4, 2, output);
463
464 /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
465 llog << filename;
466 llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n";
467 llog.close(); */
468
469 fwrite(&groupLiquid, sizeof(uint32), 1, output);
470 if (liquflags & 1)
471 {
472 fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
473 // only need height values, the other values are unknown anyway
474 for (uint32 i = 0; i < LiquEx_size / sizeof(WMOLiquidVert); ++i)
475 fwrite(&LiquEx[i].height, sizeof(float), 1, output);
477 fwrite(LiquBytes, 1, hlq->xtiles * hlq->ytiles, output);
478 }
479 }
480
481 return nColTriangles;
482}
std::uint32_t uint32
Definition: Define.h:107
std::uint16_t uint16
Definition: Define.h:108
@ WMO_MATERIAL_DETAIL
Definition: wmo.h:34
@ WMO_MATERIAL_COLLISION
Definition: wmo.h:35
@ WMO_MATERIAL_RENDER
Definition: wmo.h:37
bool preciseVectorData
Definition: vmapexport.cpp:63
Definition: wmo.h:100
int ytiles
Definition: wmo.h:101
int xtiles
Definition: wmo.h:101
Definition: wmo.h:109

References bbcorn1, bbcorn2, groupLiquid, groupWMOID, hlq, LiquBytes, LiquEx, LiquEx_size, liquflags, MOBA, moba_size, MobaEx, mogpFlags, MOPY, MOVI, MoviEx, MOVT, nTriangles, nVertices, preciseVectorData, WMO_MATERIAL_COLLISION, WMO_MATERIAL_DETAIL, WMO_MATERIAL_RENDER, WMOLiquidHeader::xtiles, and WMOLiquidHeader::ytiles.

Referenced by ExtractSingleWmo().

◆ GetLiquidTypeId()

uint32 WMOGroup::GetLiquidTypeId ( uint32  liquidTypeId)
485{
486 if (liquidTypeId < 21 && liquidTypeId)
487 {
488 switch (((static_cast<uint8>(liquidTypeId) - 1) & 3))
489 {
490 case 0: return ((mogpFlags & 0x80000) != 0) + 13;
491 case 1: return 14;
492 case 2: return 19;
493 case 3: return 20;
494 default: break;
495 }
496 }
497 return liquidTypeId;
498}
std::uint8_t uint8
Definition: Define.h:109

References mogpFlags.

Referenced by open().

◆ open()

bool WMOGroup::open ( WMORoot rootWMO)
168{
169 MPQFile f(filename.c_str());
170 if (f.isEof ())
171 {
172 printf("No such file.\n");
173 return false;
174 }
175 uint32 size;
176 char fourcc[5];
177 while (!f.isEof())
178 {
179 f.read(fourcc, 4);
180 f.read(&size, 4);
181 flipcc(fourcc);
182 if (!strcmp(fourcc, "MOGP")) //Fix sizeoff = Data size.
183 {
184 size = 68;
185 }
186 fourcc[4] = 0;
187 std::size_t nextpos = f.getPos() + size;
188 LiquEx_size = 0;
189 liquflags = 0;
190
191 if (!strcmp(fourcc, "MOGP")) //header
192 {
193 f.read(&groupName, 4);
194 f.read(&descGroupName, 4);
195 f.read(&mogpFlags, 4);
196 f.read(bbcorn1, 12);
197 f.read(bbcorn2, 12);
198 f.read(&moprIdx, 2);
199 f.read(&moprNItems, 2);
200 f.read(&nBatchA, 2);
201 f.read(&nBatchB, 2);
202 f.read(&nBatchC, 4);
203 f.read(&fogIdx, 4);
204 f.read(&groupLiquid, 4);
205 f.read(&groupWMOID, 4);
206
207 // according to WoW.Dev Wiki:
208 if (rootWMO->flags & 4)
210 else if (groupLiquid == 15)
211 groupLiquid = 0;
212 else
214
215 if (groupLiquid)
216 liquflags |= 2;
217 }
218 else if (!strcmp(fourcc, "MOPY"))
219 {
220 MOPY = new char[size];
221 mopy_size = size;
222 nTriangles = (int)size / 2;
223 f.read(MOPY, size);
224 }
225 else if (!strcmp(fourcc, "MOVI"))
226 {
227 MOVI = new uint16[size / 2];
228 f.read(MOVI, size);
229 }
230 else if (!strcmp(fourcc, "MOVT"))
231 {
232 MOVT = new float[size / 4];
233 f.read(MOVT, size);
234 nVertices = (int)size / 12;
235 }
236 else if (!strcmp(fourcc, "MONR"))
237 {
238 }
239 else if (!strcmp(fourcc, "MOTV"))
240 {
241 }
242 else if (!strcmp(fourcc, "MOBA"))
243 {
244 MOBA = new uint16[size / 2];
245 moba_size = size / 2;
246 f.read(MOBA, size);
247 }
248 else if (!strcmp(fourcc,"MODR"))
249 {
250 DoodadReferences.resize(size / sizeof(uint16));
251 f.read(DoodadReferences.data(), size);
252 }
253 else if (!strcmp(fourcc,"MLIQ"))
254 {
255 liquflags |= 1;
256 hlq = new WMOLiquidHeader();
257 f.read(hlq, sizeof(WMOLiquidHeader));
260 f.read(LiquEx, LiquEx_size);
261 int nLiquBytes = hlq->xtiles * hlq->ytiles;
262 LiquBytes = new char[nLiquBytes];
263 f.read(LiquBytes, nLiquBytes);
264
265 // Determine legacy liquid type
266 if (!groupLiquid)
267 {
268 for (int i = 0; i < hlq->xtiles * hlq->ytiles; ++i)
269 {
270 if ((LiquBytes[i] & 0xF) != 15)
271 {
272 groupLiquid = GetLiquidTypeId((LiquBytes[i] & 0xF) + 1);
273 break;
274 }
275 }
276 }
277
278 /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
279 llog << filename;
280 llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
281 llog << "\nlpos: " << hlq->pos_x << ", " << hlq->pos_y << ", " << hlq->pos_z;
282 llog << "\nx-/yvert: " << hlq->xverts << "/" << hlq->yverts << " size: " << size << " expected size: " << 30 + hlq->xverts*hlq->yverts*8 + hlq->xtiles*hlq->ytiles << std::endl;
283 llog.close(); */
284 }
285 f.seek((int)nextpos);
286 }
287 f.close();
288 return true;
289}
Definition: mpq_libmpq04.h:74
uint32 flags
Definition: wmo.h:84
int xverts
Definition: wmo.h:101
int yverts
Definition: wmo.h:101
std::vector< uint16 > DoodadReferences
Definition: wmo.h:149
uint32 GetLiquidTypeId(uint32 liquidTypeId)
Definition: wmo.cpp:484
void flipcc(char *fcc)
Definition: mpq_libmpq04.h:98

References bbcorn1, bbcorn2, MPQFile::close(), descGroupName, DoodadReferences, filename, WMORoot::flags, flipcc(), fogIdx, GetLiquidTypeId(), MPQFile::getPos(), groupLiquid, groupName, groupWMOID, hlq, MPQFile::isEof(), LiquBytes, LiquEx, LiquEx_size, liquflags, MOBA, moba_size, mogpFlags, moprIdx, moprNItems, MOPY, mopy_size, MOVI, MOVT, nBatchA, nBatchB, nBatchC, nTriangles, nVertices, MPQFile::read(), MPQFile::seek(), WMOLiquidHeader::xtiles, WMOLiquidHeader::xverts, WMOLiquidHeader::ytiles, and WMOLiquidHeader::yverts.

Referenced by ExtractSingleWmo().

Member Data Documentation

◆ bbcorn1

float WMOGroup::bbcorn1[3]

◆ bbcorn2

float WMOGroup::bbcorn2[3]

◆ descGroupName

int WMOGroup::descGroupName

Referenced by open().

◆ DoodadReferences

std::vector<uint16> WMOGroup::DoodadReferences

Referenced by ExtractSingleWmo(), and open().

◆ filename

std::string WMOGroup::filename
private

Referenced by open().

◆ fogIdx

uint32 WMOGroup::fogIdx

Referenced by open().

◆ groupLiquid

uint32 WMOGroup::groupLiquid

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ groupName

int WMOGroup::groupName

Referenced by open().

◆ groupWMOID

uint32 WMOGroup::groupWMOID

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ hlq

WMOLiquidHeader* WMOGroup::hlq

◆ LiquBytes

char* WMOGroup::LiquBytes

◆ LiquEx

WMOLiquidVert* WMOGroup::LiquEx

◆ LiquEx_size

int WMOGroup::LiquEx_size

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ liquflags

uint32 WMOGroup::liquflags

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ MOBA

uint16* WMOGroup::MOBA

◆ moba_size

int WMOGroup::moba_size

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ MobaEx

int* WMOGroup::MobaEx

Referenced by ConvertToVMAPGroupWmo().

◆ mogpFlags

int WMOGroup::mogpFlags

◆ moprIdx

uint16 WMOGroup::moprIdx

Referenced by open().

◆ moprNItems

uint16 WMOGroup::moprNItems

Referenced by open().

◆ MOPY

char* WMOGroup::MOPY

◆ mopy_size

int WMOGroup::mopy_size

Referenced by open().

◆ MOVI

uint16* WMOGroup::MOVI

◆ MoviEx

uint16* WMOGroup::MoviEx

Referenced by ConvertToVMAPGroupWmo().

◆ MOVT

float* WMOGroup::MOVT

◆ nBatchA

uint16 WMOGroup::nBatchA

Referenced by open().

◆ nBatchB

uint16 WMOGroup::nBatchB

Referenced by open().

◆ nBatchC

uint32 WMOGroup::nBatchC

Referenced by open().

◆ nTriangles

int WMOGroup::nTriangles

Referenced by ConvertToVMAPGroupWmo(), and open().

◆ nVertices

unsigned int WMOGroup::nVertices

Referenced by ConvertToVMAPGroupWmo(), and open().