Рекурсивный фрактальный 2d рисунок дерева в webgl - PullRequest
1 голос
/ 12 октября 2019

Я пытаюсь нарисовать простое двоичное фрактальное дерево в webgl, однако ветви не идут в нужных мне углах. Я рисую дерево, рисуя точки вершин в массиве, затем подключая этот массив к float32array, а затем вызывая drawArrays (LINE_STRIPE).

Это для программного назначения, назначенного на этот понедельник. Я помню, как рисовал бинарное фрактальное дерево рекурсивно еще в старшей школе, но это было сделано с нуля. Кроме того, прошло очень много времени с тех пор, как я выполнил любую математику, которая требовала триггера.

Приведенная ниже функция представляет собой рекурсивную функцию, которая помещает координаты вершин в массив, который позже будет передан в массив float32.

function createPoints(x, y, length, depth, angle, points)
{
  if(depth > 0)
  {
    //draws line
    points.push((x + length) * Math.sin(angle));
    points.push((y + length) * Math.cos(angle));

    let currentx = (x + length) * Math.sin(angle);
    let currenty = (y + length) * Math.cos(angle);

    //draw left branch
    angle += Math.PI / 4;
    console.log(angle);
    createPoints((x + length/2) * Math.sin(angle), (y + length/2) * Math.cos(angle), length/2, depth - 1, angle, points);

    //goes back somehow
    points.push(currentx);
    points.push(currenty);

    //draw right branch
    angle -= Math.PI / 2;
    console.log(angle);
    createPoints((x + length/2) * Math.sin(angle), (y + length/2) * Math.cos(angle), length/2, depth - 1, angle, points);
    return points;
  }
  return;
}

Ожидаемый результат - дерево глубины рекурсии 2, которое будет простой Y-формой. Ветви должны быть повернуты на 45 градусов от основания ствола. Однако, как вы можете видеть из моего вывода, это не так:

Правая ветвь на самом деле не под углом 45 градусов, хотя кажется,близко.

1 Ответ

0 голосов
/ 12 октября 2019

LINE_STRIPE не является правильным примитивным типом, чтобы делать то, что вы хотите, потому что линейная полоса является одной связной линией.
Используйте примитивный тип LINES. Таким образом, каждая ветвь создает отдельный отрезок линии:

Функция должна рассчитать конечную точку текущей ветки и добавить 2 вершины для отрезка линии в список точек:

let x2 = x + length * Math.sin(angle);
let y2 = y + length * Math.cos(angle);

points.push(x, y, x2, y2);

И 2 новых ветви в конце текущей ветви с помощью рекурсивного вызова:

createPoints(depth-1, x2, y2, length/2, angle+Math.PI/4, points);
createPoints(depth-1, x2, y2, length/2, angle-Math.PI/4, points);

Полное кодирование функции:

function createPoints(depth, x, y, length, angle, points) {

    if (depth <= 0)
        return;

    // end of current line segment
    let x2 = x + length * Math.sin(angle);
    let y2 = y + length * Math.cos(angle);

    // add segment
    points.push(x, y, x2, y2);

    // create 2 branches
    createPoints(depth-1, x2, y2, length/2, angle+Math.PI/4, points);
    createPoints(depth-1, x2, y2, length/2, angle-Math.PI/4, points);
}

например, 4 уровня:

let points = [];
createPoints(4, 0, -1.0, 1.0, 0.0, points);


Если вы все равно хотите использовать тип примитива LINE_STRIP, то каждая ветвь должна добавить одну конечную точку, но должна вернутьсяк этой точке после каждой дочерней ветви:

function createPointsStrip(depth, x, y, length, angle, points) {

    if (depth <= 0)
        return;

    // end of current line segment
    let x2 = x + length * Math.sin(angle);
    let y2 = y + length * Math.cos(angle);

    // add point
    points.push(x2, y2);

    // create 2 branches
    createPointsStrip(depth-1, x2, y2, length/2, angle+Math.PI/4, points);
    points.push(x2, y2);
    createPointsStrip(depth-1, x2, y2, length/2, angle-Math.PI/4, points);
    points.push(x2, y2);
}

Первая точка должна быть добавлена ​​в список точек перед вызовом рекурсивной функции:

let points = [0.0, -1.0];
createPointsStrip(4, 0, -1.0, 1.0, 0.0, points);

Сгенерированный примитивсовершенно другой, но выглядит одинаково (в данном случае).

...