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 :
Voici le résultat si je mets Pluton sur l'orbite de Mercure :
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); };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
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(); }
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
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); }
Pour représenter les planètes j'utilise une structure "Planete" contenant entre autres une instance de PRIM_Solid et les caractéristiques orbitales.
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); }
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.
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::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); }
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); }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 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; } }
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); }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.
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; }
Merci en avant pour votre aide.
Partager