Hello sa fait un baille que j'ai pas poster une ressource x), donc j'ai mit au point mon système de frustrum culling en me basant sur celui de tmyke concrètement cela sert a masquer les node non visible et donc de gagner du frame rate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | ///-------------------------------------------------------------------------------- /// @file FrustrumCulling.hpp /// @brief Technique de culling par masquage d'objet non visible ///-------------------------------------------------------------------------------- #ifndef __FRUSTRUMCULLING_HPP_INCLUDED__ #define __FRUSTRUMCULLING_HPP_INCLUDED__ #include "Plane.hpp" #include <irrlicht.h> namespace App { namespace Engine { namespace Culling { ///-------------------------------------------------------------------------------- /// Technique de culling par masquage d'objet non visible ///-------------------------------------------------------------------------------- class FrustrumCulling { public: ///-------------------------------------------------------------------------------- /// Constructeur /// /// @param _SceneManager : Gestionnaire de scene ///-------------------------------------------------------------------------------- FrustrumCulling(irr::scene::ISceneManager * _SceneManager); ///-------------------------------------------------------------------------------- /// Destructeur ///-------------------------------------------------------------------------------- ~FrustrumCulling(); ///-------------------------------------------------------------------------------- /// Pour crée le culling ///-------------------------------------------------------------------------------- void Create(); ///-------------------------------------------------------------------------------- /// Pour recrée le culling ///-------------------------------------------------------------------------------- void Recreate(); ///-------------------------------------------------------------------------------- /// Pour mettre a jour le culling ///-------------------------------------------------------------------------------- void Update(); ///-------------------------------------------------------------------------------- /// Pour ajouter un scene node /// /// @param _SceneNode : Pointeur vers le scene node ///-------------------------------------------------------------------------------- void AddSceneNode(const irr::scene::ISceneNode * _SceneNode); ///-------------------------------------------------------------------------------- /// Pour supprimer un scene node /// /// @param _SceneNode : Pointeur vers le scene node ///-------------------------------------------------------------------------------- void RemoveSceneNode(const irr::scene::ISceneNode * _SceneNode); ///-------------------------------------------------------------------------------- /// Pour tester si une box et visible /// /// @param _Box : Box a tester ///-------------------------------------------------------------------------------- bool IsVisible(const irr::core::aabbox3d<irr::f32>& box); private: ///-------------------------------------------------------------------------------- /// Gestionnaire de scene ///-------------------------------------------------------------------------------- irr::scene::ISceneManager * m_SceneManager; ///-------------------------------------------------------------------------------- /// Pour stocker les nodes ///-------------------------------------------------------------------------------- irr::core::array<irr::scene::ISceneNode *> m_Nodes; ///-------------------------------------------------------------------------------- /// Pour tester si un node est visible ///-------------------------------------------------------------------------------- App::core::Plane m_FrustumPlane[6]; ///-------------------------------------------------------------------------------- /// Dernier / derniere position et cible de la camera ///-------------------------------------------------------------------------------- irr::core::vector3df m_LastPosition, m_LastTarget; }; } // Culling } // Engine } // App #endif // __FRUSTRUMCULLING_HPP_INCLUDED__ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | ///-------------------------------------------------------------------------------- /// @file FrustrumCulling.cpp /// @brief Technique de culling par masquage d'objet non visible ///-------------------------------------------------------------------------------- #include "FrustrumCulling.hpp" namespace App { namespace Engine { namespace Culling { ///-------------------------------------------------------------------------------- /// Constructeur /// /// @param _SceneManager : Gestionnaire de scene ///-------------------------------------------------------------------------------- FrustrumCulling::FrustrumCulling(irr::scene::ISceneManager * _SceneManager) : m_SceneManager(_SceneManager) { } ///-------------------------------------------------------------------------------- /// Destructeur ///-------------------------------------------------------------------------------- FrustrumCulling::~FrustrumCulling() { } ///-------------------------------------------------------------------------------- /// Pour crée le culling ///-------------------------------------------------------------------------------- void FrustrumCulling::Create() { m_SceneManager->getSceneNodesFromType(irr::scene::ESNT_ANY, m_Nodes); for (irr::u32 __I = 0 ; __I < m_Nodes.size() ; __I++) m_Nodes[__I]->setAutomaticCulling(irr::scene::EAC_OFF); } ///-------------------------------------------------------------------------------- /// Pour recrée le culling ///-------------------------------------------------------------------------------- void FrustrumCulling::Recreate() { m_Nodes.clear(); Create(); } ///-------------------------------------------------------------------------------- /// Pour mettre a jour le culling ///-------------------------------------------------------------------------------- void FrustrumCulling::Update() { if (m_LastPosition == m_SceneManager->getActiveCamera()->getAbsolutePosition() && m_LastTarget == m_SceneManager->getActiveCamera()->getTarget()) return; irr::core::matrix4 __MatrixProj, __MatrixView; __MatrixProj = m_SceneManager->getActiveCamera()->getProjectionMatrix(); __MatrixView = m_SceneManager->getActiveCamera()->getViewMatrix(); irr::core::matrix4 __VPI = __MatrixProj * __MatrixView; App::core::Plane __col0(__VPI(0,0), __VPI(1,0), __VPI(2,0), __VPI(3,0)); App::core::Plane __col1(__VPI(0,1), __VPI(1,1), __VPI(2,1), __VPI(3,1)); App::core::Plane __col2(__VPI(0,2), __VPI(1,2), __VPI(2,2), __VPI(3,2)); App::core::Plane __col3(__VPI(0,3), __VPI(1,3), __VPI(2,3), __VPI(3,3)); m_FrustumPlane[0] = __col2; m_FrustumPlane[1] = (__col3 - __col2); m_FrustumPlane[2] = (__col3 + __col0); m_FrustumPlane[3] = (__col3 - __col0); m_FrustumPlane[4] = (__col3 - __col1); m_FrustumPlane[5] = (__col3 + __col1); for(int __I = 0 ; __I < 6 ; __I++) { m_FrustumPlane[__I].Normalize(); } for (irr::u32 __I = 0 ; __I < m_Nodes.size() ; ++__I) { if (m_Nodes[__I]->getType() == irr::scene::ESNT_ANIMATED_MESH || m_Nodes[__I]->getType() == irr::scene::ESNT_BILLBOARD || m_Nodes[__I]->getType() == irr::scene::ESNT_CUBE || m_Nodes[__I]->getType() == irr::scene::ESNT_MESH || m_Nodes[__I]->getType() == irr::scene::ESNT_OCT_TREE || m_Nodes[__I]->getType() == irr::scene::ESNT_PARTICLE_SYSTEM || m_Nodes[__I]->getType() == irr::scene::ESNT_SHADOW_VOLUME || m_Nodes[__I]->getType() == irr::scene::ESNT_SKY_BOX || m_Nodes[__I]->getType() == irr::scene::ESNT_SPHERE || m_Nodes[__I]->getType() == irr::scene::ESNT_TERRAIN || m_Nodes[__I]->getType() == irr::scene::ESNT_WATER_SURFACE ) { irr::core::aabbox3d<irr::f32> _Box = m_Nodes[__I]->getBoundingBox(); irr::core::matrix4 _MatrixMesh = m_Nodes[__I]->getAbsoluteTransformation(); _MatrixMesh.transformBoxEx(_Box); if(IsVisible(_Box) == 0) m_Nodes[__I]->setVisible(false); else m_Nodes[__I]->setVisible(true); } } } ///-------------------------------------------------------------------------------- /// Pour ajouter un scene node /// /// @param _SceneNode : Pointeur vers le scene node ///-------------------------------------------------------------------------------- void FrustrumCulling::AddSceneNode(const irr::scene::ISceneNode * _SceneNode) { ((irr::scene::ISceneNode*)_SceneNode)->setAutomaticCulling(irr::scene::EAC_OFF); m_Nodes.insert((irr::scene::ISceneNode*)_SceneNode); } ///-------------------------------------------------------------------------------- /// Pour supprimer un scene node /// /// @param _SceneNode : Pointeur vers le scene node ///-------------------------------------------------------------------------------- void FrustrumCulling::RemoveSceneNode(const irr::scene::ISceneNode * _SceneNode) { for (irr::u32 __I = 0 ; __I < m_Nodes.size() ; __I++) { if (m_Nodes[__I] == _SceneNode) m_Nodes.erase(__I); } } ///-------------------------------------------------------------------------------- /// Pour tester si une box et visible /// /// @param _Box : Box a tester ///-------------------------------------------------------------------------------- bool FrustrumCulling::IsVisible(const irr::core::aabbox3d<irr::f32>& _Box) { float __P[3]; float __Q[3]; 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) { for(int __J = 0 ; __J < 3 ; ++__J) { if( m_FrustumPlane[__I][__J] >= 0.0f ) { __P[__J] = __Min[__J]; __Q[__J] = __Max[__J]; } else { __P[__J] = __Max[__J]; __Q[__J] = __Min[__J]; } } if( m_FrustumPlane[__I].DotCoord(__Q) < 0.0f ) return false; } return true; } } // Culling } // Engine } // App |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | ///-------------------------------------------------------------------------------- /// @file Plane.hpp /// @brief Plane pour les test ///-------------------------------------------------------------------------------- #ifndef __FPLANE_HPP_INCLUDED__ #define __FPLANE_HPP_INCLUDED__ #include <math.h> namespace App { namespace core { ///-------------------------------------------------------------------------------- /// Plane pour les test ///-------------------------------------------------------------------------------- class Plane { public: ///-------------------------------------------------------------------------------- /// Constructeur ///-------------------------------------------------------------------------------- Plane(); ///-------------------------------------------------------------------------------- /// Constructeur /// /// @param _a : Point a /// @param _b : Point b /// @param _c : Point c /// @param _d : Point d ///-------------------------------------------------------------------------------- Plane(float _a, float _b, float _c, float _d); ///-------------------------------------------------------------------------------- /// Operateur de soustraction /// /// @param _Other : Autre Plan ///-------------------------------------------------------------------------------- Plane operator-(const Plane& _Other) const; ///-------------------------------------------------------------------------------- /// Operateur d'addition /// /// @param _Other : Autre Plan ///-------------------------------------------------------------------------------- Plane operator+(const Plane& _Other) const; ///-------------------------------------------------------------------------------- /// Operateur de tableau /// /// @param _I : Index ///-------------------------------------------------------------------------------- float operator[](unsigned _I) const; ///-------------------------------------------------------------------------------- /// Pour normaliser le plan ///-------------------------------------------------------------------------------- void Normalize(); ///-------------------------------------------------------------------------------- /// Retourne l'addition de la multiplication des 4 point par une valeur /// /// @param _V : Facteur de multiplication ///-------------------------------------------------------------------------------- float DotCoord(float *_V); ///-------------------------------------------------------------------------------- /// Point a ///-------------------------------------------------------------------------------- float a; ///-------------------------------------------------------------------------------- /// Point b ///-------------------------------------------------------------------------------- float b; ///-------------------------------------------------------------------------------- /// Point c ///-------------------------------------------------------------------------------- float c; ///-------------------------------------------------------------------------------- /// Point d ///-------------------------------------------------------------------------------- float d; }; } // Engine } // App #endif // __FPLANE_HPP_INCLUDED__ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | ///-------------------------------------------------------------------------------- /// @file Plane.cpp /// @brief Plane pour les test ///-------------------------------------------------------------------------------- #include "Plane.hpp" namespace App { namespace core { ///-------------------------------------------------------------------------------- /// Constructeur ///-------------------------------------------------------------------------------- Plane::Plane() : a(0),b(0),c(0),d(0) { } ///-------------------------------------------------------------------------------- /// Constructeur /// /// @param _a : Point a /// @param _b : Point b /// @param _c : Point c /// @param _d : Point d ///-------------------------------------------------------------------------------- Plane::Plane(float _a, float _b, float _c, float _d) : a(_a), b(_b), c(_c), d(_d) { } ///-------------------------------------------------------------------------------- /// Operateur de soustraction /// /// @param _Other : Autre Plan ///-------------------------------------------------------------------------------- Plane Plane::operator-(const Plane& _Other) const { return Plane(a - _Other.a, b - _Other.b, c - _Other.c, d - _Other.d); } ///-------------------------------------------------------------------------------- /// Operateur d'addition /// /// @param _Other : Autre Plan ///-------------------------------------------------------------------------------- Plane Plane::operator+(const Plane& _Other) const { return Plane(a + _Other.a, b + _Other.b, c + _Other.c, d + _Other.d); } ///-------------------------------------------------------------------------------- /// Operateur de tableau /// /// @param _I : Index ///-------------------------------------------------------------------------------- float Plane::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; } } ///-------------------------------------------------------------------------------- /// Pour normaliser le plan ///-------------------------------------------------------------------------------- void Plane::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; } ///-------------------------------------------------------------------------------- /// Retourne l'addition de la multiplication des 4 point par une valeur /// /// @param _V : Facteur de multiplication ///-------------------------------------------------------------------------------- float Plane::DotCoord(float *_V) { return (a * _V[0] + b * _V[1] + c * _V[2] + d); } } // Engine } // App |
Donc voila alors pour l'utilisation ajouter juste avant la boucle de rendu
et dans le boucle de rendu
=========================================
Exemple complet :
Dernière modification par hardcpp (31-08-2009 01:33:42)
Hors ligne
Merci pour le partage de ces codes et cool de te voir passer dans le coin.
Irrlicht a bien besoin de ce genre de code pour améliorer ses performances
Merci.
Hors ligne
Je croyais qu'irrlicht avait déjà son propre frustum culling, je comprends plus là :s
Hors ligne
oui ca peut paraitre enbicieu mais mon system et plus performent environ 34fps sur une scene avec 1000 cube , celui de irrlicht bug un peu il faut carement que le node soit derriere la camera pour qui soit detecter comme non visible
Hors ligne
Je confirme.
Hors ligne
J'ai pas encore testé ton code mais justement, si Irrlicht attend qu'un node soit bien derrière la caméra pour le cacher, ça doit être pour éviter le cas où le node est très grand.
Moi aussi en tout cas je suis interloqué, je croyais que le frustrum culling de Irrlicht agissait sur les triangles (et non les nodes) grâce à un octree... ou alors j'ai vraiment rien pigé.
Hors ligne
il y a plusieur type de culling : frustrum, ambient, oclusion...
Dernière modification par hardcpp (01-07-2009 11:44:01)
Hors ligne
Allais je relance ce topic.
Et dans la version actuel d'Irrlicht. Ce probleme de Frustum est-t-il corrigé ?.
Car effectivement j'ai l'impression qu'avec la version 1.7.2, effectivement les nodes de l'octree ne sont pas visibile si seulement ils sont derrière la caméra.
Si je ne me trompe pas, ce probleme sera-t-il corrigé dans la version futur ?
merci
a+, thoced
Hors ligne
le probleme est corriger sur le svn (1.8)
enfin sa bug encore un peut
Dernière modification par Magun (15-08-2011 05:07:22)
Hors ligne
Justement je viens juste de de compiler la version 1.8 (SVN) et j'ai toujours le meme probleme.
Mais bon pour être sur de ne pas dire de bètise: voici exactement comment je procède
1) je charge un mesh (petit terrain au format b3d)
2) je crée une node avec smgr->addOctreeSceneNode(...);
3) je spécifie le type culling node->setAutomaticCulling(EAC_FRUSTUM_BOX);
4) j'affiche le nombre de polygones qui s'affichent.
Et la je constate que lorsque je positionne ma camera sur le terrain, effectivement le nombre de poly diminue lorsque les nodes crée par l'octree se trouvent derrière la camera mais par contre lorsque je positionne la camera en hauteur en regardant vers le bas (un peu à la façon d'un jeu RTS), je constate que dés que qu'un node de l'octree se trouve dans le cone de visibilité, c'est l'ensemble du mesh qui est affiché parceque justement tous les nodes de l'octree se trouvent devant la camera.
merci de m'indiquer si je me trompe
a+, thoced
Hors ligne
non c'est sa, mais dans ce cas intéresse toi a l'oclusion culling, en gros tu fait un raytest entre la camera et les tout nodes pour déterminer leur visibiliter
par contre c'est lent, mais facil a interfacer dans un thread séparé
Hors ligne
Je trouve franchement dommage que dans un moteur graphique, le Frustum culling ne soit pas encore complètement correctement implémenté.
C'est quand même les bases je pense surtout si l'on veut que le moteur perdure dans le temps.
Attention je n'ai pas dit que c'était facile a développer mais je trouve que les choix pris pour l'amélioration du moteur sont parfois étrange.
Hors ligne