on en revient à mes questions précédentes...
Version imprimable
Bon on reprend :
-> Position Cam
-> Dessin terrain
-> Dessin traj
et pour finir dessin Avion
A ce stade de test je ne calcule pas forcément d'angles, je me contente d'incrémenter une variable pour tourner autour du point avec la souris ex : 0, +5, +10 etc ..
Les coordonnées cartésiennes sont du type :
x -111319.49079327357 y 2000.0 z 4564099.122524217
Beaucoup de chiffres après la virgule certes, mais pourtant le point suit très bien la trajectoire tant que je ne tourne pas la caméra avant..
Une idée ?
Graouuu, mais pourquoi vous n'utilisez pas les bons outils. Les glRotate, glTranslate c'est vraiment pour apprendre les transformations de bases en OpenGL, pas pour gérer des mouvements complexes. Utilisez les matrices et les quaternions, vous éviterez bien des désagréments, dont le gimbal lock et vos calculs en seront grandement simplifiés !
Merci pour les réponse,
Mais je n'arrive toujours pas à un bon résultat :(
Je suis loin d'être confirmé en ce qui est de l'OpenGL, mais tout de même j'ai beaucoup d'exemples à ma disposition, notamment les tutoriels "nehe" et autres.
J'ai toujours mon problème même en utilisant des matrices et des Quaternions .. je dois vraiment mal m'y prendre .. mais c'est pourtant si simple !!
J'utilise des Vecteur3D, avec des fonctions d'interpolations pour les positions intermédiaires entre chaque points, les positions ont pourtant bien l'air correctes .. mais à l'affichage le point se ballade de gauche à droite de la ligne mais jamais réellement dessus..
Donc là si vous pouviez m'aider et/ou m'orienter sur des exemples de suivi de trajectoire ( c'est juste qq points en ligne droite ou non ) .. JE SUIS PRENEUR !
Bonjour
Je suis surpris des valeurs que tu donnes :
Tu penses vraiment qu'un float contient autant de chiffres significatifs ?Citation:
Les coordonnées cartésiennes sont du type :
x -111319.49079327357 y 2000.0 z 4564099.122524217
A mon avis, ton problème (comme tu l'as suggéré toi même) est juste un problème d'arrondi dans les calculs. Quand tu ne fais pas de rotation, ton programme "tombe en marche" et tu ne vois pas de problème de rendu mais le problème doit toujours être présent.
Tu devrais pouvoir calculer l'angle entre la position théorique attendu et la position réelle observée et donc savoir si tu sors de la précision de calcul
Je suis tout à fait d'accord avec toi, ce n'étais qu'un exemple, j'ai d'ailleurs tenté de tronquer les valeurs de mes points de référence à 2 décimales, mais le résultat final est le même.Citation:
Tu penses vraiment qu'un float contient autant de chiffres significatifs ?
Par contre, comment je peux calculer cette position observée ??
Car je fait un drawLine de mes 2 points, puis un vertex3D du point interpolé entre ces deux points, donc en théorie le point devrai être sur la ligne .. Mais à l'affichage il es très souvent à coté .. donc la je ne vois pas trop comment je peux connaître à ce niveau la la valeur de l'écart..
Bon j'ai un petit bout de code pour expliquer mon problème plus simplement, si vous pouvez me le tester/corriger svp
A noter qu'on n'observe pas beaucoup de "perturbations" en diminuant les coordonnées .. mais cela ne m'arrangerai pas forcement ..
Le débat est ouvert !
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
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 class MyTest implements GLEventListener { Vector3f sw = new Vector3f(-111319.49f ,2000f, -4564099.12f ); Vector3f ne = new Vector3f(-222638.98f ,4000f, -4898057.59f ); // Vector3f sw = new Vector3f(-111319.49f/100f ,2000f/100f, -4564099.12f/100f ); // Vector3f ne = new Vector3f(-222638.98f/100f ,4000f/100f, -4898057.59f/100f ); private static final int TIMER_DELAY = 1000 *100; // 1 sec private Timer timer ; private float deltaTemps=0; public long startTime= System.currentTimeMillis(); private GLU glu = new GLU(); public void display(GLAutoDrawable gLDrawable) { final GL gl = gLDrawable.getGL(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); if(!timer.isRunning()) timer.start(); deltaTemps = (float) (( System.currentTimeMillis() - startTime) / (float)timer.getDelay()); if ( deltaTemps > 1 ) deltaTemps = 1; Vector3f pt = sw.clone(); pt.interpolate(pt, ne, deltaTemps); // gl.glTranslatef(0,0,-1); glu.gluLookAt(pt.x-1, pt.y +1,pt.z , pt.x, pt.y ,pt.z, 0,1,0); gl.glColor3d(1,0,0); gl.glBegin(GL.GL_LINES); gl.glVertex3f(sw.x, sw.y, sw.z); gl.glVertex3f(ne.x, ne.y, ne.z); gl.glEnd(); gl.glColor3d(1,1,0); gl.glPointSize(5.0f); gl.glBegin(GL.GL_POINTS); gl.glVertex3f(pt.x, pt.y, pt.z); gl.glEnd(); System.out.println("Dt " + deltaTemps + " Distance deb = " + sw.distance(pt) + " ### Distance fin " + ne.distance(pt)); } public void displayChanged(GLAutoDrawable gLDrawable, boolean modeChanged, boolean deviceChanged) { } public void init(GLAutoDrawable gLDrawable) { GL gl = gLDrawable.getGL(); gl.glShadeModel(GL.GL_SMOOTH); gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); gl.glClearDepth(1.0f); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(GL.GL_LEQUAL); gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); timer = new Timer(TIMER_DELAY,this); timer.setRepeats(true); } public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) { final GL gl = gLDrawable.getGL(); final GLU glu = new GLU(); if (height <= 0) height = 1; final float h = (float) width / (float) height; // gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective(45.0f, h, 1.0, 2000.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); } class Vector3f{ float x,y,z; public Vector3f() {} public Vector3f(float x, float y, float z) { this.x =x; this.y =y; this.z =z; } public final Vector3f interpolate(Vector3f current, Vector3f next, float t) { x = current.x + (next.x - current.x) * t; y = current.y + (next.y - current.y) * t; z = current.z + (next.z - current.z) * t; return this; } public Vector3f clone() { return new Vector3f(x, y, z); } public final float distance(Vector3f vector) { float dx = x - vector.x; float dy = y - vector.y; float dz = z - vector.z; float f = dx*dx + dy*dy + dz*dz; if(f == 0 || f == 1) { return f; } else { return (float) Math.sqrt(f); } } }
Proposition peut-être idiote mais... tu as testé en utilisant des double au lieu des float? Vu les valeurs que tu utilises, ça ne m'étonnerait qu'à moitié que ça ne vienne d'un problème de précision dû aux float, vu que tu tournes à 8 ou 9 chiffres significatifs... hypothèse déjà soulevée par gbdivers précédemment. Même si tu tronques à 2 décimales, il y a tout un paquet de chiffres avant ta virgule.
Sinon divises toutes tes coordonnées par 100 ou 1000. Tu as peut-être un problème de zbuffer, tu joues avec des valeurs un peu grandes...
Salut plegat
Merci encore de t'occuper de moi ^^
oui j'utilise aussi des doubles, j'ai mis ici des floats dans l'exemple mais j'ai le même problème avec les doubles ..
Et donc oui quand je divise toutes les coordonnées et tout les Traitements par 100 ou 1000 on voit moins le tremblement effectivement .. mais pour moi c'est pas la solution :(
Tu l'as testé le bout de code ??
J'ai testé ton code (en C++) et j'ai le même problème (sans surprise :) )
Je confirme que le problème vient bien des erreurs d'arrondis. Lorsque la carte graphique fait ses calculs de matrices, tu as des erreurs de calculs, ce qui est normal et habituellement pas gênant. Ici, du fait que tu utilises des nombres très grand, le nombre de chiffre significatif est trop grand et dépasse les capacités des floats.
Là, tu essaies de lire la plaque d'immatriculation d'un véhicule lunaire en ayant une précision au quart de cheveux près.
Utiliser des doubles ne changerait rien : la carte graphique convertit en float.
La seule solution : utilise des valeurs moins grande. Si tu utilises de valeurs de sw et ne compris entre 1 et 10, ton point suit parfaitement ta ligne.
Merci d'avoir testé gbdivers.
Donc on es d'accord sur le fait qu'il va falloir réduire tout mon environnement à une taille d'au moins 1/100ème, ça devrai pouvoir être faisable.
Mais ( il y a encore un mais ) je me pose toujours la question (excusez moi je suis un peu casse c... ), dans les applis , dont j'ai le code en plus (ex : worldwind ) les coordonnées sont bien en cartésiennes au niveau 3D ( du moins ce que j'ai pu découvrir dans les classes ) je n'ai pas l'impression qu'il y à ce problème de précision . malheureusement vu le nombre de classe qui me dépasse j'avoue, je ne sais pas comment avoir la même précision au niveau de la trajectoire sur des très grands nombres..
Any Idea ??
Je risque d'être un peu HS car je n'ai pas tout lu mais si ton problème est du à la précision de flottant parce que tu as un monde immense tu peux lire cet article : http://www.gamasutra.com/view/featur..._universe_.php
En gros il te propose de changer de repère, comme ça tes coordonnées se font en fonction de ce nouveau repère et sont bien plus simple. Tu fais tous tes calculs comme ça (tu ne devrais pas avoir de problème de précision) et pour afficher, ton repère c'est ta caméra (il faut calculer une matrice de passage j'imagine), du coup les problèmes d'imprécision n'apparaitront que très loin de ta caméra et ne seront pas visible, et tu en tout cas tu ne devrais plus en avoir l'hors des calculs (et donc les erreurs ne s'accumuleront pas).
Sauf que ce n'est pas la carte graphique qui fait les calculs, c'est le proc... mais on est d'accord que balancer des double à la carte au final, ça ne passera pas! :)
On limitera à la rigueur les imprécisions sur le calcul des points, mais pas sur l'affichage.
Vu que c'est la seule qui fonctionne, tu n'as pas vraiment le choix!
Ce n'est pas hyper lourd de faire intervenir une variable supplémentaire servant de mise à l'échelle... au moins pour le passage des coordonnées à opengl.
Bonjour
Je parlais bien des calculs effectués par la carte graphique, c'est à dire les calculs matriciels pour convertir les points de l'espace 3D en coordonnées écran. Si c'était les calculs sur le CPU qui posaient problèmes, il suffirait de passer à des double ou long double (moyennant perte de performances)Citation:
Sauf que ce n'est pas la carte graphique qui fait les calculs, c'est le proc...
Il n'y a pas en effet de problème pour conserver les positions avec des coordonnées cartésiennes sur une carte de très grande taille. Au pire, en fonction de la précision que l'on souhaite (au km près, au m près, au cm près...), on choisira un type de données qui permet de conserver un nombre de chiffre significatif suffisant.Citation:
Mais ( il y a encore un mais ) je me pose toujours la question (excusez moi je suis un peu casse c... ), dans les applis , dont j'ai le code en plus (ex : worldwind ) les coordonnées sont bien en cartésiennes au niveau 3D ( du moins ce que j'ai pu découvrir dans les classes ) je n'ai pas l'impression qu'il y à ce problème de précision . malheureusement vu le nombre de classe qui me dépasse j'avoue, je ne sais pas comment avoir la même précision au niveau de la trajectoire sur des très grands nombres..
Mais ça ne veut pas dire qu'il faille travailler tout le temps avec la même unité : en fonction du zoom, la taille la plus adapté sera 100km, 1km, 1m.... C'est un problème d'échelle.
Et ça ne veut par dire qu'il faille travailler tout le temps avec la même origine : si on peut afficher des objets sur une carte du monde en prenant comme origine Paris, il serait étrange de vouloir dessiner des objets sur une feuille de papier en prenant la même origine (Paris) plutôt que le coin en haut à gauche de la feuille.
D'où la proposition de changer de repère. En fait, pour réaliser le rendu, la seule chose qui est intéressante, c'est le repère local qui contient la caméra et l'objet observé.
Tu peux prendre par exemple un repère basé sur la caméra (donc soustraire les coordonnées de pt à chaque point que tu envoies à GL) et en prenant comme unité une valeur adapté (par exemple la distance entre ta caméra et l'objet, c'est à dire diviser chaque coordonnées envoyés à GL par cette distance)
Le mieux serait probablement d'encapsuler le changement de repère dans ta classe Vector3f, en ajoutant 2 variables statique (position du centre et facteur d'échelle) et une fonction getLocalPosition()
Bon, après avoir testé des dizaines de méthodes d'affichage avec matrices et quaternions, j'ai fini par me abandonner l'idée de positionner ma caméra loin dans l'espace .. gbdivers m'as bien aiguillé, merci encore!
J'ai utilisé cette astuce pour toujours garder mon point visé en (0,0,0) et je soustrait à chaque vertex la position théorique de ce point, tout en gardant mon unité de départ sans aucun besoin de retailler l'échelle.Citation:
Tu peux prendre par exemple un repère basé sur la caméra (donc soustraire les coordonnées de pt à chaque point que tu envoies à GL) et en prenant comme unité une valeur adapté (par exemple la distance entre ta caméra et l'objet, c'est à dire diviser chaque coordonnées envoyés à GL par cette distance)
J'étais retissant à cette idée au départ pensant que cela me ferai beaucoup trop de changements dans le code, mais cela ne m'as pas pris plus d'une heure pour tout changer.
Et là forcément je n'ai plus aucuns tremblements, et au contraire un super lissage sur les mouvements de mon objet !
Pour ce qui est du terrain je n'en avais pas parlé, je me suis inspiré du GeoMipmapping, et du coup j'ai une dalle de plus de 100km/100km à plus de 30fps ça pète ^^.
Voilà encore merci de m'avoir aider sur ce sujet, il me reste encore pas mal de taf pour rendre mon petit projet vraiment attrayant :P