我正在用 C++ 编程一个 3d 场景,其中树木可以在任何点和任何方向“生长”。我发现 L-systems 树/行星看起来非常好,但我无法搜索一些函数或库,这些函数或库可以让我传递点坐标、方向向量和一些其他参数,并返回该“生长”树点集的数组。
我什至无法搜索足够的信息来开始。因此,我可以参考或重复使用并进行一些调整以完成此任务的任何想法或链接。我找到了一些 L-sys 解析器,但它看起来只是在没有控制生长方向的情况下绘制到位,并且也未能给我整个点坐标。
这可能是您自己从头开始实施而不是搜索和尝试集成一些 3rd 方库的问题。
实现 L 系统相当容易。您需要实现 2 个部分。
第一部分是字符串重写系统。很简单。您只需要有一个重写规则字典(字符键、字符串值),然后将这些规则应用于初始字符串 i 次(其中 i 是迭代次数)。
伪代码:
map<char, string> rewriteRules = {{'L', "L+R+"}, {'R',"-L+R"}};
string rewrite(string str) {
string result = "";
for each (char c in str) {
if (rewriteRules contains key c) {
result += rewriteRules[c];
}
else {
result += c; // identity
}
}
}
第二个更难的部分是结果符号串的解释。在 3D 中解释龟类图形的最简单方法是使用四元数 - 将它们组合起来很简单。
上面的重写规则描述的是龙曲线,符号的语义是:
以下代码片段演示了使用四元数在 3D 中移动和旋转的实现。它来自我用 C# 编写的 L 系统解释器(希望您能原谅我:)。
Quaternion rotationQuat = Quaternion.Indentity;
Vector3D position;
Vector3D forwardVector = new Vector3D(1, 0, 0);
Vector3D upVector = new Vector3D(0, 1, 0);
Vector3D rightVector = forwardVector.Cross(upVector);
public void Forward(double distance, bool draw) {
Vector3D moveVector = rotationQuat.Transform(forwardVector * distance);
Vector3D oldPosition = position;
position += moveVector;
if (draw) {
// draw cylinder/box from oldPosition to (new) position
}
}
public void Yaw(double angle) {
rotationQuat *= new Quaternion(upVector, angle);
}
public void Pitch(double angle) {
rotationQuat *= new Quaternion(rightVector, angle);
}
public void Roll(double angle) {
rotationQuat *= new Quaternion(forwardVector, angle);
}
因此,要解释字符串,您只需要遍历字符串并解释每个符号。最简单的方法就是切换:
for each (char c in string) {
switch(c) {
case 'L':
case 'R':
Forward(10, true);
break;
case '+':
Yaw(90);
break;
case '-':
Yaw(-90);
break;
default:
break; // do nothing
}
}
如果您想尝试 L-systems(即使是 3D),有一个不错的网站http://malsys.cz可以在其中进行(那些 C# 片段来自它:)
祝 L 系统好运!
我不知道任何提供 3d L 系统算法的开源库,我怀疑你必须自己编写。
从 2d 实现开始,它非常简单,维基百科页面是查看简单示例的好地方,一旦 2d 实现完成,应该会扩展到第三个。