WMO::WMO(const std::string& filenameArg) : ManagedItem() , _filename(filenameArg) { MPQFile f(_filename); if (f.isEof()) { LogError << "Error loading WMO \"" << _filename << "\"." << std::endl; return; } uint32_t fourcc; uint32_t size; float ff[3]; char *ddnames = NULL; char *groupnames = NULL; skybox = 0; char *texbuf = 0; while (!f.isEof()) { f.read(&fourcc, 4); f.read(&size, 4); size_t nextpos = f.getPos() + size; if (fourcc == 'MOHD') { unsigned int col; // header f.read(&nTextures, 4); f.read(&nGroups, 4); f.read(&nP, 4); f.read(&nLights, 4); f.read(&nModels, 4); f.read(&nDoodads, 4); f.read(&nDoodadSets, 4); f.read(&col, 4); f.read(&nX, 4); f.read(ff, 12); extents[0] = Vec3D(ff[0], ff[1], ff[2]); f.read(ff, 12); extents[1] = Vec3D(ff[0], ff[1], ff[2]); groups = new WMOGroup[nGroups]; mat = new WMOMaterial[nTextures]; } else if (fourcc == 'MOTX') { // textures texbuf = new char[size]; f.read(texbuf, size); } else if (fourcc == 'MOMT') { // materials //WMOMaterialBlock bl; for (unsigned int i = 0; i<nTextures; ++i) { WMOMaterial *m = &mat[i]; f.read(m, 0x40); std::string texpath(texbuf + m->nameStart); m->_texture = TextureManager::newTexture(texpath); textures.push_back(texpath); } } else if (fourcc == 'MOGN') { groupnames = reinterpret_cast<char*>(f.getPointer()); } else if (fourcc == 'MOGI') { // group info - important information! ^_^ for (unsigned int i = 0; i<nGroups; ++i) { groups[i].init(this, &f, i, groupnames); } } else if (fourcc == 'MOLT') { // Lights? for (unsigned int i = 0; i<nLights; ++i) { WMOLight l; l.init(&f); lights.push_back(l); } } else if (fourcc == 'MODN') { // models ... // MMID would be relative offsets for MMDX filenames if (size) { ddnames = reinterpret_cast<char*>(f.getPointer()); f.seekRelative(size); } } else if (fourcc == 'MODS') { for (unsigned int i = 0; i<nDoodadSets; ++i) { WMODoodadSet dds; f.read(&dds, 32); doodadsets.push_back(dds); } } else if (fourcc == 'MODD') { nModels = size / 0x28; for (unsigned int i = 0; i<nModels; ++i) { int ofs; f.read(&ofs, 4); Model *m = ModelManager::add(ddnames + ofs); ModelInstance mi; mi.init2(m, &f); modelis.push_back(mi); } } else if (fourcc == 'MOSB') { if (size>4) { std::string path = std::string(reinterpret_cast<char*>(f.getPointer())); if (path.length()) { LogDebug << "SKYBOX:" << std::endl; if (MPQFile::exists(path)) { skybox = ModelManager::add(path); skyboxFilename = path; } else { skybox = NULL; } } } } else if (fourcc == 'MOPV') { WMOPV p; for (unsigned int i = 0; i<nP; ++i) { f.read(ff, 12); p.a = Vec3D(ff[0], ff[2], -ff[1]); f.read(ff, 12); p.b = Vec3D(ff[0], ff[2], -ff[1]); f.read(ff, 12); p.c = Vec3D(ff[0], ff[2], -ff[1]); f.read(ff, 12); p.d = Vec3D(ff[0], ff[2], -ff[1]); pvs.push_back(p); } } else if (fourcc == 'MOPR') { int nn = size / 8; WMOPR *pr = reinterpret_cast<WMOPR*>(f.getPointer()); for (int i = 0; i<nn; ++i) { prs.push_back(*pr++); } } else if (fourcc == 'MFOG') { int nfogs = size / 0x30; for (int i = 0; i<nfogs; ++i) { WMOFog fog; fog.init(&f); fogs.push_back(fog); } } f.seek(nextpos); } f.close(); if (texbuf) { delete[] texbuf; texbuf = NULL; } for (unsigned int i = 0; i<nGroups; ++i) groups[i].initDisplayList(); }
WMO::WMO(std::string name): ManagedItem(name) { MPQFile f(name.c_str()); ok = !f.isEof(); if (!ok) { gLog("Error loading WMO %s\n", name.c_str()); return; } gLog("Loading WMO %s\n", name.c_str()); char fourcc[5]; size_t size; float ff[3]; char *ddnames; char *groupnames; skybox = 0; char *texbuf=0; while (!f.isEof()) { f.read(fourcc,4); f.read(&size, 4); flipcc(fourcc); fourcc[4] = 0; size_t nextpos = f.getPos() + size; if (!strcmp(fourcc,"MOHD")) { unsigned int col; // header f.read(&nTextures, 4); f.read(&nGroups, 4); f.read(&nP, 4); f.read(&nLights, 4); f.read(&nModels, 4); f.read(&nDoodads, 4); f.read(&nDoodadSets, 4); f.read(&col, 4); f.read(&nX, 4); f.read(ff,12); v1 = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); v2 = Vec3D(ff[0],ff[1],ff[2]); groups = new WMOGroup[nGroups]; mat = new WMOMaterial[nTextures]; } else if (!strcmp(fourcc,"MOTX")) { // textures texbuf = new char[size]; f.read(texbuf, size); } else if (!strcmp(fourcc,"MOMT")) { // materials //WMOMaterialBlock bl; for (int i=0; i<nTextures; i++) { WMOMaterial *m = &mat[i]; f.read(m, 0x40); string texpath(texbuf+m->nameStart); fixname(texpath); m->tex = video.textures.add(texpath); textures.push_back(texpath); /* // material logging gLog("Material %d:\t%d\t%d\t%d\t%X\t%d\t%X\t%d\t%f\t%f", i, m->flags, m->d1, m->transparent, m->col1, m->d3, m->col2, m->d4, m->f1, m->f2); for (int j=0; j<5; j++) gLog("\t%d", m->dx[j]); gLog("\t - %s\n", texpath.c_str()); */ } } else if (!strcmp(fourcc,"MOGN")) { groupnames = (char*)f.getPointer(); } else if (!strcmp(fourcc,"MOGI")) { // group info - important information! ^_^ for (int i=0; i<nGroups; i++) { groups[i].init(this, f, i, groupnames); } } else if (!strcmp(fourcc,"MOLT")) { // Lights? for (int i=0; i<nLights; i++) { WMOLight l; l.init(f); lights.push_back(l); } } else if (!strcmp(fourcc,"MODN")) { // models ... // MMID would be relative offsets for MMDX filenames if (size) { ddnames = f.getPointer(); fixnamen(ddnames, size); char *p=ddnames,*end=p+size; int t=0; while (p<end) { string path(p); p+=strlen(p)+1; while ((p<end) && (*p==0)) p++; gWorld->modelmanager.add(path); models.push_back(path); } f.seekRelative((int)size); } } else if (!strcmp(fourcc,"MODS")) { for (int i=0; i<nDoodadSets; i++) { WMODoodadSet dds; f.read(&dds, 32); doodadsets.push_back(dds); } } else if (!strcmp(fourcc,"MODD")) { nModels = (int)size / 0x28; for (int i=0; i<nModels; i++) { int ofs; f.read(&ofs,4); Model *m = (Model*)gWorld->modelmanager.items[gWorld->modelmanager.get(ddnames + ofs)]; ModelInstance mi; mi.init2(m,f); modelis.push_back(mi); } } else if (!strcmp(fourcc,"MOSB")) { if (size>4) { string path = f.getPointer(); fixname(path); if (path.length()) { gLog("SKYBOX:\n"); sbid = gWorld->modelmanager.add(path); skybox = (Model*)gWorld->modelmanager.items[sbid]; if (!skybox->ok) { gWorld->modelmanager.del(sbid); skybox = 0; } } } } else if (!strcmp(fourcc,"MOPV")) { WMOPV p; for (int i=0; i<nP; i++) { f.read(ff,12); p.a = Vec3D(ff[0],ff[2],-ff[1]); f.read(ff,12); p.b = Vec3D(ff[0],ff[2],-ff[1]); f.read(ff,12); p.c = Vec3D(ff[0],ff[2],-ff[1]); f.read(ff,12); p.d = Vec3D(ff[0],ff[2],-ff[1]); pvs.push_back(p); } } else if (!strcmp(fourcc,"MOPR")) { int nn = (int)size / 8; WMOPR *pr = (WMOPR*)f.getPointer(); for (int i=0; i<nn; i++) { prs.push_back(*pr++); } } else if (!strcmp(fourcc,"MFOG")) { int nfogs = (int)size / 0x30; for (int i=0; i<nfogs; i++) { WMOFog fog; fog.init(f); fogs.push_back(fog); } } f.seek((int)nextpos); } f.close(); delete[] texbuf; for (int i=0; i<nGroups; i++) groups[i].initDisplayList(); }