Work-Package: M00-QAR-VISUAL-DIFF-001 Agent: sindo-main-codex Tests: synthetic JPG/PNG diff, manifest, coordination and documentation gates Fidelity: five build 12340 references compared; coordinate and placement gaps recorded
OpenWC
Портирование клиента World of Warcraft 3.3.5a (12340) на Godot 4.6.
Текущий фокус проекта: загрузка данных из клиента, разбор форматов WoW и отображение мира в Godot так, чтобы его можно было смотреть и дальше редактировать уже средствами движка.
Целевая архитектура клиента, Godot Editor-инструментов, Content Project, интеграции с TrinityCore/AzerothCore и тестовой стратегии собрана в docs/README.md. Фактическое состояние renderer-подсистемы ведётся в RENDER.md.
Текущая последовательность реализации и критерии завершения находятся в targets/README.md; правила работы агентов — в AGENTS.md.
Сейчас проект уже умеет:
- открывать MPQ-архивы клиента через editor plugin;
- извлекать файлы из MPQ в
res://data/extracted; - читать
BLP2текстуры; - читать
ADT-тайлы terrain; - рендерить terrain из
ADTс текстурными слоямиMCLY/MCAL; - учитывать
holesвMCNK; - читать и рендерить воду из
MH2O; - стримить мир чанками с LOD в runtime;
- стримить мир в editor preview по мере движения камеры в 3D viewport;
- читать
WDTи собирать состав мира по данным карты, а не по сканированию папки; - читать
WMOи автоматически расставлять его в мире через world-level registry с дедупом поunique_id(WMO на границе тайлов не дублируется); - подхватывать глобальный WMO из
WDT.MWMO/MODFдля WMO-only карт (инстансы); - читать
M2(MD20 + SKIN00) и ставить его черезMultiMeshиз ADT doodad placements.
Что пока не доведено до полноценного world renderer:
- вода без простого базового материала: нет нормального water shader, depth fade, shoreline blending, анимации;
- M2 renderer статический: material flags (cull/unshaded), blend modes 2+, billboards для листвы и UV-transform'ы не применяются; анимация/скиннинг не парсятся;
- импорт обратно в форматы WoW;
- полноценные инструменты редактирования мира в editor.
Текущее состояние
Реализовано
MPQManager- открытие клиентских архивов;
- список архивов по приоритету;
- listing/extract по фильтру.
BLPLoader- чтение
BLP2из файла или из байтов; - поддержка основных сжатых форматов, достаточная для terrain textures.
- чтение
ADTLoaderMTEX,MMDX/MMID,MWMO/MWID;MDDF,MODF(сunique_id,flags,doodad_set,name_set);MCVT,MCNR,MCLY,MCAL;holes;MH2O.
WDTLoaderMVER,MPHD(flags карты: global_wmo / big_alpha / sort_by_size_class);MAIN— таблица присутствия 64×64 ADT-тайлов;MWMO+MODF— глобальный WMO для инстансных/WMO-only карт.
ADTBuilder- сборка terrain в
Node3D; - terrain material с 4 слоями;
- legacy/big/compressed alpha;
- chunk-level LOD;
- первый проход рендера воды.
- сборка terrain в
StreamingWorld- runtime streaming тайлов и чанков;
- editor streaming вокруг камеры viewport;
- состав мира берётся из
WDT(fallback на папочный скан, если.wdtотсутствует); - отдельные
ADT-узлы подTerrainв дереве сцены; - world-level WMO registry с refcount-дедупом по
unique_id: WMO живёт пока на него ссылается хотя бы один загруженный тайл.
WMOLoader/WMOBuilder- root/group parsing;
WMOBuilderсобирает mesh по группам;- интегрирован в
StreamingWorldчерез world-level registry; - глобальный WMO из
WDTставится один раз при загрузке карты.
M2Loader/M2Builder- парсинг
MD20+SKIN00: vertices/normals/UVs, materials (flags + blend_mode), texture combos, batches; M2BuilderсобираетArrayMesh+StandardMaterial3D;- в
StreamingWorldрасставляется черезMultiMeshизADT.MDDF.
- парсинг
Частично реализовано
M2renderer- статическая геометрия рендерится корректно;
- material flags пока не применяются (cull_mode, unshaded, depth_write);
- blend modes 2+ (additive / modulate) схлопнуты в обычный alpha;
- билборды (leaf bones) не распознаются — листва деревьев плоская;
- UV-трансформы (waterfalls, флаги, порталы) не применяются.
Не реализовано
- скиннинг и анимации
M2(bones, key frames); - particles / ribbons;
- сохранение terrain/liquid/object placement обратно в WoW-форматы;
- редакторские инструменты изменения ADT/WMO данных.
Структура проекта
sources/- исходный клиент WoW 3.3.5a, без модификаций.
data/extracted/- извлечённые из MPQ файлы, с которыми работает Godot.
data/cache/- generated/offline cache: baked terrain, M2 GLB cache, WMO scene cache. Эти файлы не являются исходниками проекта и игнорируются git.
addons/mpq_extractor/- editor plugin и GDScript-сборщики сцен.
src/native/- C++ GDExtension: MPQ, BLP, ADT, WMO.
src/scenes/- готовые сцены для просмотра мира.
src/tools/- bake/conversion scripts.
src/resources/- Godot resources, generated GLB assets and runtime resource scripts.
reference/- external reference sources/tools: Blender WoW Studio, wow.export and Noggit RED. Runtime-project must not depend on this directory.
reference/noggit-red/- Noggit RED source reference for WoW 3.3.5 map editing, ADT/WMO/M2 placement behavior and UID workflows.
- внешние reference sources и tools для сверки форматов. Runtime-проект не должен зависеть от этой директории.
third_party/godot-cpp,StormLibи другие зависимости.
Требования
- Windows
- Godot
4.6 - Visual Studio 2022 с C++ workload
- CMake
- клиент WoW 3.3.5a (12340)
Сборка
Собрать GDExtension:
cd src\native
build.bat Release
После успешной сборки DLL появится в:
addons/mpq_extractor/bin/
VS Code/CMake использует src/native как cmake.sourceDirectory.
Подготовка данных
По умолчанию plugin смотрит на клиент в:
res://sources
И извлекает файлы в:
res://data/extracted
Через editor plugin
- Открой проект в Godot.
- Убедись, что plugin
MPQ Extractorвключён. - Внизу editor открой панель
MPQ Extractor. - Укажи путь к клиенту WoW 3.3.5a.
- Выбери locale.
- Нажми
Open Client Archives. - Для полной распаковки используй фильтр
*иExtract.
Для terrain/world обычно нужны как минимум:
World/Maps/...Textures/...World/wmo/...DBFilesClient/...если позже понадобится работа с DBC
Основные классы GDExtension
MPQManager
Доступен из GDScript. Основные методы:
open_client(base_path, locale)list_files(filter="*")extract_files(filter, output_dir)read_file(internal_path)
BLPLoader
Читает WoW BLP2 и возвращает Image.
Основные методы:
load_image(path)load_image_from_bytes(bytes)
ADTLoader
Читает ADT и возвращает Dictionary с terrain, texture layers, placements и liquid.
Основные поля результата:
texturesm2_nameswmo_namesm2_placementswmo_placementschunks
Каждый chunk содержит:
index_x,index_yoriginheightsnormalsholeslayersalpha_mapsliquids
WMOLoader
Читает root/group файлы WMO и возвращает Dictionary с materials и groups.
Подключён в StreamingWorld через world-level registry. Дедуп по unique_id из ADT.MODF, refcount по тайлам.
WDTLoader
Читает WDT карты и возвращает Dictionary:
version—MVER(ожидается 18);flags,has_global_wmo,big_alpha,sort_by_size_class— изMPHD;tiles: Array[Dictionary]— присутствующие тайлы{x, y, flags}изMAIN;global_wmo_name: String+global_wmo_placement: Dictionary— если карта WMO-only.
StreamingWorld по умолчанию строит мир из этого списка. Папочный скан остаётся fallback'ом.
M2Loader
Читает .m2 (MD20) + <basename>00.skin и возвращает Dictionary с геометрией:
textures,materials(flags,blend_mode),texture_combos;vertices,normals,uvs,indices;batches: Array[Dictionary]—{index_start, index_count, material_id, texture_combo_index}.
Кости, анимации и частицы пока не читаются.
Export/bake scripts
Все проектные скрипты экспорта и запекания лежат в src/tools/. Скрипты с расширением .gd запускаются через Godot headless и требуют собранный GDExtension, потому что используют ADTLoader, M2Loader и WMOLoader. Перед запуском данные клиента должны быть извлечены в res://data/extracted.
Если godot не добавлен в PATH, используй путь из .vscode/settings.json, например:
& 'c:\Godot 4.6\Godot_v4.6.1-stable_win64.exe' --headless --path . --script res://src/tools/bake_all.gd -- --map Azeroth --force
src/tools/bake_all.gd
Запекает terrain, M2 doodads и WMO objects за один проход.
godot --headless --path . --script res://src/tools/bake_all.gd -- --map Azeroth --force
Основные аргументы:
--map Azeroth--extracted res://data/extracted--terrain-output res://data/cache/baked_terrain_v2--m2-output res://data/cache/m2_glb--wmo-output res://data/cache/wmo_tscn--full-texture-size 2048--coarse-texture-size 512--skip-terrain,--skip-m2,--skip-wmo--force
src/tools/bake_adt_terrain_cache.gd
Запекает terrain tiles в .res ресурсы BakedADTTile. Runtime streaming читает их из baked_tile_cache_dir.
godot --headless --path . --script res://src/tools/bake_adt_terrain_cache.gd -- --map Azeroth --output res://data/cache/baked_terrain_v2 --force
Основные аргументы:
--map Azeroth--extracted res://data/extracted--output res://data/cache/baked_terrain_v2--tile-x 32,--tile-y 48для одного тайла--full-texture-size 2048--coarse-texture-size 512--texture-size Nlegacy alias для обоих размеров--force
src/tools/bake_m2_cache.gd
Сканирует ADT tiles, собирает уникальные M2 paths и запекает M2 doodads в PackedScene .tscn.
godot --headless --path . --script res://src/tools/bake_m2_cache.gd -- --map Azeroth --output res://data/cache/m2_glb --force
Основные аргументы:
--map Azeroth--extracted res://data/extracted--output res://data/cache/m2_glb--force
src/tools/bake_wmo_cache.gd
Сканирует ADT tiles, собирает уникальные WMO paths и запекает WMO world objects в PackedScene .tscn.
godot --headless --path . --script res://src/tools/bake_wmo_cache.gd -- --map Azeroth --output res://data/cache/wmo_tscn --force
Основные аргументы:
--map Azeroth--extracted res://data/extracted--output res://data/cache/wmo_tscn--force
src/tools/collect_world_m2_list.gd
Сканирует ADT tiles и сохраняет список уникальных M2 paths. Полезно перед массовой конвертацией или для оценки объема M2 cache.
godot --headless --path . --script res://src/tools/collect_world_m2_list.gd -- --map Azeroth --output res://data/cache/m2_glb/Azeroth_m2_list.txt
Основные аргументы:
--map Azeroth--extracted res://data/extracted--output res://data/cache/m2_glb/Azeroth_m2_list.txt
src/tools/m2_to_gltf.py
Python converter для WoW 3.3.5 M2 v264 в GLTF 2.0 .glb. Также экспортирует texture layers рядом с GLB. Для DXT BLP decoding нужен Pillow.
Один M2:
python src/tools/m2_to_gltf.py data/extracted/Character/BloodElf/Female/BloodElfFemale.M2 src/resources/characters/BloodElf/Female
Рекурсивная конвертация:
python src/tools/m2_to_gltf.py --all data/extracted/Character --out src/resources/characters
Аргументы:
inputпуть к одному.M2output_dirдиректория вывода для одного.M2--all SEARCH_DIRрекурсивно конвертирует все.M2под директорией--out OUT_ROOTroot вывода для--all; по умолчаниюsrc/resources
Reference-only export scripts
В reference/ лежат внешние скрипты и исходники для сверки форматов, включая Blender/WoW export tools из reference/ и reference/wow.export/. Они не являются частью project pipeline, не вызываются runtime-кодом и не должны использоваться как источник project cache без явного переноса в src/tools/.
Найденные reference scripts, связанные с export/conversion:
reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/export_m2.pyreference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/convert_m2_bones.pyreference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/m2_export_validation.pyreference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/wmo/export_wmo.pyreference/wow.export/addons/blender/io_scene_wowobj/animation_processor.pyreference/wow.export/addons/blender/io_scene_wowobj/import_wowobj.pyreference/wow.export/addons/blender/io_scene_wowobj/__init__.py
toolbar.py files в reference UI directories относятся к Blender UI этих внешних tools и не являются самостоятельными export/bake entrypoints.
reference/noggit-red/ is not an export script collection. It is a source reference for WoW 3.3.5 map editing behavior: ADT/WMO/M2 placement, UID handling, map editing workflows and related editor code.
GDScript-сборщики
ADTBuilder
Файл: addons/mpq_extractor/loaders/adt_builder.gd
Умеет:
- собрать весь
ADTвNode3D; - собрать отдельный chunk с нужным LOD;
- собрать water root для тайла;
- создать layered terrain material;
- загрузить BLP-текстуры через
BLPLoader.
WMOBuilder
Файл: addons/mpq_extractor/loaders/wmo_builder.gd
Умеет:
- собрать
Node3Dиз данныхWMOLoader; - создать по одному
MeshInstance3Dна группу; - назначить базовые материалы.
Сцены просмотра
src/scenes/streaming/test.tscn
Файл: src/scenes/streaming/test.tscn
Тестовая сцена, которая грузит квадрат тайлов вокруг центра карты.
Скрипт: src/scenes/streaming/test_world_loader.gd
Подходит для:
- быстрой проверки terrain;
- отладки парсинга
ADT; - проверки AABB и координат.
src/scenes/preview/adt_tile_preview.tscn
Файл: src/scenes/preview/adt_tile_preview.tscn
Preview одного ADT прямо в editor.
Скрипт: src/scenes/preview/adt_tile_preview.gd
Полезно для:
- проверки одного конкретного тайла;
- отладки terrain layers;
- проверки воды и дыр по отдельному
ADT.
Основные export-поля:
map_nametile_xtile_yreload_now
src/scenes/streaming/eastern_kingdoms_streaming.tscn
Файл: src/scenes/streaming/eastern_kingdoms_streaming.tscn
Главная сцена для стриминга мира.
Скрипт: src/scenes/streaming/streaming_world_loader.gd
Умеет:
- находить все доступные
ADTтайлы вWorld/Maps/Azeroth; - загружать/выгружать тайлы по мере перемещения;
- строить chunk mesh по LOD;
- отдельно добавлять воду на тайл;
- работать и в runtime, и в editor.
Editor streaming
StreamingWorld теперь умеет подгружать мир прямо в editor по мере движения камеры viewport.
Ключевые export-поля:
editor_preview_enablededitor_follow_view_cameraeditor_preview_center_xeditor_preview_center_yeditor_preview_tile_radiuseditor_reload_now
Логика такая:
editor_preview_center_x/yзадают anchor, который сдвигается кorigin, чтобы мир было удобно смотреть в Godot;- при
editor_follow_view_camera = trueстриминг идёт вокруг положения editor camera в 3D viewport; - тайлы и их children появляются под
Terrainв Scene Tree.
Это нужно, чтобы визуально проверить, что мир действительно собирается по мере перемещения по карте, а не только как статичный превью-блок.
Runtime streaming и LOD
В runtime StreamingWorld:
- подгружает
ADTтайлы по расстоянию; - для terrain использует chunk-level LOD;
- хранит дальний мир на грубом chunk LOD;
- отдельно создаёт воду на тайл.
Основные параметры:
tiles_per_tickchunk_ops_per_ticklod0_radius_chunkslod1_radius_chunkslod2_radius_chunkslod2_tile_radius
Управление камерой
Файл: src/scenes/camera/fly_camera.gd
Управление:
RMBудерживать для обзора;WASDдвижение;Q/Eвниз/вверх;Shiftускорение.
Что именно уже исправлено в terrain pipeline
По сравнению с самым ранним состоянием проекта уже поправлены:
- layout
MCNKHeader; - offsets внутри
MCNK; - чтение
MCVT; - чтение
MCNR; - legacy
MCAL; - big alpha / compressed alpha;
- корректные local coordinates внутри
ADT-узла; - holes;
- chunk winding/culling;
- editor preview одного тайла;
- streaming всего
Azeroth; - первый проход
MH2O.
Ограничения текущей версии
- terrain текстурирование уже рабочее, но ещё не 1:1 как в клиенте/Noggit во всех edge cases;
- water renderer сейчас базовый, без настоящих WoW water materials;
M2рендерится статикой без билбордов, UV-анимаций и скелетной анимации;- старые
baked_terrain_v2tile-кэши (до добавленияunique_idвMODF) не дедупят WMO на границах тайлов до перезапечки черезbake_all.gd; - проект сейчас ориентирован на просмотр и исследование данных, а не на полный round-trip import/export.
Ближайшие логичные шаги
- Довести M2 renderer:
- A. Применять material flags: корректный
cull_mode,unshaded,depth_write; blend modes 2+ (additive,modulate) вместо плоского alpha. - B. Билборды: парсить bones из
M2, помечать billboard-флаги, для батчей ссылающихся на billboard-bone выдавать отдельные ноды сBillboardMode = BILLBOARD_ENABLED. Листва деревьев перестанет быть плоской. - C. UV-трансформы и vertex colors — custom shader, per-instance UV offset в
MultiMesh. Waterfalls, порталы, флаги.
- A. Применять material flags: корректный
- Скелетная анимация и скиннинг
M2(bones, key frames, attachments) — отдельный крупный кусок. - Довести water shader (depth fade, shoreline blending, анимация).
- Editor-side инструменты редактирования terrain/liquid/object placement.
- Подготовить формат сохранения обратно в WoW-совместимые структуры.
Быстрый старт
- Положить клиент WoW 3.3.5a в
sources/или указать путь через plugin. - Собрать расширение:
cd src\native
build.bat Release
- Извлечь данные в
res://data/extractedчерезMPQ Extractor. - Открыть одну из сцен:
src/scenes/preview/adt_tile_preview.tscnsrc/scenes/streaming/test.tscnsrc/scenes/streaming/eastern_kingdoms_streaming.tscn
Если нужен именно просмотр мира в editor по движению камеры, используй:
src/scenes/streaming/eastern_kingdoms_streaming.tscneditor_preview_enabled = trueeditor_follow_view_camera = true