Précédent   Forum des professionnels en informatique > Applications > Développement 2D, 3D et Jeux > API graphiques > OpenGL
OpenGL Forum d'entraide sur le développement en OpenGL. Avant de poster -> FAQ OpenGL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 26/01/2012, 12h43   #1
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
Par défaut Rotation de squelette et skinning

Bonjour,

Mon programme est issue d'un TP modélisation par skinning. Pour le moment on a quelques bones reliés et effectuant une rotation.
Je viens de rajouter un repère lié à chaque bones avec la fonction display_axes. J'ai fais des erreurs sur la création des axes du repères. J'aimerai donc que vous me dîtes ce qui ne va pas, et me dire par quoi remplacer.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
static void display_axis(vec3 position,vec3 position_voisin, Quaternion orientation ,vec3 position_local)
{
    // Longueur des axes
    int axis_length=10;
 
    vec3 axe1=position_local;
    axe1.normalize();
 
    vec3 position2=position+axe1*axis_length;
    vec3 axe2=position_voisin-position;
    axe2.normalize();
 
    vec3 axe3=axe2.dot(axe1);
    axe3.normalize();
 
    vec3 position3=position+axe2*axis_length;
    vec3 position4=position+axe3*axis_length;
 
    glBegin(GL_LINES);
        glColor3f(0,0,1); 
        glVertex3f(position.x,position.y,position.z);
        glVertex3f(position2.x,position2.y,position2.z);
        glColor3f(0,1,0); 
        glVertex3f(position.x,position.y,position.z);
        glVertex3f(position3.x,position3.y,position3.z);
        glColor3f(1,0,0); 
        glVertex3f(position.x,position.y,position.z);
        glVertex3f(position4.x,position4.y,position4.z);
    glEnd();
merci d'avance.
Fichiers attachés
Type de fichier : cpp quaternion.cpp (1,9 Ko, 4 affichages)
Type de fichier : cpp skinning.cpp (5,8 Ko, 10 affichages)
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/01/2012, 21h22   #2
Futur Membre du Club
 
Femme sara sellos
Inscription : juin 2006
Messages : 46
Détails du profil
Informations personnelles :
Nom : Femme sara sellos
Localisation : France

Informations forums :
Inscription : juin 2006
Messages : 46
Points : 19
Points : 19
Bonjour,

serait -il possible de transmettre tous les fichiers sources (.h, autres classes?)

ton problème est un problème purement mathématiques mais ce serait plus facile de t'aider si on pouvait voir ce que ca donne et "tracer"

pourrais tu expliquer où tu souhaites dessiner ton repère ? à position ou à position local?
milena est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/01/2012, 10h48   #3
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
Cette fonction est lancée dans la fonction qui actualise les nouvelles positions des bones :
Code :
static void update_global(void)
Citation:
Envoyé par milena Voir le message
pourrais tu expliquer où tu souhaites dessiner ton repère ? à position ou à position local?
Je ne comprends pas très bien ta question.
En fait j'utilise le repère global pour positionner le centre du repère sur chaque bones:
Code :
joints_global[i].position
Et pour l'orientation des vecteurs du repère j'utilise la position local:
Code :
joints_local[i].position
A partir de là j'ai un axe de juste.

Le problème c'est de trouver les autres axes pour former une base orthogonale.

J'utilise donc un produit vectoriel par exemple pour trouver le dernier.

Mais finalement c'est le second qui pose problème. Je n'ai pas d'idée pour le trouver. J'ai utilisé l'orientation mais ça n'a aucun rapport...
Images attachées
Type de fichier : png image.VQH08V.png (14,8 Ko, 5 affichages)
Fichiers attachés
Type de fichier : gz squelette.tar.gz (519,1 Ko, 3 affichages)
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/01/2012, 21h14   #4
Futur Membre du Club
 
Femme sara sellos
Inscription : juin 2006
Messages : 46
Détails du profil
Informations personnelles :
Nom : Femme sara sellos
Localisation : France

Informations forums :
Inscription : juin 2006
Messages : 46
Points : 19
Points : 19
Bonsoir

merci pour ces compléments d'info! je comprends un peu mieux

tu as donc trouver le premier vecteur de ton repère, c'est déjà bien!

pour formé une base othornomé à partir de ce vecteur, la démarche est la suivante :

il faut déjà trouver un vecteur perpendiculaire à ce premier vecteur (et le normaliser)

ensuite, pour trouver le dernier vecteur, il suffit simplement de faire le produit vectoriel du premier vecteur par le second


notons v1 ton premier vecteur v1(x1,y1,z1)

Soit v2( x2,y2,z2) un vecteur perpendiculaire à v1 alors le produit scalaire entre les 2 est nul
x1.x2 + y1.y2 + z1.z2 = 0
Tu peux "forcer" à 0 certaines coordonnées pour résoudre le système
Différents cas sont néamoins à considérer:

si x1 = 0, y1 = 0, z1 = 0, on a le vecteur nul, donc il y a une erreur qq part
si x1 = 0 et y1 = 0, tu peux prendre n'importe quelle valeur pour x2 et y2 à condition de mettre z2 à zéro
si x1 = 0 et z1 = 0, tu peux prendre n'importe quelle valeur pour x2 et z2 à condition de mettre y2 à zéro
si y1 = 0 et z1 = 0, tu peux prendre n'importe quelle valeur pour y2 et z2 à condition de mettre x2 à zéro
enfin si aucune coordonnées de v1 est nulle, tu peux mettre par ex z2 = 0 donc tu te retrouves à résoudre x1.x2 + y1.y2 = 0
donc x2/y2 = -y1/x1
et si tu forces y2 à 1, tu trouves x2 = -y1/x1.

Une fois que tu as normalisé v2, tu calcules le produit vectoriel de v1 et v2 pour obtenir les coordonnées de v3!
milena est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2012, 00h00   #5
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
Merci sa fonctionne!!
Mais pas dans tous les cas comme tu l'as expliqué. Il faut mettre plein de condition par ra rapport au repère global.

J'ai trouvé plus simple en utilisant directement les quaternion:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
static void update_local_axis(vec3 position,vec3 position_voisin)
{
    //Repere (position;axe1,axe2,axe3)
    axes_local.axe1=position_voisin-position;
    axes_local.axe1.normalize();
 
    Quaternion rotation(1,0,0,M_PI/2.0); 
 
    // Methode classique
    //axes_local.axe2=vec3(-axes_local.axe1.y/axes_local.axe1.x,1,0);
    // Methode avec quaternion
    axes_local.axe2=rotation.rotate_point(axes_local.axe1);
    axes_local.axe2.normalize();
 
    axes_local.axe3=axes_local.axe1^axes_local.axe2;
    axes_local.axe3.normalize();
}
avec
Code :
1
2
3
4
 
struct axis
{  vec3 axe1;vec3 axe2;vec3 axe3;};
static axis axes_local;
J'ai déclaré les axes en global pour la suite du TP.

Dans ce cas plus de problème de cas au limite.

Maintenant que le plus facile est fait, il reste la partie skinning que je suis en train de commencer.

Pas très générique tout ça mais voila un début:

Création de cylindre sur chaque os:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
struct mesh
{
  std::vector<vec3> vertices;
  std::vector<int> connectivity;
};
 
// 4 bones
static mesh cyl[4];
 
mesh cylinder(float diameter,int length,int nb_pts_diameter,int nb_pts_length,vec3 position)
{
  /* diameter,length: dialetre et longueur du cylindre
     nb_pts_diameter,nb_pts_length: nombre de noeuds sur le perimetre et suivant la longueur
     position: position du cylindre
     il manque la direction */
 
  int height=nb_pts_length  ;
  int width=nb_pts_diameter ;
  double dtheta=2.0*M_PI/ width;
  mesh my_mesh;
 
  for (int i=0;i<height;++i)
  {
     for (int j=0;j<width;++j)
          my_mesh.vertices.push_back( position+vec3(diameter*cos(j*dtheta),diameter*sin(j*dtheta),(float)length*(1-(float) i/height)) );
  }
 
  return my_mesh;
}
Il faut voir pour la direction du cylindre et surement utiliser les quaternions pour le moment je n'ai pas d'idée.
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2012, 17h06   #6
Membre Expert
 
Avatar de Ange_blond
 
Homme Vincent Bourdier
Ingénieur développement en 3D temps réel
Inscription : mars 2007
Messages : 829
Détails du profil
Informations personnelles :
Nom : Homme Vincent Bourdier
Âge : 26
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur développement en 3D temps réel
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : mars 2007
Messages : 829
Points : 1 118
Points : 1 118
Citation:
Envoyé par Gakusei Voir le message
Il faut voir pour la direction du cylindre et surement utiliser les quaternions pour le moment je n'ai pas d'idée.
Comme tu as ton cylindre dans le repere mode, il suffit d'appliquer les transformation (translation et rotation) a chaque point du cylindre et voilou il sera en place et bien orienté.

(idealement tu complete ta méthode de création de cylindre avec en parametres les transformations a appliquer, comme ça tu peux apeller la méthode sur chaque bones facilement.
__________________
"le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

Ange3d.developpez.com - tutos OpenSceneGraph

Ni ma boite de MP ni ma page de profil ne sont des extensions du forum OpenSceneGraph ! Merci.
Ange_blond est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/02/2012, 14h57   #7
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
C'est bon j'ai fait les bonnes transformation: du vrai skinning rigide.

Il reste maintenant des erreurs sur l'affichage :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
static void display(void)
{
  static double current_time = 0;
  static double last_time = 0;
  static double info_last_time = 0;
 
  current_time = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
 
  info_last_time += (current_time - last_time) / 6.0;
  last_time = current_time;
  if (info_last_time >= 1.0)
      info_last_time -= 1.0;
 
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); PRINT_OPENGL_ERROR ();
 
  update_orientations(info_last_time);
  update_global();
  glMatrixMode(GL_MODELVIEW);             PRINT_OPENGL_ERROR();
  glLoadIdentity();                       PRINT_OPENGL_ERROR();
  gluLookAt(0,100,300, 20,100,0, 0,1,0);  PRINT_OPENGL_ERROR();
  glRotatef(angle,0,1,0);                 PRINT_OPENGL_ERROR();
  glColor3f(1,1,0);                       PRINT_OPENGL_ERROR();
  glPointSize(8);                         PRINT_OPENGL_ERROR();
  glLineWidth(3);                         PRINT_OPENGL_ERROR();
  //Affichage du squelette
  glVertexPointer(3, GL_FLOAT, sizeof(Joint), &joints_global[0].position.x); PRINT_OPENGL_ERROR();
  glDrawArrays(GL_POINTS, 0, 4);          PRINT_OPENGL_ERROR();
  glDrawArrays(GL_LINE_STRIP, 0, 4);      PRINT_OPENGL_ERROR();
 
 
 
  for(unsigned int i=0;  i<cyl.vertices.size(); ++i )
  {
    glPopMatrix();
      glBegin(GL_POINTS);
        glColor3f(1,0,0);
        glVertex3f((float)cyl.vertices[i].x,(float)cyl.vertices[i].y,(float)cyl.vertices[i].z);PRINT_OPENGL_ERROR(); 
      glEnd();PRINT_OPENGL_ERROR();// invalid operation
    glPushMatrix();PRINT_OPENGL_ERROR();
  }
  glutSwapBuffers(); PRINT_OPENGL_ERROR();
}
Bien que l'on voit l'affichage comme il faut. L'erreur invalid operation apparaît à la ligne commentée (Pourtant entre glBegin et glEnd les opération sont bien conforme).

J'ai voulu par la suite changer l'affichage immédiat en créant et appelant cette fonction:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
static void draw(void)
{
        unsigned int N_tri=cyl.triangle_number();
        unsigned int* p_connectivity=&cyl.connectivity[0];
        float* p_vertex=&cyl.vertices[0].x;
 
        glEnableClientState(GL_VERTEX_ARRAY);PRINT_OPENGL_ERROR();
        //setup pointers
        glVertexPointer(3,GL_DOUBLE,0,p_vertex);PRINT_OPENGL_ERROR();
        //draw triangles
        glDrawElements(GL_TRIANGLES,3*N_tri,GL_UNSIGNED_INT,p_connectivity);PRINT_OPENGL_ERROR();
        glDisableClientState(GL_VERTEX_ARRAY);PRINT_OPENGL_ERROR();
}
Pas d'erreur mais plus rien ne s'affiche

Est-ce que vous pouvez m'éclairer?

PS: gDEBugger plante (erreur de segmentation non résolue).
Images attachées
Type de fichier : png skin_resultat.png (3,1 Ko, 5 affichages)
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2012, 12h06   #8
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
Voila le problème d'affichage est résolue. J'ai donc pu afficher la triangulation.

Il me reste plus qu'a réaliser la partie skinning lisse.
Images attachées
Type de fichier : png skinning.png (5,6 Ko, 6 affichages)
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2012, 13h27   #9
Membre confirmé
 
Homme Thomas Pegot
Étudiant
Inscription : janvier 2012
Messages : 195
Détails du profil
Informations personnelles :
Nom : Homme Thomas Pegot
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2012
Messages : 195
Points : 299
Points : 299
C'est bon pour le skinning souple !

Merci pour votre aide
Images attachées
Type de fichier : png skin_souple.png (3,5 Ko, 4 affichages)
Gakusei est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h02.


 
 
 
 
Partenaires

Hébergement Web