Гладка місцевість вокселів


13

Як особистий проект, я намагаюся зробити генератор рельєфу, який створить рельєф місцевості, схожий на рівну місцевість Castle Story.

Якщо ви ще цього не бачили, ось: введіть тут опис зображення

Отже, як бачите, це комбінація блоків і «гладких» блоків.

Що я намагався зробити, щоб наслідувати цей вигляд - це надати кожному поверхневому блоку міні-мапу висоти. Це, як правило, спрацьовує, але є деякі проблеми, що дають такий ландшафт:

введіть тут опис зображення

Проблема полягає в тому, що кожен блок є 1x1x1, але іноді висота в певному місці є негативною або> 1. У такому випадку я затискаю його і встановлюю висоту на 0 або 1.

Щоб краще проілюструвати, що я маю на увазі, ось схема: введіть тут опис зображення

Щоб створити висоту, я в основному роблю:

genColumn(int x, int z)
{
    int highestBlockY = (int)noise2d(x, z);

    bool is_surface = true;

    for(int y = max_height - 1; y >= 0; y--)
    {
        Block b;

        if(is_surface)
        {
            b = Block.Grass;
            b.HasHeightMap = true;

            // generate heightmap
            for(int ix = 0; ix < 5; ix++)
            {
                for(int iz = 0; iz < 5; iz++)
                {
                    float heightHere = noise2d(x + ix / 4, z + iz / 4) - y;

                    // clip heights
                    if(heightHere > 1)
                        heightHere = 1;

                    if(heightHere < 0)
                        heightHere = 0;

                    b.HeightMap[ix][iz] = heightHere;
                }
            }

            is_surface = false;
        }
        else
        {
            b = Block.Dirt;
        }

        setBlock(x, y, z, b);
    }
}

Можливо, я підходжу до цього неправильно, використовуючи "справжнє" значення шуму перлін?

Будь-яка допомога буде дуже вдячна!

Відповіді:


11

Castle Story виглядає приблизно так через технічні обмеження: якби мапа висоти на кожен воксель у всьому обсязі, а не лише карта висоти на кожен поверхневий воксель, вартість зберігання була б значно більшою, на порядок O (n ^ 3 ), що може бути заборонним, на відміну від більш сприятливого O (n ^ 2), де n - довжина сторони кубічного воксельного простору, що представляє ваш світ. Майте на увазі, що інформація про мапу висоти для підземних вокселів неявна в структурі сітки, тому інформацію про мапу висоти потрібно зберігати лише явно для тих вокселів, які лежать на поверхні. Тож хлопці Castle Story зачепили вершини для сітки міжвузлів, щоб заощадити на вартості зберігання та складності конструкції сітки ... читайте далі.

Спочатку давайте розглянемо ваші варіанти:

введіть тут опис зображення

(1) стане для вас складним, оскільки в одному стовпчику вокселів ви хочете лише інформацію міні-висоти для найвищого вокселя - поверніться до першого абзацу з причин того, чому. Дивлячись на (1), стовпець праворуч містить інформацію про мапу висоти як для верхнього, так і для другого - зверху (і це може стосуватися третього зверху тощо), якщо нахил буде досить екстремальним.). Це не добре.

(2) Можливо, тоді кращий варіант; тобто забезпечення того, щоб кутові вершини стикалися з міжряддями воксельної сітки. Але як тоді ми вирішувати питання крайнього схилу? Ну, нам потрібно вибрати деякий градієнт, де ми просто прив’яжемось до вертикального стовпця і таким чином переконаємось, що у нас немає градієнтів, ніж ми можемо перетнути через n верхніх вокселів. 45-градусний градієнт - це природне відсічення з причин, пояснених нижче. Тож замість (3) у нас було б (4):

введіть тут опис зображення

(4) Розв’язання кутової вершини вокселя до найближчого міжряддя сітки - це рішення. Візуальний ефект - діагональне згладжування - можна побачити на екрані екрану Castle Story. Нахил відсікання вокселів - градієнт 1: 1, або 45 градусів (як ортогонально). Працюючи назад від рішення, розглянемо причини:

  • Єдиний спосіб, коли ми можемо мати неперервний, крайній нахил, це якби воксель був вертикально витягнутий ...
  • .... Але жодна сітка вокселя не може перевищувати її межу, незалежно від фактичної згладженої форми; воксель повинен сидіти у визначеному просторі в 3D-сітці, яка призначає, якщо не точну форму, то, принаймні, для обмеженого вікна, орієнтованого на вісь.

Ще одна причина підходити до цього способу полягає в тому, що, як ви вже виявили, не використання оснащення (дискретизації) призводить до цілого ряду геометрично складних сценарії згладжування поверхні, яких найкраще взагалі уникати ... Ігор такого роду, як правило, не потрібно. ступінь точності, який би забезпечував належний алгоритм CSG, і це всьому причина, що ми використовуємо в першу чергу вокселі: Voxels набагато простіше працювати поступово з обсягами, ніж алгоритми перетину полігону з плаваючою комою / CSG алгоритми .


Я просто спробував це здійснити, і я зіткнувся з деякою плутаниною - що ви маєте на увазі під "заступниками"? Ви маєте на увазі координати інтегральної сітки?
без назви

@ThomasBradworth. "Простір, який втручається між речами". Для 2D, якщо у вас є anxn сітка комірок, у вас буде (n + 1) x (n + 1) проміжки. Це поширюється безпосередньо на 3D. Вони є "вершинами", які зв'язали кожну клітинку, які в основному діляться між декількома клітинками / вокселями. Якщо ви зведете його до 1D (рядок), то якщо клітинки і проміжки представлені як масив, то клітинка 0 обмежена проміжком 0 і проміжком 1, тоді як клітинка 1 обмежена проміжком 1 і проміжком 2 ... пр.
Інженер

Дякую за відповідь! Я намагався робити саме це, але отримав деякі несприятливі результати. Спочатку я спробував просто округлити значення висоти в краях (коли x дорівнює 0 або 4, або z дорівнює 0 або 4), але це отримало мене: i.imgur.com/eQW7Y.png ( pastebin.com/Lr8vyyHB ) Далі я спробував розгладити точки посередині, тому я додав функцію "виправити висоту": pastebin.com/AazQ07Xm , однак, це також дало мені більш кутовий, але й поганий результат: i.imgur.com/q1JVP .png Можливо, щось не в порядку з моєю шумовою функцією?
без назви

@ThomasBradsworth На жаль, я відчуваю, що ти лише наполовину прочитав / зрозумів відповідь, який мені знадобилася протягом години, щоб написати та відредагувати. Забудьте про шум; до того ж, якщо ви не розумієте функцію шуму, видаліть її з рівняння. Ваша проблема полягає в тому, як будуються окремі дані воксельної сітки, і шум не має нічого спільного з цим, оскільки ви можете створити карту висоти за відсутності шуму. Робота з найпростішим тестовим випадком, тобто жорстким кодом масиву висоти. Потім перегляньте результати та налаштуйте алгоритм створення сітки. Повторюйте, поки не виконаєте те, що очікується. Потім поверніть шум і перегляньте.
Інженер

Ви говорите, що я повинен просто зберігати значення висоти для кутів, а не зберігати значення висоти "проміжних" точок?
без назви
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.