2011-06-23 6 views
1

J'utilise les fonctions gluTess * pour dessiner des polygones non-convexes. Pour éviter de refaire la tesselation à chaque étape, je stocke le résultat dans un tableau et j'utilise les capacités de tableau de vertex d'OpenGL pour dessiner.Pourquoi gluTess ne fonctionne pas au premier appel?

Mon problème est que, pour une raison ou une autre, la première fois que j'utilise le gluTess *, seule une partie des triangles est dessinée. Si je force à recréer le gluTess *, alors tout va bien.

Notez que, pour recréer le gluTess *, je détruis complètement l'objet contenant le tableau de vertex et le recréer (ce qui force le recalcul de l'objet tableau de vertex).

Une idée de pourquoi ce serait le cas?

Quelques idées au hasard:

  • pourrait-il être parce que pour la première OpenGL appeler la fenêtre est pas encore à sa pleine taille?
  • Dois-je définir un état OpenGL, ce qui sera fait plus tard, mais pas lors du premier appel?

Merci.

Édition: En tant que test, je viens de créer, détruire et recréer la matrice de vertex. Cela résout le problème. Ce qui signifie: sans aucun changement dans l'état OpenGL, le premier appel à gluTess * ne corrige pas correctement le polygone. Mais le second réussit. Quelqu'un a-t-il remarqué cela avant?

Edit (2): Voici le code:

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

Comme le second appel réussit, je soupçonne que beginVA, endVA et vertexVA fonctionnent très bien (comme je l'ai dit, le deuxième appel est fait par détruire la structure de données VA, qui contient principalement le tableau de vertex).

Edit (3): Voici le code manquant:

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

Edit (4): En fin de compte, l'erreur était ailleurs. Je devais être fatigué, j'ai utilisé un std :: vector pour stocker le résultat de la fonction de combinaison. Je ne sais pas pourquoi ça a marché plus tard, mais c'était normal que ça ne marche pas la première fois! Désolé à ce sujet, je vais maintenant fermer ce sujet.

Répondre

2

OpenGL et GLU sont indépendants l'un de l'autre. Ils viennent généralement ensemble, mais les fonctions de tesselation GLU fonctionnent indépendamment d'OpenGL.

Si vous stockez les données de vertex tesselées, c'est une bonne chose, c'est comme cela que cela doit être fait.

EDIT: répondu par deux premières questions modifications:

Avez-vous essayé de délivrer un redessiner sans recréation des tesselé données?

Il serait beaucoup plus facile de donner un bon et une bonne réponse si vous montriez le code pertinent et son contexte.

EDIT: répondu par la troisième édition de la question:

question suivante: Quelle est la signature de beginVA, endVA, vertexVA? Et comment est-ce que vertexVA insère le sommet dans VA. Comment VA ressemble? (classe, définition de structure, etc.).

Puis-je faire une suggestion:

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

utilisé comme celui-ci

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

Et dessiner à l'aide de 3 appels consécutifs à glDrawElements soit en mode dessiner.

+0

J'ai mis le code de tessellation comme une modification à mon poste. Mais qu'entendez-vous par "redessiner sans recréer les données tesselées"? Mon objet est constamment redessiné, car je peux le contourner. Le dessin est parfaitement cohérent, il n'y a pas de scintillement, les triangles ne sont vraiment pas là. – PierreBdR

+0

@PierreBdR: certaines personnes relisent leur maillage pour chaque itération de la fonction de dessin; puisque vous avez dit que vous avez stocké vos vertices une question stupide par moi cependant. – datenwolf

+0

mmmh .. Je préfère ne pas, car j'aurais beaucoup de polygones à dessiner, et l'utilisation de _STRIP ou _FAN implique un appel à glDrawElements par bande ou fan. – PierreBdR

Questions connexes