openGL : Un cercle d'angle > 3*PI ??????

openGL : Un cercle d'angle > 3*PI ?????? - C - Programmation

Marsh Posté le 01-03-2006 à 23:15:29    

Salutations,  
 
Je poste un message parce que j'ai un souci (bug ?) des plus étranges.....
Je developpe une petite appli openGL, et là je tante de dessiner un cylindre de la maniére suivante:
je trace les deux cercles, supérieurs et inférieurs, en fonction d'un nombre de points, en incrémentant un angle de (2 PI)/nb_points...
 :)  
Jusque là, ca va !!!
Mais j'ai repris la même méthode dans un autre script, et là, surprise magnifique, lorsque mon angle fait 2pi, mon cercle n'est fermé qu'à deux tiers !!! :??:  
 
J'admet ne pas étre une grande lumiére en maths, mais là........ :pfff:  
 
J'ai essaye de pousser l'experience, en bloquant l'incrementation de mon angle à 3pi... :lol:  
Le cercle est plus fermé, mais pas encore complettement...... :heink:  
 
Si qqn veut essayer de me convaincre que ce n'est pas possible, je veux bien, mais j'ai repassé l'algo du début à la fin des dizaines de fois... ;)  
mais là j'abdique....... :pt1cable:  

Reply

Marsh Posté le 01-03-2006 à 23:15:29   

Reply

Marsh Posté le 02-03-2006 à 02:51:32    

J'ai le même probléme en ce qui concerne un cube......
le volume n'est fait qu'aux trois quarts....
 
Probléme d'algo ??? logiciel ???
 
Quelqu'un pourait-il m'aider ?

Reply

Marsh Posté le 02-03-2006 à 10:00:58    

tu vas dessiner nb points , chacun espacé d'un angle de (2 *PI ) / nb point)
il y a peut etre un pb d'arrondi  
 
essaye de dessiner nb+1 points esapcés de (2 PI ) /nb


---------------

Reply

Marsh Posté le 02-03-2006 à 11:50:45    

c'est problème d'itération....
 
si tu génères n points "espacés" de 360°/n , quand tu relies ces points par  des lignes, il y a le cas particulier du dernier segment qui relie le premier et le dernier.
 
Pas: 2Pi/n
4 itérations  
 
      0
 1  /\
     \/ 3
     2
 
0->1
1->2
2->3
3->0
 
ou sinon tu génères une itération supplémentaire:
 
      0 & 4
 1  /\
     \/ 3
     2
 
0->1
1->2
2->3
3->4
 
 

Reply

Marsh Posté le 02-03-2006 à 16:57:01    

Normalement, ma fonction qui initialise les coordonnées de mes points prends en compte ce cas de figure:  
le premier point defini est le centre du cercle (pour permettre un remplissage par GL_TRIANGLE_FAN),  
et le dernier récupére les coordonnées du deuxieme (soit le premier point qui est sur le cercle), afin de fermer le triangle...
 
Je met le code de la fonction:
 
void initialiser_cercle (GLfloat *vertices, GLfloat alt)
{
   int i = 1;
  float angle = 0;
 
  vertices[0] = 0;
  vertices[1] = 0;
  vertices[2] = alt;
   
  while(angle < (2 * PI))
  {
       vertices[3 * i] = (RAYON * cos(angle));
       vertices[3 * i + 1] = (RAYON * sin(angle));
       vertices[3 * i + 2] = alt;
       angle += ((2 * PI) / POINTS);
     i++;
     }
  vertices[(3 * (POINTS-1))] = vertices[3];
  vertices[(3 * (POINTS-1))+1] = vertices[4];
  vertices[(3 * (POINTS-1))+2] = vertices[5];
}
 
Quant au tableau de sommets, voila comment je le declare:
GLfloat vertices_c1[(3 * POINTS)];
initialiser_cercle(vertices_c1, -10);
 
 
 
 
Par contre, pour ce qui est d'un probléme d'arrondi, c'est possible mais je vois ni ou ni comment....
Quelqu'un y comprens quelque chose ???

