VBOs dynamic...

jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007 - 18 nov. 2006 à 18:06
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 - 22 nov. 2006 à 17:41
Bonjour,

Je dois pouvoir dessiner plus de 300 000 polygons dont la pluspart son concave... J'utilise donc les gluTess, j'utilise actuellement les glList pour que mon rendering soit plus "fluide", seulement je dois pouvoir en temps reel modifier la hauteur de mes couches, la couleur (alpha compris)... bref, certain parametre de mes polygon doivent pouvoir etre changé en temps reel et la glList n offre pas cette possibilité et avec 300 000 polygon, a chaque fois reecrire la gllist ca prend du temp!!!
J'aimerai utiliser les VBOs, seulement je ne vois pas comment avec ma structure! J'ai lu le tuto nehe a ce sujet, mais je vois pas comment faire dans mon cas! quelqu'un pourrait il m aiguiller?
voici mon code correspondant au coordonnée de mes polygon et a l enregsitrement dans la list actuelle... comment faire ca avec les VBO?

Mes classes :

class QUAD                                // Build our Quads Structure
{
public:
    int num_pts;
    int type;
    GLdouble* bottom;  // Bottom est un tableau de coordonnée des sommets de mes polygons de la forme {x1,y1,z1,x2,y2,z2,x3, ...}
    int layer;
};

// CLASS D'UN COUCHE
class LAYER                                // Build our LAYER Class, correspond a une couche, j'en ai 10 differente a dessiner
{
public:
    int num_quads; //nombre de polygon dans cette couche
    bool visible, existe; // visible determine si la couche doit s afficher ou non, ce qui permet en temps réél de cacher une ou plusieur couche
    float hauteur, zstart, h, penetration; h et zstart doivent pouvoir etre changé en temps réél, zstart et la hauteur dela face du bas et zsart+h la hauteur de la face du dessus
    char* nom_cif;
    char* nom_couche;
    vec4 color; // doit aussi pouvoir etre changé en temps réél pour modifier la couleur ou l opacité d'une des couches!
    QUAD* quad;    // Tableau des polygons a dessiner dans la couche Layer

// ici se trouve les restes des methode : constructeur, ...

};

Enregistrement des polygon a dessiner dans les lists :

GLUtesselator *tobj;
    glListBase(DrawList);
    int num_pts;
    GLdouble pt_bottom[250][3];
    GLdouble pt_top[250][3];

    for(i= 0; i<11; i++) // j'ai 10 couches différentes a dessiner
        {
            glNewList(DrawList+i+1, GL_COMPILE); // 10 listes de créé pour mes 10 couches différentes, ca me permet en temps réél de cacher une couche ou plusieur couche c'est actuellement la seul chose que j arrive a faire sur mes couche en temps réél
                for(int q=0; q<LLayer[i].num_quads; q++)
              {
                    num_pts = LLayer[i].quad[q].num_pts;
                       
                    for(int p=0; p<num_pts; p++)
                    {
                      // Enregistremen des sommets des faces du dessus et du dessous
                        pt_bottom[p][0]=LLayer[i].quad[q].bottom[p*2];
                        pt_bottom[p][1]=LLayer[i].zstart;
                        pt_bottom[p][2]=LLayer[i].quad[q].bottom[p*2+1];

                        pt_top[p][0]=LLayer[i].quad[q].bottom[p*2];
                        pt_top[p][1]=LLayer[i].zstart + LLayer[i].h;
                        pt_top[p][2]=LLayer[i].quad[q].bottom[p*2+1];
                    }

                    for(p=0; p<num_pts; p++)
                    {
                      // On dessiner les faces de coté
                        int p2 = p+1;
                        if(p2 == num_pts)
                            p2 = 0;
                        glColor4f(LLayer[i].color.r,LLayer[i].color.g,LLayer[i].color.b, LLayer[i].color.a);

                        glBegin(GL_POLYGON);
                            glVertex3f(pt_bottom[p][0],pt_bottom[p][1],pt_bottom[p][2]);
                            glVertex3f(pt_bottom[p2][0],pt_bottom[p2][1],pt_bottom[p2][2]);
                            glVertex3f(pt_top[p2][0],pt_top[p2][1],pt_top[p2][2]);
                            glVertex3f(pt_top[p][0],pt_top[p][1],pt_top[p][2]);
                        glEnd();
                       
                        // ON DESSINE TOUTES LES ARRETES
                       
                        glColor4f(0.0,0.0,0.0, 1.0);
                           
                        glBegin(GL_LINES);
                            glVertex3f(pt_bottom[p][0],pt_bottom[p][1],pt_bottom[p][2]);
                            glVertex3f(pt_bottom[p2][0],pt_bottom[p2][1],pt_bottom[p2][2]);
                   
                            if(p2!=0)
                            {
                                glVertex3f(pt_bottom[p2][0],pt_bottom[p2][1],pt_bottom[p2][2]);
                                glVertex3f(pt_top[p2][0],pt_top[p2][1],pt_top[p2][2]);
                            }
                            glVertex3f(pt_top[p2][0],pt_top[p2][1],pt_top[p2][2]);
                            glVertex3f(pt_top[p][0],pt_top[p][1],pt_top[p][2]);
                       
                            if(p==0)
                            {
                                glVertex3f(pt_top[p][0],pt_top[p][1],pt_top[p][2]);
                                glVertex3f(pt_bottom[p][0],pt_bottom[p][1],pt_bottom[p][2]);
                            }
                        glEnd();
                    }   

                    glColor4f(LLayer[i].color.r,LLayer[i].color.g,LLayer[i].color.b, LLayer[i].color.a);

                    tobj = gluNewTess();
                    gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (CALLBACK*) ()) &glVertex3dv);
                    gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid (CALLBACK*) ())&beginCallback);
                    gluTessCallback(tobj, GLU_TESS_END, (GLvoid (CALLBACK*) ())    &endCallback);
                    gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ())&errorCallback);
                    //glShadeModel(GL_FLAT);

                   // On dessine la face de dessous
                    gluTessBeginPolygon(tobj, NULL);
                        gluTessBeginContour(tobj);
                            for(int u=0; u<num_pts; u++)
                                gluTessVertex(tobj, pt_bottom[u], pt_bottom[u]);
                        gluTessEndContour(tobj);
                    gluTessEndPolygon(tobj);

                    // On dessine la face de dessus

                    gluTessBeginPolygon(tobj, NULL);
                        gluTessBeginContour(tobj);
                            for(u =0; u<num_pts; u++)
                                gluTessVertex(tobj, pt_top[u], pt_top[u]);
                        gluTessEndContour(tobj);
                    gluTessEndPolygon(tobj);

                    gluDeleteTess(tobj);               
                }
            glEndList();
        }

Comment puis je transformer ca en VBOs? C'est possible? Et apres comment j'interagis avec mes couches?
Par exemple mon pt_bottom et pt_top on en y une valeur qui est egale au zstart et h de la LLayer[] correspondant. Si en temps reel avec les VBOs je modifie dans mon LLayer[] le zstart et le h, ca changera automatiquement sur mon rendu? ou je devrai modifier ca directement dans le VBO?

Merci beaucoup pour votre aide!

Jojo

10 réponses

luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
19 nov. 2006 à 23:12
La transformation en vbo est simple pour le début de ta fonction. Les
glBegin/End (à proscrire absolument !) sont facilement intégrables dans
un vbo.


Pour les fonctions de fragmentation de glu. Il faut redéfinir la fonction de callback;
gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (CALLBACK*) ()) &glVertex3dv);

ainsi que les callback GLU_TESS_BEGIN et GLU_TESS_END, de facon a ce qu'ils n'appellent pas glBegin/End.

D'après le redbook "l'algorithme de fragmentation choisit le type de primitive trinagulaire le plus efficace". Donc impossible de forcer l'utilisation d'une primitive. Donc va falloir ruser un peu:


Dans ton callback "beginCallback", l'argument
GLenum which
va te donner le type de primitive qu'il s'apprete a créer. Donc tu
stockes ca dans une variable globale accessible par le callback
GLU_TESS_VERTEX et tu construits les triangles générés par l'objet de
fragmentation. Donc ton callback GLU_TESS_VERTEX aura la forme suivante:


On définie deja le callback
gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (CALLBACK*) ()) &MyCallBack);


puis, admettons que nb_vertex donne le nombre de vertex généré jusqu'a maintenant:


void MyCallBack(GLvoid * vertex)

{

static counter = 0;

counter++;     // Nous permet de savoir le numéro du vertex actuellement envoyé.


switch(type_de_primitive_actuel_généré_par_glutess)

{

case GL_TRIANGLES:

if (counter != 1) Annomalie, test a faire pour etre sur que tout est correct.

memcpy(Mon_tableau_de_vertex[nb_vertex], vertex, 4*sizeof(double));

nb_vertex++;

if (counter 3) counter 0;

break;


case GL_TRIANGLE_STRIP:

if (counter > 3)  Si counter > 3, chaque nouveau point est en fait un nouveau triangle

{

memcpy(Mon_tableau_de_vertex[nb_vertex], Mon_tableau_de_vertex[nb_vertex-2], 8*sizeof(double));

nb_vertex+=2;

memcpy(Mon_tableau_de_vertex[nb_vertex], vertex);

nb_vertex++;

}

else

{

memcpy(Mon_tableau_de_vertex[nb_vertex], vertex);


nb_vertex++;

}

break;


case GL_TRIANGLE_FAN:

...

break;

}

}


