了解toxiclibs库的基本框架
上图是toxiclibs库核心元素的说明图。开始时我们需要声明VerletPhysics3D physics变量,在void setup(){}函数中添加physics.addBehavior(new GravityBehavior3D())重力与physics.addParticle()添加粒子;在void draw(){}函数中添加physics.update()更新变化的函数与physics.addSpring()添加弹簧力。构建Particle粒子类与Spring弹簧类(利用面向对象语言的继承特性)
class Particle extends VerletParticle3D{ Particle(float x,float y,float z){ super(x,y,z); } void display(){ pushMatrix(); translate(x,y,z); fill(255); ellipse(0,0,3,3); popMatrix(); } 在粒子类中,其是VerletParticle3D的子类(VerletParticle3D是toxiclibs库内置的粒子库),通过super(x,y,z);函数,在构造函数中,继承了需要在VerletParticle3D中传递的三个参数,即粒子的xyz坐标。 在void display(){}函数中,每次将坐标系移动到粒子位置translate(x,y,z);并再在这个位置画一个圆来可视化粒子ellipse(0,0,3,3); class Spring extends VerletSpring3D{ Spring(Particle a,Particle b){ super(a,b,8,0.2 ); } void display(){ stroke(255); strokeWeight(1); line(a.x,a.y,a.z,b.x,b.y,b.z); } } 在弹簧类中,其是VerletSpring3D的子类(VerletSpring3D是toxiclibs库内置的弹簧库),通过super(a,b,8,0.2 ); 在构造函数中,继承了需要在VerletSpring3D中传递的四个参数: a 是第一个粒子,b是第二个粒子,8是a与b的距离,0.2是a与b的弹力,其范围在0-1之间。当等于1时,相当于成为了刚体,其值越小形成的弹簧粒子模型越柔软。构建布料的粒子二维矩阵
在processing中库面板下载toxiclibs库,并在菜单栏中将其引用 import toxi.geom.*; import toxi.physics3d.*; import toxi.physics3d.behaviors.*; import toxi.physics3d.constraints.*; 上图是粒子二维矩阵的简图,在子循环中,即黄色的方框内先执行。再按照图底下01234的顺序依次执行。w是粒子之间的间隔。 以下是30*30粒子二维矩阵的代码: int cols = 30; int rows = 30; Particle[][] p = new Particle[cols][rows] ; float w = 10; float x = -200; for(int i = 0;i float z = -200; for(int j = 0;j p[i][j] = new Particle(x,-200,z); physics.addParticle(p[i][j]); z += w; } x += w; } p[0][0].lock(); p[cols-1][0].lock(); 其中,将每个粒子对象new Particle(x,-200,z);数据传递到p[i][j]二维矩阵中,并且在physics.addParticle(p[i][j]);物理世界中添加粒子。 之后并将左上角粒子 p[0][0].lock();与右上角粒子p[cols-1][0].lock();固定。 for(int i = 0;i for(int j = 0;j p[i][j].display(); } } 然后在void draw(){}循环中,调用p[i][j].display();函数,将ellipse(0,0,3,3);圆画出来。构建布料的粒子弹簧模型
for(int i = 0;i for(int j = 0;j Particle a1 = p[i][j]; Particle b1 = p[i+1][j]; Particle b2 = p[i][j+1]; Spring s1 = new Spring(a1,b1); Spring s2 = new Spring(a1,b2); s1.display(); s2.display(); physics.addSpring(s1); physics.addSpring(s2); } } 图4中,蓝色的线即表示粒子与粒子之间的弹簧力。在布料的粒子弹簧模型中,每一个粒子与其右边的和下边的粒子建立弹簧力 Particle a1 = p[i][j]; Particle b1 = p[i+1][j]; Particle b2 = p[i][j+1]; Spring s1 = new Spring(a1,b1); Spring s2 = new Spring(a1,b2); 并且将弹簧添加到物理世界中: physics.addSpring(s1); physics.addSpring(s2); 让我们看一下目前的效果利用三维柏林噪音模拟微风吹拂
float xoff = 0; float yoff = 0; float zoff = 0; float increment = 0.8; for(int i = 0;i for(int j = 0;j float windx = map(noise(xoff,yoff,zoff),0,1,-5,5); float windy = map(noise(xoff+6000,yoff+6000,zoff+6000),0,1,-0.08,0); float windz = map(noise(xoff+3000,yoff+3000,zoff),0,1,-5,5); p[i][j].display(); p[i][j].addForce(new Vec3D(windx,windy,windz)); yoff += increment; } xoff += increment; } zoff += increment; 在柏林噪声noise()函数中,windx /windy /windz的沿x轴的增量 xoff /xoff+3000/ xoff+6000跨度较大,所以可以认为windx /windy /windz映射(map())的柏林噪声数值是相互独立的,并且是随机连续的。(柏林噪声的详细讲解可参考: 代码检查|粒子系统下的柏林噪声美学) 将之前存储在数组中的每一个粒子p[i][j].display();显示出来。并且添加风力p[i][j].addForce(new Vec3D(windx,windy,windz));,其中addForce()是toxiclibs库内置的函数,函数中要传递的参数是一个Vec3D对象。设计灵感与更改点
在布料的视觉表现上,我参考了 https://hello.processing.org/ 的网页设计元素 其中的最小单元有两个同心圆组成,小圆的opacity=100%,大圆是半透明的。 当两个半透明的圆又重叠到一起时,又会产生深颜色的视觉效果 更新了一下粒子类: class Particle extends VerletParticle3D{ Particle(float x,float y,float z){ super(x,y,z); } void display(){ pushMatrix(); translate(x,y,z); fill(255); noStroke(); fill(255,51); ellipse(0,0,1.8,1.8); noStroke(); fill(1,156,255,12); ellipse(0,0,12,12); popMatrix(); } } 当程序逻辑确定无误时,我们可以通过更改 1. physics.addBehavior(new GravityBehavior3D(new Vec3D(0,0.2,0))); 重力的参数 2. p[0][0].lock(); p[cols-1][0].lock(); 锁定的粒子的位置 3. float windx = map(noise(xoff,yoff,zoff),0,1,-5,5); float windy = map(noise(xoff+6000,yoff+6000,zoff+6000),0,1,-0.08,0); float windz = map(noise(xoff+3000,yoff+3000,zoff),0,1,-5,5); 柏林噪声与windx/windy/windz的映射关系(调整风力的强弱) 4. super(a,b,16,0.26); 弹簧类中的原始长度与弹力 来使展示的布料拥有更加丰富的变换。 同时调节各个函数的参数也是熟悉函数特性与程序逻辑的一个很好的方式。成果展示
程序下载链接:
https://github.com/SeanSun9/cloth-simulation-based-on-processing-toxiclibs-library
参考资料:
代码本色/the nature of code P202+
https://www.youtube.com/watch?v=jrk_lOg_pVA&list=PLRqwX-V7Uu6aiaU4s30tXvUmwGMlb9UUS&index=6&t=0s
代码检查
往期回顾
代码检查 | 极具科技感的涟漪几何体
代码检查 | 用Processing做出烟雾弥漫的效果
代码检查 | 数学中的三角函数之美
为了提供更好的课程服务
OF的软件学习兴趣小调查来啦!
希望大家可以抽 1min 的时间回答下面问题!