Bonsoir, je fais face à un étrange problème de précision dans mon simulateur de système solaire : Au plus les planètes sont éloignées de l'origine du repère 3D au plus les sommets semblent avoir subi un décalage. Jugez par vous-mêmes ce qu'il en est de Pluton :

Nom : AlphaSun-2021-05-10-23-23-24-67.gif
Affichages : 168
Taille : 700,8 Ko

Voici le résultat si je mets Pluton sur l'orbite de Mercure :

Nom : AlphaSun-2021-05-10-23-26-11-83.gif
Affichages : 149
Taille : 1,13 Mo

Pour modéliser des sphères j'utilise une classe "PRIM_Solid" qui contient un VBO et des méthodes d'initialisation et de rendu :

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
typedef struct PRIM_VBO
{
    vector<float> coordVertices;
    vector<float> coordTex;
    vector<float> normales;
    vector<float> couleurs;
    GLuint bufferVRAM;
    GLuint VAO;
    vector<GLuint> textures;
}PRIM_VBO;
 
class PRIM_Solid
{
    private :
 
    PRIM_VBO data;
 
    public :
 
    void InitBrick(const float width,const float depth,const float height,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
    void InitSphere(const float radius,const int slices,const int stacks,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
    void InitDisk(const float radiusInt,const float radiusExt,const int slices,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
    void InitVBO(void);
    void Draw(GLuint shaderUser,glm::mat4 projection=glm::mat4(1.0),glm::mat4 modele=glm::mat4(1.0),glm::mat4 vue=glm::mat4(1.0));
    void Free(void);
};
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
void PRIM_Solid::InitSphere(const float radius,const int slices,const int stacks,glm::vec4 color,GLuint tex)
{
    float latitude=-90.0,longitude;
    glm::vec3 sommets[4];
    glm::vec2 coordtex[4];
    glm::vec3 normales[4];
    const float deltaLong=360.0/slices;
    const float deltaLat=180.0/stacks;
 
    while(1)
    {
        longitude=0.0;
        while(1)
        {
            ...// Calcul coordonnées vertices, coordonnées texture, normales
 
            longitude+=deltaLong;
            if(longitude>=360.0)
                break;
        }
 
        latitude+=deltaLat;
        if(latitude>=90.0)
            break;
    }
 
    ////////////////////////////////////////////////////////////
 
    int compteur=0;
    while(1)
    {
        data.couleurs.push_back(color.x);		//Ajout couleur
        data.couleurs.push_back(color.y);
        data.couleurs.push_back(color.z);
        data.couleurs.push_back(color.w);
 
        compteur++;
        if(compteur==data.coordVertices.size())
            break;
    }
 
    data.textures.push_back(tex);		//Ajout texture
 
    ////////////////////////////////////////////////////////////
 
    InitVBO();
}
Initialisation VBO :

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
void PRIM_Solid::InitVBO(void)
{
    glGenVertexArrays(1,&data.VAO);
    glGenBuffers(1,&data.bufferVRAM);
 
    glBindVertexArray(data.VAO);
    glBindBuffer(GL_ARRAY_BUFFER,data.bufferVRAM);
 
    glBufferData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float)+data.couleurs.size()*sizeof(float),NULL,GL_STREAM_DRAW);
 
    glBufferSubData(GL_ARRAY_BUFFER,0,data.coordVertices.size()*sizeof(float),&data.coordVertices[0]);
    glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float),data.coordTex.size()*sizeof(float),&data.coordTex[0]);
    glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float),data.normales.size()*sizeof(float),&data.normales[0]);
    glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float),data.couleurs.size()*sizeof(float),&data.couleurs[0]);
 
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    glEnableVertexAttribArray(0);
 
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,2*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)));
    glEnableVertexAttribArray(1);
 
    glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)));
    glEnableVertexAttribArray(2);
 
    glVertexAttribPointer(3,4,GL_FLOAT,GL_FALSE,4*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float)));
    glEnableVertexAttribArray(3);
 
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
}
Rendu sphère :

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
void PRIM_Solid::Draw(GLuint shaderUser,glm::mat4 projection,glm::mat4 modele,glm::mat4 vue)
{
    glUseProgram(shaderUser);
 
    glUniformMatrix4fv(glGetUniformLocation(shaderUser,"projection"),1,false,glm::value_ptr(projection));
    glUniformMatrix4fv(glGetUniformLocation(shaderUser,"modele"),1,false,glm::value_ptr(modele));
    glUniformMatrix4fv(glGetUniformLocation(shaderUser,"vue"),1,false,glm::value_ptr(vue));
 
    glBindVertexArray(data.VAO);
 
    glBindTexture(GL_TEXTURE_2D,data.textures[0]);
 
    if(data.textures[0]==0)
        glUniform1i(glGetUniformLocation(shaderUser,"textured"),false);
    else
        glUniform1i(glGetUniformLocation(shaderUser,"textured"),true);
 
    glDrawArrays(GL_TRIANGLES,0,data.coordVertices.size()/3);
 
    glBindVertexArray(0);
}
Pour représenter les planètes j'utilise une structure "Planete" contenant entre autres une instance de PRIM_Solid et les caractéristiques orbitales.
J'utilise une classe Map contenant un tableau d'instances de "Planete" ainsi que les shaders, les matrices et les méthodes d'initialisation et de rendu.

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
void Map::chargeCaracPlanetes(Bureau *bur)
{
    FILE *fichier=fopen("AlphaSun/data/CaracPlanetes.txt","r");
 
    Planete p;
 
    while(1)
    {
        ...// Chargement données depuis fichier
 
        p.sphere.InitSphere(p.rayon,40,40,glm::vec4(1.0,1.0,1.0,1.0),loadTexture(cheminTex.c_str(),1));		//Initialisation sphère
 
        planetes.push_back(p);
    }
 
    fclose(fichier);
}
Le rendu :

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
void Map::rendu(Camera *cam,Bureau *bur)
{
    if(!bur->getPleinEcran())
        matriceProjection=glm::perspective(FOVY,4.0/3,NEAR,FAR);
    else
        matriceProjection=glm::perspective(FOVY,(double)bur->getRatio(),NEAR,FAR);
 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 
    matriceVue=glm::lookAt(glm::vec3(cam->getPosition().x,cam->getPosition().y,cam->getPosition().z),
                                 glm::vec3(cam->getCible().x,cam->getCible().y,cam->getCible().z),
                                 glm::vec3(0.0,0.0,1.0));
 
    matriceModele=glm::mat4(1.0);
 
    renduSystSolaire(bur,cam);
}
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
void Map::renduSystSolaire(Bureau *bur,Camera *cam)
{
    int compteur=0;
 
    while(1)
    {
        glUseProgram(shaderPlanetes);
 
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
	glm::mat4 sauvegarde=matriceModele;
 
        matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].LongitudeNoeudAsc,glm::vec3(0.0,0.0,1.0));
        matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].inclinaisonOrbite,glm::vec3(1.0,0.0,0.0));
        matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].angleRevolution,glm::vec3(0.0,0.0,1.0));
        matriceModele=glm::translate(matriceModele,glm::vec3(planetes[compteur].demiGrandAxe,0.0,0.0));
        matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].angleRevolution,glm::vec3(0.0,0.0,1.0));
        matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].inclinaisonOrbite,glm::vec3(1.0,0.0,0.0));
        matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].LongitudeNoeudAsc,glm::vec3(0.0,0.0,1.0));
        matriceModele=glm::rotate(matriceModele,(float)(angleObliquite*180/M_PI),glm::vec3(vecteurRotation.x,vecteurRotation.y,vecteurRotation.z));
        matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].angleRotation,glm::vec3(0.0,0.0,1.0));
	//Transformations géométriques
 
        planetes[compteur].sphere.Draw(shaderPlanetes,matriceProjection,matriceModele,matriceVue);		//Rendu
 
        matriceModele=sauvegarde;
 
        compteur++;
        if(compteur==planetes.size())
            break;
    }
}
Les shaders :

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
#version 330 core
 