Apres, c'est simple, suffit de créer le tableau d'index qui est trivial a faire ici:

unsigned short * index = new unsigned short[nb_vertex/3];

for (int k 0 ; k < nb_vertex ; ++k) index[k] k;


Apres tu balances les deux tableaux (index, et vertex) et color éventuellement a la carte graphique.


Enfin voila a quoi j'en pensé en étudiant le pb.
0
jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007
20 nov. 2006 à 13:56
Oki, je viens d'étudier ton idée, je commence a m'y lancer.
1 question cependant, le Mon_tableau_de_vertex[nb_vertex] doit etre declaré egalement en global comme etant une GLdouble * Mon_tableau_de_vertex, comme ca a chaque fois qu'on fait memcpy, ca ajoute dynamiquement les valeur a la suite?

Et a quoi sert le tableau d index?
0
jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007
20 nov. 2006 à 14:35
Hello,

voila comment j'ai modifié mes callbacks, seulement j'ai des erreur au niveau des memcpy:
donc en fait la, normalement tous mes polygons sont enregistré dans TabVertex sous forme de tableau de triangles!?

GLenum TypePrimitive;
GLdouble * TabVertex;
int nb_vertex = 0;
bool trifan = false;

void CALLBACK beginCallback(GLenum which)
{
    //glBegin(which);
    TypePrimitive = which;

}
void CALLBACK endCallback(void)
{
    //glEnd();
}

