Bonjour, je suis tout nouveau sur irrlicht.
Après quelques temps de découvertes, je me suis mis à l'écriture d'un ensemble de fonctions pour créer un mesh unique à partir de cubes (oui, la grande mode étant au voxel ... j'fait comme tout le monde :p
C'est la que tout bascule :s
... Je vous explique
J'ai d'abord écris une fonction pour créer un mesh de cube avec uniquement certaines faces (dans l'optique de ne pas créer celles invisibles pour mon gros mesh final)
// ========================================================================================= IMesh * createCubeMesh ( u16 size, bool FT, bool BK, bool LT, bool RT, bool DN, bool UP ,u32 offsetX ,u32 offsetY ,u32 offsetZ) // ========================================================================================= { // Création buffer SMeshBuffer* buffer = new SMeshBuffer(); // Initialisation n° vertex // FtRtDn:0 FtRtUp:1 FtLtDn:2 FtLtUp:3 BkRtDn:4 BkRtUp:5 BkLtDn:6 BkLtUp:7 u16 nV[] = { 0,1,2,3,4,5,6,7 }; // Déterminat. nb. vertex util. + Ajustement n° vertex en fct des faces à afficher u16 verticesCount = 0; if (FT||RT||DN) verticesCount++; else for (int i=0; i<8; i++) nV[i]--; if (FT||RT||UP) verticesCount++; else for (int i=1; i<8; i++) nV[i]--; if (FT||LT||DN) verticesCount++; else for (int i=2; i<8; i++) nV[i]--; if (FT||LT||UP) verticesCount++; else for (int i=3; i<8; i++) nV[i]--; if (BK||RT||DN) verticesCount++; else for (int i=4; i<8; i++) nV[i]--; if (BK||RT||UP) verticesCount++; else for (int i=5; i<8; i++) nV[i]--; if (BK||LT||DN) verticesCount++; else for (int i=6; i<8; i++) nV[i]--; if (BK||LT||UP) verticesCount++; else for (int i=7; i<8; i++) nV[i]--; // Définition des vertex utilisés pour chaque faces (Indices) u16 indicesFtFace[] = { nV[0], nV[1], nV[2], nV[1], nV[3], nV[2] }; u16 indicesBkFace[] = { nV[6], nV[5], nV[4], nV[6], nV[7], nV[5] }; u16 indicesLtFace[] = { nV[2], nV[3], nV[6], nV[3], nV[7], nV[6] }; u16 indicesRtFace[] = { nV[4], nV[1], nV[0], nV[4], nV[5], nV[1] }; u16 indicesDnFace[] = { nV[2], nV[4], nV[0], nV[2], nV[6], nV[4] }; u16 indicesUpFace[] = { nV[1], nV[5], nV[3], nV[5], nV[7], nV[3] }; // Calcul nb indices utilisés u16 indices[ (FT+BK+LT+RT+DN+UP)*6 ]; // Chargement des indices de chaques faces dans le tableau d'indices complet u16 indicesCount = 0; if (FT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesFtFace[i]; if (BK) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesBkFace[i]; if (LT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesLtFace[i]; if (RT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesRtFace[i]; if (DN) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesDnFace[i]; if (UP) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesUpFace[i]; // Affectation nb indices utilisés buffer->Indices.set_used( indicesCount ); for (u16 i=0; i<indicesCount; ++i) buffer->Indices[i] = indices[i]; // Allocation nb vertex utilisés buffer->Vertices.reallocate( verticesCount ); // Ajout vertex if ( FT || RT || DN ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 0+offsetY*size, 0+offsetZ*size, 0,0,0, Rouge, 0, 0) ); if ( FT || RT || UP ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 1+offsetY*size, 0+offsetZ*size, 0,0,0, Vert, 0, 0) ); if ( FT || LT || DN ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 0+offsetY*size, 0+offsetZ*size, 0,0,0, Bleu, 0, 0) ); if ( FT || LT || UP ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 1+offsetY*size, 0+offsetZ*size, 0,0,0, Cyan, 0, 0) ); if ( BK || RT || DN ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 0+offsetY*size, 1+offsetZ*size, 0,0,0, Jaune, 0, 0) ); if ( BK || RT || UP ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 1+offsetY*size, 1+offsetZ*size, 0,0,0, Magenta, 0, 0) ); if ( BK || LT || DN ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 0+offsetY*size, 1+offsetZ*size, 0,0,0, Noir, 0, 0) ); if ( BK || LT || UP ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 1+offsetY*size, 1+offsetZ*size, 0,0,0, Blanc, 0, 0) ); // Reset bounding box buffer->BoundingBox.reset(0,0,0); // Affectation point central + chgt taille mesh for (u16 i=0; i<verticesCount; ++i) { buffer->Vertices[i].Pos -= vector3df(0.5f, 0.5f, 0.5f); buffer->Vertices[i].Pos *= size; buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos); } // Création mesh + destruction buffer SMesh* mesh = new SMesh; mesh->addMeshBuffer(buffer); buffer->drop(); // Recalcul bounding box mesh->recalculateBoundingBox(); // Renvoi mesh return mesh; }
Puis une autre qui prend en parametres une "map de cubes" et apelle la premiere methode pour les générer et les stocker dans un tableau.
// ========================================================================================= array<IMesh*> createCubeMeshMap( vector<vector<vector<int> > > mapCube, u16 dimX, u16 dimY, u16 dimZ ) // ========================================================================================= { array<IMesh*> imeshArray; for (u16 PosX=0; PosX<dimX; PosX++) for (u16 PosY=0; PosY<dimY; PosY++) for (u16 PosZ=0; PosZ<dimZ; PosZ++) if ( mapCube[PosX][PosY][PosZ] ) { bool FT = true; bool BK = true; bool LT = true; bool RT = true; bool DN = true; bool UP = true; if (PosX!=dimX-1) if( mapCube[PosX+1] [PosY] [PosZ] ) LT=false; if (PosX!=0) if( mapCube[PosX-1] [PosY] [PosZ] ) RT=false; if (PosY!=dimY-1) if( mapCube[PosX] [PosY+1] [PosZ] ) UP=false; if (PosY!=0) if( mapCube[PosX] [PosY-1] [PosZ] ) DN=false; if (PosZ!=dimZ-1) if( mapCube[PosX] [PosY] [PosZ+1] ) BK=false; if (PosZ!=0) if( mapCube[PosX] [PosY] [PosZ-1] ) FT=false; if (FT || BK || LT || RT || DN || UP) { IMesh* mesh = createCubeMesh ( 1, FT, BK, LT, RT, DN, UP, PosX, PosY, PosZ ); imeshArray.push_back(mesh); } } return imeshArray; }
Ensuite une dernière qui combine tout ce petit monde (tableau) dans un gros mesh
// ========================================================================================= u16 combineMeshes( array<IMesh*> imeshs ) // ========================================================================================= { voxelMesh = new SMesh; for (u32 i=0; i<imeshs.size(); i++) { for (u32 j=0; j<imeshs[i]->getMeshBufferCount(); j++) { IMeshBuffer* currentMeshBuffer = imeshs[i]->getMeshBuffer(j); voxelMesh->addMeshBuffer( currentMeshBuffer ); } } voxelMesh->recalculateBoundingBox(); return 1; }
Du coup, maintenant que je vous ai planté le décor j'peux pour exprimer mon problème:
Quand j’appelle ces fonctions j'ai comportement "étrange"
- Si j’appelle avec un tableau plein de 20x20x20 cubes, j'ai en résultat 4800 vertex
=> 20x20 (faces de petits cubes) x6(faces du gros cube) x2(vertex par petites faces)
Mais seulement 60fps
- Si j'appelle avec un tableau ou il y à 1/15 des cubes (aléatoire), j'ai en résultat plus de vertex (~=6000).
Evidement car même si il y à moins de petits cubes mais aussi moins de faces "collées les unes aux autres" qui sont supprimées dans le cas du cube plein.
Mais ici, c'est la ou ca deviens drole ... j'ai plus de 200fps
La preuve en images:
J'ai du faire une connerie ... mais quoi :s
Je vous remercie d'avance pour votre aide.
Et je m'excuse d'avance pour le code dégueulasse sans classes, etc (ca viendra après, quand ca marchera à peu près :p)
Tout le code, pour ceux qui veulent essayer de l’exécuter ^^:
#include <cstdlib> #include <ctime> #include <vector> #include <irrlicht.h> using namespace std; using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif ISceneManager* smgr; IVideoDriver* driver; IrrlichtDevice* device; int lastFPS = -1; SColor Rouge (255, 255, 0, 0); SColor Vert (255, 0, 255, 0); SColor Bleu (255, 0, 0, 255); SColor Cyan (255, 0, 255, 255); SColor Jaune (255, 255, 255, 0); SColor Magenta (255, 255, 0, 255); SColor Noir (255, 0, 0, 0); SColor Blanc (255, 255, 255, 255); int rand_a_b(int a, int b){ return rand()%(b-a) +a; } void DisplayInfos (void) { int fps = driver->getFPS(); u32 nbVertex = driver->getPrimitiveCountDrawn() - 12; // - skybox if (lastFPS != fps) { stringw tmp(L"["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; tmp += L" vertex: "; tmp += nbVertex; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } SMesh* voxelMesh; // ========================================================================================= IMesh * createCubeMesh ( u16 size, bool FT, bool BK, bool LT, bool RT, bool DN, bool UP ,u32 offsetX ,u32 offsetY ,u32 offsetZ) // ========================================================================================= { // Création buffer SMeshBuffer* buffer = new SMeshBuffer(); // Initialisation n° vertex // FtRtDn:0 FtRtUp:1 FtLtDn:2 FtLtUp:3 BkRtDn:4 BkRtUp:5 BkLtDn:6 BkLtUp:7 u16 nV[] = { 0,1,2,3,4,5,6,7 }; // Déterminat. nb. vertex util. + Ajustement n° vertex en fct des faces à afficher u16 verticesCount = 0; if (FT||RT||DN) verticesCount++; else for (int i=0; i<8; i++) nV[i]--; if (FT||RT||UP) verticesCount++; else for (int i=1; i<8; i++) nV[i]--; if (FT||LT||DN) verticesCount++; else for (int i=2; i<8; i++) nV[i]--; if (FT||LT||UP) verticesCount++; else for (int i=3; i<8; i++) nV[i]--; if (BK||RT||DN) verticesCount++; else for (int i=4; i<8; i++) nV[i]--; if (BK||RT||UP) verticesCount++; else for (int i=5; i<8; i++) nV[i]--; if (BK||LT||DN) verticesCount++; else for (int i=6; i<8; i++) nV[i]--; if (BK||LT||UP) verticesCount++; else for (int i=7; i<8; i++) nV[i]--; // Définition des vertex utilisés pour chaque faces (Indices) u16 indicesFtFace[] = { nV[0], nV[1], nV[2], nV[1], nV[3], nV[2] }; u16 indicesBkFace[] = { nV[6], nV[5], nV[4], nV[6], nV[7], nV[5] }; u16 indicesLtFace[] = { nV[2], nV[3], nV[6], nV[3], nV[7], nV[6] }; u16 indicesRtFace[] = { nV[4], nV[1], nV[0], nV[4], nV[5], nV[1] }; u16 indicesDnFace[] = { nV[2], nV[4], nV[0], nV[2], nV[6], nV[4] }; u16 indicesUpFace[] = { nV[1], nV[5], nV[3], nV[5], nV[7], nV[3] }; // Calcul nb indices utilisés u16 indices[ (FT+BK+LT+RT+DN+UP)*6 ]; // Chargement des indices de chaques faces dans le tableau d'indices complet u16 indicesCount = 0; if (FT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesFtFace[i]; if (BK) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesBkFace[i]; if (LT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesLtFace[i]; if (RT) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesRtFace[i]; if (DN) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesDnFace[i]; if (UP) for (u16 i=0; i<6; i++) indices[indicesCount++] = indicesUpFace[i]; // Affectation nb indices utilisés buffer->Indices.set_used( indicesCount ); for (u16 i=0; i<indicesCount; ++i) buffer->Indices[i] = indices[i]; // Allocation nb vertex utilisés buffer->Vertices.reallocate( verticesCount ); // Ajout vertex if ( FT || RT || DN ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 0+offsetY*size, 0+offsetZ*size, 0,0,0, Rouge, 0, 0) ); if ( FT || RT || UP ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 1+offsetY*size, 0+offsetZ*size, 0,0,0, Vert, 0, 0) ); if ( FT || LT || DN ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 0+offsetY*size, 0+offsetZ*size, 0,0,0, Bleu, 0, 0) ); if ( FT || LT || UP ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 1+offsetY*size, 0+offsetZ*size, 0,0,0, Cyan, 0, 0) ); if ( BK || RT || DN ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 0+offsetY*size, 1+offsetZ*size, 0,0,0, Jaune, 0, 0) ); if ( BK || RT || UP ) buffer->Vertices.push_back( S3DVertex( 0+offsetX*size, 1+offsetY*size, 1+offsetZ*size, 0,0,0, Magenta, 0, 0) ); if ( BK || LT || DN ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 0+offsetY*size, 1+offsetZ*size, 0,0,0, Noir, 0, 0) ); if ( BK || LT || UP ) buffer->Vertices.push_back( S3DVertex( 1+offsetX*size, 1+offsetY*size, 1+offsetZ*size, 0,0,0, Blanc, 0, 0) ); // Reset bounding box buffer->BoundingBox.reset(0,0,0); // Affectation point central + chgt taille mesh for (u16 i=0; i<verticesCount; ++i) { buffer->Vertices[i].Pos -= vector3df(0.5f, 0.5f, 0.5f); buffer->Vertices[i].Pos *= size; buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos); } // Création mesh + destruction buffer SMesh* mesh = new SMesh; mesh->addMeshBuffer(buffer); buffer->drop(); // Recalcul bounding box mesh->recalculateBoundingBox(); // Renvoi mesh return mesh; } // ========================================================================================= u16 combineMeshes( array<IMesh*> imeshs ) // ========================================================================================= { voxelMesh = new SMesh; for (u32 i=0; i<imeshs.size(); i++) { for (u32 j=0; j<imeshs[i]->getMeshBufferCount(); j++) { IMeshBuffer* currentMeshBuffer = imeshs[i]->getMeshBuffer(j); voxelMesh->addMeshBuffer( currentMeshBuffer ); } } voxelMesh->recalculateBoundingBox(); return 1; } // ========================================================================================= array<IMesh*> createCubeMeshMap( vector<vector<vector<int> > > mapCube, u16 dimX, u16 dimY, u16 dimZ ) // ========================================================================================= { array<IMesh*> imeshArray; for (u16 PosX=0; PosX<dimX; PosX++) for (u16 PosY=0; PosY<dimY; PosY++) for (u16 PosZ=0; PosZ<dimZ; PosZ++) if ( mapCube[PosX][PosY][PosZ] ) { bool FT = true; bool BK = true; bool LT = true; bool RT = true; bool DN = true; bool UP = true; if (PosX!=dimX-1) if( mapCube[PosX+1] [PosY] [PosZ] ) LT=false; if (PosX!=0) if( mapCube[PosX-1] [PosY] [PosZ] ) RT=false; if (PosY!=dimY-1) if( mapCube[PosX] [PosY+1] [PosZ] ) UP=false; if (PosY!=0) if( mapCube[PosX] [PosY-1] [PosZ] ) DN=false; if (PosZ!=dimZ-1) if( mapCube[PosX] [PosY] [PosZ+1] ) BK=false; if (PosZ!=0) if( mapCube[PosX] [PosY] [PosZ-1] ) FT=false; if (FT || BK || LT || RT || DN || UP) { IMesh* mesh = createCubeMesh ( 1, FT, BK, LT, RT, DN, UP, PosX, PosY, PosZ ); imeshArray.push_back(mesh); } } return imeshArray; } // ========================================================================================= IMesh * createVoxelMesh( vector<vector<vector<int> > > mapCube, u16 dimX, u16 dimY, u16 dimZ ) // ========================================================================================= { combineMeshes ( createCubeMeshMap ( mapCube, dimX, dimY, dimZ ) ); return voxelMesh; } // ========================================================================================= int main() // ========================================================================================= { // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters SIrrlichtCreationParameters params; params.DriverType=EDT_OPENGL; params.WindowSize=dimension2d<u32>(640, 480); device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. driver = device->getVideoDriver(); smgr = device->getSceneManager(); // add camera ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,0.1f); camera->setPosition(vector3df(0,0,-20)); // disable mouse cursor device->getCursorControl()->setVisible(false); driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/skybox-up.jpg"), driver->getTexture("../../media/skybox-down.jpg"), driver->getTexture("../../media/skybox-left.jpg"), driver->getTexture("../../media/skybox-right.jpg"), driver->getTexture("../../media/skybox-front.jpg"), driver->getTexture("../../media/skybox-back.jpg")); driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true); skybox->setVisible(true); u16 MapSizeX = 20; u16 MapSizeY = 20; u16 MapSizeZ = 20; vector<vector<vector<int> > > cubeMap (MapSizeX, vector<vector<int> >(MapSizeY, vector <int>(MapSizeZ) ) ); srand(time(NULL)); for (u16 PosX=0; PosX<MapSizeX; PosX++) for (u16 PosY=0; PosY<MapSizeY; PosY++) for (u16 PosZ=0; PosZ<MapSizeZ; PosZ++) cubeMap[PosX][PosY][PosZ] = 1; // !rand_a_b( 0, 15 ); <==================== Ici pour le cube "éclaté" IMesh* mesh = createVoxelMesh( cubeMap, MapSizeX, MapSizeY, MapSizeZ ); ImeshSceneNode* node = smgr->addMeshSceneNode(mesh); node->setMaterialFlag(EMF_LIGHTING, false); while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0 ); smgr->drawAll(); driver->endScene(); DisplayInfos(); } device->drop(); return 0; }
EDIT: Oups, j'me suis trompé de forum quand j'ai posté.
Si un admin pouvais déplacer dans "http://irrlicht-fr.org/viewforum.php?id=5003" ce serais merveilleux ^^
Dernière modification par yata (08-12-2013 19:12:51)
Hors ligne
La différence de fps est normale. Ce qui compte ce n'est pas les vertices affichés, ce sont les triangles.
Tu as moins de vertices car ils sont partagés avec 4 triangles pour beaucoup. T'as carte graphique affiche des triangles, d'ailleurs dans les caractéristiques techniques d'un GPU, on remarque 2 caractéristiques importantes :
- la capacité de calcul en triangles/secondes;
- la capacité de calcul en texels/secondes.
En plus, il y a le culling qui agit : le backface culling principalement et d'autres techniques (occlusion culling...).
En tout cas, diminuer le nombre de triangles augmente les FPS. Tu peux aussi t'aider des VBOs si ta carte les supportent.
Dans le premiers cas, tu as 20x20x20 cubes en vue isométrique ça donne : 20x20x2 triangles pour une face du "gros cube" donc 20x20x2x3 pour la vue soit 2400 triangles.
Dans le deuxième cas, il y en a clairement moins, d'où le grand nombre de fps.
Hors ligne
salut john,
merci pour tes explications.
j'ai finalement trouvé la source de mon problème.
en fait le soucis est que pour chaque cubes, je créais un mesh pour ensuite tous les combiner (ce qui semble consommer gros).
maintenant, je crée un unique buffer dans lequel je stocke tous mes vertices et indices.
Hors ligne
Options | Liens officiels | Caractéristiques | Statistiques | Communauté |
---|---|---|---|---|
Corrections |
|
xhtml 1.0 css 2.1 Propulsé par FluxBB Traduit par FluxBB.fr |
882 membres 1429 sujets 11119 messages |
Dernier membre inscrit: LiseBuisson96 40 invités en ligne Aucun membre connecté RSS Feed |