layout (location=0) in vec3 vertex;
layout (location=1) in vec2 coordTex;
layout (location=2) in vec3 normale;
layout (location=3) in vec4 color;
 
uniform mat4 projection;
uniform mat4 modele;
uniform mat4 vue;
 
out vec2 coordTexFrag;
out vec4 couleurFrag;
 
void main(void)
{
	vec4 vertex2=vec4(vertex,1.0);
 
	vec4 vertexApresTranf=modele*vertex2;
 
	vec4 normaleApresTransf=modele*vec4(normale,0.0);
 
	gl_Position=projection*vue*modele*vertex2;
 
	coordTexFrag=coordTex;
 
	vec3 rayonLumiere=vec3(0.0-vertexApresTranf.x,0.0-vertexApresTranf.y,0.0-vertexApresTranf.z);
 
	float luminosite=dot(normalize(vec3(normaleApresTransf.x,normaleApresTransf.y,normaleApresTransf.z)),normalize(rayonLumiere));
	//Eclairage
 
	luminosite=clamp(luminosite,0.05,1.0);
 
	couleurFrag=vec4(luminosite*color[0],luminosite*color[1],luminosite*color[2],1.0);
}
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
#version 330 core
 
uniform sampler2D tex;
 
in vec2 coordTexFrag;
in vec4 couleurFrag;
 
out vec4 FragColor;
 
uniform bool textured;
 
void main(void)
{
	if(!textured)
		FragColor=couleurFrag;
	else
		FragColor=texture(tex,coordTexFrag.xy)*couleurFrag;
}
Voilà en gros comment fonctionne ce simulateur, je ne vois pas d'où pourrait venir ce problème de précision, il doit bien y avoir un moyen de le corriger étant donné que des logiciels comme Stellarium n'ont pas ce problème.

Merci en avant pour votre aide.