2011-06-23 16 views
1

gluTess *関数を使用して、非凸多角形を描画しています。すべてのステップでテッセレーションをやり直すのを避けるために、結果を配列に格納し、OpenGLの頂点配列機能を使用して描画します。最初の呼び出しでgluTessが機能しないのはなぜですか?

私の問題は、何らかの理由で初めてgluTess *を使うときに、三角形の一部だけが描画されることです。私がgluTess *を再現するように強制すると、すべてうまくいきます。

gluTess *を再作成するには、頂点配列を含むオブジェクトを完全に破棄して再作成します(これにより、頂点配列オブジェクトの再計算が強制されます)。

なぜそうなのでしょうか?

いくつかのランダムなアイデア:

  • 最初のOpenGLのためのウィンドウを呼び出すので、それができるが、そのフルサイズではまだないのですか?
  • 私はいくつかのOpenGL状態を設定する必要があります。これは後で実行されますが、最初の呼び出しでは実行されませんか?

ありがとうございます。

:テストとして、私はちょうど、頂点配列を作成、破棄、再作成しました。それは問題を解決する。つまり、OpenGL状態を変更しなければ、gluTess *への最初の呼び出しではポリゴンを正しくテッセレーションできません。しかし、第二のものは成功する。誰かがそれに気づいたか?

編集(2):2番目の呼び出しが成功したように、私は(私が言ったように、2番目の呼び出しがで作られbeginVA、endVAとvertexVAが正常に動作することを疑う

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); 

:ここでは、コードです主に頂点配列を保持するデータ構造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を使って結合関数の結果を格納しました。なぜそれが後で働いたのかわかりませんが、初めて正常に動作しなかったのは確かです!申し訳ありません、私は今この問題を閉じるでしょう。

答えて

2

OpenGLとGLUは互いに独立しています。彼らは通常、一緒に来るが、GLUのtesselation関数はOpenGLから独立して動作します。

テッセレーションされた頂点データを保存することは良いことです。その方法を実行する必要があります。

EDIT:最初の二つの質問で答えが編集:

あなたはテッセレーション データのレクリエーションせずに再描画 を発行しようとしましたか?

関連コードとその文脈を表示すると、良い数字を与える方がはるかに簡単です。 と賢明な答えです。

EDIT:3番目の質問の編集によって答え:

次の質問:beginVA、endVA、vertexVAの署名 は何ですか?そして、どのように は、頂点VAを VAに挿入するのですか? VAはどのように見えますか? (クラス、 構造体定義など)。

は私が提案提供することがあります:この

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); 

のように使用

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; 
    } 
} 

をドローモードのいずれかのためにglDrawElementsから3つの連続で呼び出しを使用して描画します。

+0

テッセレーションコードを投稿として編集しました。しかし、「データを再作成せずに再描画」することはどういう意味ですか?私のオブジェクトは常に動き回ります。図面は完全に一貫しており、フリッカーはなく、三角形は実際には存在しません。 – PierreBdR

+0

@PierreBdR:一部の人は、描画関数の反復ごとにメッシュを再テッセレーションします。あなたがあなたの頂点を私によるばかげた質問に保存したと言ったからです。 – datenwolf

+0

mmmh ..描画するポリゴンがたくさんあるため、_STRIPまたは_FANを使用すると、ストリップまたはファンごとにglDrawElementsを呼び出す必要があります。 – PierreBdR

関連する問題