Monde infini en openGL

Monde infini en openGL - C++ - Programmation

Marsh Posté le 04-02-2004 à 13:03:13    

Kikoo tous,
 
j'essaye de programmer un petit soft en openGL a la magic carpet. Je bloque sur un algo qui me permettrait d'avoir mon monde 3D "rond", c'est a dire que je puisse infiniment avancer tout droit sans jamais en voir la fin. J'ai pensé a un algo utilisant 9 maps et qui les bougerai au fur et a mesure
 
/****/****/****/
/  1 /  2 /  3 /
/****/****/****/
/  4 /  5 /  6 /
/****/****/****/
/  7 /  8 /  9 /
/****/****/****  
 
si je passe du 5 au 1
-------------------->
 
 
 
/****/****/****/
/  9 /  7 /  8 /
/****/****/****/  
/  3 /  1 /  2 /
/****/****/****/
/  6 /  4 /  5 /
/****/****/****/
 
 
Apparement ca devrai marcher mais je n'arrive pas a coder les algo :(
 
Pouvez vous m'aider
 
Merci de vos réponses


Message édité par iceteapeche le 08-02-2004 à 10:00:18

---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 04-02-2004 à 13:03:13   

Reply

Marsh Posté le 04-02-2004 à 13:18:04    

ASV ?

Reply

Marsh Posté le 04-02-2004 à 13:23:10    

ben tu decoupes ton monde en patch (ou secteur). chaque secteur centré sur l'origine
tu trouves le secteur ou est le viewer (S)
 
tu dessine le carre de (s-1,s-1) a  (s+1,s+1) avec des modulos/test  pour cycler, avec bricolage de la matrice de transformation pour chaque secteur
 
bref jvois pas le pb :o

Reply

Marsh Posté le 04-02-2004 à 13:23:18    

En fait tu as 9 cases pour ton monde.
Pour chaque case, tu fais une structure du genre :
 
typedef struct _Case
{
   int ID;
   _Case * NE, // Nord Est
         * N,
         * NO,
         * E,
         * O,
         * SE,
         * S,
         * SO;
} Case;
 
A l'init tu mets pour chacune des 9 cases les bonnes valeurs de NE, N, ..., S, SO.
 
A l'affichage, tu regardes ds quelle case tu es, par ex la case 5, et tu affiches toutes les cases NE, N, ..., S, SO voisines définies ds la structure ;)

Reply

Marsh Posté le 04-02-2004 à 13:52:46    

Merci pour vos réponses!!!  
 
L'algo de Dav Vador m'a l'air bien sympathique :D
 
 
merci tous


---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 04-02-2004 à 14:06:19    

Oublie pas de bricoler ta matrice de translation

Reply

Marsh Posté le 04-02-2004 à 15:35:08    

IceTeaPeche a écrit :

Merci pour vos réponses!!!  
 
L'algo de Dav Vador m'a l'air bien sympathique :D
 
 
merci tous

C'est une soluce parmis tant d'autres, c'est ptet pas la meilleure ;)

Reply

Marsh Posté le 08-02-2004 à 10:07:16    

Je me permet de relancer le sujet meme s'il devait etre bouclé ;)
En fait l'algo ne marche pas... Deja il m'est pas facile de savoire exactement ou je suis puisqu'en fait les cases bougent tout le temps, je ne peux donc pas faire de tests direct sur les coordonées...
 
mon monde est représenté par neuf cubes disposés de la facon suivante :
1 2 3
4 5 6
7 8 9
 
et je translate a chaque fois mon repere sur le coin haut droit du cube n pour le dessiner.
 
Je stocke quelque part les coordonnées du coin haut droit du cube du milieu.
 
Jusque la tout marche.
 
Si je rajoute avant tout ca la fonction suivante pour mettre a jour le cube ou je me trouve ca plante...

Code :
  1. int SetMondeCourant()
  2. {
  3. tVector3 MaPosition = Camera.Position();
  4. glScalef(Echelle,Echelle,Echelle);
  5. glTranslatef(coinhautdroit.x,coinhautdroit.y,coinhautdroit.z);
  6. if (MaPosition.x >0)
  7. {
  8.  coinhautdroit.x=coinhautdroit.x + 85*MAP_SCALE;
  9.  coinhautdroit.y=coinhautdroit.y;
  10.  coinhautdroit.z=coinhautdroit.z;
  11.  return monde[mondecourant-1].E;
  12. }
  13. if (MaPosition.x < -85*MAP_SCALE)
  14. {
  15.  coinhautdroit.x=coinhautdroit.x - 85*MAP_SCALE;
  16.  coinhautdroit.y=coinhautdroit.y;
  17.  coinhautdroit.z=coinhautdroit.z;
  18.  return monde[mondecourant-1].O;
  19. }
  20. if (MaPosition.z > 0)
  21. {
  22.  coinhautdroit.x=coinhautdroit.x;
  23.  coinhautdroit.y=coinhautdroit.y;
  24.  coinhautdroit.z=coinhautdroit.z + 85*MAP_SCALE;
  25.  return monde[mondecourant-1].N;
  26. }
  27. if (MaPosition.z < -85*MAP_SCALE)
  28. {
  29.  coinhautdroit.x=coinhautdroit.x + 85*MAP_SCALE;
  30.  coinhautdroit.y=coinhautdroit.y;
  31.  coinhautdroit.z=coinhautdroit.z - 85*MAP_SCALE;
  32.  return monde[mondecourant-1].S ;
  33. }
  34. return mondecourant;
  35. }


 