Message cité 1 fois
Message édité par melchiaa le 29-08-2007 à 20:48:31
Reply

Marsh Posté le 02-03-2006 à 18:45:06    

Salut,
L'ideal serait que tu donne le code source entier...

Reply

Marsh Posté le 02-03-2006 à 19:47:30    

Le fichier est "un peu" grand, alors je l'ai mis en ligne...
 
...
 
Par contre, je previens qu'il a été légérément modifié....
et que là, le résultat de compilation est du genre incompréhensible...
Mais je vais essayer de corriger le probléme et d'en remettre un mieux assés vite.
 
Mais tout conseil reste le bienvenu !!


Message édité par melchiaa le 29-08-2007 à 20:48:57
Reply

Marsh Posté le 02-03-2006 à 20:18:12    

Bon j'ai deux trait qui s'affiche, je suppose c'est les axes, mais pas de cercle en vue, pas d'animations rien...

Reply

Marsh Posté le 02-03-2006 à 20:27:00    

J'suis encore en train de regarder ca, mais là, moi je vois pas les axe et à la place j'ai droit à une masse informe blanchâtre....
 
Plutôt dépitant....

Reply

Marsh Posté le 02-03-2006 à 20:44:39    

Bon j'ai reussi a avoir un cercle (entier!) mais pas possible d'avoir le cylindre!
Cela dit je trouve ton code pas terrible... (sans etre mechant hein, disons mal organisé!)

Reply

Marsh Posté le 02-03-2006 à 20:44:39   

Reply

Marsh Posté le 02-03-2006 à 21:02:19    

Tu peux dire que c'est pas terrible, y'a pas de soucis, bien au contraire !!!  :D  
Je débute pour ce qui est de la 3D et je me demandais justement si je partais sur un truc correct....  :??:  
Je suis bien conscient que mon algo à un certain nombre de "failles", et je suppose qu'il y'en a encore beaucoup dont je ne me rend pas compte....
 
Et pour en revenir au cylindre, j'ai aussi eu le cercle fermé, et cela dit je comprend pas pourquoi, parce que j'ai rien retouché en ce qui concerne le cercle... :heink:  
Par contre, j'avais le cylindre (mise à part qu'il n'était pas fermé)...

Reply

Marsh Posté le 02-03-2006 à 23:00:06    

melchiaa a écrit :

Normalement, ma fonction qui initialise les coordonnées de mes points prends en compte ce cas de figure:  
le premier point defini est le centre du cercle (pour permettre un remplissage par GL_TRIANGLE_FAN),  
et le dernier récupére les coordonnées du deuxieme (soit le premier point qui est sur le cercle), afin de fermer le triangle...
 
Je met le code de la fonction:
 
void initialiser_cercle (GLfloat *vertices, GLfloat alt)
{
   int i = 1;
  float angle = 0;
 
  vertices[0] = 0;
  vertices[1] = 0;
  vertices[2] = alt;
   
  while(angle < (2 * PI))
  {
       vertices[3 * i] = (RAYON * cos(angle));
       vertices[3 * i + 1] = (RAYON * sin(angle));
       vertices[3 * i + 2] = alt;
       angle += ((2 * PI) / POINTS);
     i++;
     }
  vertices[(3 * (POINTS-1))] = vertices[3];
  vertices[(3 * (POINTS-1))+1] = vertices[4];
  vertices[(3 * (POINTS-1))+2] = vertices[5];
}
 
Quant au tableau de sommets, voila comment je le declare:
GLfloat vertices_c1[(3 * POINTS)];
initialiser_cercle(vertices_c1, -10);
 
A savoir que cette fonction me fait un cercle impeccable dans un autre script, mais là.....
Voyez par vous même :
 
 
http://julien.gambone.ifrance.com/autre/Cylindre.jpg
 
 
 :heink:  
 
Par contre, pour ce qui est d'un probléme d'arrondi, c'est possible mais je vois ni ou ni comment....
Quelqu'un y comprens quelque chose ???


 
tu commences à i=1 au lieu de i=0.
 
