本次基于processing创作了一个应用,主要参考书籍为《代码本色》
主要应用的技术为下面三部分:
- 力
- 粒子系统
- 分形
首先简单介绍一下这个系统
1. 整个主体是一棵随风摆动的树,你可以通过点击空白处来得到不同形状的独一无二的树
关于分形,首先需要了解,分形的两个重要特征:自相似性、递归。
首先比较简单的一种分型树规则是:
1. 画一段线段
2. 在线段末尾(a)向左旋转画一条更短的线段 (b)向右旋转画一条更短的线段
3. 不断地在新线段上重复步骤二
4.设置递归终止条件
这样那你就可以构建一棵树枝是线段的简单分型树。那么在分形树中加入一点点随机性就可以使它的外形更贴近自然。查看一棵树的外形,你 会发现每根树枝的角度和长度都不相同,此外,每根树枝的分支数量也不相同。简单地改变树枝的角度和长度很容易实现,只要在绘制时获取一个随机数即可。你也可以选择一个随机数作为树枝的数量,只需改变branch()函数的调用次数。
同时为了获得更逼真的树,请可以用Perlin噪声算法确定树枝的长度。随时间调整噪声值,同时可以用toxiclibs模拟树的物理效果,每一根树枝都是用弹簧相连的两个粒子,这样就可以获得树木被风吹动的效果。
其中Perlin噪声算法表现出了一定的自然性,因为它能生成符合自然排序(“平滑”)的伪随机数序列。Processing内置了Perlin噪声算法的实现:noise()函数。noise()函数可以有1~3个参数,分别代表一维、二维和三维的随机数。Processing的noise()函数告诉我们噪声是通过几个“八度”计算出来的。调用noiseDetail()函数会改变“八度”的数量以及各个八度的重要性,这反过来会影响noise()函数的行为。
关于Perlin噪声不作更多详谈,指路传送门:
代码如下:
class branch
{
PVector[] location;
float[] thickness;
int[][] baseIndex = new int[2][];
// float[] baseDtheta;
boolean isCandidate = false;
float[] dTheta;
branch(PVector loc, float thic, int id, int branchIndex)
{
location = new PVector[1];
thickness = new float[1];
location[0] = new PVector(loc.x, loc.y);
thickness[0] = thic;
baseIndex[0] = new int[1];
baseIndex[1] = new int[1];
baseIndex[0][0] = id;
baseIndex[1][0] = branchIndex;
}
void branchRotate(int index, float theta, PVector reference)
{
location[index].sub(reference);
rotate2D(location[index], theta);
location[index].add(reference);
}
void rotate2D(PVector v, float theta)
{
float xTemp = v.x;
v.x = v.x * cos(theta) - v.y * sin(theta);
v.y = xTemp * sin(theta) + v.y * cos(theta);
}
}
class frontier
{
PVector location;
PVector velocity;
float thickness;
boolean finished;
frontier(PVector startPoint, PVector direction)
{
location = new PVector(startPoint.x, startPoint.y);
velocity = new PVector(direction.x, direction.y);
thickness = random(10, 30);
finished