mes cubes sont de 85x85 et MAP_SCALE est l'echelle de ma height map. monde[9] est ma structure de monde et coinhautdroit le coin haut droit associé au cube du milieu.
 
Bah ca fait n'importe quoi le cubes apparaissent puis disparaissent c'est une catastrophe.
Voila aussi ma fonction de rendu

Code :
  1. void Render()
  2. {
  3.  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  4.  glMatrixMode(GL_MODELVIEW);
  5.  glLoadIdentity();
  6.  Camera.Update();
  7.  Camera.Look();
  8.  Frustum.CalculateFrustum();
  9.  glPushMatrix();
  10.   mondecourant = SetMondeCourant();
  11.  glPopMatrix();
  12.  glPushMatrix();
  13.  //glLoadIdentity();
  14.   glScalef(Echelle,Echelle,Echelle);
  15.   glTranslatef(coinhautdroit.x,coinhautdroit.y,coinhautdroit.z);
  16.   DrawMonde(mondecourant-1);
  17.  glPopMatrix();
  18.   //CUBE SUD  
  19.  glPushMatrix();
  20.   glTranslatef(coinhautdroit.x,coinhautdroit.y,coinhautdroit.z);
  21.   glScalef(Echelle,Echelle,Echelle);
  22.   if (Frustum.CubeInFrustum(-85*MAP_SCALE/2,85*MAP_SCALE/2 ,-85*MAP_SCALE/2, -85*MAP_SCALE-85*MAP_SCALE/2))
  23.   {
  24.    glTranslatef(0.0f, 0.0f , -85*MAP_SCALE);
  25.    DrawMonde(monde[mondecourant-1].S-1);
  26.   }
  27.  glPopMatrix();
  28.                 //etc  
  29. }


 
Si vous pouvez m'aider ...
 
Merci


Message édité par iceteapeche le 08-02-2004 à 10:08:06

---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 08-02-2004 à 13:23:40    

IceTeaPeche a écrit :

[..] magic carpet.

De mémoire, c'était une map carrée, le terrain était une map d'élévation avec des mesh par dessus. Comment ça marche chez toi ? '9 carrés', c'est vague.

Reply

Marsh Posté le 08-02-2004 à 21:03:40    

C'etait bien une map carré. J'utilise aussi une heightmap avec des mesh par dessus. Les "9 carrés" c'est en fait une division de mon carré en 9 zones du type  
123
456
789
 
pour me permettre de faire basculer les carrés et donner l'illusion du monde infini
 
du genre je commence dans le carré 5 puis des que je passe dans le carré 2 mon monde est affiché comme il suit :
 
789
123
456
 
Maintenant je n'ai qu'un seul bmp pour la carte d'elevation.  
 
Si tu connais un meilleur algo pour l'illusion d'infini... :)
 
[J'espere qu'on comprends quand meme un minimum ce que j'essaye de dire ;)]
 
Merci tous


---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 08-02-2004 à 21:03:40   

Reply

Marsh Posté le 08-02-2004 à 21:40:27    

iceteapeche a écrit :

Les "9 carrés" c'est en fait une division de mon carré en 9 zones du type

Une méthode de barbare, donc :D
 
Pour un truc similaire (rendu voxel de comanche, rotozoom 3d), ça marchait comme ça - ton champ de vision est une pyramide, formée par 4 rayons. Intersecte ces 4 rayons avec ta heightmap et tu vas obtenir un quadrilatère quelconque : c'est ce que tu dois afficher à l'écran. Rasterize ce quadrilatère comme 2 triangles, tu pourras ainsi afficher la partie de ton paysage qui t'intéresse.
 
Maintenant il va sûrement falloir que tu subdivises ta map en carrés, comme tu as fait - là tu ne rasterizes plus ta heightmap mais ta heightmap subdivisée.
 
Pour simuler l'infini, ça se fait à la toute dernière étape, avant de récupérer les texels à afficher. Mettons que ta map fasse 256x256, tu vas obtenir des coordonnées (312, 260), tu fais un petit and (312 & 255, 260 & 255) et hop - ton terrain est infini.


Message édité par youdontcare le 08-02-2004 à 21:40:49
Reply

Marsh Posté le 09-02-2004 à 02:24:13    

Euhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
 
j'ai pas tout compris je crois ; desolé :(
 
j'arrive a avoir les quatres rayons de la pyramdie (c'est mon frustum) et je pense avoir compris pour la rasterization
 