pour éviter ce genre d'erreurs, vire ton while, mets un for, vires tes constantes en #define (dont POINTS), et implémente le code pour une fonction plus flexible style:
 
void initialiser_cercle (GLfloat *vertices, int numvertices, GLfloat alt);
 
sachant que tu utilise le cas où tu recopies le premier dans le dernier point, il faut que tu en prennes compte.  
 
ie avec 6 points =>
 
angle=0;
step=2*pi/6;
for( i=0 ; i < 5 ; ++i )
{
   ....  
   ....
   tab[3*i...]=
}
 
tab[3*5...]=tab[...];
 
 
 

Reply

Marsh Posté le 02-03-2006 à 23:06:28    

tes fontions de construction de forme géométriques ne doivent être dépendantes que des paramètres passés à l'appel, pas de variable globale à la con, pas de #define à la con, il faut que du:
 
generate_object( float *buffer, int num_machin, int num_machin2, float paramtruc......);
 
ndlr, si les paramètres décrivent de manière intime l'objet, fais des structs, ça sera plus propre....
 
style:
 
generate_cylinder( float *buffer, cylinder *cyl);
 
struct cyl {
   float ray, height;
   int cap_steps, corpse_steps;
};
 
 
le float *buffer tu le remplaçe par ce que tu veux, structure définissant ton vertex {float x,y,z}, ou le GLfloat qui de toutes manières sera -toujours- un float dans la pratique...  
 
