From bfe1c335afdd1fb57186ab858d5b43db9c1e0219 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 25 Dec 2016 03:41:42 +0100 Subject: [PATCH 1/5] [IGfxWorld] Import experiments --- .../Modules/AssetInterfaces/IGfxWorld.cpp | 73 ++++++++++++++++++- src/Game/Structs.hpp | 1 + 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 1ba89c3a..4b5eadc7 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -1,13 +1,78 @@ #include +#define IW4X_GFXMAP_VERSION 1 + namespace Assets { - void IGfxWorld::load(Game::XAssetHeader* /*header*/, std::string name, Components::ZoneBuilder::Zone* /*builder*/) + void IGfxWorld::load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) { - Game::GfxWorld* map = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_GFX_MAP, name.data()).gfxWorld; - if (map) return; + if (name != "maps/iw4_credits.d3dbsp") return; + Game::GfxWorld* map = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_GFX_MAP, "maps/iw4_credits.d3dbsp").gfxWorld; + if (!map) return; - Components::Logger::Error("Missing GfxMap %s... you can't make them yet you idiot.", name.data()); + map->name = "maps/mp/mp_toujane.d3dbsp"; + map->baseName = "mp_toujane"; + + Game::Material* basemat = /*Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, "white").material;*/map->dpvs.surfaces[0].material; + if (!basemat) return; + + Components::FileSystem::File mapFile(fmt::sprintf("gfxworld/%s.iw4xGfxWorld", map->baseName)); + + if (mapFile.exists()) + { + Utils::Stream::Reader reader(builder->getAllocator(), mapFile.getBuffer()); + + if (reader.read<__int64>() != *reinterpret_cast<__int64*>("IW4xGfxW")) + { + Components::Logger::Error(0, "Reading gfxworld '%s' failed, header is invalid!", name.data()); + } + + int version = reader.read(); + if (version != IW4X_GFXMAP_VERSION) + { + Components::Logger::Error(0, "Reading gfxworld '%s' failed, expected version is %d, but it was %d!", name.data(), IW4X_GFXMAP_VERSION, version); + } + + std::string _name = reader.readString(); // Name + std::string bname = reader.readString(); // Basename + + map->worldDraw.indexCount = reader.read(); + map->worldDraw.indices = reader.readArray(map->worldDraw.indexCount); + + map->worldDraw.vertexCount = reader.read(); + map->worldDraw.vd.vertices = reader.readArray(map->worldDraw.vertexCount); + + map->worldDraw.vertexLayerDataSize = reader.read(); + map->worldDraw.vld.data = reader.readArray(map->worldDraw.vertexLayerDataSize); + + for (unsigned int i = 0; i < map->worldDraw.vertexCount; ++i) + { + map->worldDraw.vd.vertices[i].color.uArray[0] = 0xFF; + map->worldDraw.vd.vertices[i].color.uArray[1] = 0xFF; + map->worldDraw.vd.vertices[i].color.uArray[2] = 0xFF; + } + + map->dpvs.staticSurfaceCount = reader.read(); + map->dpvsSurfaceCount = map->dpvs.staticSurfaceCount; + map->dpvs.sortedSurfIndex = reader.readArray(map->dpvs.staticSurfaceCount); + map->dpvs.surfaces = builder->getAllocator()->allocateArray(map->dpvs.staticSurfaceCount); + + for (unsigned int i = 0; i < map->dpvs.staticSurfaceCount; ++i) + { + Game::GfxSurface* surf = reader.readArray(1); + std::memcpy(&map->dpvs.surfaces[i], surf, sizeof(Game::GfxSurface)); + + if (map->dpvs.surfaces[i].material) + { + std::string matname = reader.readString(); // Name + map->dpvs.surfaces[i].material = basemat; + } + } + + header->gfxWorld = map; + } + + //Components::Logger::Error("Missing GfxMap %s... you can't make them yet you idiot.", name.data()); } void IGfxWorld::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index aabeb604..11798051 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -2725,6 +2725,7 @@ namespace Game { unsigned int packed; char array[4]; + unsigned char uArray[4]; }; union PackedUnitVec From b4fd5a11d13c42b4d5be6486c34640a9d8cd65d9 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 25 Dec 2016 15:17:31 +0100 Subject: [PATCH 2/5] [Stream] Add pointer interface to the reader --- src/Game/Structs.hpp | 5 +++-- src/Utils/Stream.cpp | 23 +++++++++++++++++++++++ src/Utils/Stream.hpp | 5 +++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 11798051..65f134e0 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -2948,8 +2948,8 @@ namespace Game struct GfxPortalWritable { - bool isQueued; - bool isAncestor; + char isQueued; + char isAncestor; char recursionDepth; char hullPointCount; float(*hullPoints)[2]; @@ -2959,6 +2959,7 @@ namespace Game { float coeffs[4]; char side[3]; + char pad; }; struct GfxPortal diff --git a/src/Utils/Stream.cpp b/src/Utils/Stream.cpp index 596003cc..0c2a0435 100644 --- a/src/Utils/Stream.cpp +++ b/src/Utils/Stream.cpp @@ -59,6 +59,29 @@ namespace Utils } } + void* Stream::Reader::readPointer() + { + void* pointer = this->read(); + if (!this->hasPointer(pointer)) + { + this->pointerMap[pointer] = 0; + } + return pointer; + } + + void Stream::Reader::mapPointer(void* oldPointer, void* newPointer) + { + if (this->hasPointer(oldPointer)) + { + this->pointerMap[oldPointer] = newPointer; + } + } + + bool Stream::Reader::hasPointer(void* pointer) + { + return this->pointerMap.find(pointer) != this->pointerMap.end(); + } + Stream::Stream() : criticalSectionState(0) { memset(this->blockSize, 0, sizeof(this->blockSize)); diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index 4074ac99..599dbf41 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -49,9 +49,14 @@ namespace Utils bool end(); void seek(unsigned int position); + void* readPointer(); + void mapPointer(void* oldPointer, void* newPointer); + bool hasPointer(void* pointer); + private: unsigned int position; std::string buffer; + std::map pointerMap; Utils::Memory::Allocator* allocator; }; From d6c0e17bcb539987661fc9994d935862d146c8f6 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 25 Dec 2016 20:55:42 +0100 Subject: [PATCH 3/5] [IGfxWorld] Exporter progress and new struct --- .../Modules/AssetInterfaces/IGfxWorld.cpp | 194 ++++++++++++------ src/Components/Modules/Maps.cpp | 18 +- src/Game/Structs.hpp | 52 +++-- 3 files changed, 173 insertions(+), 91 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 4b5eadc7..2d8b393e 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -9,6 +9,7 @@ namespace Assets if (name != "maps/iw4_credits.d3dbsp") return; Game::GfxWorld* map = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_GFX_MAP, "maps/iw4_credits.d3dbsp").gfxWorld; if (!map) return; + header->gfxWorld = map; map->name = "maps/mp/mp_toujane.d3dbsp"; map->baseName = "mp_toujane"; @@ -16,7 +17,17 @@ namespace Assets Game::Material* basemat = /*Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, "white").material;*/map->dpvs.surfaces[0].material; if (!basemat) return; - Components::FileSystem::File mapFile(fmt::sprintf("gfxworld/%s.iw4xGfxWorld", map->baseName)); + for (unsigned int i = 0; i < map->dpvs.staticSurfaceCount; ++i) + { + if (map->dpvs.surfaces[i].material) + { + map->dpvs.surfaces[i].material = basemat; + } + } + + //return; + + Components::FileSystem::File mapFile(fmt::sprintf("gfxworld/%s.iw4xGfxWorld", /*map->baseName*/"mp_waw_toujane_night")); if (mapFile.exists()) { @@ -36,31 +47,83 @@ namespace Assets std::string _name = reader.readString(); // Name std::string bname = reader.readString(); // Basename - map->worldDraw.indexCount = reader.read(); - map->worldDraw.indices = reader.readArray(map->worldDraw.indexCount); + map->nodeCount = reader.read(); + map->planeCount = reader.read(); - map->worldDraw.vertexCount = reader.read(); - map->worldDraw.vd.vertices = reader.readArray(map->worldDraw.vertexCount); + map->bounds.midPoint[0] = reader.read(); + map->bounds.midPoint[1] = reader.read(); + map->bounds.midPoint[2] = reader.read(); - map->worldDraw.vertexLayerDataSize = reader.read(); - map->worldDraw.vld.data = reader.readArray(map->worldDraw.vertexLayerDataSize); + map->bounds.halfSize[0] = reader.read(); + map->bounds.halfSize[1] = reader.read(); + map->bounds.halfSize[2] = reader.read(); - for (unsigned int i = 0; i < map->worldDraw.vertexCount; ++i) + map->dpvsPlanes = reader.read(); + map->dpvsPlanes.planes = reader.readArray(map->planeCount); + map->dpvsPlanes.nodes = reader.readArray(map->nodeCount); + map->dpvsPlanes.sceneEntCellBits = reinterpret_cast(reader.readArray(map->dpvsPlanes.cellCount << 11)); + map->aabbTreeCounts = reader.readArray(map->dpvsPlanes.cellCount); + + //map->aabbTrees = reader.readArray(map->dpvsPlanes.cellCount); + map->aabbTrees = builder->getAllocator()->allocateArray(map->dpvsPlanes.cellCount); + + for (int i = 0; i < map->dpvsPlanes.cellCount; ++i) { - map->worldDraw.vd.vertices[i].color.uArray[0] = 0xFF; - map->worldDraw.vd.vertices[i].color.uArray[1] = 0xFF; - map->worldDraw.vd.vertices[i].color.uArray[2] = 0xFF; + map->aabbTrees[i].aabbTree = reader.readArray(map->aabbTreeCounts[i].aabbTreeCount); } - map->dpvs.staticSurfaceCount = reader.read(); - map->dpvsSurfaceCount = map->dpvs.staticSurfaceCount; - map->dpvs.sortedSurfIndex = reader.readArray(map->dpvs.staticSurfaceCount); + map->cells = reader.readArray(map->dpvsPlanes.cellCount); + + for (int i = 0; i < map->dpvsPlanes.cellCount; ++i) + { + Game::GfxCell* cell = &map->cells[i]; + cell->portals = reader.readArray(cell->portalCount); + + for (int j = 0; j < cell->portalCount; ++j) + { + cell->portals[i].vertices = reader.readArray(cell->portals[i].vertexCount); + } + } + + //return; + + Game::GfxWorldVertex* originalVerts = map->draw.vd.vertices; + + map->draw.indexCount = reader.read(); + map->draw.indices = reader.readArray(map->draw.indexCount); + + map->draw.vertexCount = reader.read(); + map->draw.vd.vertices = reader.readArray(map->draw.vertexCount); + + map->draw.vertexLayerDataSize = reader.read(); + map->draw.vld.data = reader.readArray(map->draw.vertexLayerDataSize); + + for (unsigned int i = 0; i < map->draw.vertexCount; ++i) + { + map->draw.vd.vertices[i].lmapCoord[0] = originalVerts[i % 3].lmapCoord[0]; + map->draw.vd.vertices[i].lmapCoord[1] = originalVerts[i % 3].lmapCoord[1]; + + map->draw.vd.vertices[i].texCoord[0] = originalVerts[i % 3].texCoord[0]; + map->draw.vd.vertices[i].texCoord[1] = originalVerts[i % 3].texCoord[1]; + map->draw.vd.vertices[i].texCoord[2] = originalVerts[i % 3].texCoord[2]; + } + + for (int i = 0; i < 8; ++i) + { + (&map->dpvs.staticSurfaceCount)[i] = reader.read(); + } + + map->surfaceCount = map->dpvs.staticSurfaceCount; + map->dpvs.sortedSurfIndex = reader.readArray(map->dpvs.staticSurfaceCount + map->dpvs.staticSurfaceCountNoDecal); + //map->dpvs.surfacesBounds = reader.readArray(map->dpvs.staticSurfaceCount); map->dpvs.surfaces = builder->getAllocator()->allocateArray(map->dpvs.staticSurfaceCount); for (unsigned int i = 0; i < map->dpvs.staticSurfaceCount; ++i) { - Game::GfxSurface* surf = reader.readArray(1); - std::memcpy(&map->dpvs.surfaces[i], surf, sizeof(Game::GfxSurface)); + //Game::GfxSurface* surf = reader.readArray(1); + //std::memcpy(&map->dpvs.surfaces[i], surf, sizeof(Game::GfxSurface)); + + map->dpvs.surfaces[i] = reader.read(); if (map->dpvs.surfaces[i].material) { @@ -68,10 +131,13 @@ namespace Assets map->dpvs.surfaces[i].material = basemat; } } - - header->gfxWorld = map; } + map->draw.reflectionImages = 0; + map->draw.reflectionProbeCount = 0; + map->draw.reflectionProbes = 0; + map->draw.reflectionProbeTextures = 0; + //Components::Logger::Error("Missing GfxMap %s... you can't make them yet you idiot.", name.data()); } @@ -79,38 +145,38 @@ namespace Assets { Game::GfxWorld* asset = header.gfxWorld; - if (asset->worldDraw.reflectionImages) + if (asset->draw.reflectionImages) { - for (unsigned int i = 0; i < asset->worldDraw.reflectionProbeCount; ++i) + for (unsigned int i = 0; i < asset->draw.reflectionProbeCount; ++i) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->worldDraw.reflectionImages[i]); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.reflectionImages[i]); } } - if (asset->worldDraw.lightmaps) + if (asset->draw.lightmaps) { - for (int i = 0; i < asset->worldDraw.lightmapCount; ++i) + for (int i = 0; i < asset->draw.lightmapCount; ++i) { - if (asset->worldDraw.lightmaps[i].primary) + if (asset->draw.lightmaps[i].primary) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->worldDraw.lightmaps[i].primary); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmaps[i].primary); } - if (asset->worldDraw.lightmaps[i].secondary) + if (asset->draw.lightmaps[i].secondary) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->worldDraw.lightmaps[i].secondary); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmaps[i].secondary); } } } - if (asset->worldDraw.skyImage) + if (asset->draw.skyImage) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->worldDraw.skyImage); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.skyImage); } - if (asset->worldDraw.outdoorImage) + if (asset->draw.outdoorImage) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->worldDraw.outdoorImage); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.outdoorImage); } if (asset->sun.spriteMaterial) @@ -125,7 +191,7 @@ namespace Assets if (asset->skies) { - for (unsigned int i = 0; i < asset->skyCount; ++i) + for (int i = 0; i < asset->skyCount; ++i) { if (asset->skies[i].skyImage) { @@ -145,14 +211,14 @@ namespace Assets } } - if (asset->unknownImage) + if (asset->outdoorImage) { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->unknownImage); + builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->outdoorImage); } if (asset->dpvs.surfaces) { - for (int i = 0; i < asset->dpvsSurfaceCount; ++i) + for (unsigned int i = 0; i < asset->surfaceCount; ++i) { if (asset->dpvs.surfaces[i].material) { @@ -463,7 +529,7 @@ namespace Assets if (asset->sortedSurfIndex) { buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->sortedSurfIndex, asset->staticSurfaceCount + asset->litSurfsBegin); + buffer->saveArray(asset->sortedSurfIndex, asset->staticSurfaceCount + asset->staticSurfaceCountNoDecal); Utils::Stream::ClearPointer(&dest->sortedSurfIndex); } @@ -486,9 +552,9 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); Game::GfxSurface* destSurfaceTable = buffer->dest(); - buffer->saveArray(asset->surfaces, world->dpvsSurfaceCount); + buffer->saveArray(asset->surfaces, world->surfaceCount); - for (int i = 0; i < world->dpvsSurfaceCount; ++i) + for (unsigned int i = 0; i < world->surfaceCount; ++i) { Game::GfxSurface* surface = &asset->surfaces[i]; Game::GfxSurface* destSurface = &destSurfaceTable[i]; @@ -509,7 +575,7 @@ namespace Assets SaveLogEnter("GfxSurfaceBounds"); buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->surfacesBounds, world->dpvsSurfaceCount); + buffer->saveArray(asset->surfacesBounds, world->surfaceCount); Utils::Stream::ClearPointer(&dest->surfacesBounds); SaveLogExit(); @@ -547,7 +613,7 @@ namespace Assets SaveLogEnter("GfxDrawSurf"); buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->surfaceMaterials, world->dpvsSurfaceCount); + buffer->saveArray(asset->surfaceMaterials, world->surfaceCount); Utils::Stream::ClearPointer(&dest->surfaceMaterials); SaveLogExit(); @@ -644,7 +710,7 @@ namespace Assets Game::GfxSky* destSkyTable = buffer->dest(); buffer->saveArray(asset->skies, asset->skyCount); - for (unsigned int i = 0; i < asset->skyCount; ++i) + for (int i = 0; i < asset->skyCount; ++i) { Game::GfxSky* destSky = &destSkyTable[i]; Game::GfxSky* sky = &asset->skies[i]; @@ -797,7 +863,7 @@ namespace Assets SaveLogExit(); } - this->saveGfxWorldDraw(&asset->worldDraw, &dest->worldDraw, builder); + this->saveGfxWorldDraw(&asset->draw, &dest->draw, builder); this->saveGfxLightGrid(&asset->lightGrid, &dest->lightGrid, builder); if (asset->models) @@ -838,25 +904,25 @@ namespace Assets this->savesunflare_t(&asset->sun, &dest->sun, builder); - if (asset->unknownImage) + if (asset->outdoorImage) { - dest->unknownImage = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->unknownImage).image; + dest->outdoorImage = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->outdoorImage).image; } buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - if (asset->cellCasterBits[0]) + if (asset->cellCasterBits) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->cellCasterBits[0], cellCount * ((cellCount + 31) >> 5)); - Utils::Stream::ClearPointer(&dest->cellCasterBits[0]); + buffer->saveArray(asset->cellCasterBits, cellCount * ((cellCount + 31) >> 5)); + Utils::Stream::ClearPointer(&dest->cellCasterBits); } - if (asset->cellCasterBits[1]) + if (asset->cellHasSunLitSurfsBits) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->cellCasterBits[1], ((cellCount + 31) >> 5)); - Utils::Stream::ClearPointer(&dest->cellCasterBits[1]); + buffer->saveArray(asset->cellHasSunLitSurfsBits, ((cellCount + 31) >> 5)); + Utils::Stream::ClearPointer(&dest->cellHasSunLitSurfsBits); } if (asset->sceneDynModel) @@ -880,29 +946,29 @@ namespace Assets if (asset->primaryLightEntityShadowVis) { buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->primaryLightEntityShadowVis, 1, (asset->unkCount2 + 0x1FFFF - asset->unkCount1) << 15); + buffer->save(asset->primaryLightEntityShadowVis, 1, (asset->primaryLightCount + 0x1FFFF - asset->lastSunPrimaryLightIndex) << 15); Utils::Stream::ClearPointer(&dest->primaryLightEntityShadowVis); } if (asset->primaryLightDynEntShadowVis[0]) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->primaryLightDynEntShadowVis[0], asset->dpvsDyn.dynEntClientCount[0] * (asset->unkCount2 - 1 - asset->unkCount1)); + buffer->saveArray(asset->primaryLightDynEntShadowVis[0], asset->dpvsDyn.dynEntClientCount[0] * (asset->primaryLightCount - 1 - asset->lastSunPrimaryLightIndex)); Utils::Stream::ClearPointer(&dest->primaryLightDynEntShadowVis[0]); } if (asset->primaryLightDynEntShadowVis[1]) { buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->primaryLightDynEntShadowVis[1], asset->dpvsDyn.dynEntClientCount[1] * (asset->unkCount2 - 1 - asset->unkCount1)); + buffer->saveArray(asset->primaryLightDynEntShadowVis[1], asset->dpvsDyn.dynEntClientCount[1] * (asset->primaryLightCount - 1 - asset->lastSunPrimaryLightIndex)); Utils::Stream::ClearPointer(&dest->primaryLightDynEntShadowVis[1]); } - if (asset->primaryLightForModelDynEnt) + if (asset->nonSunPrimaryLightForModelDynEnt) { // no align cause char - buffer->saveArray(asset->primaryLightForModelDynEnt, asset->dpvsDyn.dynEntClientCount[0]); - Utils::Stream::ClearPointer(&dest->primaryLightForModelDynEnt); + buffer->saveArray(asset->nonSunPrimaryLightForModelDynEnt, asset->dpvsDyn.dynEntClientCount[0]); + Utils::Stream::ClearPointer(&dest->nonSunPrimaryLightForModelDynEnt); } buffer->popBlock(); @@ -914,9 +980,9 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); Game::GfxShadowGeometry* destShadowGeometryTable = buffer->dest(); - buffer->saveArray(asset->shadowGeom, asset->unkCount2); + buffer->saveArray(asset->shadowGeom, asset->primaryLightCount); - for (int i = 0; i < asset->unkCount2; ++i) + for (unsigned int i = 0; i < asset->primaryLightCount; ++i) { Game::GfxShadowGeometry* destShadowGeometry = &destShadowGeometryTable[i]; Game::GfxShadowGeometry* shadowGeometry = &asset->shadowGeom[i]; @@ -947,9 +1013,9 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); Game::GfxLightRegion* destLightRegionTable = buffer->dest(); - buffer->saveArray(asset->lightRegion, asset->unkCount2); + buffer->saveArray(asset->lightRegion, asset->primaryLightCount); - for (int i = 0; i < asset->unkCount2; ++i) + for (unsigned int i = 0; i < asset->primaryLightCount; ++i) { Game::GfxLightRegion* destLightRegion = &destLightRegionTable[i]; Game::GfxLightRegion* lightRegion = &asset->lightRegion[i]; @@ -994,12 +1060,12 @@ namespace Assets this->saveGfxWorldDpvsStatic(asset, &asset->dpvs, &dest->dpvs, asset->dpvsPlanes.cellCount, builder); this->saveGfxWorldDpvsDynamic(&asset->dpvsDyn, &dest->dpvsDyn, builder); - if (asset->heroOnlyLight) + if (asset->heroOnlyLights) { - // no assert cause we use save manually here + AssertSize(Game::GfxHeroOnlyLight, 56); buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->heroOnlyLight, 56, asset->heroOnlyLightCount); - Utils::Stream::ClearPointer(&dest->heroOnlyLight); + buffer->saveArray(asset->heroOnlyLights, asset->heroOnlyLightCount); + Utils::Stream::ClearPointer(&dest->heroOnlyLights); } buffer->popBlock(); diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index a67f5462..54a1b93d 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -306,11 +306,11 @@ namespace Components map.append(fmt::sprintf("mtllib %s.mtl\n\n", world->baseName)); Logger::Print("Writing vertices...\n"); - for (unsigned int i = 0; i < world->worldDraw.vertexCount; ++i) + for (unsigned int i = 0; i < world->draw.vertexCount; ++i) { - float x = world->worldDraw.vd.vertices[i].xyz[1]; - float y = world->worldDraw.vd.vertices[i].xyz[2]; - float z = world->worldDraw.vd.vertices[i].xyz[0]; + float x = world->draw.vd.vertices[i].xyz[1]; + float y = world->draw.vd.vertices[i].xyz[2]; + float z = world->draw.vd.vertices[i].xyz[0]; map.append(fmt::sprintf("v %.6f %.6f %.6f\n", x, y, z)); } @@ -318,9 +318,9 @@ namespace Components map.append("\n"); Logger::Print("Writing texture coordinates...\n"); - for (unsigned int i = 0; i < world->worldDraw.vertexCount; ++i) + for (unsigned int i = 0; i < world->draw.vertexCount; ++i) { - map.append(fmt::sprintf("vt %.6f %.6f\n", world->worldDraw.vd.vertices[i].texCoord[0], -world->worldDraw.vd.vertices[i].texCoord[1])); + map.append(fmt::sprintf("vt %.6f %.6f\n", world->draw.vd.vertices[i].texCoord[0], -world->draw.vd.vertices[i].texCoord[1])); } Logger::Print("Searching materials...\n"); @@ -395,9 +395,9 @@ namespace Components int indexOffset = world->dpvs.surfaces[i].tris.baseIndex; for (unsigned short j = 0; j < world->dpvs.surfaces[i].tris.triCount; ++j) { - int a = world->worldDraw.indices[indexOffset + j * 3 + 0] + vertOffset; - int b = world->worldDraw.indices[indexOffset + j * 3 + 1] + vertOffset; - int c = world->worldDraw.indices[indexOffset + j * 3 + 2] + vertOffset; + int a = world->draw.indices[indexOffset + j * 3 + 0] + vertOffset; + int b = world->draw.indices[indexOffset + j * 3 + 1] + vertOffset; + int c = world->draw.indices[indexOffset + j * 3 + 2] + vertOffset; map.append(fmt::sprintf("f %d/%d %d/%d %d/%d\n", a, a, b, b, c, c)); } diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 65f134e0..3c0717f9 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1530,6 +1530,7 @@ namespace Game float dist; char type; char signbits; + char pad[2]; }; struct cbrushside_t @@ -2906,9 +2907,16 @@ namespace Game { unsigned int smodelCount; unsigned int staticSurfaceCount; + unsigned int staticSurfaceCountNoDecal; unsigned int litSurfsBegin; unsigned int litSurfsEnd; - char unknown1[0x20]; + unsigned int decalSurfsBegin; + unsigned int decalSurfsEnd; + unsigned int emissiveSurfsBegin; + unsigned int emissiveSurfsEnd; + unsigned int smodelVisDataCount; + unsigned int surfaceVisDataCount; + int surfStuff; int sunShadowCount; char *smodelVisData[3]; char *surfaceVisData[3]; @@ -3138,48 +3146,56 @@ namespace Game int skySamplerState; }; + struct GfxHeroOnlyLight + { + char pad[56]; + }; + struct GfxWorld { const char *name; const char *baseName; int planeCount; int nodeCount; - int dpvsSurfaceCount; - unsigned int skyCount; - GfxSky* skies; - int unkCount1; - int unkCount2; - char unknown1[16]; - GfxWorldDpvsPlanes dpvsPlanes; //The following rely on the count in this + unsigned int surfaceCount; + int skyCount; + GfxSky *skies; + unsigned int lastSunPrimaryLightIndex; + unsigned int primaryLightCount; + unsigned int sortKeyLitDecal; + unsigned int sortKeyEffectDecal; + unsigned int sortKeyEffectAuto; + unsigned int sortKeyDistortion; + GfxWorldDpvsPlanes dpvsPlanes; GfxCellTreeCount *aabbTreeCounts; GfxCellTree *aabbTrees; GfxCell *cells; - GfxWorldDraw worldDraw; + GfxWorldDraw draw; GfxLightGrid lightGrid; int modelCount; GfxBrushModel *models; - float mins[3]; - float maxs[3]; + Bounds bounds; unsigned int checksum; int materialMemoryCount; MaterialMemory *materialMemory; sunflare_t sun; - char pad[64]; - GfxImage* unknownImage; - unsigned int *cellCasterBits[2]; + float outdoorLookupMatrix[4][4]; + GfxImage *outdoorImage; + unsigned int *cellCasterBits; + unsigned int *cellHasSunLitSurfsBits; GfxSceneDynModel *sceneDynModel; GfxSceneDynBrush *sceneDynBrush; unsigned int *primaryLightEntityShadowVis; unsigned int *primaryLightDynEntShadowVis[2]; - char *primaryLightForModelDynEnt; + char *nonSunPrimaryLightForModelDynEnt; GfxShadowGeometry *shadowGeom; GfxLightRegion *lightRegion; GfxWorldDpvsStatic dpvs; GfxWorldDpvsDynamic dpvsDyn; - int pad2; + unsigned int mapVtxChecksum; unsigned int heroOnlyLightCount; - char * heroOnlyLight; - int unknown5; + GfxHeroOnlyLight *heroOnlyLights; + char fogTypesAllowed; }; #pragma pack(pop) From 4f608b3a19b17a2ebbadadb83b23583263144840 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 26 Dec 2016 01:44:45 +0100 Subject: [PATCH 4/5] [IGfxImage] Non-streamed image importer --- .../Modules/AssetInterfaces/IGfxImage.cpp | 125 ++++++++++-------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp index a6709810..8b967b1b 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -1,5 +1,7 @@ #include +#define IW4X_IMG_VERSION "0" + namespace Assets { void IGfxImage::load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) @@ -19,71 +21,90 @@ namespace Assets image->category = 0; image->cardMemory = 0; - image->loadDef = builder->getAllocator()->allocate(); - if (!image->loadDef) + const char* tempName = image->name; + if (tempName[0] == '*') tempName++; + + Components::FileSystem::File imageFile(fmt::sprintf("images/%s.iw4xImage", tempName)); + if (imageFile.exists()) { - Components::Logger::Error("Failed to allocate GfxImageLoadDef structure!"); - return; + Utils::Stream::Reader reader(builder->getAllocator(), imageFile.getBuffer()); + + if (reader.read<__int64>() != *reinterpret_cast<__int64*>("IW4xImg" IW4X_IMG_VERSION)) + { + Components::Logger::Error(0, "Reading image '%s' failed, header is invalid!", name.data()); + } + + AssertSize(Game::MapType, 1); + image->mapType = reader.read(); + image->semantic = reader.read(); + image->category = reader.read(); + + image->dataLen1 = reader.read(); + image->dataLen2 = image->dataLen1; + + image->loadDef = reinterpret_cast(reader.readArray(image->dataLen1 + 16)); } - - char nameBuffer[MAX_PATH] = { 0 }; - Components::Materials::FormatImagePath(nameBuffer, sizeof(nameBuffer), 0, 0, name.data()); - Components::FileSystem::File iwi(nameBuffer); - - if (!iwi.exists()) + else { - Components::Logger::Error("Loading image '%s' failed!", iwi.getName().data()); - return; - } + char nameBuffer[MAX_PATH] = { 0 }; + Components::Materials::FormatImagePath(nameBuffer, sizeof(nameBuffer), 0, 0, name.data()); + Components::FileSystem::File iwi(nameBuffer); - auto iwiBuffer = iwi.getBuffer(); - - const Game::GfxImageFileHeader* iwiHeader = reinterpret_cast(iwiBuffer.data()); - - image->mapType = Game::MAPTYPE_2D; - image->dataLen1 = iwiHeader->fileSizeForPicmip[0] - 32; - image->dataLen2 = iwiHeader->fileSizeForPicmip[0] - 32; - - if (std::memcmp(iwiHeader->tag, "IWi", 3)) - { - Components::Logger::Error("Image is not a valid IWi!"); - return; - } - - std::memcpy(image->loadDef->dimensions, iwiHeader->dimensions, 6); - image->loadDef->flags = 0; - image->loadDef->levelCount = 0; - - switch (iwiHeader->format) - { - case Game::IWI_COMPRESSION::IWI_ARGB: + if (!iwi.exists()) { - image->loadDef->format = 21; - break; + Components::Logger::Error("Loading image '%s' failed!", iwi.getName().data()); + return; } - case Game::IWI_COMPRESSION::IWI_RGB8: + auto iwiBuffer = iwi.getBuffer(); + + const Game::GfxImageFileHeader* iwiHeader = reinterpret_cast(iwiBuffer.data()); + + image->mapType = Game::MAPTYPE_2D; + image->dataLen1 = iwiHeader->fileSizeForPicmip[0] - 32; + image->dataLen2 = iwiHeader->fileSizeForPicmip[0] - 32; + + if (std::memcmp(iwiHeader->tag, "IWi", 3) && iwiHeader->version == 8) { - image->loadDef->format = 20; - break; + Components::Logger::Error("Image is not a valid IWi!"); + return; } - case Game::IWI_COMPRESSION::IWI_DXT1: - { - image->loadDef->format = 0x31545844; - break; - } + std::memcpy(image->loadDef->dimensions, iwiHeader->dimensions, 6); + image->loadDef->flags = 0; + image->loadDef->levelCount = 0; - case Game::IWI_COMPRESSION::IWI_DXT3: + switch (iwiHeader->format) { - image->loadDef->format = 0x33545844; - break; - } + case Game::IWI_COMPRESSION::IWI_ARGB: + { + image->loadDef->format = 21; + break; + } - case Game::IWI_COMPRESSION::IWI_DXT5: - { - image->loadDef->format = 0x35545844; - break; + case Game::IWI_COMPRESSION::IWI_RGB8: + { + image->loadDef->format = 20; + break; + } + + case Game::IWI_COMPRESSION::IWI_DXT1: + { + image->loadDef->format = 0x31545844; + break; + } + + case Game::IWI_COMPRESSION::IWI_DXT3: + { + image->loadDef->format = 0x33545844; + break; + } + + case Game::IWI_COMPRESSION::IWI_DXT5: + { + image->loadDef->format = 0x35545844; + break; + } } } From 3406baca4d3ff60a7bd5d3ccef009627d8ffee0b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 26 Dec 2016 02:27:54 +0100 Subject: [PATCH 5/5] [IGfxWorld] Fix portal importing --- src/Components/Modules/AssetInterfaces/IGfxWorld.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 2d8b393e..b3f82e9d 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -81,7 +81,10 @@ namespace Assets for (int j = 0; j < cell->portalCount; ++j) { - cell->portals[i].vertices = reader.readArray(cell->portals[i].vertexCount); + if (cell->portals[j].vertices) + { + cell->portals[j].vertices = reader.readArray(cell->portals[j].vertexCount & 0xFF); + } } }