par contre le and la je crois qu'il me manque une notion ou deux... Pourrais tu m'expliquer la manip stp


---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 09-02-2004 à 10:31:05    

C'est du raytracing standard. Tu intersectes le plan xOz, tu obtiens un point 3d P. Tout point d'intersection du plan xOz aura le même y (=0), tu considères donc x & z comme étant les coordonnées de ta texture. Tu obtiens qq chose comme P = (-1054.28, 3123.2). Ta texture fait 256x256. Il faut donc trouver un moyen de mapper des coordonnées infinies sur des coordonnées finies (ta texture). Pour ça, il suffit de les passer par un modulo % 256 (reste de la division par 256) : toute coordonnée sera ramenée entre 0 et 255.
 
Le modulo sur des puissances de 2, c'est un cas particulier dans lequel on utilise un & binaire. Tes coordonées peuvent varier entre 0 et 255, soit 8 bits :
 
11111111
 
Si tu files une coordonnée plus grande
 
1010010101001110
 
tu gicles bêtement les bits qui ne t'intéressent pas (ceux de poids fort. Ça se passe avec un AND :
 
1010010101001110 AND 0000000011111111 = 0000000001001110
 
et voilà la coordonnée bornée entre 0 et 255.

Reply

Marsh Posté le 09-02-2004 à 10:35:23    

(la plupart des compilos sont suffisament intelligent pour remplacer un %(2^n) par un &((2^n) - 1) )

Reply

Marsh Posté le 09-02-2004 à 10:50:20    

Oui. Vieux réflexe :D

Reply

Marsh Posté le 09-02-2004 à 11:31:39    

oki mais ca veut dire qu'a ce moment la je ne reviendrai pas au début de ma map si je la depasse. Ce que j'appelle une simulation d'inifini ce serai de tourner en rond infiniment sur ma map en avancant tout droit...
Je me sens boulet la je suis dslé


---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 09-02-2004 à 11:51:55    

IceTeaPeche a écrit :

oki mais ca veut dire qu'a ce moment la je ne reviendrai pas au début de ma map si je la depasse.

Ben si ! Ça veut dire que quelles que soient les coords de ta caméra, leurs rayons intersecteront toujours le plan de ta texture.  
 
Imagine : tu es en (0, 0), tu traces un rayon juste en bas, tu te retrouves avec les coords terrain (0, 0). tu te déplaces tout droit, tu te retrouves en (256, 0), tu traces à nouveau un rayon, tu obtiens (256, 256) qui une fois modulé donne (0, 0) -> tu es revenu à ton point de départ.

Reply

Marsh Posté le 09-02-2004 à 12:18:28    

(ca m'a l'air bien puissant comme algo) et vu que je calcule ca a partir des rayons meme la vue sera ajustée?? Je ne pense pas que je saurai coder ca :S n'y a t il pas un tutorial ou n'as tu pas une portion de code avec cet algo histoire de voir a quoi ca ressemble?
 
En tout cas merci pour l'info, ca a l'air d'etre exactement ce que je cherchais!


---------------
Se souvenir des belles choses...
Reply

Marsh Posté le 09-02-2004 à 12:45:05    

Oui c'est puissant, enfin c'est surtout le seul vraiment adapté. Ça affiche exactement ce qu'il faut à l'écran, et tu peux limiter en profondeur facilement. Comme tu as des objets sur ton terrain, tu peux savoir lesquels afficher avec la même méthode.
 
Côté code, tu peux regarder des sources de voxel ou de rotozooms 3d. Je ne connais rien de spécifique.
 
Enfin c'est vraiment pas compliqué. Pour résumer, il te faut :
* définir un plan qui contient ta heightmap
* définir une caméra 3d (x, y, z) avec son orientation
* à partir de ça, calculer les 4 rayons de la pyramide de vision (faire gaffe lorsque tu regardes l'horizon)
* intersecter ces rayons avec ton plan
* traiter le quadrilatère comme 2 triangles à rasterizer. (c'est largement plus simple que du mapping standard, vu que tu peux choisir le sens dans lequel partir, et que tu n'interpoles pas les coords de texture)
* chaque coordonnée obtenue par la méthode précédente te donne sa position dans le repère monde, la modulation de ces coordonnées te donne l'index dans la map. Tu as donc tout ce qu'il te faut pour l'affichage : une position 3d & son texel correspondant.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed