feat: IW3 d3dbsp dumping / loading#834
Open
michaeloliverx wants to merge 35 commits into
Open
Conversation
OAT linked + unlinked `.d3dbsp` can be read by IW3xRadiant viewer
This preserves lightdef names, reads the disk exponent field, derives cosHalfFovExpanded like the linker, and uses the stock sun-light index convention.
Also mirrors linker_pc angle/quaternion conversion behaviour for dynamic entity poses.
Use the loaded leaf cluster value directly and recover firstLeafBrush from the packed leafbrush cursor when OAT-built fastfiles contain copied per-node leafbrush arrays. This keeps static model visibility intact when dumping BSPs from OAT-built fastfiles.
Recover raw leafbrush offsets when leaf brush nodes contain copied per-node arrays instead of pointers into the shared leafbrush list, preserving byte-identical BSP dumps after OAT round trips.
Rebuild clipmap leafbrush nodes, box hull data, visibility fallback, material content masking, and collision partition pointers from raw BSP data. Also improve d3dbsp dumping of raw material contents, leafbrush ranges, and submodel brush/AABB ranges for more stable linker_pc-compatible round trips.
OAT-built fastfiles from raw d3dbsp data now load into game with no crashes. World is not rendering at this time.
LUMP_MODELS = 37 is now byte identical with this change
This makes dumped d3dbsp lumps DRAWINDICES and UNLAYERED_DRAWINDICES byte exact compared to a linker_pc-built ff.
This makes dumped d3dbsp lumps DRAWVERTS and SIMPLE_VERTS byte exact compared to a linker_pc-built ff.
Recompute linker-style drawSurf sort keys for BSP world materials before sorting surfaces, including pixel-constant tie breakers and camera-region fallbacks for referenced techsets. This makes dumped d3dbsp TRIANGLES and SIMPLE_TRI_SOUPS lumps byte-exact compared to a linker_pc-built fastfile.
Use linker_pc-compatible misc_model key lookup, vector/scale parsing, angle matrix intermediates, and inverse-scale packing. This makes dumped d3dbsp lump 39 ENTITIES byte-identical between linker_pc-built and OAT-built fastfiles for the same source BSP.
Reconstruct static model primary light data and AABB tree handling closely enough for OAT-built and linker_pc-built fastfiles from the same source d3dbsp to dump byte-identical raw d3dbsp output. Also emits a canonical decal-split SIMPLE_AABBTREES lump instead of preserving unstable runtime zero-padding.
Improve the triangle key hash used for coincident surface lookup so 32-bit MSVC builds do not collapse dense map geometry into huge unordered_map buckets. Also store only the first triangle key per surface, matching the linker_pc decal classification behaviour while avoiding unnecessary per-surface key vectors.
|
Reconstruct dyn_model entity blocks from clipMap
michaeloliverx
marked this pull request as ready for review
June 24, 2026 10:55
Contributor
Author
Contributor
Author
|
Relates to #532 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

[WIP] This needs cleanup and review, especially around structure/readability, but the core IW3 d3dbsp loader/dumper path is now working and producing linker_pc-compatible output.
Scope
IW3 raw .d3dbsp files use IBSP version
22with named/typed chunks. The current loader/dumper work targets this v22 CoD4 Mod Tools format.Radiant still has internal raw BSP/world loading code embedded in the executable. IW3xRadiant exposes that path, and the stock asserts/sanity checks have been useful for validating generated BSPs. Also the CoD4 decomp still has raw bsp loading code: https://github.com/SwagSoftware/KisakCOD/blob/1d8ff8d579187354ff595cce9477f2f78d5f2382/src/qcommon/cm_load_obj.cpp#L343
Current status
My primary testing map has been mp_backlot because the devs gave the full map source for it in the mod tools. The original
cod4map.exeBSP is not expected to be byte-identical to the dumped fixed point.linker_pcconsumes and normalizes parts of the source BSP into runtime assets, then OAT dumps the canonical post-link representation.Given the same source
.d3dbspproduced bycod4map.exe, the dumped raw BSP output is now byte-identical between the stock linker and OAT:Both dumped BSPs have
35chunks and all35 / 35are byte-identical:Source BSP vs Dumped BSP
16 chunks byte-identical
13 chunks same-size byte diffs
6 chunks size diffs
4 source chunks omitted from dumped fixed point
Byte-identical source chunks:
Source chunks not emitted in the dumped fixed point:
These chunks are also omitted by the
linker_pc-origin dump, so this is not an OAT-only omission.Notes on the omitted chunks:
Resources
CM_LoadMapFromBspAI Disclaimer
AI assistance was heavily used during reverse engineering and implementation, especially for the loader. The output has been validated against
linker_pcand runtime/Radiant loading tests described above.