我使用gluTess *函数绘制非凸多边形。为了避免在每一步重做细分,我将结果存储在一个数组中,并使用OpenGL的顶点数组功能进行绘制。
我的问题是,出于某种原因,我第一次使用gluTess *时只绘制了三角形的一部分。如果我强制重新创建gluTess *,那么一切都很好。
注意,要重新创建gluTess *,我会完全销毁包含顶点数组的对象并重新创建它(这会强制重新计算顶点数组对象)。
为什么会出现这种情况?
一些随意的想法:
感谢。
编辑:作为测试,我只是创建,销毁并重新创建了顶点数组。它解决了这个问题。这意味着:在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函数的结果。我不知道它为什么会在以后工作,但它确实正常,它第一次不起作用!对不起,我现在关闭这个主题。
答案 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
绘制两种绘图模式。