非凸多角形を描画するために gluTess* 関数を使用しています。すべてのステップでテッセレーションをやり直すのを避けるために、結果を配列に格納し、OpenGL の頂点配列機能を使用して描画します。
私の問題は、何らかの理由で、初めて gluTess* を使用したときに、三角形の一部しか描画されないことです。gluTess* を強制的に再作成すれば、すべて問題ありません。
gluTess* を再作成するために、頂点配列を含むオブジェクトを完全に破棄して再作成することに注意してください (これにより、頂点配列オブジェクトの再計算が強制されます)。
なぜそうなるのかについて何か考えはありますか?
いくつかのランダムなアイデア:
- 最初の OpenGL 呼び出しでは、ウィンドウがまだフルサイズになっていないためでしょうか?
- 後で行うOpenGLの状態を設定する必要がありますか?最初の呼び出しではありませんか?
ありがとう。
編集:テストとして、頂点配列を作成、破棄、および再作成しました。それは問題を解決します。つまり、OpenGL の状態を変更しないと、gluTess* への最初の呼び出しでポリゴンを正しくテッセレートできません。しかし、2つ目は成功します。誰かが前にそれに気づきましたか?
編集(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);
2 番目の呼び出しが成功すると、beginVA、endVA、および vertexVA が正常に機能すると思われます (前述のとおり、2 番目の呼び出しは、主に頂点配列を保持するデータ構造 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 を使用して結合関数の結果を格納しました。後でうまくいった理由はわかりませんが、最初はうまくいかなかったのは当然のことでした。申し訳ありませんが、これで本件はクローズさせていただきます。