fix(render): select terrain LOD from native camera cells
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
This commit is contained in:
9 files changed
+776
-21
No files matched your search
+37
-8
@@ -1030,11 +1030,39 @@ Node38, а диапазоны граней — в 68-байтовых Slot68. В
|
||||
проверяются на единственное назначение, а выходящий за массив, повторный или
|
||||
неподдерживаемый диапазон считается ошибкой загрузки.
|
||||
|
||||
Первый рендер карты, terrain-запросы высоты и пересечения, receiver-ы теней и
|
||||
обрезка контуром зданий используют только LOD0. Отбор сохраняет порядок
|
||||
исходных граней, а контурный проход отдельно переводит индекс спроецированной
|
||||
грани обратно в исходный. LOD1 пока не подставляется по расстоянию: такой
|
||||
переход не реализован.
|
||||
Рисуемый уровень выбирается по ячейкам, а не по расстоянию до отдельного
|
||||
треугольника. Начало сетки находится в первых двух float заголовка Slot68,
|
||||
размер ячейки — в границах первого слота LOD0. Атрибут 2 потока Node38 задаёт
|
||||
число ячеек по X; индекс ячейки равен `x * count_y + y`. Приложение проверяет,
|
||||
что границы всех слотов образуют эту регулярную сетку. Все 33 карты GOG
|
||||
проходят такую проверку, включая вырожденные грани на общей границе ячеек:
|
||||
принадлежность грани берётся из слота, а не угадывается по её центру.
|
||||
|
||||
Координаты камеры переводятся в целые координаты сетки округлением вниз.
|
||||
Если `dx * dx + dy * dy >= 9` и горизонтальный FOV не меньше 0,5 радиана,
|
||||
выбирается LOD1. При увеличении масштаба, отсутствии дальнего слота или
|
||||
наличии геометрического patch остаётся LOD0. Камера за границей карты не
|
||||
прижимается к крайней ячейке для этого расчёта. Правило восстановлено по
|
||||
GOG `Terrain.dll` ([сборка и SHA-256](../reference/original-binaries.md)):
|
||||
`CLandscape::Render`, RVA `0x11340`, выбор уровня `0x11878–0x11A03`.
|
||||
Исполнение оригинала подтверждает выбор дальнего слота, а getter камеры
|
||||
`Ngi32.dll` RVA `0x4D960` возвращает именно FOV.
|
||||
|
||||
Основания строений сохраняют подробную геометрию. Нативная регистрация
|
||||
patch (`Terrain.dll` RVA `0x12E20`) проверяет его треугольники против каждой
|
||||
ячейки через `mrnParaIntersectsPoly`. Поэтому учитываются и соседние ячейки,
|
||||
которых касается край треугольника. Перед проверкой координаты нормализуются
|
||||
в `f32` относительно центра ячейки; замена этой операции сравнением мировых
|
||||
границ меняет результат на общих рёбрах. На «Конструкторе» игнорируемый
|
||||
ресурсный тест сверяет все 22 ячейки с принудительным LOD0 с набором,
|
||||
полученным в живом оригинале.
|
||||
|
||||
Vulkan получает оба уровня один раз. Диапазоны индексов разделены по
|
||||
материалу и исходной ячейке; на каждом кадре включается только выбранный
|
||||
уровень. Сгенерированные отмостки остаются включены. Terrain-запросы высоты
|
||||
и пересечения, receiver-ы теней и обрезка контуром зданий используют
|
||||
канонический LOD0. Отбор сохраняет порядок исходных граней, а контурный проход
|
||||
отдельно переводит индекс спроецированной грани обратно в исходный.
|
||||
|
||||
```rust
|
||||
let assignments = mesh.face_lod_assignments()?;
|
||||
@@ -1052,9 +1080,10 @@ for (face, assignment) in mesh.faces.iter().zip(assignments.iter()) {
|
||||
исходные фрагменты рельефа вместе с треугольниками отмостки в одном наборе.
|
||||
`TerrainWorld::with_basement_foundation` принимает этот набор во владение и
|
||||
устанавливает те же координаты и маски в BVH высотных запросов и пересечений.
|
||||
Предпросмотр миссии на Vulkan пока строит только LOD0: связывание BAS-записей
|
||||
с этой подготовкой ещё не подключено, поэтому наличие API не означает, что
|
||||
геометрия миссии уже обрезана.
|
||||
Предпросмотр миссии связывает BAS-записи с этой подготовкой до загрузки
|
||||
материалов. Полученная поверхность общая для изображения, теней и запросов;
|
||||
поправка размещения основания один раз применяется к корню строения и его
|
||||
присоединённым компонентам.
|
||||
|
||||
Внешнее кольцо должно лежать на области LOD0, а каждый его сегмент — оставаться
|
||||
покрытым текущей поверхностью. Непокрытый сегмент или пересекающиеся контуры
|
||||
|
||||
Reference in new issue
Block a user