【问题标题】:Creating a fractal tree in opengl在opengl中创建分形树
【发布时间】:2012-10-30 06:08:33
【问题描述】:

在 opengl 中创建分形有点麻烦。这是我当前的代码

void generateTree(){
  Point3f startPoint({0.0f,0.0f,0.0f});
  Point3f endPoint({1.0f,0.0f,0.0f});
  float rotation = 90.0f;
  glutWireSphere(0.05, 4, 4);
  _generateTreeBranches(startPoint,1.0f,rotation,0);
}

void _generateTreeBranches(const Point3f& newPosition,
                       float length,
                       float rotation,
                       const int depth)
{
  if(depth > MAX_DEPTH) return;
  cout << "at depth = " << depth << endl;


  if(depth == 0){
      glColor3f(1.0f,1.0f,1.0f);
  }else if(depth == 1){
      glColor3f(1.0f,0.0f,0.0f);
  }else{
      glColor3f(0.0f,1.0f,0.0f);
  }

  glTranslatef(newPosition.x,newPosition.y,newPosition.z);
  glRotatef(rotation, 0.0f, 0.0f, 1.0f);
  drawLine(length);
  glRotatef(-rotation, 0.0f, 0.0f, 1.0f);
  glTranslatef(-newPosition.x,-newPosition.y,-newPosition.z);



  const float newLength = length * BRANCH_LENGTH_DECREASE_FACTOR;
  int nextDepth = depth + 1;
  Point3f nextPosition = {newPosition.x+length, newPosition.y, newPosition.z};

  float leftRotation = rotation + CHILD_BRANCH_ANGLE * nextDepth;
  _generateTreeBranches(nextPosition,newLength,leftRotation,nextDepth);

  float rightRotation = rotation - CHILD_BRANCH_ANGLE * nextDepth;
  _generateTreeBranches(nextPosition,newLength,rightRotation,nextDepth);

}

定位不正确,尽管旋转似乎是正确的。新分支不是从父分支的终点开始绘制的。有人可以帮我解决这个问题。查看完整代码here

【问题讨论】:

  • 我可以看到您依靠通过递归调用堆叠 glTranslatef 和 glRotatef 函数来实现您的分形树。这很糟糕,因为最终结果并不总是很明显,而且很容易出错。我建议您以数学方式执行当前分支的旋转和平移计算,并使用 glPushMatrix/glPopMatrix 在每个分支上应用一对 glRotatef+glTranslatef 以将其重置为下一个分支。更少的混乱和更合理的数学。
  • 您好,感谢您的帮助。我试图避免进行手动计算,而让 opengl 完成这项工作,但对于这种情况,如果我手动完成它可能会更好,更容易阅读

标签: c++ opengl fractals


【解决方案1】:

nextPosition 的公式不正确,因为它没有考虑当前分支面向的方向

 Point3f nextPosition = {newPosition.x+length, newPosition.y, newPosition.z};

应该是这样的(请仔细检查):

Point3f nextPosition = {newPosition.x+length*cos(rotation), newPosition.y+length*sin(rotation), newPosition.z};

另外,请使用 glLoadIdentity() 立即重置矩阵,如下所示:

glTranslatef(newPosition.x,newPosition.y,newPosition.z);
glRotatef(rotation, 0.0f, 0.0f, 1.0f);
drawLine(length);
glLoadIdentity();

它会比你想要做的更清楚。

【讨论】:

  • 您好,感谢您的帮助,您能解释一下为什么我会使用 glLoadIdentity 而不是抵消之前的转换吗?我还需要在当前堆栈中推送/弹出矩阵吗?
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多