Graphics Map Asset (MW2): Difference between revisions
| Line 409: | Line 409: | ||
==== Notes ==== | ==== Notes ==== | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
// sceneEntCellBits count = cellCount << 9 uint32_t values. | // sceneEntCellBits count = cellCount << 9 uint32_t values. | ||
// rowDataStart count = maxs[rowAxis] - mins[rowAxis] + 1 uint16_t values. | // rowDataStart count = maxs[rowAxis] - mins[rowAxis] + 1 uint16_t values. | ||
Latest revision as of 22:25, 5 July 2026
The graphics map (or gfx_map) has existed on every Call of Duty so far and is part of the D3DBSP system produced by Radiant. Where the collision map is used for collision data in the map, the graphics map holds visual systems such as lights and particularly the dPVS system. The Dynamic Potentially Visible Sets (dPVS) were developed by Umbra Software to compute visibility databases in real time, and power the Call of Duty engine to this day.
Rendering
Structures
#pragma pack(push, 4)
typedef struct GfxImage GfxImage;
typedef struct Material Material;
typedef struct XModel XModel;
typedef struct DpvsPlane
{
float normal[3];
float dist;
uint8_t type;
uint8_t signbits;
uint16_t pad12;
} DpvsPlane; // 0x14
typedef struct GfxWorldDpvsPlanes
{
int32_t cellCount;
DpvsPlane *planes;
uint16_t *nodes;
uint32_t *sceneEntCellBits;
} GfxWorldDpvsPlanes; // 0x10
typedef struct GfxSky
{
int32_t skySurfCount;
int32_t *skyStartSurfs;
GfxImage *skyImage;
int32_t skySamplerState;
} GfxSky; // 0x10
typedef struct GfxCellTreeCount
{
uint32_t aabbTreeCount;
} GfxCellTreeCount; // 0x04
typedef struct GfxAabbTree
{
float mins[3];
float maxs[3];
uint16_t childCount;
uint16_t surfaceCount;
uint16_t startSurfIndex;
uint16_t smodelIndexCount;
uint16_t *smodelIndexes;
int32_t childrenOffset;
} GfxAabbTree; // 0x28
typedef struct GfxCellTree
{
GfxAabbTree *aabbTrees;
} GfxCellTree; // 0x04
typedef struct GfxPortalVertex
{
float xyz[3];
} GfxPortalVertex; // 0x0C
typedef struct GfxPortal
{
uint8_t isQueued;
uint8_t isAncestor;
uint8_t recursionDepth;
uint8_t hullPointCount;
int32_t hullPointsRuntimePointer;
DpvsPlane plane;
GfxPortalVertex *vertices;
uint8_t unknown20To21[2];
uint8_t vertexCount;
uint8_t pad23;
float hullAxis[2][3];
} GfxPortal; // 0x3C
typedef struct GfxCell
{
float mins[3];
float maxs[3];
int32_t portalCount;
GfxPortal *portals;
uint8_t reflectionProbeCount;
uint8_t pad21[3];
uint8_t *reflectionProbes;
} GfxCell; // 0x28
typedef struct GfxReflectionProbe
{
float offset[3];
} GfxReflectionProbe; // 0x0C
typedef struct GfxTexture
{
uint32_t words[6];
} GfxTexture; // 0x18
typedef struct GfxLightmapArray
{
GfxImage *primary;
GfxImage *secondary;
} GfxLightmapArray; // 0x08
typedef struct GfxWorldVertexData
{
uint8_t *vertices;
int32_t worldVbHandle;
int32_t worldVbOffset;
} GfxWorldVertexData; // 0x0C
typedef struct GfxWorldVertexLayerData
{
uint8_t *data;
int32_t layerVbHandle;
int32_t layerVbOffset;
} GfxWorldVertexLayerData; // 0x0C
typedef struct GfxWorldDraw
{
uint32_t reflectionProbeCount;
GfxImage **reflectionImages;
GfxReflectionProbe *reflectionProbes;
GfxTexture *reflectionProbeTextures;
int32_t lightmapCount;
GfxLightmapArray *lightmaps;
GfxTexture *lightmapPrimaryTextures;
GfxTexture *lightmapSecondaryTextures;
GfxImage *skyImage;
GfxImage *outdoorImage;
uint32_t vertexCount;
GfxWorldVertexData vd;
uint32_t vertexLayerDataSize;
GfxWorldVertexLayerData vld;
int32_t indexCount;
uint16_t *indices;
int32_t indexBufferRaw;
} GfxWorldDraw; // 0x54
typedef struct GfxLightGridEntry
{
uint16_t colorsIndex;
uint8_t primaryLightIndex;
uint8_t needsTrace;
} GfxLightGridEntry; // 0x04
typedef struct GfxLightGridColors
{
uint8_t rgb[56][3];
} GfxLightGridColors; // 0xA8
typedef struct GfxLightGrid
{
uint32_t hasLightRegions;
uint32_t sunPrimaryLightIndex;
uint16_t mins[3];
uint16_t maxs[3];
uint32_t rowAxis;
uint32_t colAxis;
uint16_t *rowDataStart;
uint32_t rawRowDataSize;
uint8_t *rawRowData;
uint32_t entryCount;
GfxLightGridEntry *entries;
uint32_t colorCount;
GfxLightGridColors *colors;
} GfxLightGrid; // 0x38
typedef struct GfxBrushModel
{
float writableMins[3];
float writableMaxs[3];
float boundsMins[3];
float boundsMaxs[3];
uint32_t surfaceCount;
uint32_t startSurfIndex;
} GfxBrushModel; // 0x38
typedef struct MaterialMemory
{
Material *material;
int32_t memory;
} MaterialMemory; // 0x08
typedef struct Sunflare
{
uint32_t hasValidData;
Material *spriteMaterial;
Material *flareMaterial;
float spriteSize;
float flareMinSize;
float flareMinDot;
float flareMaxSize;
float flareMaxDot;
float flareMaxAlpha;
int32_t flareFadeInTime;
int32_t flareFadeOutTime;
float blindMinDot;
float blindMaxDot;
float blindMaxDarken;
int32_t blindFadeInTime;
int32_t blindFadeOutTime;
float glareMinDot;
float glareMaxDot;
float glareMaxLighten;
int32_t glareFadeInTime;
int32_t glareFadeOutTime;
float sunFxPosition[3];
} Sunflare; // 0x60
typedef struct GfxSceneDynModel
{
uint16_t lod;
uint16_t surfId;
uint16_t dynEntId;
} GfxSceneDynModel; // 0x06
typedef struct GfxSceneDynBrush
{
uint16_t surfId;
uint16_t dynEntId;
} GfxSceneDynBrush; // 0x04
typedef struct GfxShadowGeometry
{
uint16_t surfaceCount;
uint16_t smodelCount;
uint16_t *sortedSurfIndex;
uint16_t *smodelIndex;
} GfxShadowGeometry; // 0x0C
typedef struct GfxLightRegionAxis
{
float dir[3];
float midPoint;
float halfSize;
} GfxLightRegionAxis; // 0x14
typedef struct GfxLightRegionHull
{
float kdopMidPoint[9];
float kdopHalfSize[9];
uint32_t axisCount;
GfxLightRegionAxis *axis;
} GfxLightRegionHull; // 0x50
typedef struct GfxLightRegion
{
int32_t hullCount;
GfxLightRegionHull *hulls;
} GfxLightRegion; // 0x08
typedef struct GfxPackedPlacement
{
float origin[3];
uint32_t packedAxis[3];
float scale;
} GfxPackedPlacement; // 0x1C
typedef struct GfxStaticModelInst
{
float mins[3];
float maxs[3];
uint32_t groundLighting;
uint8_t unknown1CTo23[8];
} GfxStaticModelInst; // 0x24
typedef struct SrfTriangles
{
int32_t vertexLayerData;
int32_t baseVertex;
uint32_t minVertexIndex;
uint16_t vertexCount;
uint16_t triCount;
int32_t baseIndex;
} SrfTriangles; // 0x14
typedef struct GfxSurface
{
SrfTriangles tris;
Material *material;
uint8_t lightmapIndex;
uint8_t reflectionProbeIndex;
uint8_t primaryLightIndex;
uint8_t castsSunShadow;
} GfxSurface; // 0x1C
typedef union GfxMapDrawSurf
{
uint64_t packed;
} GfxMapDrawSurf; // 0x08
typedef struct GfxCullGroup
{
float mins[3];
float maxs[3];
int32_t surfaceCount;
int32_t startSurfIndex;
} GfxCullGroup; // 0x20
typedef struct GfxStaticModelDrawInst
{
GfxPackedPlacement placement;
XModel *model;
uint16_t cullDist;
uint16_t lightingHandle;
uint8_t reflectionProbeIndex;
uint8_t primaryLightIndex;
uint8_t flags;
uint8_t firstMaterialSkinIndex;
uint8_t unknown28;
uint8_t unknown29;
uint8_t unknown2A;
uint8_t unknown2B;
} GfxStaticModelDrawInst; // 0x2C
typedef struct GfxWorldDpvsStatic
{
uint32_t smodelCount;
uint32_t staticSurfaceCount;
uint32_t litSurfsBegin;
uint32_t litSurfsEnd;
uint32_t visibilityCounts[8];
uint32_t *smodelVisData[3];
uint32_t *surfaceVisData[3];
uint16_t *sortedSurfIndex;
GfxStaticModelInst *smodelInsts;
GfxSurface *surfaces;
GfxCullGroup *cullGroups;
GfxStaticModelDrawInst *smodelDrawInsts;
GfxMapDrawSurf *surfaceMaterials;
uint32_t *surfaceCastsSunShadow;
volatile uint32_t usageCount;
} GfxWorldDpvsStatic; // 0x68
typedef struct GfxWorldDpvsDynamic
{
uint32_t dynEntClientWordCount[2];
uint32_t dynEntClientCount[2];
uint32_t *dynEntCellBits[2];
uint8_t *dynEntVisData[6];
} GfxWorldDpvsDynamic; // 0x30
typedef struct GfxHeroOnlyLight
{
uint8_t bytes[0x38];
} GfxHeroOnlyLight; // 0x38
typedef struct GfxWorld
{
const char *name;
const char *baseName;
int32_t planeCount;
int32_t nodeCount;
int32_t surfaceCount;
uint32_t skyCount;
GfxSky *skies;
int32_t primaryLightFirstShadowable;
int32_t primaryLightCount;
int32_t sortKeyLitDecal;
int32_t sortKeyEffectDecal;
int32_t sortKeyEffectAuto;
int32_t sortKeyDistortion;
GfxWorldDpvsPlanes dpvsPlanes;
GfxCellTreeCount *cellTreeCounts;
GfxCellTree *cellTrees;
GfxCell *cells;
GfxWorldDraw worldDraw;
GfxLightGrid lightGrid;
int32_t modelCount;
GfxBrushModel *models;
float mins[3];
float maxs[3];
uint32_t checksum;
int32_t materialMemoryCount;
MaterialMemory *materialMemory;
Sunflare sun;
float outdoorLookupMatrix[16];
GfxImage *outdoorImage;
uint32_t *cellCasterBits;
uint32_t *cellCasterBits2;
GfxSceneDynModel *sceneDynModel;
GfxSceneDynBrush *sceneDynBrush;
uint32_t *primaryLightEntityShadowVis;
uint32_t *primaryLightDynEntShadowVis[2];
uint8_t *primaryLightForModelDynEnt;
GfxShadowGeometry *shadowGeom;
GfxLightRegion *lightRegion;
GfxWorldDpvsStatic dpvs;
GfxWorldDpvsDynamic dpvsDyn;
uint32_t unknown26C;
uint32_t heroOnlyLightCount;
GfxHeroOnlyLight *heroOnlyLights;
uint32_t unknown278;
int32_t umbraGateCount;
uint8_t *umbraGateData;
uint8_t *umbraGateData2;
} GfxWorld; // 0x288 on PS3/32-bit
#pragma pack(pop)Notes
// sceneEntCellBits count = cellCount << 9 uint32_t values.
// rowDataStart count = maxs[rowAxis] - mins[rowAxis] + 1 uint16_t values.
// vertices payload size = vertexCount * 0x10 bytes.
// vertexLayerData payload size = vertexLayerDataSize bytes.
// cellCasterBits count = cellCount * ((cellCount + 31) >> 5) uint32_t values.
// cellCasterBits2 count = ((cellCount + 31) >> 5) uint32_t values.
// sceneDynModel count = dpvsDyn.dynEntClientCount[0].
// sceneDynBrush count = dpvsDyn.dynEntClientCount[1].
// primaryLightEntityShadowVis count = max(0, primaryLightCount - primaryLightFirstShadowable - 1) * 0x2000 uint32_t values.
// primaryLightDynEntShadowVis[0] count = same shadowable tail * sceneDynModel count.
// primaryLightDynEntShadowVis[1] count = same shadowable tail * sceneDynBrush count.
// primaryLightForModelDynEnt count = sceneDynModel count bytes.
// dpvs.smodelVisData[i] count = dpvs.visibilityCounts[6] uint32_t values.
// dpvs.surfaceVisData[i] count = dpvs.visibilityCounts[7] uint32_t values.
// dpvs.sortedSurfIndex count = dpvs.staticSurfaceCount uint16_t values.
// dpvs.smodelInsts and dpvs.smodelDrawInsts count = dpvs.smodelCount.
// dpvs.surfaces, dpvs.cullGroups, and dpvs.surfaceMaterials count = surfaceCount.
// dpvs.surfaceCastsSunShadow count = dpvs.visibilityCounts[7] uint32_t values.
// dpvsDyn.dynEntCellBits[i] count = dynEntClientWordCount[i] * dpvsPlanes.cellCount uint32_t values.
// dpvsDyn.dynEntVisData load order is [0, 3, 1, 4, 2, 5].
// dpvsDyn.dynEntVisData[0..2] byte size = dynEntClientWordCount[0] << 5.
// dpvsDyn.dynEntVisData[3..5] byte size = dynEntClientWordCount[1] << 5.
// heroOnlyLights count = heroOnlyLightCount, stride 0x38.
// umbraGateData and umbraGateData2 byte size = umbraGateCount + 0x1000.Keep in mind that the checksum is checked on other clients using the mapcrc dvar.