令人不安的递归分形山

时间:2015-02-19 19:21:28

标签: c++ opengl recursion fractals

我正在编写一些OpenGl代码来创建分形山。我正在使用递归,并且我很难过。

我遇到的问题是三角形的撕裂和重叠: http://imgur.com/DWSuUJH

问题是,我以为我已经解决了这个问题,这是我的代码。

我的三角类,vec2只是一个通用的二维向量

struct Triangle {
vec2 A, B, C;

Triangle(vec2 a, vec2 b, vec2 c) {
    A = a;
    B = b;
    C = c;
};

这是我的递归函数,最初在默认查看卷中使用顶点(-1,-1),(0,1)和(1,-1)三角形调用。

 void divide_triangle(const Triangle& baseTriangle, int count) {

if (count > 0) {
    std::vector<Triangle> subTriangles = subdivideTriangle(baseTriangle);
    for (int i = 0; i < subTriangles.size(); i++) {
        divide_triangle(subTriangles[i], count - 1);
    }
}

else {
    triangle(baseTriangle); // Draw triangle at the end of recursion
}

这是我的subDivideTriangles函数,它简单地将传递的三角形分成四个独立的三角形

std::vector<Triangle> subdivideTriangle(const Triangle& triangle){

vec4 aPrime = getMidpoint(triangle.B, triangle.C);
vec4 bPrime = getMidpoint(triangle.C, triangle.A);
vec4 cPrime = getMidpoint(triangle.A, triangle.B);

return{
    { Triangle(triangle.A, cPrime, bPrime) }, // Top triangle
    { Triangle(cPrime, triangle.B, aPrime) }, // Bottom left triangle
    { Triangle(bPrime, aPrime, triangle.C) }, // Bottom right triangle
    { Triangle(cPrime, aPrime, bPrime) }      // Center triangle
};

这是我认为会停止撕裂的函数,我跟踪对应于一对向量的中点值,如果找到相应的向量对,则返回原始中点,因此不会移动中点两次。

然而,这种方法似乎并没有像我想象的那样有效。

vec4 getMidpoint(const vec4& a, const vec4& b) {

auto AB = std::make_pair(a, b), BA = std::make_pair(b, a);

auto foundResult1 = memo.find(AB);
auto foundResult2 = memo.find(BA);

if (foundResult1 != memo.end())
    return memo[AB];

if (foundResult2 != memo.end())
    return memo[BA];

auto result = (a + b) / 2; 
result += randVector() * getLength(a, b) * randomness; 

memo.insert(std::make_pair(AB, result)); 
memo.insert(std::make_pair(BA, result));

return result;

你们有什么见解,我的中点功能有问题吗?

1 个答案:

答案 0 :(得分:0)

您的问题来自相邻的边缘。

假设你有两个三角形ABC和DBC,BC是公共边缘,你想通过添加一些嘈杂的中间点来修改它们。

根据三角形,您可以在BC的中间使用两个不同的点。

  • 当您使用ABC修改它时,让E成为BC的中间。
  • 当您使用DBC修改它时,让F成为BC的中间位置。

E和F必须相同。否则会出现大的差距。它很容易在你的照片上看到。

在我看来,您应该使用索引顶点并使用表(或任何方法)来查找已存在的给定边的中间位置。即:当它在DBC中计算BC的中间时,我们检查并发现它已经存在为E.