为什么gluTess没有在第一次通话时工作?

时间:2011-06-23 12:46:47

标签: opengl glu tesselation

我使用gluTess *函数绘制非凸多边形。为了避免在每一步重做细分,我将结果存储在一个数组中,并使用OpenGL的顶点数组功能进行绘制。

我的问题是,出于某种原因,我第一次使用gluTess *时只绘制了三角形的一部分。如果我强制重新创建gluTess *,那么一切都很好。

注意,要重新创建gluTess *,我会完全销毁包含顶点数组的对象并重新创建它(这会强制重新计算顶点数组对象)。

为什么会出现这种情况?

一些随意的想法:

  • 可能是因为对于第一次OpenGL调用,窗口尚未达到其完整大小?
  • 我是否需要设置一些OpenGL状态,这将在以后完成,但不是在第一次调用时?

感谢。

编辑:作为测试,我只是创建,销毁并重新创建了顶点数组。它解决了这个问题。这意味着:在OpenGL状态没有任何变化的情况下,对gluTess *的第一次调用无法正确地对多边形进行细分。但第二个成功了。之前有人注意到了吗?

编辑(2):以下是代码:

VA va;
GLUtesselator *t = gluNewTess();
gluTessCallback(t, GLU_TESS_BEGIN_DATA, (GLvoid (*)())beginVA);
gluTessCallback(t, GLU_TESS_END_DATA, (GLvoid (*)())endVA);
gluTessCallback(t, GLU_TESS_VERTEX_DATA, (GLvoid (*)())vertexVA);
gluTessCallback(t, GLU_TESS_ERROR, (GLvoid (*)())&tessError);
gluTessCallback(t, GLU_TESS_COMBINE, (GLvoid (*)())&tessCombine);

gluTessProperty(t, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
gluTessProperty(t, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);

gluTessBeginPolygon(t, &va);
gluTessBeginContour(t);
foreach(Point3d& p, points)
  gluTessVertex(t, const_cast<GLdouble*>(p.c_data()), (void*)&p);
gluTessEndContour(t);
gluTessEndPolygon(t);
gluDeleteTess(t);

当第二次调用成功时,我怀疑beginVA,endVA和vertexVA工作正常(正如我所说,第二次调用是通过销毁主要保存顶点数组的数据结构VA来实现的。)

编辑(3):这是缺少的代码:

struct VA
{
  std::vector<Point3d> positions; // Vertex array
  GLenum current_mode; // Drawing mode (GL_TRIANGLE, *_FAN or *_STRIP)
  Point3d v1, v2; // Two last vertices for _FAN or _STRIP
  bool has_v1, has_v2; // did we get the two last vertices?
  int n; // Index of the vertex, for *_STRIP
};


void beginVA(GLenum mode, VA *va)
{
  va->current_mode = mode; // Store the mode
  va->has_v1 = va->has_v2 = false; // We haven't had any vertex yet
  va->n = 0;
}

void endVA(VA *va)
{
  va->current_mode = 0; // Not really necessary, but cleaner
}

void vertexVA(Point3d *p, VA *va)
{
  ++va->n;
  if(va->current_mode == GL_TRIANGLES) // The simple case
    va->positions.push_back(*p);
  else if(!va->has_v1) {
    va->v1 = *p;
    va->has_v1 = true;
  } else if(!va->has_v2) {
    va->v2 = *p;
    va->has_v2 = true;
  } else if(va->current_mode == GL_TRIANGLE_STRIP) {
    if(va->n%2 == 1) {
      va->positions.push_back(va->v1);
      va->positions.push_back(va->v2);
      va->positions.push_back(*p);
    } else {
      va->positions.push_back(va->v2);
      va->positions.push_back(va->v1);
      va->positions.push_back(*p);
    }
    va->v1 = va->v2;
    va->v2 = *p;
  } else { // GL_TRIANGLE_FAN
    va->positions.push_back(va->v1);
    va->positions.push_back(va->v2);
    va->positions.push_back(*p);
    va->v2 = *p;
  }
}

编辑(4):最后,错误发生在其他地方。我一定很累,我用std :: vector来存储combine函数的结果。我不知道它为什么会在以后工作,但它确实正常,它第一次不起作用!对不起,我现在关闭这个主题。

1 个答案:

答案 0 :(得分:2)

OpenGL和GLU彼此独立。它们通常结合在一起,但GLU tesselation函数独立于OpenGL工作。

你存储tesselated顶点数据是一件好事,这就是它应该如何完成。

编辑:通过前两个问题编辑回答:

  

您是否尝试过重绘   没有重新设计的细节   数据

     

给予好处要容易得多   如果你要表现出来,那就是明智的答案   相关代码及其背景。

编辑:通过第三个问题编辑回答:

  

下一个问题:签名是什么   beginVA,endVA,vertexVA?如何   vertexVA是否将顶点插入   VA。 VA怎么样? (类,   结构定义等。)

我可以提出一个建议:

struct VA
{
  std::vector<Point3d> positions; // Vertex array
  std::vector<GLuint> triangle_face_indices;
  std::vector<GLuint> tristrip_face_indices;
  std::vector<GLuint> trifan_face_indices;
  GLenum current_mode; // Drawing mode (GL_TRIANGLE, *_FAN or *_STRIP)
};

void beginVA(GLenum mode, VA *va)
{
  va->current_mode = mode; // Store the mode
}

void endVA(VA *va)
{
  va->current_mode = 0; // Not really necessary, but cleaner
}

void vertexVA(void *p, VA *va)
{
  GLuint idx = (GLuint)((intptr_t) p);

  switch(va->current_mode) {
  case      GL_TRIANGLES: va->triangle_face_indices.push_back(i); break;
  case GL_TRIANGLE_STRIP: va->tristrip_face_indices.push_back(i); break;
  case   GL_TRIANGLE_FAN: va->trifan_face_indices.push_back(i); break;
  }
}

像这样使用

gluTessBeginPolygon(t, &va);
gluTessBeginContour(t);
for(GLuint i = 0; i < va.positions.size(); i++) {
  gluTessVertex(t, const_cast<GLdouble*>(va.positions[i].c_data()), (void*)((intptr_t)i));
}
gluTessEndContour(t);
gluTessEndPolygon(t);
gluDeleteTess(t);

使用连续3次调用glDrawElements绘制两种绘图模式。