Я использую функции 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 для хранения результата функции объединения. Я не знаю, почему это сработало позже, но это было нормально, это не сработало с первого раза! Извините, я сейчас закрою эту тему.