Как генерировать трехмерные деревья в любой заданной точке и направлении в пространстве с помощью C++ и L-Systems?

Я программирую на C++ 3d-сцену, в которой деревья можно "выращивать" в любой точке и в любом направлении. Я нахожу, что деревья / планеты L-систем выглядят очень хорошо, но я не могу найти в Google какую-либо функцию или библиотеку, которые могут позволить мне передать координату точки, вектор направления и некоторые другие параметры и вернуть массив этого "выращенного" набора точек дерева.

Я не могу даже Google достаточно информации, чтобы начать. Так что любая идея или ссылка, на которую я могу сослаться, или повторно использовать и внести некоторые коррективы, чтобы выполнить эту задачу. Я нашел несколько парсеров L-sys, но это выглядело как просто рисование на месте без контроля растущих направлений, а также не смог дать мне целые координаты точки.

2 ответа

Вероятно, это проблема, которую быстрее реализовать самостоятельно, а не искать и пытаться интегрировать некоторые сторонние библиотеки.

Реализовать L-системы довольно просто. Вам нужно реализовать 2 части.

Первая часть - система перезаписи строк. Это просто. Вам просто нужно иметь словарь правил перезаписи (ключ ключа, строковое значение), а затем применять эти правила для начальной строки i-times (где i - количество итераций).

Псевдо-код:

map<char, string> rewriteRules = {{'L', "L+R+"}, {'R',"-L+R"}};

string rewrite(string str) {
    string result = "";
    for each (char c in str) {
        if (rewriteRules contains key c) {
            result += rewriteRules[c];
        }
        else {
            result += c; // identity
        }
    }
}

Вторая, более сложная часть - это интерпретация результирующей строки символов. Самый простой способ интерпретировать графику, похожую на черепаху, в 3D - это использовать кватернионы - их легко объединить.

Правила переписывания, описанные выше, описывают кривую Дракона, а семантическое значение символов:

  • L, R: провести линию вперед
  • +: повернуть налево на 90 градусов
  • -: повернуть направо на 90 градусов

Следующие фрагменты кода демонстрируют реализацию перемещения и вращения в 3D с использованием кватернионов. Это от моего интерпретатора L-системы, написанного на C# (надеюсь, вы меня простите:).

Quaternion rotationQuat = Quaternion.Indentity;
Vector3D position;

Vector3D forwardVector = new Vector3D(1, 0, 0);
Vector3D upVector = new Vector3D(0, 1, 0);
Vector3D rightVector = forwardVector.Cross(upVector);

public void Forward(double distance, bool draw) {
    Vector3D moveVector = rotationQuat.Transform(forwardVector * distance);
    Vector3D oldPosition = position;
    position += moveVector;

    if (draw) {
        // draw cylinder/box from oldPosition to (new) position
    }
}

public void Yaw(double angle) {
    rotationQuat *= new Quaternion(upVector, angle);
}

public void Pitch(double angle) {
    rotationQuat *= new Quaternion(rightVector, angle);
}

public void Roll(double angle) {
    rotationQuat *= new Quaternion(forwardVector, angle);
}

Таким образом, чтобы интерпретировать строку, вам просто нужно пройти строку и интерпретировать каждый символ. Самый простой способ - просто переключиться:

for each (char c in string) {
    switch(c) {
    case 'L':
    case 'R':
        Forward(10, true);
        break;
    case '+':
        Yaw(90);
        break;
    case '-':
        Yaw(-90);
        break;
    default:
        break; // do nothing
    }
}

Если вы хотите поэкспериментировать с L-системами (даже в 3D), есть хороший веб-сайт http://malsys.cz/ где вы можете сделать это (эти фрагменты C# взяты из него:)

Удачи с L-системами!

Я не знаю ни одной библиотеки с открытым исходным кодом, которая бы обеспечивала алгоритмы 3d L-системы, я подозреваю, что вам придется написать свою собственную.

Начните с реализации 2d, это довольно просто, страница википедии - хорошее место, чтобы увидеть простые примеры, как только реализация 2d будет завершена, отсюда следует расширение до трети.

Другие вопросы по тегам