void CALLBACK MyCallBack(GLvoid* vertex)
{
     static int counter = 0;
    static int nb_fan = 0;
    counter++;
    switch(TypePrimitive)
    {
        case GL_TRIANGLES:
            trifan=false;
            memcpy(TabVertex[nb_vertex], vertex, 4*sizeof(double));
            nb_vertex++;
            if(counter==3)
                counter=0;
            break;
        case GL_TRIANGLE_STRIP:
            trifan = false;
            if(counter>3)
            {
                memcpy(TabVertex[nb_vertex],TabVertex[nb_vertex-2],8*sizeof(double));
                nb_vertex+=2;
                memcpy(TabVertex[nb_vertex],vertex, 4*sizeof(double));
                nb_vertex++;
            }
            else
            {
                memcpy(TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            break;
        case GL_TRIANGLE_FAN :
            if(!trifan)
            {
                trifan=true;
                nb_fan = nb_vertex;
            }
            if(counter>3)
            {
                memcpy(TabVertex[nb_vertex],TabVertex[nb_fan],4*sizeof(double));
                nb_vertex++;
                memcpy(TabVertex[nb_vertex],TabVertex[nb_vertex-1],4*sizeof(double));
                nb_vertex++;
                memcpy(TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            else
            {
                memcpy(TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            break;
    }
}

voila l erreur pour tous mes memcpy :
c:\documents and settings\joh@n\mes documents\epfl\projet de semestre\3d_visu vbos\gestionfichier.cpp(45) : error C2664: 'memcpy' : cannot convert parameter 1 from 'double' to 'void *'
        There is no context in which this conversion is possible
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
20 nov. 2006 à 18:20
Bas évidemment, suffit d'etre rigoureux au niveau des types. Lui il veut un pointeur et  toi, tu lui files un double ...

Faut lui filer l'adresse du double.


Pk un tableau d'index ? Car on va pas utiliser un vbo basic mais un vbo
indexé (plus rapide). Les vbos se base ne sont plus utilisés toute
facon, on fait systèmétiquement des buffers indexés. Cad un tableau de
vertex puis un tableau d'index qui contient les indices de chaque
vertex qui forment le triangle.


Sinon, oui, tout le tableau doit etre construit sur la base des triangles pour pouvoir utiliser les vbos pour l'ensemble.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007
20 nov. 2006 à 18:29
J'ai reussi al enregistrer .. seulement faut que je donne une taille a mon TabVertex avant! on peut pas l ajouter simplement dedans, mais par contre mes trianlge s affichent n importe comment, pour tester j'ai simplement dans mon Draw ajouter la fonction glDrawArrays pour le TabVertex... et bref ca me donne n importe quoi, peut etre mon Callback est faux et que ca enregistre mal mes vertex!

GLenum TypePrimitive;

int nb_vertex = 0;
int counter = 0;

#ifndef CALLBACK
#define CALLBACK
#endif

void CALLBACK beginCallback(GLenum which)
{
    //glBegin(which);
    TypePrimitive = which;

}
void CALLBACK errorCallback(GLenum errorCode)
{
    const GLubyte *estring;
    estring = gluErrorString(errorCode);
    fprintf(stderr, "Tessellation Error: %s\n", estring);
    exit(0);
}
void CALLBACK endCallback(void)
{
   // glEnd();
    counter=0;
}

void CALLBACK MyCallBack(GLvoid* vertex)
{
    counter++;
    switch(TypePrimitive)
    {
        case GL_TRIANGLES:
            if(counter>3)
                counter = 1;
            memcpy(&TabVertex[nb_vertex], vertex, 4*sizeof(double));
            nb_vertex++;
            if(counter==3)
                counter=0;
            break;
        case GL_TRIANGLE_STRIP:
            if(counter>3)
            {
                memcpy(&TabVertex[nb_vertex],&TabVertex[nb_vertex-2],8*sizeof(double));
                nb_vertex+=2;
                memcpy(&TabVertex[nb_vertex],vertex, 4*sizeof(double));
                nb_vertex++;
            }
            else
            {
                memcpy(&TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            break;
        case GL_TRIANGLE_FAN :
            if(counter>3)
            {
                memcpy(&TabVertex[nb_vertex],&TabVertex[nb_vertex-3],4*sizeof(double));
                nb_vertex++;
                memcpy(&TabVertex[nb_vertex],&TabVertex[nb_vertex-1],4*sizeof(double));
                nb_vertex++;
                memcpy(&TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            else
            {
                memcpy(&TabVertex[nb_vertex],vertex,4*sizeof(double));
                nb_vertex++;
            }
            break;
    }

}
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
20 nov. 2006 à 18:31
Donc le but, c'est de construire le tableau de vertex de facon a ce que :

Soit k, un entier positif inférieur au nombre de triangle total;

Les vertex 3*k, 3*k+1 et 3*k + 2 forment un triangle.
0
jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007
20 nov. 2006 à 19:19
oui ca je comprend, mais pourquoi mes triangles s affichent n importe comment?
Apparement normalement MyCallBack() enregsitre dans TabVertex[] chaqu'un des vertex des triangle par 3! donc apres avec glDrawArrays qui parcour TabVertex par 3, ca devrai dessiner les triangles!!!!
Mes case sont ils juste?
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
20 nov. 2006 à 22:50
Bas si ca affiche n'importe quoi, c'est que tes "case" sont faux...


       case GL_TRIANGLES:

            if(counter>3)

                counter = 1; // Faux pas mettre ca


Je te disais de gérer l'anomalie en avertissant le programmeur, pas en
corrigeant discretement. C'est un cas qui doit jamais arriver, donc
faut tout stopper si tu rencontres ca:



Pour le triangle fan, ca m'a l'air louche ton truc. Regarde comment sont contruite les primitives avec le mode "fan".


     case GL_TRIANGLE_FAN :

            if(counter>3)

            {

           
   
memcpy(&TabVertex[nb_vertex],&TabVertex[nb_vertex-counter +
1],4*sizeof(double)); // ya un counter qui intervient forcément

                nb_vertex++;

           
   
memcpy(&TabVertex[nb_vertex],&TabVertex[nb_vertex-1],4*sizeof(double));

                nb_vertex++;

           
   
memcpy(&TabVertex[nb_vertex],vertex,4*sizeof(double));

                nb_vertex++;

            }

            else

            {

           
   
memcpy(&TabVertex[nb_vertex],vertex,4*sizeof(double));

                nb_vertex++;

            }

            break;


Enfin bricole et test. Met des cout partout, pour savoir quelles sont
les primitives utilisées. Si c'est tjs la meme... Si c'est le cas,
concentre toi sur celle la jusqu'à la faire marcher.
0
jojomillenium Messages postés 136 Date d'inscription samedi 1 mai 2004 Statut Membre Dernière intervention 26 mai 2007
22 nov. 2006 à 15:31
Ca y est! J'ai reussi !! .... a enregistrer dans un tableau toutes les coordonnées des mes triangles et a l es afficher par un glDrawArrays!
Maintenant, comment on fait pour envoyer ca dans le buffer de la carte? mais surtout en dynamique, que je puisse modifier la coordonnée y des chaque triangles si necessaire!

J'ai donc 10 tableau, un pour chacune de mes couches!

Merci encore pour ton aide! elle m a ete precieuse! Tres malin la ruse des CallBacks!

Jojo
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
22 nov. 2006 à 17:41
Cool, comme ca je sais que si un jour j'ai besoin de ca, ca marche.

Pour envoyer ca dans la carte video, je te laisse regarder ce site très bien expliqué:


http://www.g-truc.net/article/vbo-fr.pdf


Si tu rencontres un pb, repost un nouveau message sur le forum, ou contact moi en privé si je le vois pas.
0
Rejoignez-nous