如何生成三维树在任何给定的点和方向的空间与c++和l系统
How to generate 3d trees in any given point and direction in space with C++ and L-Systems?
我正在用c++编程一个3d场景,其中树木可以在任何点和任何方向"生长"。我发现l系统的树/行星看起来非常好,但我不能谷歌一些函数或库,可以让我传递一个点坐标,一个方向矢量和一些其他参数,并返回一个数组的"生长"的树点集。
我甚至不能谷歌足够的信息来开始。所以任何想法或链接,我可以参考,或重用,并作出一些调整,以完成这项任务。我找到了一些L-sys解析器,但它看起来只是在原地绘图,而没有控制生长方向,也无法给出整个点的坐标。
这可能是你自己从头开始实现比搜索和尝试集成一些第三方库更快的问题。
实现l -系统相当容易。你需要实现两个部分。
第一部分是字符串重写系统。这很简单。你只需要有一个重写规则的字典(char键,字符串值),然后将这些规则应用于初始字符串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中类似乌龟的图形——将它们组合起来很简单。
上面重写的规则是描述龙曲线,符号的语义含义为:
- L, R:向前划线
- +:左转90度
- -:右转90度
下面的代码片段演示了使用四元数在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系统(即使在3D)有一个很好的网站http://malsys.cz在那里你可以这样做(那些c#片段来自它:)
祝你L-systems好运!
我不知道有任何提供3d L-system算法的开源库,我想你必须自己编写。
从2d实现开始,这非常简单,维基百科页面是查看简单示例的好地方,一旦2d实现完成,扩展到第三个应该遵循。
相关文章:
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 在命名空间中定义函数还是限定函数
- 使用Unreal C++获取VR耳机的世界位置/方向
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- OpenGL相机和相机空间转型的困惑
- CUDA内核和数学函数的显式命名空间
- 打印第二列时的2d字符矢量打印空间
- 嵌套的匿名命名空间
- 在C++中向零方向近似的最佳方法
- CMakeLists.txt中的命名空间表示法
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 内存空间的反转方向?
- 将面向方向的(局部空间)照相机投射到全局空间 x-y 平面
- 为什么在分配较大空间时堆地址的增长方向相反?
- 如何生成三维树在任何给定的点和方向的空间与c++和l系统