为了账号安全,请及时绑定邮箱和手机立即绑定

在 webgl 中绘制递归分形 2d 树

在 webgl 中绘制递归分形 2d 树

紫衣仙女 2021-11-18 16:20:44
我试图在 webgl 中绘制一个简单的二叉分形树,但是分支没有以我想要的正确角度。我通过将顶点的点绘制到一个数组中来绘制树,然后将该数组插入一个 float32array 中,然后调用 drawArrays(LINE_STRIPE)。这是本周一到期的编程任务。我确实记得在高中时递归地绘制二叉分形树,但它是使用scratch完成的。自从我做任何需要触发的数学运算也已经很长时间了。下面的函数是一个递归函数,它将顶点的坐标推入一个数组,稍后将传递给一个 float32array。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 回答

?
临摹微笑

TA贡献1982条经验 获得超2个赞

LINE_STRIPE不是做你想做的合适的原始类型,因为线条是一条连贯的线。

使用原始类型LINES。所以每个分支创建一个单独的线段:


该函数必须计算当前分支的终点并将线段的 2 个顶点添加到点列表中:


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

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


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

通过 e 递归调用,在当前分支的末尾有 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);

//img1.sycdn.imooc.com//61960d0a0001603e02520247.jpg

如果你无论如何想使用原始类型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);

生成的基元完全不同,但看起来相同(在这种情况下)。


查看完整回答
反对 回复 2021-11-18
  • 1 回答
  • 0 关注
  • 289 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信