#0 

08-12-2013 14:53:52

yata
Petit nouveau
Date d'inscription: 08-12-2013
Messages: 8

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)

Code:

// =========================================================================================
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.

Code:

// =========================================================================================
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

Code:

// =========================================================================================
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 ^^:

Code:

#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


#1 

08-12-2013 22:32:02

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

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.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#2 

13-12-2013 13:12:48

yata
Petit nouveau
Date d'inscription: 08-12-2013
Messages: 8

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
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
Analysé par
880 membres
1424 sujets
11113 messages
Dernier membre inscrit: mandrifidy
2 invités en ligne
Aucun membre connecté
RSS Feed