sindoring 3d528e3bbf rnd(M03): introduce renderer facade seam
Work-Package: M03-RND-FACADE-001
Agent: sindo-main-codex
Tests: facade/focus/coordinate/manifest contracts, renderer dry-run, coordination and documentation gates
Fidelity: focus targets, budgets, queues, caches and visible renderer behavior remain unchanged
2026-07-15 23:48:53 +04:00
2026-05-23 00:56:16 +04:00
2026-06-27 12:13:17 +04:00
2026-07-15 23:32:50 +04:00
2026-07-14 11:48:14 +04:00
2026-04-20 20:26:14 +04:00
2026-04-20 20:26:14 +04:00
2026-07-10 18:29:56 +04:00
2026-04-20 20:26:14 +04:00
2026-04-20 20:26:14 +04:00

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.
  • ADTLoader
    • MTEX, MMDX/MMID, MWMO/MWID;
    • MDDF, MODF (с unique_id, flags, doodad_set, name_set);
    • MCVT, MCNR, MCLY, MCAL;
    • holes;
    • MH2O.
  • WDTLoader
    • MVER, 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;
    • первый проход рендера воды.
  • 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.

Частично реализовано

  • M2 renderer
    • статическая геометрия рендерится корректно;
    • 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

  1. Открой проект в Godot.
  2. Убедись, что plugin MPQ Extractor включён.
  3. Внизу editor открой панель MPQ Extractor.
  4. Укажи путь к клиенту WoW 3.3.5a.
  5. Выбери locale.
  6. Нажми Open Client Archives.
  7. Для полной распаковки используй фильтр * и 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.

Основные поля результата:

  • textures
  • m2_names
  • wmo_names
  • m2_placements
  • wmo_placements
  • chunks

Каждый chunk содержит:

  • index_x, index_y
  • origin
  • heights
  • normals
  • holes
  • layers
  • alpha_maps
  • liquids

WMOLoader

Читает root/group файлы WMO и возвращает Dictionary с materials и groups.

Подключён в StreamingWorld через world-level registry. Дедуп по unique_id из ADT.MODF, refcount по тайлам.

WDTLoader

Читает WDT карты и возвращает Dictionary:

  • versionMVER (ожидается 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 N legacy 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 путь к одному .M2
  • output_dir директория вывода для одного .M2
  • --all SEARCH_DIR рекурсивно конвертирует все .M2 под директорией
  • --out OUT_ROOT root вывода для --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.py
  • reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/convert_m2_bones.py
  • reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/m2_export_validation.py
  • reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/wmo/export_wmo.py
  • reference/wow.export/addons/blender/io_scene_wowobj/animation_processor.py
  • reference/wow.export/addons/blender/io_scene_wowobj/import_wowobj.py
  • reference/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_name
  • tile_x
  • tile_y
  • reload_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_enabled
  • editor_follow_view_camera
  • editor_preview_center_x
  • editor_preview_center_y
  • editor_preview_tile_radius
  • editor_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_tick
  • chunk_ops_per_tick
  • lod0_radius_chunks
  • lod1_radius_chunks
  • lod2_radius_chunks
  • lod2_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_v2 tile-кэши (до добавления unique_id в MODF) не дедупят WMO на границах тайлов до перезапечки через bake_all.gd;
  • проект сейчас ориентирован на просмотр и исследование данных, а не на полный round-trip import/export.

Ближайшие логичные шаги

  1. Довести 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, порталы, флаги.
  2. Скелетная анимация и скиннинг M2 (bones, key frames, attachments) — отдельный крупный кусок.
  3. Довести water shader (depth fade, shoreline blending, анимация).
  4. Editor-side инструменты редактирования terrain/liquid/object placement.
  5. Подготовить формат сохранения обратно в WoW-совместимые структуры.

Быстрый старт

  1. Положить клиент WoW 3.3.5a в sources/ или указать путь через plugin.
  2. Собрать расширение:
cd src\native
build.bat Release
  1. Извлечь данные в res://data/extracted через MPQ Extractor.
  2. Открыть одну из сцен:
    • src/scenes/preview/adt_tile_preview.tscn
    • src/scenes/streaming/test.tscn
    • src/scenes/streaming/eastern_kingdoms_streaming.tscn

Если нужен именно просмотр мира в editor по движению камеры, используй:

  • src/scenes/streaming/eastern_kingdoms_streaming.tscn
  • editor_preview_enabled = true
  • editor_follow_view_camera = true
S
Description
Перенос World of Warcraft 3.3.5a на Godot
Readme 78 MiB
Languages
Python 61.2%
GDScript 26.2%
C++ 7.4%
GLSL 3.3%
CSS 0.6%
Other 1.2%