c'est cool les types des API, mais quand c'est stable depuis 10 ans, et que ça a pas raison de changer, des fois c'est moins pet-couilles d'utiliser les vrai types standard que des GLfloat, machin_BOOL.... (dumoins ça dépends de l'api aussi...)


Message édité par bjone le 02-03-2006 à 23:08:31
Reply

Marsh Posté le 03-03-2006 à 03:13:31    

J'ai essayé comme ca...
J'ai viré quasiment toute les variables globales, et les ai passées en paramétres à mes fonctions, par contre niveau structures, j'avait commencé l'apli en les utilisant, mais j'me suis rendu compte que j'me compliquait la tâche...Du coup j'les avaient abandonnées, et là, j'ai plus vraiment le temps de les réinserrer;
 
Pour le reste, c'est OK, j'arrive à visualiser mon cylindre (en tant que forme de départ), mon cube (forme d'arrivée)...
Les deux passent pas mal (quelques petites umperfections sur le cube)...
 
Le hic, c'est lorsque je veux démarrer ma tâche de fond...  :ouch: :(  
On peut pas dire que l'explosion des volumes 3D ne soit pas artistique (un peu genre art moderne...), j'ai eu droit à des putains d'fractales !!!  :D  
Mais c'était pas le but recherché    :pfff:  
 
Cela pourrait-il venir du fait que je n'ai spécifié aucune normale lorsque j'ai implémenté mon éclairage ???  
 
 


Message édité par melchiaa le 29-08-2007 à 20:49:38
Reply

Marsh Posté le 03-03-2006 à 10:46:41    

rahhhhhhhhh
 
y'a encore des i=0
 
en C/C++ les tableaux commencent en 0, en 1 c'est du pascal ou du vb...
 
edit: pardon j'avais pas vu que le vertex 0 était géré comme cas particulier :D


Message édité par bjone le 03-03-2006 à 10:47:25
Reply

Marsh Posté le 03-03-2006 à 10:49:05    

Code :
  1. void initialiser_cercle (float *vertices, int num_vertices, float rayon, float alt)
  2. {
  3.   int i = 1;
  4.  float angle = 0;
  5.  vertices[0] = 0;
  6.  vertices[1] = 0;
  7.  vertices[2] = alt;
  8.  for(i = 1; i < (num_vertices-1); i++)
  9.  {
  10.       vertices[3 * i] = (rayon * cos(angle));
  11.       vertices[3 * i + 1] = (rayon * sin(angle));
  12.       vertices[3 * i + 2] = alt;
  13.       angle += ((2 * PI) / (num_vertices-2));        ça doit pas être bon ça
  14.      }
  15.  vertices[(3 * (num_vertices-1))] = vertices[3];      pourquoi le deuxième vertex et pas le premier ?
  16.  vertices[(3 * (num_vertices-1))+1] = vertices[4];
  17.  vertices[(3 * (num_vertices-1))+2] = vertices[5];
  18. }


 
edit: je me suis fourvoyé, le premier vertex et le vertex central :D
(ça va pas bien ce matin moi  :heink: )


Message édité par bjone le 03-03-2006 à 10:52:47
Reply

Marsh Posté le 03-03-2006 à 22:35:32    

lol, tout juste, en fait, ce point au centre sert juste pour le remplissage du cercle:  
dans la fonction afficher_scene, j'utilise glBegin(GL_TRIANGLE_FAN) pour remplir les faces de mes volumes...

Reply

Marsh Posté le 04-03-2006 à 00:33:44    

tu as toujours des corruptions ?
 
parceque je suis en train de me demander que vu que tes tableaux de vertex sont perdus en sortant de afficher_scene(), un traitement différé par le driver OpenGl pourrait provoquer des corruptions de ressources.
 
calles un glFlush() / glFinish() ou je sais plus quoi qui permet d'attendre la fin de traitement ou je sais plus quoi.
 
mais c'est pas dit que ça marche alors fait un essai avec un seul objet, et le tableau de vertex en global et pas dans afficher_scene().


Message édité par bjone le 04-03-2006 à 00:52:01
Reply

Marsh Posté le 04-03-2006 à 01:04:34    

Ca a un peut évolué depuis hier....Sans pour autant que je retouche au code...... :heink:  
 
Maintenant j'ai plus un éspece de truc informe dés que je démarre ma tache de fond, mais toujours pas une évolution vers un cube... Il y'a juste une partie du cylindre qui disparait (une bande du côté à la hauteur de l'axe x)...
J'ai constaté ca en reprennant l'apli aujourd'hui.....
 
Mais pour ce qui est du rafraîchissement de la scéne, j'utilise un double buffer et à la fin de ma fonction, j'ai posé un glutSwapBuffers()....
Ca a pas le même effet que glFlush() pour ce qui est de forcer le réaffichage de la scéne ???

Reply

Marsh Posté le 04-03-2006 à 01:10:25    

glFlush() ou glFinish(): ca donne la même chose...
aucun changement par rapport à swapbuffers...

Reply

Marsh Posté le 04-03-2006 à 01:15:29    

nope en fait l'idée c'est que les drivers DirectX/OpenGl bufferisent quelques images....  
et comme je supposent qu'ils bufferisent les commandes et pas la géométrie, et vu que ta géométrie est perdue en sortie de afficher_scene()....
 
c'est pour ça, mets un tableau de vertex en global, et traçe que cet géométrie pour voir si ça aide...

Reply

Marsh Posté le 04-03-2006 à 02:14:43    

Ben là ca passe de moins en moin....
J'ai essayé de sortir mes deux tableaux de sommets, le cylindre et le cube, et de les afficher chacun séparéments...
Pour le cube, il à pas changé, mais le cylindre a perdu la moitiée inférieure de son corp  :??:  
 
Pis si je démarre la tache de fond, alors là, c'est l'apothéose: le même genre de fractale que précédement !!!! mais en plus bourin...
 
J'soupsonne le code à deux bals, pasque j'ai pas mal galéré avec des conflicts de biduls et trucs.....
 :pfff:

Reply

Marsh Posté le 04-03-2006 à 02:23:43    

Hummm !!!
Là j'ai eu droit à un truc chouette c'coup-ci !!!
j'laisse le lien !!!
 
lien parti...


Message édité par melchiaa le 29-08-2007 à 20:50:19
Reply

Marsh Posté le 04-03-2006 à 10:48:20    

je comprends pas, c'est quoi ton histoire de tache de fond ?

Reply

Marsh Posté le 04-03-2006 à 14:31:44    

En fait c'et pas compliqué, le but de l'algo est de definir 2 volumes (le cylindre et le cube) et de calculer une déformation de l'un vers l'autre....
En gros tu transforme le cylindre en cube...
 
Pour ca, j'utilise une tache de fond (glutIdleFunc(avancer(INCREMENTER))) que je lance en utilisant la touche espace....
A chaque passage dans afficher_scene, on calcul le volume en cours grace à un avancement, qui qui lui même est incrémenté par la tâche de fond...
 
Modeliser les volumes séparéments, ca marche....Mais lors du démarage de l'anim, la ca merde....

Reply

Marsh Posté le 04-03-2006 à 16:22:53    

bon ok tu tentes de faire un lerp entre la position de tes vertexs.
 
bon question code, tu te compliques la vie pour rien avec ton:
 
void tacheDeFond(void)
{
 avancer(INCREMENTER);
 glutPostRedisplay;
}
 
 
float avancer (int action)
{
    static float avancement = 0;
 
    if(action == INCREMENTER && avancement <= 1)
    {
    if( avancement <= 1)
      avancement += 0.005;
   else
      avancement = 0;
   }
      return (avancement);
}
 
et ton avancer(0) dans la fonction de rendu de scène.
 
met un bête float en global, avec une fonction style:
 
void tacheDeFond(void)
{
 anim+=0.005;
        anim%=1;
 glutPostRedisplay;
}
 
déjà ça te fera une rampe périodique en 0 & 1 si je me plante pas.
 
ensuite, tes tableaux de vertexs du cube et du cylindre, tu les mets en global, tu les remplis dans le main(), et tu fais uniquement le lerp par vertex dans un tableau temporaire uniquement dans le traçage de scène.

Reply

Marsh Posté le 04-03-2006 à 17:53:50    

J'ai sorti les tableaux de vertices de la fonction, et pour les déclarer en global, j'ai du utiliser un #define num_vertices....
Effectivement avec tout ca, ca tourne !!!
 
je vois qu'il y'a une déformation quand j'appuie sur espace; Tout du moin, la deformation est calculée...Mais pour que je puisse l'entrevoir, il faut que je réappuis sur espace....
 
En gros, le réaffichage de la scéne ne se fait pas pendant que la tache de fond est active....
 :??:  Pourtant,j'ai un glutSwapBuffers() dans afficher_scene et un glutPostRedisplay() dans ma tâche de fond....

Reply

Marsh Posté le 04-03-2006 à 20:01:03    

pas de corruption ?

Reply

Marsh Posté le 04-03-2006 à 20:16:01    

déjà, tes fonctions de clavier/souris ne devraient pas utiliser glutPostRedisplay()
 
ensuite c'est pas tellement "tâche de fond", mais plustôt la fonction appellée quand la queue des évenements est terminée.  
 
ça permet de basculer entre un mode de rafraichissement par évenement/timer (glutTimerFunc) -ou- sans limites à fond les ballons pas vraiment user-friendly :D (glutIdleFunc)
 
enfin c'est comme ça que je comprends la doc.
 

Reply

Marsh Posté le 04-03-2006 à 22:31:28    

A premiere vue, le volume ne semble pas avoir de problémes d'affichage notoire (a part le fait que le rafraichissement ne s'effectue pas)...
 
Par contre, dans ce programme, si je virre glutPostRedisplay de la fonction key, les touches ne sont plus prises en compte....
Je peux plus naviguer autour du volume, ni demarrer l'annimation...Et c'est vrai que dans mes précédent scripts, je ne le placait pas et ca fonctionnait impec (et mes anim étaient fluides)!!!  :pfff:  
J'ai utilisé glutIdleFunc à plusieures reprises pour creer le même type d'apli (mais seulement en deux dimensions), et je n'ai eu aucun des problémes que j'ai pu rencontrer avec celle-ci... :pt1cable:

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed