如何在p5.js中实现带分支的分形树绕X轴旋转?
解决分形树绕X轴旋转的问题
核心要点
- 必须启用WEBGL渲染模式:p5.js的2D环境不支持3D旋转操作,初始化画布时要指定
createCanvas(windowWidth, windowHeight, WEBGL)。 - 用
push()/pop()隔离变换上下文:每个分支的旋转操作要放在独立的变换栈中,避免父分支的变换影响子分支或其他元素。 - 适配WEBGL坐标系:WEBGL原点在画布中心,需通过
translate调整树的初始位置,避免分支超出可视范围。
修改后的完整代码示例
let tree; function setup() { createCanvas(windowWidth, windowHeight, WEBGL); angleMode(DEGREES); // 用角度控制旋转更直观 // 把树根放在画布底部中心(WEBGL坐标系Y轴向上) tree = new Branch(createVector(0, 250, 0), createVector(0, -1, 0), 100); } function draw() { background(220); // 让整个树缓慢绕X轴旋转 rotateX(frameCount * 0.5); tree.show(); tree.grow(); } class Branch { constructor(start, dir, len) { this.start = start; this.dir = dir.copy(); this.len = len; this.thickness = map(this.len, 20, 100, 2, 10); this.ended = false; } show() { push(); // 移动到当前分支的起点 translate(this.start.x, this.start.y, this.start.z); // 计算绕X轴的旋转角度,让分支朝向正确方向 rotateX(atan2(this.dir.y, this.dir.z)); strokeWeight(this.thickness); stroke(101, 67, 33); // WEBGL中线的坐标为(x1,y1,z1,x2,y2,z2) line(0, 0, 0, 0, 0, -this.len); pop(); } grow() { if (!this.ended) { // 生成两个子分支(绕Y轴调整分支角度) let newDir1 = this.dir.copy().rotate(20); let newDir2 = this.dir.copy().rotate(-20); const endPos = p5.Vector.add(this.start, p5.Vector.mult(this.dir, this.len)); this.child1 = new Branch(endPos, newDir1, this.len * 0.7); this.child2 = new Branch(endPos, newDir2, this.len * 0.7); this.ended = true; } else { this.child1.grow(); this.child1.show(); this.child2.grow(); this.child2.show(); } } }
常见问题排查
- 旋转后树消失:检查
translate的位置,WEBGL的Y轴向上,树根初始位置可调整为createVector(0, height/2, 0),确保树在画布可视范围内。 - 分支方向异常:若使用弧度模式,
rotateX的参数需为弧度值;如果习惯用角度,务必调用angleMode(DEGREES)。 - 变换混乱:所有分支的绘制操作必须用
push()/pop()包裹,防止不同分支的变换互相干扰。
内容的提问来源于stack exchange,提问作者Leonardo
相关产品推荐
相关产品推荐

