(搬运工)Ogre动画拾取函数

IEntity *  GraphicalWorld::pickEntity( const  Ray &  ray, uint32 mask)
    {
        WS_ASSERT( msCore );
//  
//          const unsigned long mask = 0xFFFFFFFF;
        Ogre::Ray ogreRay( VEC_WS2OGRE(ray.getOrigin()), VEC_WS2OGRE(ray.getDirection()) );
        
if  ( ! mpRaySceneQuery)
        {
            mpRaySceneQuery 
=  msCore -> getSceneMgr() -> createRayQuery( ogreRay, mask );            
        }
        
else
        {
            mpRaySceneQuery
-> setRay(ogreRay );    
            mpRaySceneQuery
-> setQueryMask(mask);
        }        
        mpRaySceneQuery
-> setSortByDistance( true );
        
        Ogre::Real closest_distance 
=   99999.0f ;
        Ogre::RaySceneQueryResult 
& query_result  =  mpRaySceneQuery -> execute();
        Ogre::MovableObject
*  movable;
        IEntity
*  pEntity  =  NULL;


        
for  (size_t qr_idx  =   0 ; qr_idx  <  query_result.size(); qr_idx ++ )
        {
            
//  stop checking if we have found a raycast hit that is closer
            
//  than all remaining entities
             if  ((closest_distance  >=   0.0f &&  (closest_distance  <  query_result[qr_idx].distance))
                
break ;

            
//  only check this result if its a hit against an entity
            movable  =  query_result[qr_idx].movable;            
            
if  (( movable  !=  NULL)  &&  (movable -> getMovableType().compare( " Entity " ==   0 &&  movable -> isVisible())
            {
                
                EntityMap::const_iterator itFind 
=  mEntityMap.find( static_cast < Ogre::Entity *> (movable));
                
if  (itFind  ==  mEntityMap.end())
                    
continue ;

                
//  get the entity to check
                Ogre::Entity  * pentity  =  static_cast < Ogre::Entity *> (movable);

                
//  mesh data to retrieve
                size_t vertex_count;
                size_t index_count;

                pentity
-> _getSkelAnimVertexData();
                
//  get the mesh information
                GetMeshInformation(pentity, vertex_count, index_count, 
                    pentity
-> getParentNode() -> _getDerivedPosition(),
                    pentity
-> getParentNode() -> _getDerivedOrientation(),
                    pentity
-> getParentNode() -> _getDerivedScale());

                
//  test for hitting individual triangles on the mesh
                 bool  new_closest_found  =   false ;
                
for  ( int  i  =   0 ; i  <  static_cast < int > (index_count); i  +=   3 )
                {
                    assert(mIndexBuffer[i] 
<  vertex_count);
                    assert(mIndexBuffer[i 
+   1 <  vertex_count);
                    assert(mIndexBuffer[i 
+   2 <  vertex_count);
                    
//  check for a hit against this triangle

                    std::pair
< bool , Ogre::Real >  hit  =  Ogre::Math::intersects(ogreRay, mVertexBuffer[mIndexBuffer[i]],
                        mVertexBuffer[mIndexBuffer[i
+ 1 ]], mVertexBuffer[mIndexBuffer[i + 2 ]],  true false );

                    
//  if it was a hit check if its the closest
                     if  (hit.first)
                    {
                        
if  ((closest_distance  <   0.0f ||  (hit.second  <  closest_distance))
                        {
                            
//  this is the closest so far, save it off
                            closest_distance  =  hit.second;
                            new_closest_found 
=   true ;
                        }
                    }
                }

                
//  if we found a new closest raycast for this object, update the
                
//  closest_result before moving on to the next object.
                 if  (new_closest_found)
                {
                    pEntity 
=  itFind -> second;
                }
            }
        }


//          Ogre::RaySceneQueryResult &result = mpRaySceneQuery->execute();
//          Ogre::RaySceneQueryResult::iterator it = result.begin();
//          if (it != result.end())
//          {
//               // it->distance
//               // if (it->worldFragment)
//              if (it->movable)
//              {
//                   // Ogre::UserDefinedObject* udo = Ogre::MovableObject::getUserObject();
//                  if (it->movable->getMovableType() == "Entity")
//                  {
//                      EntityMap::const_iterator itFind = mEntityMap.find( static_cast<Ogre::Entity*>( it->movable ) );
//                      if (itFind != mEntityMap.end())
//                          return itFind->second;
//                  }
//              }
//          }
         return  pEntity;
    }

取得动画顶点数据
void  GetMeshInformation( const  Entity  * entity,
                                size_t 
& vertex_count,
                                Ogre::Vector3
*   & vertices,
                                size_t 
& index_count,
                                unsigned 
long *   & indices,
                                
const  Ogre::Vector3  & position,
                                
const  Ogre::Quaternion  & orient,
                                
const  Ogre::Vector3  & scale)
{
    
bool  added_shared  =   false ;
    size_t current_offset 
=   0 ;
    size_t shared_offset 
=   0 ;
    size_t next_offset 
=   0 ;
    size_t index_offset 
=   0 ;
    vertex_count 
=  index_count  =   0 ;
 
   Ogre::MeshPtr mesh 
=  entity -> getMesh();
 
 
   
bool  useSoftwareBlendingVertices  =  entity -> hasSkeleton();
 
   
if  (useSoftwareBlendingVertices)
   {
      entity
-> _updateAnimation();
   }
 
    
//  Calculate how many vertices and indices we're going to need
     for  (unsigned  short  i  =   0 ; i  <  mesh -> getNumSubMeshes();  ++ i)
    {
        Ogre::SubMesh
*  submesh  =  mesh -> getSubMesh( i );
 
        
//  We only need to add the shared vertices once
         if (submesh -> useSharedVertices)
        {
            
if ! added_shared )
            {
                vertex_count 
+=  mesh -> sharedVertexData -> vertexCount;
                added_shared 
=   true ;
            }
        }
        
else
        {
            vertex_count 
+=  submesh -> vertexData -> vertexCount;
        }
 
        
//  Add the indices
        index_count  +=  submesh -> indexData -> indexCount;
    }
 
 
    
//  Allocate space for the vertices and indices
    vertices  =   new  Ogre::Vector3[vertex_count];
    indices 
=   new  unsigned  long [index_count];
 
    added_shared 
=   false ;
 
    
//  Run through the submeshes again, adding the data into the arrays
     for  ( unsigned  short  i  =   0 ; i  <  mesh -> getNumSubMeshes();  ++ i)
    {
        Ogre::SubMesh
*  submesh  =  mesh -> getSubMesh(i);
 
      
// ----------------------------------------------------------------
      
//  GET VERTEXDATA
      
// ----------------------------------------------------------------
 
        
// Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
      Ogre::VertexData *  vertex_data;
 
      
// When there is animation:
       if (useSoftwareBlendingVertices)
#ifdef BUILD_AGAINST_AZATHOTH
         vertex_data 
=  submesh -> useSharedVertices  ?  entity -> _getSharedBlendedVertexData() : entity -> getSubEntity(i) -> _getBlendedVertexData();
#else
         vertex_data 
=  submesh -> useSharedVertices  ?  entity -> _getSkelAnimVertexData() : entity -> getSubEntity(i) -> _getSkelAnimVertexData();
#endif
      
else
         vertex_data 
=  submesh -> useSharedVertices  ?  mesh -> sharedVertexData : submesh -> vertexData;
 
 
        
if (( ! submesh -> useSharedVertices) || (submesh -> useSharedVertices  &&   ! added_shared))
        {
            
if (submesh -> useSharedVertices)
            {
                added_shared 
=   true ;
                shared_offset 
=  current_offset;
            }
 
            
const  Ogre::VertexElement *  posElem  =
                vertex_data
-> vertexDeclaration -> findElementBySemantic(Ogre::VES_POSITION);
 
            Ogre::HardwareVertexBufferSharedPtr vbuf 
=
                vertex_data
-> vertexBufferBinding -> getBuffer(posElem -> getSource());
 
            unsigned 
char *  vertex  =
                static_cast
< unsigned  char *> (vbuf -> lock (Ogre::HardwareBuffer::HBL_READ_ONLY));
 
            
//  There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
            
//   as second argument. So make it float, to avoid trouble when Ogre::Real will
            
//   be comiled/typedefed as double:
            
//       Ogre::Real* pReal;
             float *  pReal;
 
            
for ( size_t j  =   0 ; j  <  vertex_data -> vertexCount;  ++ j, vertex  +=  vbuf -> getVertexSize())
            {
                posElem
-> baseVertexPointerToElement(vertex,  & pReal);
 
                Ogre::Vector3 pt(pReal[
0 ], pReal[ 1 ], pReal[ 2 ]);
 
                vertices[current_offset 
+  j]  =  (orient  *  (pt  *  scale))  +  position;
            }
 
            vbuf
-> unlock();
            next_offset 
+=  vertex_data -> vertexCount;
        }
 
 
        Ogre::IndexData
*  index_data  =  submesh -> indexData;
        size_t numTris 
=  index_data -> indexCount  /   3 ;
        Ogre::HardwareIndexBufferSharedPtr ibuf 
=  index_data -> indexBuffer;
 
        
bool  use32bitindexes  =  (ibuf -> getType()  ==  Ogre::HardwareIndexBuffer::IT_32BIT);
 
        unsigned 
long *   pLong  =  static_cast < unsigned  long *> (ibuf -> lock (Ogre::HardwareBuffer::HBL_READ_ONLY));
        unsigned 
short *  pShort  =  reinterpret_cast < unsigned  short *> (pLong);
 
 
        size_t offset 
=  (submesh -> useSharedVertices) ?  shared_offset : current_offset;
        size_t index_start 
=  index_data -> indexStart;
        size_t last_index 
=  numTris * 3   +  index_start;
 
        
if  (use32bitindexes)
            
for  (size_t k  =  index_start; k  <  last_index;  ++ k)
            {
                indices[index_offset
++ =  pLong[k]  +  static_cast < unsigned  long > ( offset );
            }
 
        
else
            
for  (size_t k  =  index_start; k  <  last_index;  ++ k)
            {
                indices[ index_offset
++  ]  =  static_cast < unsigned  long > ( pShort[k] )  +
                    static_cast
< unsigned  long > ( offset );
            }
 
        ibuf
-> unlock();
        current_offset 
=  next_offset;
    }
}




你可能感兴趣的:((搬运工)Ogre动画拾取函数)