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 ^^