AI_World.h

Go to the documentation of this file.
00001 #ifndef AI_WORLD_H
00002 #define AI_WORLD_H
00003 
00004 #include "utils/AI_List.h"
00005 #include "AI_NavigationMesh.h"
00006 #include "AI_Actor.h"
00007 
00008 
00019 class AI_World
00020 {
00021 //*** Attributes
00022 protected:
00024     AI_List m_list_agents;
00026     AI_NavigationMesh m_navigation_mesh;
00028     AI_SDB_SpatialAABBTree m_spatial_tree;
00030     AI_SDB_VisibilityVisitor::VisibleElements m_visible_elements;
00032     float m_f_enable_dist;
00034     float m_f_disable_dist;
00036     AI_Ref<AI_Actor> m_ref_actor_pivot;
00038     AI_Ref<AI_Actor> m_ref_hero;
00040     ai_dword m_dw_db_version;
00042     double m_d_time_auto_enable;
00043 
00044     AI_Actor::ActorArray m_arr_enabled_actors;
00045     AI_Actor::ActorArray m_arr_temp_actors;
00046 
00047     struct {
00048         bool m_b_auto_enable : 1;
00049         bool m_b_auto_disable : 1;
00050         bool m_b_wide_agents : 1;
00051     };
00052 
00053 public:
00054     AI_World(void);
00055     ~AI_World(void);
00056 
00057     //run
00058     void trigger (double d_time);
00059     bool findWay( AI_Actor &actor );
00060     bool testVisibility( const AI_Vector3 &v_first, const AI_Vector3 &v_second);
00061     const bool testWallDistance( const AI_Vector3 &v_first, const AI_Vector3 &v_second, float &f_distance );
00062     bool isOnSurface(const AI_Vector3 &v_pos);
00063     bool getNearestSurfacePosition(const AI_Vector3 &v_position,float radius,bool cylinder,AI_Vector3 &v_nearest_position);
00064 
00065     //creation
00066     bool addAgent( AI_Agent *ptr_agent );
00067     void removeAgent( AI_Agent *ptr_agent );
00068 
00069     //sets
00070     void setAutoEnable( bool b_enable );
00071     void setAutoDisable( bool b_enable );
00072     void setAutoEnableDisablePivot( AI_Actor *ptr_actor );
00073     void setAutoEnableDistance( const float f_dist );
00074     void setAutoDisableDistance( const float f_dist );
00075     void setWideAgents( bool b );
00076     void setHero( AI_Actor *ptr_actor );
00077 
00078     //gets
00079     AI_NavigationMesh &getNavigationMesh( void );
00080     bool isAutoEnable( void ) const;
00081     bool isAutoDisable( void ) const;
00082     const float getAutoEnableDistance( void ) const;
00083     const float getAutoDisableDistance( void ) const;
00084     AI_Actor *getAutoEnableDisablePivot( void );
00085     bool isWideAgents( void );
00086     const ai_dword getDBVersion( void );
00087     AI_Actor *getHero( void );
00088     AI_Actor::ActorArray &getEnabledActors(void);
00089 
00090     //others
00091     void updateSpatialElement( AI_SDB_SpatialElement *ptr_spatial_element, const AI_BBox &bbox_new );
00092     void getNearAgents( const AI_Vector3 &v_position, const float f_range, AI_Agent::AgentArray &arr_near_agents, AI_Agent *ptr_agent_exclude = NULL );
00093     void enableActor( AI_Actor *ptr_actor );
00094     void disableActor( AI_Actor *ptr_actor );
00095 
00096 private:
00097     void increaseDBVersion( void );
00098 };
00099 
00100 
00103 inline
00104 AI_World::AI_World(void) :
00105     m_b_auto_enable(false),
00106     m_b_auto_disable(false),
00107     m_f_enable_dist(10.0f),
00108     m_f_disable_dist(20.0f),
00109     m_dw_db_version(0),
00110     m_d_time_auto_enable(AI_AUTO_ENABLE_CHECK)
00111 {
00112 }
00113 
00114 
00117 inline
00118 AI_World::~AI_World(void)
00119 {
00120 }
00121 
00122 
00127 inline
00128 bool AI_World::addAgent(AI_Agent *ptr_agent)
00129 {
00130     //*** Add agent in the world
00131     m_list_agents.AddTail(ptr_agent);
00132     ptr_agent->setWorld( this );
00133 
00134     //*** Add agent in the spatial tree
00135     AI_BBox bbox_agent ( ptr_agent->getPosition(), ptr_agent->getAura() );
00136     AI_SDB_BBoxSpatialElement *ptr_element = new AI_SDB_BBoxSpatialElement( bbox_agent );
00137 
00138     ptr_agent->setSpatialElement( ptr_element );
00139     ptr_element->SetPtr( ptr_agent );
00140 
00141     m_spatial_tree.AddElement ( ptr_element );
00142     increaseDBVersion();
00143 
00144     return true;
00145 }
00146 
00147 
00150 inline
00151 void AI_World::removeAgent(AI_Agent *ptr_agent)
00152 {
00153     //*** Remove from spatial database
00154     m_spatial_tree.RemoveElement( ptr_agent->getSpatialElement() );
00155     increaseDBVersion();
00156 
00157     //*** Remove from list
00158     ptr_agent->Remove();
00159 
00160     //*** Reset world
00161     ptr_agent->setWorld( NULL );
00162 
00163     //*** Reset pivot
00164     if ( ptr_agent==m_ref_actor_pivot.get_unsafe() )
00165         m_ref_actor_pivot.invalidate();
00166 
00167     //*** Disable
00168     ptr_agent->setEnable( false );
00169     if ( ptr_agent->getType()==AI_Agent::ACTOR )
00170         disableActor( (AI_Actor*)ptr_agent );
00171 }
00172 
00173 
00176 inline
00177 AI_NavigationMesh &AI_World::getNavigationMesh( void )
00178 {
00179     return m_navigation_mesh;
00180 }
00181 
00182 
00185 inline
00186 bool AI_World::findWay( AI_Actor &actor )
00187 {
00188     return m_navigation_mesh.findWay( actor.getNavmeshSession() );
00189 }
00190 
00191 
00196 inline
00197 bool AI_World::isOnSurface(const AI_Vector3 &v_pos)
00198 {
00199     return m_navigation_mesh.identifyTriangle(v_pos) ? true : false;
00200 }
00201 
00202 
00205 inline
00206 bool AI_World::getNearestSurfacePosition(const AI_Vector3 &v_position,float radius,bool cylinder,AI_Vector3 &v_nearest_position)
00207 {
00208     return m_navigation_mesh.getNearestPosition(v_position,radius,cylinder,v_nearest_position);
00209 }
00210 
00211 
00214 inline
00215 bool AI_World::testVisibility( const AI_Vector3 &v_first, const AI_Vector3 &v_second)
00216 {
00217     return m_navigation_mesh.testVisibility( v_first, v_second );
00218 }
00219 
00220 
00227 inline
00228 const bool AI_World::testWallDistance( const AI_Vector3 &v_first, const AI_Vector3 &v_second, float &f_distance )
00229 {
00230     return m_navigation_mesh.testBorderIntersection(v_first, v_second, f_distance);
00231 }
00232 
00233 
00236 inline
00237 void AI_World::setAutoEnable( bool b_enable )
00238 {
00239     m_b_auto_enable = b_enable;
00240 }
00241 
00242 
00245 inline
00246 void AI_World::setAutoDisable( bool b_enable )
00247 {
00248     m_b_auto_disable = b_enable;
00249 }
00250 
00251 
00254 inline
00255 bool AI_World::isAutoEnable( void ) const
00256 {
00257     return m_b_auto_enable;
00258 }
00259 
00260 
00263 inline
00264 bool AI_World::isAutoDisable( void ) const
00265 {
00266     return m_b_auto_disable;
00267 }
00268 
00269 
00274 inline
00275 void AI_World::setAutoEnableDisablePivot( AI_Actor *ptr_actor )
00276 {
00277     if ( ptr_actor->getWorld()!=this )
00278     {   ai_log(AI_STR_AGENT_ISNT_IN_WORLD);
00279         return;
00280     }
00281 
00282     m_ref_actor_pivot = ptr_actor;
00283     
00284     ptr_actor->setEnable(true);
00285 }
00286 
00287 
00290 inline
00291 AI_Actor *AI_World::getAutoEnableDisablePivot( void )
00292 {
00293     return m_ref_actor_pivot.get_unsafe();
00294 }
00295 
00296 
00299 inline
00300 void AI_World::setAutoEnableDistance( const float f_dist )
00301 {
00302     m_f_enable_dist = f_dist;
00303 }
00304 
00305 
00308 inline
00309 void AI_World::setAutoDisableDistance( const float f_dist )
00310 {
00311     m_f_disable_dist = f_dist;
00312 }
00313 
00314 
00317 inline
00318 const float AI_World::getAutoEnableDistance( void ) const
00319 {
00320     return m_f_enable_dist;
00321 }
00322 
00323 
00326 inline
00327 const float AI_World::getAutoDisableDistance( void ) const
00328 {
00329     return m_f_disable_dist;
00330 }
00331 
00332 
00335 inline
00336 void AI_World::updateSpatialElement( AI_SDB_SpatialElement *ptr_spatial_element, const AI_BBox &bbox_new )
00337 {
00338     m_spatial_tree.MoveElement( ptr_spatial_element, bbox_new );
00339 }
00340 
00341 
00344 inline
00345 void AI_World::setWideAgents( bool b )
00346 {
00347     m_navigation_mesh.setWideAgents( b );
00348 }
00349 
00350 
00353 inline
00354 bool AI_World::isWideAgents( void )
00355 {
00356     return m_navigation_mesh.isWideAgents();
00357 }
00358 
00359 
00362 inline
00363 const ai_dword AI_World::getDBVersion( void )
00364 {
00365     return m_dw_db_version;
00366 }
00367 
00368 
00371 inline
00372 void AI_World::increaseDBVersion( void )
00373 {
00374     m_dw_db_version++;
00375     
00376     //*** If we keep 100FPS and made DB change every frame and AI world runs nearly 500 hours
00377     //    then DB version number can overflow. If some agent's last used DB version was not 
00378     //    changed within 500 hours then db actor's DB version and this DB version can match.
00379     //    Thus the actor can work with invalid data and cause crash.
00380     //if (m_dw_db_version)
00381     //{
00382     //    ai_log("AI spatial databse overflow!");
00383     //}
00384 }
00385 
00386 
00389 inline
00390 void AI_World::setHero( AI_Actor *ptr_actor )
00391 {
00392     m_ref_hero = ptr_actor;
00393 }
00394 
00395 
00398 inline
00399 AI_Actor *AI_World::getHero( void )
00400 {
00401     return m_ref_hero.get_unsafe();
00402 }
00403 
00404 
00409 inline 
00410 void AI_World::enableActor( AI_Actor *ptr_actor )
00411 {
00412     AI_Actor::ActorArrayIt it = m_arr_enabled_actors.Find( ptr_actor );
00413     if ( !it )
00414         m_arr_enabled_actors.Append( ptr_actor );
00415 }
00416 
00417 
00420 inline 
00421 void AI_World::disableActor( AI_Actor *ptr_actor )
00422 {
00423     AI_Actor::ActorArrayIt it = m_arr_enabled_actors.Find( ptr_actor );
00424     if ( it )
00425         m_arr_enabled_actors.Erase( it );
00426 }
00427 
00428 
00429 inline
00430 AI_Actor::ActorArray &AI_World::getEnabledActors(void)
00431 {
00432     return m_arr_enabled_actors;
00433 }
00434 
00435 
00436 #endif