Bonjour tout le monde,
Voila, apres deux semaines avec irrlicht, je me suis fait un petit truc qui marche (a moitier). Je suppose que mon code est hyper loin d'etre optimiser et je voudrais vos conseils pour comprendre certain truc et en realisé d'autre ^^.
Donc voila, j'essaye de réaliser un personnage qui se déplace sur un terrain 3D. Pour cela, j'ai un tableau 2D qui represente mon terrain.
1 2 1 3 4
2 3 4 1 1
1 2 3 4 2
2 1 2 2 4
4 1 2 3 3
Chaque nombre representent un type de terrain particulier (0=herbe, 1=foret, ...).
Donc ca c'est mon terrain 2D, et avec je voudrais charger des heightmap en fonction du terrain.
Donc pour pas que je doive charger toute les heightmap d'un coup, ce qui est impossible tellement ca prendrait de memoire, je charge un carré de 3x3. Sur cette aire constitué de 9 heightmap, mon personnage se trouve sur la case du milieu et quand mon personnage change de heightmap, (pour l'instant), je remove les 9 anciennes heightmap et charge les 9 nouvelles.
Par exemple, de base je charge (ca provient de mon tableau 2D ci dessus)
1 2 1
2 3 4
1 2 3
vu que mon personnage est sur le 3 du milieu si il se déplace a droite, je charge et mon perso reste au milieu
2 1 3
3 4 1
2 3 4
Voici mon code :
Dans la boucle du rendu, je fait appelle a cette méthode, et si le joueur a changer de map, ca rentre dans le if qui detruit et charge le nouveau carré de 9 maps.
void genereTerrain::modifieTerrain(irr::scene::ISceneManager *maScene, irr::scene::ICameraSceneNode *cam, irr::video::IVideoDriver *drive) { posJoueurX = (int)floor(cam->getPosition().X) / tailleCase; posJoueurZ = (int)floor(cam->getPosition().Z) / tailleCase; if (posJoueurX != posPrecJoueurX || posJoueurZ != posPrecJoueurZ) { std::cout << std::endl << std::endl; std::cout << "Position X : " << posJoueurX << std::endl; std::cout << "Position Z : " << posJoueurZ << std::endl; std::cout << "Effacement des terrains ..." << std::endl; for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { terrain[i][j]->remove(); } } for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { const irr::c8* ntexTerrain; int texTerrain = tabTypTerr[posJoueurX+i][posJoueurZ+j]; switch (texTerrain) { case 0: ntexTerrain = "../../media/plaine.jpg"; std::cout << "Plaine : "; break; case 1: ntexTerrain = "../../media/montagne.jpg"; std::cout << "Montagne : "; break; case 2: ntexTerrain = "../../media/eau.jpg"; std::cout << "Eau : "; break; case 3: ntexTerrain = "../../media/foret.jpg"; std::cout << "Foret : "; break; } terrain[i][j] = maScene->addTerrainSceneNode ( "../../media/heightmap2.bmp", 0, i+j, core::vector3df((float)(i+posJoueurX-1)*tailleCase, 0.f, (float)(j+posJoueurZ-1)*tailleCase)); terrain[i][j]->setScale(core::vector3df(40, 4.4f, 40)); terrain[i][j]->setMaterialFlag(video::EMF_LIGHTING, false); terrain[i][j]->setMaterialTexture(0, drive->getTexture(ntexTerrain)); terrain[i][j]->setMaterialTexture(1, drive->getTexture("../../media/detailmap3.jpg")); terrain[i][j]->setMaterialType(video::EMT_DETAIL_MAP); terrain[i][j]->scaleTexture(1.0f, 20.0f); selector[i][j] = maScene->createTerrainTriangleSelector(terrain[i][j], 0); terrain[i][j]->setTriangleSelector(selector[i][j]); selector[i][j]->drop(); anim[i][j] = maScene->createCollisionResponseAnimator ( selector[i][j], cam, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); cam->addAnimator(anim[i][j]); anim[i][j]->drop(); } } } posPrecJoueurX = posJoueurX; posPrecJoueurZ = posJoueurZ; }
Mon probleme, c'est que avec le remove, je dois avoir des grosses traces dans la mémoire étant donner que plus je change de map, plus mon programme prend de mémoire. Si j'utilise un drop, ca plante carrement.
Donc voila tout ca pour vous posez ces questions :
Comment arriver a faire qu'il ne reste plus rien des anciennes maps dans la mémoire ?
Quel est la différence entre remove, drop et drag ?
Et ca je comprend pas :
selector[i][j] = maScene->createTerrainTriangleSelector(terrain[i][j], 0); terrain[i][j]->setTriangleSelector(selector[i][j]); selector[i][j]->drop(); anim[i][j] = maScene->createCollisionResponseAnimator ( selector[i][j], cam, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); cam->addAnimator(anim[i][j]); anim[i][j]->drop();
On creer un selector et desuite apres on detruit l'objet avec drop. Donc comment on peut l'utilisé juste après ? Ca marche comment ce truc. Parce que en fait, ca marche ce que j'ai fait mais je sais pas comment. Du coup, j'ai aucune idée de comment je peux optimise ça.
Si vous avez tout lu, je vous remercie.
Dernière modification par Morrigan (30-01-2008 15:34:01)
Hors ligne
Salut. deja ca va bien à Albi ou quoi?
Je t'explique vite fait pour le drop :
En réalité le moteur travaille par copie pour certaines chose donc tu peux les virer après les avoir ajouté.
Comment savoir s'il copie ou non? a priori je pense qu'il copie a peu pres tout excepté les trucs trop volumineux (les Mesh, les MeshBuffers, les nodes, les images)mais essaie de mettre des ->drop() sur tous les types d'éléments et tu verra bien si tu leve de l'exception. Si tu en leve une c'est que l'élément était utile. Si tu utilise gdb, le debuger, tu auras une exception directement dans le code irrlicht apres cette opération au prochain appel de sceneManager->drawAll.
virtual IAnimatedMesh* irr::scene::ISceneManager::addTerrainMesh ( const c8 * meshname,
video::IImage * texture,video::IImage * heightmap,...)
)
Cette fonction par exemple travaille sur trois pointeurs. Il est peu probable qu'irrlicht les recopie (les éléments sont volumineux et font donc perdre de la place en mémoire et du temps).
Pour la premiere question tu utilises jusqu'alors :
terrain[i][j] = maScene->addTerrainSceneNode ( "../../media/heightmap2.bmp", 0, i+j, core::vector3df((float)(i+posJoueurX-1)*tailleCase, 0.f, (float)(j+posJoueurZ-1)*tailleCase)); terrain[i][j]->setScale(core::vector3df(40, 4.4f, 40)); terrain[i][j]->setMaterialFlag(video::EMF_LIGHTING, false); terrain[i][j]->setMaterialTexture(0, drive->getTexture(ntexTerrain)); terrain[i][j]->setMaterialTexture(1, drive->getTexture("../../media/detailmap3.jpg")); terrain[i][j]->setMaterialType(video::EMT_DETAIL_MAP); terrain[i][j]->scaleTexture(1.0f, 20.0f);
Je suspecte grandement cette fonction de défoncer ta mémoire en copiant "../../media/heightmap2.bmp" à l'infini. Cette chene represente un mesh, c'est à dire la géométrie exacte et relativement gourmande en mémoire de ton objet. Souvent Irrlicht se rappelle qu'il a deja chargé quelque chose en mémoire mais pour le terrain, étant donné qu'on en utilise un seul en général, il est probable que ce ne soit pas sauvegardé.
Donc je te conseillerai plutot de faire une save de ton taff et de changer ton algo pour utiliser:
// PHASE A : le loading (dans le main ou à l'initialisation) // A-1.1 : la plaine IAnimatedMesh *terrainPlaine = maScene->irr::scene::ISceneManager::addTerrainMesh("terrainPlaine", drive->getImage("../../media/plaine.jpg"), drive->getImage(""../../media/heightmapMaPlaine.bmp""), [... arguments par defaut ...]); // A- 1.2 & 1.3 & 1.4 & etc. ... // B instancier 9 meshs scene node > tableau MaCarte[3][3] // c'est du loading tu peux te permettre de perdre un peu de temps for(...) for(...) maCarte[i][j] = maScene->addAnimatedMeshSceneNode(terrainPlaine.....); (ou desertique ou ce que tu veux) // PHASE 2 : En cours de partie for... { for... { // trouver le type de terrain switch() { case 0: meshTerrain = terrainPlaine; break; case 1: ... } // changer le terrain : maCarte[i][j]->setMesh(meshTerrain); } }
Pour optimiser l'algo je suis sur que t'aura pas de probleme . Par contre j'ai juste un doute... Je suis pas
sur que les TerrainSceneNode soit pas plus optimisé pour ce genre d'affichage... C'est douteux mais si tes FPS prennent un tir tu sauras d'ou viens le probleme
Bon courage.
P.S. : le probleme s'appelle, pompeusement, le 'dynamic loading' et pour le réaliser bien te faudrait des cases suffisemment petites pour être chargées rapidement et pas encombrer la mémoire... mais ca gache le coté grandiose non?
Dernière modification par Aseiy (03-02-2008 02:20:19)
Hors ligne
Salut
Je voulais dire pour les drop qu'ils ne doivent être utiliser que quand la fonction qui le creer possède create dans son nom. Je ne suis pas sur a 100% et vous le saviez peut etre mais sa peut toujours servir de le rappeller(si quelqu'un était sur que j'ai dit une connerie ou pas il peut confirmer). Enfin dans tous les cas l'aide d'irrlicht indique dans la description de chaque fonction si l'objet doit être droper ou non.
Je trouve qu'une recherche dans l'api est quand même mieu que mettre des drop partout et voir quand l'ordi plante ou pas, enfin c mon avis mais je trouve que la méthode empirique a quand même des limites, en particulier dans ce cas.
enfin bon courage
dark calculator
P.S. Vu que ton perssonage devra se deplacer d'un bout à l'autre de la ca en instant je pense que tu pourrai ne charger et droper que les map qui change et pas tout decharger, recharger a chaque fois. Et puis ne vaut-il pas mieu tout charger en mémoire puis ensuite n'afficher que les maps qui t'intérésse par ce que refaire 9 heightmaps a chaque fois sa doit en manger du FPS.
Dernière modification par dark calculator (03-02-2008 12:28:30)
Hors ligne
Voila donc, j'ai appliquer ton code aseiy un peu modifier ^^. Note que getimage, ca existe pas ^^ J'ai utilisé createImageFromFile().
C'est niquel, c'est exactement ce que je voulais, ca marche sans ramer et sans pourri ma mémoire sur un long temps. Un grand merci. Je l'ai couplé a l'idée de dark calculator en chargant en mémoire mes maps. J'en est que quatre donc ca va ^^ On vera plus tard si je dois en ajouter beaucoup d'autre.
Sinon oui ca va niquel à albi ^^ Pourquoi xD ? T'habite dans le coin aussi ^^ ?
Dernière modification par Morrigan (04-02-2008 23:26:53)
Hors ligne
O LE BOULET! snif mec c'est moi qui t'ais fait jeter Ogre à la poubelle :p en tout cas c'est cool si ca marche. Bon courage pour votre jeu.
PS : si t'as besoin d'aide pour modeler tu as mon adresse à coté de mon pseudo. je commence à tater blender un peu (mais oublie les animations de personnages ok? )
PS2 : dsl pour getImage il me semblait l'avoir trouvé dans l'API du 1.4
PS3 : y a une contre partie je pense au niveau de la gestion des collisions. Celle des terrainSceneNode était peut être optimisée... enfin ca reste à tester.
Dernière modification par Aseiy (05-02-2008 00:21:14)
Hors ligne
Mouarf, fallait le préciser directement N'hesite pas a passer plus souvent et n'importe quand si ta rien a faire, ca serait cool. Pas besoin d'antho pour venir ^^
Pour le modelage, y a pas de soucis, je penserais a toi ^^ Mais pour l'instant, j'en utilise pas, je fais surtout la partie code avec des trucs trouvé sur internet. Ensuite quand sa marchera bien, on fera des bon modele ^^ Sinon comme je l'ai dis au dessus passe, on pourra en parler ou tu vera comment sa rend mon truc pourri xD
Hors ligne