IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques, systèmes et outils C Discussion :

[OpenGL] La caméra tremble


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut [OpenGL] La caméra tremble
    Bonsoir à tous, je me permets de vous faire part d'un problème qui ne m'était jamais apparu auparavant : La caméra tremble.
    Je code un petit jeu en OpenGL où l'on conduit un TGV, j'utilise l'axe des Z comme axe vertical et le train est initialement orienté dans la direction de X, ainsi que la caméra. Lorsque l'on active la vue en cabine, le calcul de la position de la caméra connaissant celle du train ainsi que l'orientation de ce dernier se fait de cette façon :

    A = xTrain + 7 * cos(angleTrain)
    B = yTrain + 7 * sin(angleTrain)

    xCam = A - 0.5*sin(angleTrain)
    yCam = B + 0.5*cos(angleTrain)

    Voici un schéma explicatif :

    Nom : Image1.jpg
Affichages : 298
Taille : 32,8 Ko

    Pour calculer la position de la cible de la caméra, je prends comme distance 900 (Par exemple) et je procède ainsi :

    xCible = xCam + 900 * cos(angleCam + angleTrain)
    yCible = yCam + 900 * sin(angleCam + angleTrain)

    Un autre schéma pour expliquer :

    Nom : Image2.jpg
Affichages : 301
Taille : 35,3 Ko

    Lorsque je teste, je me rends compte que la caméra tremble dès que la somme (angleCam + angleTrain) a une valeur différente de 0, 90, 180 ou 270° ! J'ai toujours géré la caméra de cette façon et je n'ai jamais eu ce problème.

    Voici le code résumé du main:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    int main(int argc,char *argv[])
    {
        SDL_Surface *ecran;
        SDL_Event evenement;
     
        if(SDL_Init(SDL_INIT_VIDEO)!=0)		//Initialisation mode vidéo SDL
            return -1;
     
        SDL_WM_SetCaption("TGV Driving",NULL);
        putenv("SDL_VIDEO_CENTERED=1");
     
        ecran=SDL_SetVideoMode(800,600,32,SDL_OPENGL);	//Fenêtre SDL
     
        glMatrixMode(GL_PROJECTION);	//Appel matrice de projection
        glLoadIdentity();
        gluPerspective(70,4.0/3,0.1,1000);
     
        glEnable(GL_TEXTURE_2D);	//Initialisations texturing et Z-buffer
        glEnable(GL_DEPTH_TEST);
     
        //Chargement textures et initialisations paramètres
     
        while(1)    //BOUCLE PRINCIPALE
        {
            SDL_PollEvent(&evenement);
            if(evenement.type==SDL_QUIT)
                break;
            if(evenement.type==SDL_KEYDOWN)
            {
                ...
            }
     
            CommandeTrain(&infos);		//Mouvement du train
            gestionCam(&infos,evenementCam);	//Gestion de la caméra
            Dessiner(&infos);		//Dessin 3D
     
            glFlush();
            SDL_GL_SwapBuffers();
        }
     
        SDL_Quit();
        return 0;
    }
    Et celui de la fonction gestionCam() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void gestionCam(Principale *ptr)
    {
        ptr->vuesCam[1].xRepere1=ptr->convoi[ptr->numTrain].voitures[0].x+7*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);	//Calcul A et B
        ptr->vuesCam[1].yRepere1=ptr->convoi[ptr->numTrain].voitures[0].y+7*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[1].x=ptr->vuesCam[1].xRepere1-0.5*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);		//Calcul xCam et yCam
        ptr->vuesCam[1].y=ptr->vuesCam[1].yRepere1+0.5*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[1].xCible=ptr->vuesCam[1].x+900*cos((ptr->convoi[ptr->numTrain].voitures[0].angle+ptr->vuesCam[1].angle)*M_PI/180);	//Calcul xCible et yCible
        ptr->vuesCam[1].yCible=ptr->vuesCam[1].y+900*sin((ptr->convoi[ptr->numTrain].voitures[0].angle+ptr->vuesCam[1].angle)*M_PI/180);
    }
    ptr est un pointeur sur une structure contenant les différents paramètres, vuesCam[] est un tableau de structures qui contiennent les coordonnées de A et B (xRepere1 et yRepere1) ainsi que celles de la caméra (x et y) et celles de la cible de la caméra (xCible et yCible), ainsi que l'orientation de la caméra par rapport au train (angle). convoi[] est un tableau de structures représentant les différents trains, chaque case de ce tableau contient un tableau de structures appelé voitures[] (La motrice et les wagons) contenant entre autres l'orientation de la voiture de train).

    Je n'arrive pas au bout de ce problème, j'y ai passé tout l'après-midi, auriez-vous une solution svp ??
    Images attachées Images attachées  

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Bonsoir,

    Le projet a l'air intéressant : est-il possible d'avoir accès à la totalité du code source ? Ce serait bien de pouvoir le compiler et de constater par nous mêmes les effets que tu constates.

    En tout état de cause, la seule fois où j'ai été confronté à un problème similaire, il y a 25 ans lorsque j'essayais de faire défiler de manière fluide un texte sur mon écran de droite à gauche avec mon 8 bits, et qu'il fallait pour cela attendre le retour du raster en haut de l'écran (Bit 7 de &HE7E7 sur TO8D, l'équivalent de WAIT &H3DA,8 sur les PC de l'époque).

    J'obtenais un gros tremblement parce que j'attendais deux VBL au lieu d'une, alternant ainsi phases de mouvement et phases statiques, ce qui était très perturbant pour l'œil.

    Il est tout-à-fait possible que le mélange d'OpenGL et de la SDL provoque des conflits, notamment au niveau de glFlush() et SDL_GL_SwapBuffers(). Il est possible que l'un des deux implique déjà l'autre. Fais un test en désactivant celui de ton choix.

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut PollEvent
    Bonjour,

    Est-ce que le mouvement de la caméra est associé aux évènements (comme SDL_KEYDOWN) ?

    Parceque la gestion des évènements ici n'est pas correcte (ligne 25) :
    Il faut tester le retour de SDL_PollEvent() pour associer la condition à UN évènement.
    Sinon on éxecute plusieurs fois au rythme de la boucle principale la condition du dernier évènement.

    Classiquement, on teste dans un boucle while{} pour dépiler tous les évènements avant de reprendre la boucle principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    while(SDL_PollEvent(&event))
    {
       switch(event.type)
       {
     
     
     
       } 
     
     
    }

  4. #4
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    Bonjour,

    Est-ce que le mouvement de la caméra est associé aux évènements (comme SDL_KEYDOWN) ?

    Parceque la gestion des évènements ici n'est pas correcte (ligne 25) :
    Il faut tester le retour de SDL_PollEvent() pour associer la condition à UN évènement.
    Sinon on éxecute plusieurs fois au rythme de la boucle principale la condition du dernier évènement.

    Classiquement, on teste dans un boucle while{} pour dépiler tous les évènements avant de reprendre la boucle principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    while(SDL_PollEvent(&event))
    {
       switch(event.type)
       {
     
     
     
       } 
     
     
    }

    Effectivement, je devrais de préférence tester la valeur de retour de SDL_PollEvent().
    Les événements SDL permettent juste de faire pivoter la caméra ou de la déplacer, mais en vue cabine elle reste à un position fixe, et ce sont les touches fléchées latérales qui permettent de faire pivoter la caméra en agissant sur son angle. L'angle du train quant à lui est géré par une fonction Orientation() qui détecte sur quelle voie ou quel virage se trouve le convoi et modifie l'angle en fonction.

    Citation Envoyé par Obsidian Voir le message
    Il est tout-à-fait possible que le mélange d'OpenGL et de la SDL provoque des conflits, notamment au niveau de glFlush() et SDL_GL_SwapBuffers(). Il est possible que l'un des deux implique déjà l'autre. Fais un test en désactivant celui de ton choix.
    La désactivation de glFlush() ou SDL_GL_SwapBuffers() ne change rien malheureusement.

    Citation Envoyé par Obsidian Voir le message
    Bonsoir,

    Le projet a l'air intéressant : est-il possible d'avoir accès à la totalité du code source ? Ce serait bien de pouvoir le compiler et de constater par nous mêmes les effets que tu constates.
    Je voudrais bien mais le code est réparti sur une vingtaine de fichiers, et il y également les textures, dll et divers fichiers.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Citation Envoyé par KevinduC Voir le message
    Je voudrais bien mais le code est réparti sur une vingtaine de fichiers, et il y également les textures, dll et divers fichiers.
    Dans ce cas, tu peux faire un gros *.zip et le présenter ici en pièce jointe.
    Si tu comptes ouvrir ton projet à la collaboration publique, tu peux également ouvrir un compte github pour cela, voire même le faire héberger ici si tu comptes travailler dessus un petit moment.

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    OK,

    une autre piste : des arrondis de calcul qui ne conduisent pas toujours au même résultat.
    Car apparemment la position caméra est calculée à chaque fois dans gestionCam() , non ?

  7. #7
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Primo, +1 pour avoir présenté ta requête de façon claire en introduisant le contexte clairement et avec des schémas explicatifs.


    Secundo, concernant le comportement dont tu es témoin : comme ça tout de go je lis « train » donc « grandes valeurs de distance » et je suppute un souci de précision dû au fait que tu stockes de « grandes » coordonnées dans des variables à virgule flottante. Tu n'as pas précisé si tu utilisais des float ou des double. Il faut savoir qu'en simple précision (float) ce genre de comportement peut apparaître dès ~1000.0f (je parle d'expérience).

    Si tu es en float, passe en double pour confirmer ou infirmer cette hypothèse. Si c'est bien la cause tu as deux solutions : rester définitivement en double avec les contraintes techniques qui vont avec, ou t'arranger pour effectuer les calculs dans un repère ou les valeurs de coordonnées sont faibles (idéalement inférieures à 100.0f).


    Terzio, pourquoi as-tu besoin d'avoir la target de caméra à 900 mètres de l'oeil ? Un vecteur unitaire suffit.

  8. #8
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Primo, +1 pour avoir présenté ta requête de façon claire en introduisant le contexte clairement et avec des schémas explicatifs.


    Secundo, concernant le comportement dont tu es témoin : comme ça tout de go je lis « train » donc « grandes valeurs de distance » et je suppute un souci de précision dû au fait que tu stockes de « grandes » coordonnées dans des variables à virgule flottante. Tu n'as pas précisé si tu utilisais des float ou des double. Il faut savoir qu'en simple précision (float) ce genre de comportement peut apparaître dès ~1000.0f (je parle d'expérience).

    Si tu es en float, passe en double pour confirmer ou infirmer cette hypothèse. Si c'est bien la cause tu as deux solutions : rester définitivement en double avec les contraintes techniques qui vont avec, ou t'arranger pour effectuer les calculs dans un repère ou les valeurs de coordonnées sont faibles (idéalement inférieures à 100.0f).


    Terzio, pourquoi as-tu besoin d'avoir la target de caméra à 900 mètres de l'oeil ? Un vecteur unitaire suffit.
    1) Merci beaucoup, après je sais pas si mes schémas sont bien clairs

    2) J'ai pensé à cela, j'ai essayé en remplaçant les coordonnées de caméra par des double (Il est vrai que j'ai l'habitude d'utiliser des float). Après je précise que la map est immense (Un carré de 500 000 × 500 000 et l'échelle est en mètres), mais je pense pas que ça soit la cause du problème sauf erreur de ma part. Après comme le dit nanosoft, je pense à des valeurs erronées et c'est pour cela que j'ai fait un test en remplaçant les float de la caméra par des double (cos() et sin() renvoient des double)

    3) Euh, c'est une habitude ^^ Après j'ai aussi essayé de réduire cette valeur mais ça n'a pas résolu le problème non plus

  9. #9
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    500 kilomètres.. woké c'est bon tu peux oublier en float.

    Qu'est-ce qui se passe concrètement lorsque tu passes en double précision ? Rien ne semble différent ? C'est différent mais ce n'est toujours pas le comportement attendu ? Tu aurais une vidéo de ce qu'il se passe pour qu'on puisse visualiser le truc ?

  10. #10
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    Je viens d'effectuer un test : J'ai mis le train à la position (0 ; 0) (Jusqu'à présent il était à la position (-250000 ; 0) et son angle à 30° et plus de tremblement cette fois, cela confirme l'hypothèse comme quoi les valeurs utilisées sont trop grandes (En valeur absolue) pour être stockées dans des float. J'ai donc mis les coordonnées de la caméra et de la cible en double, mais ça n'a pas résolu le problème lorsque j'ai remis le train à -250000. Que faire ? Je connais pas de type de variable permettant de stocker un réel plus précis que double

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En fait, tu devrais faire une prétransformation, pour que les coordonnées des choses visibles soient petites.

    Par exemple, ajouter un décalage de 250000 quand le train est "dans ce coin là"?
    En OpenGL, les doubles/float ne sont vraiment stables que quand les variations sont du même ordre de grandeur que les nombres manipulés.

    Par contre, tu peux aussi utiliser l'astuce que le cosinus et le sinus sont des rapports de longueurs (coté adjacent et opposé par rapport à l'hypothénuse).
    Ou alors peut-être arrondir le sinus avant de l'ajouter.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    J'hésite à mettre l'échelle en kilomètres finalement

  13. #13
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Oui, sinon leternel a proposé une solution élégante qui peut peut-être te convenir : partitionner ta carte en secteurs. Tu choisis une grille, voire un quadtree avec une résolution donnée, et tu réalises les translations qui vont bien en amont et en aval des calculs pour conserver une précision suffisante. Au final cela revient à stocker tout ou partie de la partie entière de tes coordonnées dans une autre variable.

  14. #14
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    Salut, comme prévu j'ai divisé toutes les distances du jeu par 1000. Le problème est toujours là, je ne comprends plus, les coordonnées de la caméra sont de l'ordre de 250 !

  15. #15
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Peux-tu nous transmettre le maximum d'informations sur la manière dont tu réalises tes calculs ?

  16. #16
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    Je vous transmets une partie du code, je tiens à préciser que suite à une confusion, j'ai pris l'habitude d'inverser l'axe des Z et des Y, les coordonnées de la caméra par rapport au sol sont donc X et Z et non X et Y, IDEM pour le reste.

    Le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    int main(int argc,char *argv[])
    {
        SDL_Surface *ecran;
        SDL_Event evenement;
        Principale infos;
        int delaiBoucle,tpsActuel,evenementCam;
     
        if(SDL_Init(SDL_INIT_VIDEO)!=0)
            return -1;
     
        Init(&infos);
     
        SDL_WM_SetCaption("TGV Driving",NULL);              //Nom barre de titre
        putenv("SDL_VIDEO_CENTERED=1");
     
        if(infos.pleinEcran==false)
            ecran=SDL_SetVideoMode(800,600,32,SDL_OPENGL);
        if(infos.pleinEcran==true)
            ecran=SDL_SetVideoMode(infos.largeurBureau,infos.hauteurBureau,32,SDL_OPENGL|SDL_NOFRAME);
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        if(infos.pleinEcran==false)
            gluPerspective(70,4.0/3,0.0001,1);
        if(infos.pleinEcran==true)
            gluPerspective(70,infos.ratioEcran,0.0001,1);
     
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);
     
        chargeTextures(&infos);
        //chargeBMP(&infos);
        chargeFichiers(&infos);
        InitTrains(&infos);       //Chargement caractéristiques trains
        InitCam(&infos);        //Initialisation position caméra
     
        delaiBoucle=SDL_GetTicks();
        while(1)    //BOUCLE PRINCIPALE
        {
            evenementCam=-1;
     
            SDL_PollEvent(&evenement);
            if(evenement.type==SDL_QUIT)
                break;
            if(evenement.type==SDL_KEYDOWN)
            {
                if(evenement.key.keysym.sym==SDLK_ESCAPE&&infos.pleinEcran==true)
                    break;
     
                if(infos.vue!=1)
                {
                    if(evenement.key.keysym.sym==SDLK_KP8)      //Contrôle vertical caméra
                        infos.vuesCam[infos.vue].y+=infos.vitesseCamVert;
                    if(evenement.key.keysym.sym==SDLK_KP2)
                        infos.vuesCam[infos.vue].y-=infos.vitesseCamVert;
                }
     
                if(evenement.key.keysym.sym==SDLK_RIGHT)    //Rotation caméra
                    infos.vuesCam[infos.vue].angle-=infos.vitesseRotation;
                if(evenement.key.keysym.sym==SDLK_LEFT)
                    infos.vuesCam[infos.vue].angle+=infos.vitesseRotation;
     
                if(evenement.key.keysym.sym==SDLK_PAGEUP)    //Inclinaison caméra
                    infos.vuesCam[infos.vue].htCam+=10;
                if(evenement.key.keysym.sym==SDLK_PAGEDOWN)
                    infos.vuesCam[infos.vue].htCam-=10;
     
                if(evenement.key.keysym.sym==SDLK_UP)
                    evenementCam=0;
                if(evenement.key.keysym.sym==SDLK_DOWN)
                    evenementCam=1;
     
                if(evenement.key.keysym.sym==SDLK_SPACE)
                {
                    if(infos.vue==0)
                    {
                        infos.vuesCam[0].htCam=0;
                        infos.vuesCam[0].distTrainX=DIST_X_INIT;
                        infos.vuesCam[0].distTrainZ=DIST_Z_INIT;
                        infos.vuesCam[0].y=2;
                    }
                    if(infos.vue==1)
                    {
                        infos.vuesCam[1].htCam=0;
                        infos.vuesCam[1].angle=0;
                    }
                }
     
                if(evenement.key.keysym.sym==SDLK_KP5)
                {
                    infos.convoi[infos.numTrain].phares=!infos.convoi[infos.numTrain].phares;
                    SDL_Delay(100);
                }
                if(evenement.key.keysym.sym==SDLK_p)
                    infos.commandePantographe=true;
     
                if(evenement.key.keysym.sym==SDLK_1)
                    infos.vue=0;
                if(evenement.key.keysym.sym==SDLK_2)
                    infos.vue=1;
     
                if(evenement.key.keysym.sym==SDLK_KP6&&infos.convoi[infos.numTrain].angleManipulateur>=-80)
                    infos.convoi[infos.numTrain].angleManipulateur-=0.1;
                if(evenement.key.keysym.sym==SDLK_KP4&&infos.convoi[infos.numTrain].angleManipulateur<=80)
                    infos.convoi[infos.numTrain].angleManipulateur+=0.1;
            }
     
            CommandeTrain(&infos);
            gestionCam(&infos,evenementCam);
            Dessiner(&infos);
     
            glFlush();
            SDL_GL_SwapBuffers();
     
            tpsActuel=SDL_GetTicks();       //Un tour de boucle dure 10 ms
            if(tpsActuel-delaiBoucle<10)
                SDL_Delay(10-(tpsActuel-delaiBoucle));
            if(tpsActuel-delaiBoucle>=10)
                delaiBoucle=SDL_GetTicks();
        }
     
        SDL_Quit();
        return 0;
    }
    La fonction Init() initialise les principaux paramètres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    void Init(Principale *ptr)
    {
        const SDL_VideoInfo *infosEcran=SDL_GetVideoInfo();
     
        ptr->pleinEcran=false;
        ptr->largeurBureau=infosEcran->current_w;
        ptr->hauteurBureau=infosEcran->current_h;
        ptr->ratioEcran=(float)ptr->largeurBureau/ptr->hauteurBureau;
     
        ptr->vitesseCamHoriz=0.0001;
        ptr->vitesseCamVert=0.0001;
        ptr->vitesseRotation=1;
     
        ptr->vue=0;
        ptr->numTrain=0;
     
        ptr->enDehorsVoie=false;
        ptr->commandePantographe=false;
    }
    La fonction InitCam() initialise les coordonnées des caméras :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void InitCam(Principale *ptr)
    {
        float X,Z;
        int compteur=0;
     
        while(1)
        {
            ptr->vuesCam[compteur].angle=0;
            ptr->vuesCam[compteur].y=0.002;
            ptr->vuesCam[compteur].distTrainX=DIST_X_INIT;
            ptr->vuesCam[compteur].distTrainZ=DIST_Z_INIT;
            //ptr->vuesCam[compteur].distCamRepere=0;
            ptr->vuesCam[compteur].htCam=0;
     
            compteur++;
            if(compteur==NB_VUES)
                break;
        }
        ptr->vuesCam[0].numVoiture=0;   //Par rapport à la motrice
        ptr->vuesCam[1].numVoiture=0;   //Par rapport à la motrice
        ptr->vuesCam[1].y=0.003;
    }
    La fonction InitTrains() initialise les paramètres des trains et récupère les longueurs des voitures stockées dans un fichier sousla forme d'une chaîne de caractères représentant des nombres séparés par des tirets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    void InitTrains(Principale *ptr)
    {
        int compteur=0,compteurChaineLue,compteurChaineEcrite,compteurLong=0;
        char chaine[100]="",nombre[10]="";
     
        while(1)
        {
            compteurLong=0;
            compteurChaineLue=0;
            compteurChaineEcrite=0;
            strcpy(chaine,ptr->convoi[compteur].longueurs);
            while(1)
            {
                nombre[compteurChaineEcrite]=chaine[compteurChaineLue];
                if(nombre[compteurChaineEcrite]=='-'||nombre[compteurChaineEcrite]=='\0')
                {
                    if(nombre[compteurChaineEcrite]=='\0')
                    {
                        ptr->convoi[compteur].voitures[compteurLong].longueur=atof(nombre);
                        break;
                    }
     
                    nombre[compteurChaineEcrite]='\0';
                    ptr->convoi[compteur].voitures[compteurLong].longueur=atof(nombre);
                    nombre[0]='\0';
                    compteurLong++;
                    compteurChaineEcrite=-1;
                }
     
                compteurChaineEcrite++;
                compteurChaineLue++;
            }
     
            compteur++;
            if(compteur==NB_TRAINS)
                break;
        }
     
        compteur=1;
        ptr->convoi[ptr->numTrain].voitures[0].x=-249.9;
        ptr->convoi[ptr->numTrain].voitures[0].z=0;
        ptr->convoi[ptr->numTrain].voitures[0].angle=0;
        ptr->convoi[ptr->numTrain].vitesse=0;
        ptr->convoi[ptr->numTrain].anglePantographe=0;
        ptr->convoi[ptr->numTrain].PantoBaisse=false;
        ptr->convoi[ptr->numTrain].PantoLeve=false;
        ptr->convoi[ptr->numTrain].angleRoues=0;
        ptr->convoi[ptr->numTrain].angleManipulateur=0;
        while(1)     //Initilalisations positions voitures du train
        {
            ptr->convoi[ptr->numTrain].voitures[compteur].x=ptr->convoi[ptr->numTrain].voitures[compteur-1].x-ptr->convoi[ptr->numTrain].voitures[compteur-1].longueur/2-ptr->convoi[ptr->numTrain].voitures[compteur].longueur/2;
            ptr->convoi[ptr->numTrain].voitures[compteur].z=0;
            ptr->convoi[ptr->numTrain].voitures[compteur].angle=0;
     
            compteur++;
            if(compteur==ptr->convoi[ptr->numTrain].nbVoitures)
                   break;
        }
     
        compteur=0;
        while(1)        //Divers
        {
            ptr->convoi[compteur].phares=false;
     
            compteur++;
            if(compteur==NB_TRAINS)
                break;
        }
    }
    La fonction gestionCam() calcule en permanence les coordonnées de la caméra et celles de la cible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    void gestionCam(Principale *ptr,int evenement)
    {
        int compteur=0;
     
        ptr->vuesCam[0].xRepere1=ptr->convoi[ptr->numTrain].voitures[0].x+ptr->vuesCam[0].distTrainX*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
        ptr->vuesCam[0].zRepere1=ptr->convoi[ptr->numTrain].voitures[0].z+ptr->vuesCam[0].distTrainX*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[0].xRepere2=ptr->vuesCam[0].xRepere1-ptr->vuesCam[0].distTrainZ*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
        ptr->vuesCam[0].zRepere2=ptr->vuesCam[0].zRepere1+ptr->vuesCam[0].distTrainZ*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[0].x=ptr->vuesCam[0].xRepere2+ptr->vuesCam[0].distTrainX*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
        ptr->vuesCam[0].z=ptr->vuesCam[0].zRepere2+ptr->vuesCam[0].distTrainZ*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        if(evenement==0)       //Déplacement caméra indépendant
        {
            /*ptr->vuesCam[0].x+=ptr->vitesseCamHoriz*cos(ptr->vuesCam[0].angle*M_PI/180);
            ptr->vuesCam[0].z+=ptr->vitesseCamHoriz*sin(ptr->vuesCam[0].angle*M_PI/180);*/
            ptr->vuesCam[0].distTrainX+=ptr->vitesseCamHoriz*cos(ptr->vuesCam[0].angle*M_PI/180);
            ptr->vuesCam[0].distTrainZ+=ptr->vitesseCamHoriz*sin(ptr->vuesCam[0].angle*M_PI/180);
        }
        if(evenement==1)
        {
            /*ptr->vuesCam[0].x-=ptr->vitesseCamHoriz*cos(ptr->vuesCam[0].angle*M_PI/180);
            ptr->vuesCam[0].z-=ptr->vitesseCamHoriz*sin(ptr->vuesCam[0].angle*M_PI/180);*/
            ptr->vuesCam[0].distTrainX-=ptr->vitesseCamHoriz*cos(ptr->vuesCam[0].angle*M_PI/180);
            ptr->vuesCam[0].distTrainZ-=ptr->vitesseCamHoriz*sin(ptr->vuesCam[0].angle*M_PI/180);
        }
     
        ptr->vuesCam[0].xCible=ptr->vuesCam[0].x+0.9*cos(ptr->vuesCam[0].angle*M_PI/180);
        ptr->vuesCam[0].zCible=ptr->vuesCam[0].z+0.9*sin(ptr->vuesCam[0].angle*M_PI/180);
        ptr->vuesCam[0].yCible=ptr->vuesCam[0].y+ptr->vuesCam[0].htCam;
     
        //////////////////////////////////
     
        ptr->vuesCam[1].xRepere1=ptr->convoi[ptr->numTrain].voitures[0].x+0.007*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
        ptr->vuesCam[1].zRepere1=ptr->convoi[ptr->numTrain].voitures[0].z+0.007*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[1].x=ptr->vuesCam[1].xRepere1-0.0005*sin(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
        ptr->vuesCam[1].z=ptr->vuesCam[1].zRepere1+0.0005*cos(ptr->convoi[ptr->numTrain].voitures[0].angle*M_PI/180);
     
        ptr->vuesCam[1].xCible=ptr->vuesCam[1].x+0.9*cos((ptr->convoi[ptr->numTrain].voitures[0].angle+ptr->vuesCam[1].angle)*M_PI/180);
        ptr->vuesCam[1].zCible=ptr->vuesCam[1].z+0.9*sin((ptr->convoi[ptr->numTrain].voitures[0].angle+ptr->vuesCam[1].angle)*M_PI/180);
        ptr->vuesCam[1].yCible=ptr->vuesCam[1].y+ptr->vuesCam[1].htCam;
    }
    Et enfin le fichier d'en-tête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    #ifndef T_D
    #define T_D
     
    #define NB_TEX 14
    #define NB_VUES 2
    #define NB_RAILS 3
    #define NB_VIR 2
    #define NB_TRAINS 1
    #define DIST_X_INIT 0.01
    #define DIST_Z_INIT 0.008
    #define LARGMAP 500
    #define LARGEUR 0.0029
     
    #endif
     
    typedef struct Voiture
    {
        float x;
        float z;
        double angle;
        float longueur;
    }Voiture;
     
    typedef struct TGV
    {
        int nbVoitures;
        char longueurs[100];
        Voiture voitures[15];
        int numtex;
        float masse;
        float vitesse;
        float acceleration;
        float forceTraction;
        bool sens;
        bool phares;
        double anglePantographe;
        bool PantoBaisse;
        bool PantoLeve;
        double angleRoues;
        double angleManipulateur;
    }TGV;
     
    typedef struct Vue
    {
        double x;
        double z;
        double y;
        double angle;
        double htCam;
        double xCible;
        double zCible;
        double yCible;
        float distTrainX;
        float distTrainZ;
        //float distCamRepere;
        int numVoiture;
        float xRepere1;
        float zRepere1;
        float xRepere2;
        float zRepere2;
    }Vue;
     
    typedef struct VoieFerree
    {
        float x;
        float z;
        double angle;
        float lg;
    }VoieFerree;
     
    typedef struct Virage
    {
        int numRail;
        char cote[7];
        float rayon;
        double angle;
    }Virage;
     
    typedef struct Principale
    {
        int vue;
        int numTrain;
        Vue vuesCam[NB_VUES];
        float vitesseCamHoriz;
        float vitesseCamVert;
        double vitesseRotation;
     
        bool enDehorsVoie;
     
        GLuint textures[NB_TEX];
     
        bool pleinEcran;
        int largeurBureau;
        int hauteurBureau;
        float ratioEcran;
     
        TGV convoi[NB_TRAINS];
     
        VoieFerree rails[NB_RAILS];
        Virage virages[NB_VIR];
     
        bool commandePantographe;
    }Principale;
     
    void Init(Principale *ptr);
    void InitCam(Principale *ptr);
    void chargeTextures(Principale *ptr);
    void Dessiner(Principale *ptr);
    void Sol(Principale *ptr);
    void gestionCam(Principale *ptr,int evenement);
    void chargeBMP(Principale *ptr);
    void chargeFichiers(Principale *ptr);
    void InitTrains(Principale *ptr);
    void Rails(Principale *ptr);
    void Virages(Principale *ptr);
    void Orientation(Principale *ptr,int numVoiture);
    void Train(Principale *ptr);
    void Motrice(Principale *ptr);
    void CommandeTrain(Principale *ptr);
    void Essieu(Principale *ptr,bool sens);
    void Cabine(Principale *ptr);
    void Manipulateur(void);

  17. #17
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je n'ai pas encore eu le temps de regarder ton code en détail. Je me permets toutefois de te faire une remarque annexe mais qui a son importance lorsque tu traques un bug : c'est vraiment difficile à lire avec ces formules mathématiques non aérées et la répétition d'expressions à rallonge comme ptr->convoi[ptr->numTrain] et ptr->vuesCam[0].

    À la place tu pourrais écrire quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TGV *convoi = &ptr->convoi[ptr->numTrain];
    convoi-> ... = ... ;
    convoi-> ... = ... ;
    convoi-> ... = ... ;
    convoi-> ... = ... ;
    ...
    ou mieux : écrire des fonctions qui ne prennent en paramètre que ce sur quoi elles agissent.

  18. #18
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Alors, trois choses rapidement :
    • Je ne vois ni calcul explicite de la matrice modelview pour envoi au vertex shader, ni appel à glMatrixMode(GL_MODELVIEW) : comment appliques-tu la transformation de la caméra au monde ?
    • Comment calcules-tu cette transformation d'ailleurs ? Je ne vois aucune normalisation de coordonnées dans ton code ce qui pourrait expliquer l'explosion arithmétique, je suis curieux de voir ton look at.
    • Tu fais réellement de la 3D sans utiliser de structure pour représenter tes vecteurs mathématiques ? Si c'est le cas arrêtes de suite ce que tu es en train de faire et écris-moi ce vec.h sur-le-champ !

  19. #19
    Membre régulier
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Points : 105
    Points
    105
    Par défaut
    1) L'appel à MODELVIEW est dans la fonction Dessiner(), je n'ai pas mis son code

    2) Voici le look at : gluLookAt(ptr->vuesCam(ptr->vue).x,ptr->vuesCam(ptr->vue).z,ptr->vuesCam(ptr->vue).y,ptr->vuesCam(ptr->vue).xCible,ptr->vuesCam(ptr->vue).zCible,ptr->vuesCam(ptr->vue).yCible,0,0,1)

    3) Non, je ne passe pas par des vecteurs, simplement par des coordonnées, j'ai toujours fait comme ça et il n'y a jamais eu de problème jusqu'à présent.

    Je vois pas pourquoi tu t'énerves soudainement, bref j'ai trouvé un moyen de contourner le problème de toute façon. A+

  20. #20
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Tu te méprends, j'essaie simplement d'être direct pour cerner ton problème. Je ne vais pas placer un smiley « clin d'oeil » à chaque phrase. Prends ce que j'écris comme ce que c'est : d'humbles conseils.

    Le contenu de la fonction Dessiner est primordial car c'est probablement là que ça coince. Je soupçonne la manière de calculer la transfo modelview.

    Au sujet de ta solution de contournement : peux-tu nous en dire plus ? Cela pourrait aussi dépanner les gens qui lisent le sujet et pourraient être confrontés au même comportement.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. OpenGL et Caméra
    Par Boubou01 dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 10/02/2011, 18h13
  2. Windows mobile : capture caméra et openGL ES
    Par toukito dans le forum DirectX
    Réponses: 1
    Dernier message: 28/03/2009, 14h01
  3. Réponses: 2
    Dernier message: 04/11/2007, 13h10
  4. [OpenGL][Debutant]bouger la caméra
    Par luckyvae dans le forum OpenGL
    Réponses: 7
    Dernier message: 01/05/2007, 11h01
  5. Problème de caméra/OpenGL
    Par nicl75 dans le forum 3D
    Réponses: 2
    Dernier message: 10/03/2007, 17h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo