Bonjour a tous.
Je vien vers vous apres un bon paquet de recherche sur le net je me tourne vers vous.
Je suis entrain de develloper un client graphique pour un projet de fin d'annee. Je dois generer un terrain (jusqu'ici aucun probleme), y appliquer une texure qui inclus des cases (et c'est ici que ca se complique).
En effet le soucis et que quel que soit le scale que j'applique a ma texture (500x500), j'aurais toujours la texture coupe sur l'extremite Sud et Est du terrain (voir ci-dessous) :
Voici le code generant la map :
void Map::constructMap(float lenght, float width, irr::video::IVideoDriver *driver, irr::scene::ISceneManager *sceneManager)
{
Terrain_ = sceneManager->addTerrainSceneNode("./ressources/HeightMap.bmp", 0, -1, irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(lenght, 4.4f, width), irr::video::SColor ( 255, 255, 255, 255 ), 5, irr::scene::ETPS_17, 3);
Terrain_->setMaterialFlag(irr::video::EMF_LIGHTING, true);
Terrain_->setMaterialFlag(irr::video::EMF_ANISOTROPIC_FILTER , true);
Terrain_->setMaterialTexture(0, driver->getTexture("./ressources/terrdirtgrass.jpg"));
if (lenght >= 500)
Terrain_->scaleTexture(500, 500);
else
Terrain_->scaleTexture(lenght, lenght);
mapSizeX_ = lenght;
mapSizeZ_ = width;
}
Si quelqu'un aurait une piste ca serait d'une grande aide !
merci
Hors ligne
Mmmh je sais pas trop comment irrlicht gère en interne ses textures mais en principe une texture doit avoir une largeur et une hauteur en puissance de 2. En général quand ce n'est pas le cas, une texture plus grande au multiple de 2 près le plus proche est créée avec des data bidon sur les partie manquantes. Je comprend pas trop pourquoi ou comment irrlicht se démerde avec ta texture de 500 mais il me semble qu'elle a été stretchée sur 512 avant d'être clampée à 500 sur ton skinning...
Essaie de recommencer la même chose avec une texture de 512 par 512 pour être sûr de ce que j'avance ou sinon attend que quelqu'un qui connait bien le moteur réponde.
Dernière modification par Akabane87 (28-06-2012 19:03:38)
Hors ligne
En cherchant un peu apres mon poste je me rend compte que le probleme ne vien pas de mes textures mais du ITerrainSceneNode que je cree.
En effet lorsque je demande a mon programme de generer une map de 50x50 et que je deplace mon personnage en coordonnee 50,50 je me rend compte que le personnage est en dehors de la map.
J'en deduis donc que quelque chose cloche avec cette ligne lorsque je cree mon terrain :
edit : J'ai deja tester avec different format de texture (512x512, 256x256, etc..) mais merci
Dernière modification par 3wic (27-06-2012 17:41:08)
Hors ligne
Tu fais de la répétition de texture avec makePlanarTextureMapping (IMesh *mesh, f32 resolution=0.001f) et en jouant avec la résolution.
void Map::constructMap(float lenght, float width, irr::video::IVideoDriver *driver, irr::scene::ISceneManager *sceneManager) { Terrain_ = sceneManager->addTerrainSceneNode("./ressources/HeightMap.bmp", 0, -1, irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(lenght, 4.4f, width), irr::video::SColor ( 255, 255, 255, 255 ), 5, irr::scene::ETPS_17, 3); Terrain_->setMaterialFlag(irr::video::EMF_LIGHTING, true); Terrain_->setMaterialFlag(irr::video::EMF_ANISOTROPIC_FILTER , true); Terrain_->setMaterialTexture(0, driver->getTexture("./ressources/terrdirtgrass.jpg")); /// créé un mapping plat, il faut jouer avec "résolution_à_réglée" pour donner le nombre de répétition voulue sceneManager->getMeshManipulator()->makePlanarTextureMapping(Terrain_->getMesh(), résolution_à_réglée); if (lenght >= 500) Terrain_->scaleTexture(500, 500); else Terrain_->scaleTexture(lenght, lenght); mapSizeX_ = lenght; mapSizeZ_ = width; }
Hors ligne
Ca n'a pas l'air de fonctionner =/ ... Comme dit je pense que le probleme ne vien pas des textures mais de la generation du ITerrain ...
Hors ligne
Quelles valeurs as-tu utilisé pour makeplanar? Peux-tu montrer ta texture?
Edit : J'avais pas vu mais tu utilises scale texture! Utilise-la avec scale = 1.0f puis scale = 2.0f et compare le nombre de fois que ta texture est répétée. Et scale2 mets-la à 0.
virtual void scaleTexture (f32 scale=1.0f, f32 scale2=0.0f)=0
Scales the base texture, similar to makePlanarTextureMapping.
scale : The scaling amount. Values above 1.0 increase the number of time the texture is drawn on the terrain. Values below 0 will decrease the number of times the texture is drawn on the terrain. Using negative values will flip
the texture, as well as still scaling it.
scale2 : If set to 0 (default value), this will set the second texture coordinate set to the same values as in the first set. If this is another value than zero, it will scale the second texture coordinate set by this value.
Dernière modification par johnplayer (27-06-2012 19:54:04)
Hors ligne
Ok voici les resultats suivant les valeurs passe en scale :
1.0f :
2.0f :
Formule trouve se rapprochant le plus du resultat voulu (on veut une map de 10x10 on a du 9.5x9.5) avec le code en dessous :\
void Map::constructMap(float lenght, float width, irr::video::IVideoDriver *driver, irr::scene::ISceneManager *sceneManager)
{
Terrain_ = sceneManager->addTerrainSceneNode("./ressources/HeightMap.bmp", 0, -1, irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(lenght / 64 * 50, 0.0f, width / 64 * 50), irr::video::SColor ( 255, 255, 255, 255 ), 5, irr::scene::ETPS_17, 3);
Terrain_->setMaterialFlag(irr::video::EMF_LIGHTING, true);
Terrain_->setMaterialFlag(irr::video::EMF_ANISOTROPIC_FILTER , true);
Terrain_->setMaterialTexture(0, driver->getTexture("./ressources/terrdirtgrass.jpg"));
Terrain_->setPosition(irr::core::vector3df((lenght / 2) * 32 , 0, (width / 2) * 32));
Terrain_->scaleTexture((lenght * 64) / 50, (width * 64) / 50);
mapSizeX_ = lenght;
mapSizeZ_ = width;
}
On remarque que avec un scale de 1.0f la texture ne s'affiche pas au complet ... Donc ca engendre des soucis quelque soit le scale choisis ...
Voici la texture au complet :
Merci du temps que vous consacrez a mon probleme
Hors ligne
Premièrement une texture doit TOUJOURS avoir une dimension en puissance de 2. Donc dans ton cas, 512x512, En tatonnant j'ai trouvé un coef qui palie au problème :
ITerrainSceneNode *Terrain_ = smgr->addTerrainSceneNode("../MEDIAS/terrain-heightmap.bmp", 0, -1, vector3df(0.f, 0.f, 0.f), vector3df(0.f, 0.f, 0.f), vector3df(10.f, 0.0f, 10.f), SColor ( 255, 255, 255, 255 ), 5, ETPS_17, 3); Terrain_->setMaterialFlag(EMF_LIGHTING, false); //Terrain_->setMaterialFlag(EMF_ANISOTROPIC_FILTER , true); Terrain_->setMaterialTexture(0, driver->getTexture("../MEDIAS/herbe.jpg")); Terrain_->setPosition(vector3df(0 , 0, 0)); Terrain_->scaleTexture(1.063f*5, 0.0f);
1.063f est le coef que multiplie par le nombre de fois que tu veux répéter la texture.
Hors ligne
C'est quand même étrange la manière dont irrlicht gère les textures de taille non puissance de 2... A mon avis c'est un bug parce que au pire ça aurait du donner une texture fucked si c'était pas du tout pris en charge, ou alors ça aurait du scaler automatiquement la texture de manière à "cacher" les données manquantes de la texture. Là ce qu'il fait avec un scale de 1 m'échappe totalement vu que la puissance de 2 inférieure pour 500 est 256 et la supérieure est 512 ; ce qui ne correspond à aucun de ces 2 cas sur le screenshot de scale 1.
Donc pour moi il y a un bug à ce niveau dans irrlicht (scale inversé ?).
Hors ligne
Non le problème ne vient pas de la texture, j'ai essayé avec une texture en 512x512 mais ça fait pareil. Le problème réside certainement dans une approximation des coordonnées de texture données aux vertices du Terrain. Mais bon avec le coef ça devrait être résolu, il n'y a plus qu'à attendre les retours.
Dernière modification par johnplayer (28-06-2012 20:16:54)
Hors ligne
J'ai donc test avec ton coef et une repetition de 10 (voir code ci dessous) :
void Map::constructMap(float lenght, float width, irr::video::IVideoDriver *driver, irr::scene::ISceneManager *sceneManager)
{
Terrain_ = sceneManager->addTerrainSceneNode("./ressources/HeightMap.bmp", 0, -1, irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(lenght / 64 * 50, 0.0f, width / 64 * 50), irr::video::SColor ( 255, 255, 255, 255 ), 5, irr::scene::ETPS_17, 3);
Terrain_->setMaterialFlag(irr::video::EMF_LIGHTING, true);
Terrain_->setMaterialFlag(irr::video::EMF_ANISOTROPIC_FILTER , true);
Terrain_->setMaterialTexture(0, driver->getTexture("./ressources/terrdirtgrass.jpg"));
sceneManager->getMeshManipulator()->makePlanarTextureMapping(Terrain_->getMesh(), 500.0f);
Terrain_->setPosition(irr::core::vector3df((lenght / 2) * 32 , 0, (width / 2) * 32));
Terrain_->scaleTexture( 1.064f * lenght, 0.0f);
mapSizeX_ = lenght;
mapSizeZ_ = width;
}
et le resultat est le meme qu'en temps normal ... =/
je continue a chercher de mon cote, si quelqu'un a une illumination entre temps je suis preneur, merci en tous cas
Hors ligne
C'est 1.063f, pas 1.064f mais faut peut-être l'ajuster. Sinon pourquoi tu mets "vector3df(lenght / 64 * 50, 0.0f, width / 64 * 50)", je vois pas trop l'intérêt d'une telle formule. Mets "vector3df(lenght, high, width)" et utilise des valeurs multiple de 10 voir de 100, dans un float tu as de la marge ( ±1.5 × 10^(−45) à ±3.4 × 10^(38) ) alors ne reste pas autour de zéro. De plus ton terrain est tout petit d'où une erreur d'arrondi peut-être (si lenght = 10, le terrain fait 10/64*50 = 7.8125 unitéIrrlicht), ce qui veut dire que ta texture doit être dessinée dans même pas 1 unitéIrrlicht². Moi je prends 100 unitésIrrlicht pour 1 mètre, comme ça ça concorde aussi avec 3DSMax. Et rajoutes high dans tes paramètres pour avoir une hauteur réglable.
Pour le code que je t'ai donné j'obtiens ça :
terrain texturé correctement
Autrement, je ne vois pas d'autres moyens que de faire ton propre terrainscenenode à moins que tu modifies celui d'Irrlicht afin qu'il convienne à tes attentes. Mais bon, c'est lourd comme travail donc si un coef peut résoudre l'affaire...
Au fait, tu utilises quelle version d'Irrlicht parce que moi, j'utilise la 1.8?
Hors ligne
En gros tu veux que j'arrive a un truc comme ca ?
void Map::constructMap(float lenght, float width, irr::video::IVideoDriver *driver, irr::scene::ISceneManager *sceneManager)
{
Terrain_ = sceneManager->addTerrainSceneNode("./ressources/HeightMap.bmp", 0, -1, irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(0.f, 0.f, 0.f), irr::core::vector3df(lenght, 0.0f, width), irr::video::SColor ( 255, 255, 255, 255 ), 5, irr::scene::ETPS_17, 3);
Terrain_->setMaterialFlag(irr::video::EMF_LIGHTING, true);
Terrain_->setMaterialFlag(irr::video::EMF_ANISOTROPIC_FILTER , true);
Terrain_->setMaterialTexture(0, driver->getTexture("./ressources/terrdirtgrass.jpg"));
Terrain_->setPosition(irr::core::vector3df(0, 0 , 0));
Terrain_->scaleTexture( 1.063f * lenght, 0.0f);
mapSizeX_ = lenght;
mapSizeZ_ = width;
}
Edit : Je suis en version 1.7.2
Hors ligne
Voilà. Ca t'évite de faire des calculs inutiles est répétitifs. Par contre, il y a un truc qui m'étonne, tu n'utilises pas pas la hauteur dans vector3df(lenght, 0.0f, width), le scale Y est à zéro. Parce que si tu veux que ça reste plat, j'ai la solution à ton problème.
Hors ligne
Et bien j'arrive au meme resultat que mon premier post avec le code ci-dessus...
Je devrais essayer avec la version 1.8 peut etre ... Sinon j'y comprend plus rien ><
Hors ligne
J'ai le même problème que 3wic, la version 1.8 du svn ne donne pas plus de résultat
Je suis aussi preneur si quelqu'un a une solution ;-)
Hors ligne
Je ne comprends pas, je code sous la version 1.8 et j'ai le même problème que toi mais le coef résoud le problème. Tu as essayé de changer le coef (genre 1.7f, 1.8f...) pour voir si ça améliore le rendu? Et tu n'as pas répondu à ma question, tu n'utilises pas pas la hauteur dans vector3df(lenght, 0.0f, width), le scale Y est à zéro. Donc tu veux faire un plan texturé ou un terrain avec du relief?
Hors ligne
J'essayerais des que je booterais ma fedora
Non je n'utilise pas le coef Y car je veux un simple plan texturé
Hors ligne
Dans ce cas, il y a bien plus simple! Tu t'es vraiment compliqué la vie pour rien.
Pour créer un plan :
ImeshSceneNode *node_plan = scenemanager->addHillPlaneMesh(...);
addHillPlaneMesh
Pour le texturing et la répétition de texture :
sceneManager->getMeshManipulator()->makePlanarTextureMapping(node_plan->getMesh(), répétition);
makePlanarTextureMapping
Avec ça tu peux faire un plan avec le nombre de quads que tu veux, régler la taiile des quads et donc de ta map et bien sûr le texturé facilement. Bien sûr, pour la répétition, faut tester des valeurs en partant de celle par défaut. Il faut aussi appliquer le material sur le node_plan comme tu l'as fait pour le terrain avant.
Hors ligne
Je teste ca demain matin à la première heure thx pour le tuyaux
Hors ligne
Ca fonctionne niquel maintenant ! Merci beaucoup encore ! A tres bientot !
Hors ligne