#0 

23-11-2008 20:53:58

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Il y a quelque chose qui me chagrinne pas mal en ce moment. Dans l'optique d'un prochain projet, je commence
à coder quelques fonctions bien utiles dont je disposais sous DM3D.
Cherchant à faire une fonction de test de visibilité toute bête d'un mesh, j'ai donc employé les fonctions
natives d'Irrlicht, mais là, je suis un peu bloqué car cela ne fonctionne pas vraiment, tout du moins comme
je l'attendais... sad

Le résultat est toujours TRUE, même quand on sort de la zone visible. Il faut vraiment presque être
derriere la camera pour enfin passer à FALSE.
Bug ou mauvaise utilisation des fonctions d'Irrlicht ?


Voici mon code de test:

Code:

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
#ifdef _IRR_WINDOWS_
    #pragma comment(lib, "Irrlicht.lib")
#endif

//    données globales
bool _bExit = false;



int main()
{
    // choix driver
    video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
    

    printf("Please select the driver you want for this example:\n"\
        " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
        " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
        " (f) NullDevice\n (otherKey) exit\n\n");
        
    char i;
    std::cin >> i;

    switch(i)
    {
        case 'a': driverType = video::EDT_DIRECT3D9;break;
        case 'b': driverType = video::EDT_DIRECT3D8;break;
        case 'c': driverType = video::EDT_OPENGL;   break;
        case 'd': driverType = video::EDT_SOFTWARE; break;
        case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': driverType = video::EDT_NULL;     break;
        default: return 0;
    }

    IrrlichtDevice *device = createDevice( driverType, 
                                            dimension2d<s32>(640, 480), 
                                            32,
                                            false, 
                                            false, 
                                            true, 
                                            NULL);
    
    IVideoDriver* driver        = device->getVideoDriver();
    ISceneManager* scenegraph    = device->getSceneManager();

        
    // cube 1
    ISceneNode* cube1 = scenegraph->addCubeSceneNode(2.0f, scenegraph->getRootSceneNode());
    //cube1->setPosition( vector3df(10,0,0) );

    // définition camera.
    SKeyMap keyMap[4] = 
    {
        {EKA_MOVE_FORWARD,    KEY_UP},
        {EKA_MOVE_BACKWARD,    KEY_DOWN},
        {EKA_STRAFE_LEFT,    KEY_LEFT},
        {EKA_STRAFE_RIGHT,    KEY_RIGHT},
    };
    ICameraSceneNode* cam = scenegraph->addCameraSceneNodeFPS( scenegraph->getRootSceneNode() , 100.0f, 50.0f, -1, keyMap, 4);
    cam->setPosition(core::vector3df(0,1,-10));


    // boucle principale
    int lastFPS = -1;

    while(device->run() & !_bExit)
    {
        driver->beginScene(true, true, SColor(255,100,101,140));
            scenegraph->drawAll();
        driver->endScene();
        //============================
        // frustum test
        //============================
        const scene::SViewFrustum* frustum = cam->getViewFrustum();
        bool FrustumCode = frustum->getBoundingBox().intersectsWithBox(cube1->getBoundingBox());

        // info des information temps réél
        int fps = driver->getFPS();
        if (lastFPS != fps)
        {
            core::stringw str = L"Test visibilité: ";
            str += FrustumCode;
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
        }
    }
    device->drop();
    return 0;
}

Force et sagesse...

Hors ligne


#1 

24-11-2008 00:10:38

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

const scene::SViewFrustum* frustum = smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera, 0, false);
bool FrustumCode = frustum->getBoundingBox().intersectsWithBox(cube1->getBoundingBox());

voila normalement sa devrai marcher wink

Dernière modification par pspmy (24-11-2008 00:14:09)

Hors ligne


#2 

24-11-2008 07:02:18

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

pspmy :

const scene::SViewFrustum* frustum = smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera, 0, false);
bool FrustumCode = frustum->getBoundingBox().intersectsWithBox(cube1->getBoundingBox());

voila normalement sa devrai marcher wink


Non d'un lutin, fallais la trouver celle-la... je vais voir cela, Merci pspmy wink

[EDIT]
....mais heu non.

smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera, 0, false);  retourne visiblement un ISceneNode.
Et même en faisant cela, ça ne fonctionne pas, pire même ça plante au bout de quelques seconde.
Hmmm, plus qu'a me mettre à creuser le truc ce soir


Force et sagesse...

Hors ligne


#3 

24-11-2008 10:50:02

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

ptetre

Code:

ISceneNode* cube1 = addCubeSceneNode(2.0f, scenegraph->getRootSceneNode(), 1);
while (.....)
//=============
ISceneNode *wievNode = smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera, 0, false);
if (wievNode->getID() == cube1->getID()))
{
//ton cube et visible
}

mais dans ce qua il fo donner des id ou des nom a tes node

Dernière modification par pspmy (24-11-2008 10:50:33)

Hors ligne


#4 

24-11-2008 18:36:41

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Hmm, pas vraiment convaincu par la méthode, alors qu'un simple test de Frustum culling tout bête suffit. J'vais me retrouver de nouveau à coder mes
propres fonctions...
Je vais voir cela dans la soirée.


Force et sagesse...

Hors ligne


#5 

24-11-2008 18:40:59

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

dsl

Hors ligne


#6 

25-11-2008 21:46:59

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Bon, j'ai donc pris le temps ce soir de re-coder ma fonction DM3D qui était basée sur du code DX9c pour pouvoir tourner avec
Irrlicht. Cela semble bien fonctionner, je vais l'éprouver pour pouvoir l'intégrer dans mon moteur de terrain.

Le code se décompose en 4 parties:
1- une petite classe Plane, pour me faciliter les choses, quelques lignes pas bien sorcier.
2- UpdateCullInfo: partie qui permet d'établir les 6 plans du cube de polygone de vue.
3- _isVisible: fonction d'interogation pour savoir si un mesh (ou plutot son boundingBox) est visible ou non.
4- corps du programme de test (identique au code ci-dessus du message initial.


Voilà, voici donc le code complet, fonctions et corps de test.

Code:

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
#ifdef _IRR_WINDOWS_
    #pragma comment(lib, "Irrlicht.lib")
#endif

//    données globales
bool _bExit = false;
ISceneManager* scenegraph;



//-----------------------------------------------------------------------------
// Name: Plane class
// Desc: petite classe plane personnalisée pour pour ce codage.
//-----------------------------------------------------------------------------
class Plane
{
public:
    float a;
    float b;
    float c;
    float d;

    Plane():  a(0),b(0),c(0),d(0) {}
    Plane(float aa, float bb, float cc, float dd): a(aa), b(bb), c(cc), d(dd){}
    Plane operator-(const Plane& other) const { return Plane(a - other.a, b - other.b, c - other.c, d - other.d); }
    Plane operator+(const Plane& other) const { return Plane(a + other.a, b + other.b, c + other.c, d + other.d); }
    float operator[](unsigned i) const     { switch(i)    {case 0: return a; case 1: return b; case 2: return c; case 3: return d;default: return 0;    }    }
    void Normalize() { float m;    m = sqrt( a*a + b*b + c*c + d*d );    a = a / m;    b = b / m;    c = c/ m;    d = d /m;    }
    float DotCoord(float *V) {    return (a * V[0] + b * V[1] + c * V[2] + d);    }
};
// donnée globale, ou autre en fonction des besoins
Plane    mFrustumPlane[6];
//-----------------------------------------------------------------------------
// Name: UpdateCullInfo()
// Desc: Update Cull Info, attention  avec la camera courante
//-----------------------------------------------------------------------------
void UpdateCullInfo()
{
    scene::ICameraSceneNode* cam = scenegraph->getActiveCamera();
    core::matrix4 pMatProj, pMatView;
    pMatProj = cam->getProjectionMatrix();
    pMatView = cam->getViewMatrix();
    core::matrix4 VPI = pMatProj * pMatView;

    Plane col0(VPI(0,0), VPI(1,0), VPI(2,0), VPI(3,0));
    Plane col1(VPI(0,1), VPI(1,1), VPI(2,1), VPI(3,1));
    Plane col2(VPI(0,2), VPI(1,2), VPI(2,2), VPI(3,2));
    Plane col3(VPI(0,3), VPI(1,3), VPI(2,3), VPI(3,3));
    // construit les 6 plane du Frustum view
    mFrustumPlane[0] = col2;          // near
    mFrustumPlane[1] = (col3 - col2); // far
    mFrustumPlane[2] = (col3 + col0); // left
    mFrustumPlane[3] = (col3 - col0); // right
    mFrustumPlane[4] = (col3 - col1); // top
    mFrustumPlane[5] = (col3 + col1); // bottom
    for(int i = 0; i < 6; i++)        
    {
        mFrustumPlane[i].Normalize();
    }
}
//-----------------------------------------------------------------------------
// Name: _isVisible()
// Desc: test de visibilité d'un mesh
//-----------------------------------------------------------------------------
int _isVisible(const core::aabbox3d<f32>& box)
{
    float P[3];
    float Q[3];
    // la classe vector3d ne possédant pas d'opérateur de surcharge []....
    float Min[3];    memcpy( Min, &box.MinEdge.X, sizeof(float)*3);
    float Max[3];    memcpy( Max, &box.MaxEdge.X, sizeof(float)*3);
    for(int i = 0; i < 6; ++i)
    {
        // pour chaque coordonnées x, y, z...
        for(int j = 0; j < 3; ++j)
        {
            // etabli le poiont PQ dans la même direction que le plan normal sur l'axe.
            if( mFrustumPlane[i][j] >= 0.0f )
            {
                P[j] = Min[j];
                Q[j] = Max[j];
            }
            else 
            {
                P[j] = Max[j];
                Q[j] = Min[j];
            }
        }
        if( mFrustumPlane[i].DotCoord(Q) < 0.0f  ) // en dehor, exit procedure
            return false;
    }
    return true;
}




int main()
{
    // choix driver
    video::E_DRIVER_TYPE driverType;
    
    printf("Please select the driver you want for this example:\n"\
        " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
        " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
        " (f) NullDevice\n (otherKey) exit\n\n");
        
    char i;
    std::cin >> i;

    switch(i)
    {
        case 'a': driverType = video::EDT_DIRECT3D9;break;
        case 'b': driverType = video::EDT_DIRECT3D8;break;
        case 'c': driverType = video::EDT_OPENGL;   break;
        case 'd': driverType = video::EDT_SOFTWARE; break;
        case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': driverType = video::EDT_NULL;     break;
        default: return 0;
    }
    IrrlichtDevice *device = createDevice( driverType, 
                                            dimension2d<s32>(640, 480), 
                                            32,
                                            false, 
                                            false, 
                                            true, 
                                            NULL);
    
    IVideoDriver* driver    = device->getVideoDriver();
    scenegraph                = device->getSceneManager();

        
    // cube 1
    ISceneNode* cube1 = scenegraph->addCubeSceneNode(2.0f, scenegraph->getRootSceneNode());
    cube1->setPosition( vector3df(10,0,0) );


    // définition camera.
    SKeyMap keyMap[4] = 
    {
        {EKA_MOVE_FORWARD,    KEY_UP},
        {EKA_MOVE_BACKWARD,    KEY_DOWN},
        {EKA_STRAFE_LEFT,    KEY_LEFT},
        {EKA_STRAFE_RIGHT,    KEY_RIGHT},
    };
    ICameraSceneNode* cam = scenegraph->addCameraSceneNodeFPS( scenegraph->getRootSceneNode() , 100.0f, 50.0f, -1, keyMap, 4);
    cam->setPosition(core::vector3df(0,1,-10));


    // boucle principale
    int lastFPS = -1;

    while(device->run() & !_bExit)
    {
        driver->beginScene(true, true, SColor(255,100,101,140));
            scenegraph->drawAll();
        driver->endScene();
        //============================
        // mise a jour frustum
        //============================
        UpdateCullInfo();
        //============================
        // frustum test
        //============================
        // récupération du boundingBox, puis transformation pour faire le test
        core::aabbox3d<f32> box = cube1->getBoundingBox();
        core::matrix4 matMesh = cube1->getAbsoluteTransformation();
        matMesh.transformBoxEx(box);
        int FrustumCode = _isVisible(box);


        // des information temps réél
        int fps = driver->getFPS();
        core::stringw str = L"Test visibilité: ";
        str += FrustumCode;
        device->setWindowCaption(str.c_str());
        lastFPS = fps;
    }
    device->drop();
    return 0;
}

Force et sagesse...

Hors ligne


#7 

25-11-2008 23:06:12

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

bravo ^^

Hors ligne


#8 

26-11-2008 18:45:35

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Merci, je vais mettre à jour donc mon code de terrain,  je posterais la mise à jour  ici http://forum.irrlicht.fr/viewtopic.php?id=533
quand cela sera fait


Force et sagesse...

Hors ligne


#9 

26-11-2008 18:52:16

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

ok tu menvera un mail ok ?

Hors ligne


#10 

26-11-2008 19:03:15

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

pspmy :

ok tu menvera un mail ok ?


Pas de soucis wink


Force et sagesse...

Hors ligne


#11 

26-11-2008 20:46:40

hardcpp
Abonné
Date d'inscription: 26-04-2008
Messages: 229

big_smile

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
881 membres
1427 sujets
11117 messages
Dernier membre inscrit: Bidule
20 invités en ligne
Aucun membre connecté
RSS Feed