Раніше я реалізовував маршируючі кубики / тетраедри для візуалізації IsoSurface. Це спрацювало ( YouTube ), але продуктивність була жахливою, оскільки я ніколи не замислювався над тим, щоб реалізувати змінний рівень деталізації на основі відстані перегляду (або навіть видалення старих віддалених фрагментів).
Я вирішив ще раз поїхати і зробити це належним чином цього разу. Я почав зі створення OctreeNode, який працює так, коли Build()
викликається.
- Якщо шматок занадто малий для будівництва, повертайтеся негайно.
- Опрацюйте, якщо поверхня проходить через об'єм цього шматка.
- Якщо так, то вирішуємо, чи хочемо ми підняти LOD (оскільки камера закрита)
- Якщо так, то нерестуйте 8 дітей і викликайте той самий процес на них
- Якщо ні, побудуйте сітку за допомогою розмірів поточного вузла
Деякі псевдокоди:
OctNode Build() {
if(this.ChunkSize < minChunkSize) {
return null;
}
densityRange = densitySource¹.GetDensityRange(this.bounds);
if(densityRange.min < surface < densityRange.max) {
if(loDProvider.DesiredLod(bounds)² > currentLoD) {
for(i 1 to 8) {
if(children[i] == null) {
children[i] = new OctNode(...)
}
children[i] = children[i].Build();
}
} else {
BuildMesh();
}
return this;
}
}
¹ Окрім повернення щільності в точці, джерело щільності може визначити можливий діапазон щільності для заданого об'єму.
² Постачальник LoD приймає обмежувальне поле і повертає максимум бажаного LoD залежно від положення камери / фрустуму, налаштувань користувача тощо ...
Отже ... Це все працює досить добре. Використання простої сфери як джерела щільності та показ усіх вузлів:
І просто листя:
Однак є кілька питань:
- Я повинен визначити початковий обмежувальний об'єм (і чим він більший, тим більше мені потрібно обробити)
- У корені дерева я не знаю, наскільки глибокими будуть листя, тому моя нумерація LoD починається з найнижчої якості (корінь) і збільшується, коли шматки стають меншими. Оскільки LoD зараз відносно початкового обсягу, він не дуже корисний, коли я хочу робити речі за певними розмірами / якостями.
Я продумав кілька варіантів, але обидва здаються недоліками:
- Підтримуйте колекцію Octrees та додайте / видаляйте залежно від відстані. Не можу зрозуміти, як я добре перетинаюсь¹, плюс мені знадобиться список відомих порожніх вузлів, особливо якщо я хочу довільні тривимірні поверхні (щоб уникнути повторного обчислення порожніх томів повторно)
- Додайте батьківський вузол до поточного кореня, а потім додайте сім побратимів для вихідного вузла. Це спрацювало б і на вимогу, але здається складним розумне скорочення вниз, коли гравець рухається по пейзажу. Це також зробить номери LoD ще менш значущими.
¹ [У поясненні до Q нижче] В даний час, якщо два фізично суміжних вузла на дереві знаходяться на різних LOD, у мене є який-небудь код, щоб примусити верти, щоб у них не було шва при створенні сітки. Я можу це зробити, знаючи щільність для кількох оточуючих вузлів. У випадку, коли у мене є 2 незалежних октриси поруч, я не мав би простого способу отримати цю інформацію, що призвело до появи швів.
Який оптимальний спосіб підійти до цього?