class DynamicPrimitiveEntityStorage;

///////////////////////////////////////////////////////////////////////////////////////////////////
///Информация о уровне детализации
///////////////////////////////////////////////////////////////////////////////////////////////////
struct EntityLodDesc
{
  RendererOperationList&         operations;                         //операции рендеринга
  DynamicPrimitiveEntityStorage& dynamic_primitive_storage;          //хранилище динамических примитивов
  bool                           has_frame_dependent_operations;     //есть ли операции зависящие от кадра
  bool                           has_frame_independent_operations;   //есть ли операции не зависящие от кадра
  bool                           has_entity_dependent_operations;    //есть ли операции зависящие от объекта
  bool                           has_entity_independent_operations;  //есть ли операции не зависящие от объекта

  EntityLodDesc (RendererOperationList& in_operations, DynamicPrimitiveEntityStorage& in_storage)
    : operations (in_operations)
    , dynamic_primitive_storage (in_storage)
    , has_frame_dependent_operations ()
    , has_frame_independent_operations ()
    , has_entity_dependent_operations ()
    , has_entity_independent_operations ()
  {
  }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
///Объект рендеринга
///////////////////////////////////////////////////////////////////////////////////////////////////
class EntityImpl: public Object
{
  public:
///////////////////////////////////////////////////////////////////////////////////////////////////
///Конструктор / деструктор
///////////////////////////////////////////////////////////////////////////////////////////////////
    EntityImpl  (const DeviceManagerPtr&, const TextureManagerPtr&, const PrimitiveManagerPtr&);
    ~EntityImpl ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Хранилище динамических текстур
///////////////////////////////////////////////////////////////////////////////////////////////////
    DynamicTextureEntityStorage& DynamicTextureStorage ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Матрица мировых преобразований
///////////////////////////////////////////////////////////////////////////////////////////////////
    void               SetWorldMatrix     (const math::mat4f&);
    const math::mat4f& WorldMatrix        ();
    const math::mat4f& InverseWorldMatrix ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Свойства рендеринга
///////////////////////////////////////////////////////////////////////////////////////////////////
    void                       SetProperties (const common::PropertyMap&);
    const common::PropertyMap& Properties    ();
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Макро-определения шейдера
///////////////////////////////////////////////////////////////////////////////////////////////////
    void                       SetShaderOptions (const common::PropertyMap&);
    const common::PropertyMap& ShaderOptions    ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Пользовательские данные
///////////////////////////////////////////////////////////////////////////////////////////////////
    void  SetUserData (void* data);
    void* UserData    ();
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Работа с костями (для скиннинга)
///  преобразования умножаются на матрицу Entity::Transformation в случае если она не единична
///////////////////////////////////////////////////////////////////////////////////////////////////
    void               SetJointsCount         (size_t count);
    size_t             JointsCount            ();
    void               SetJointTransformation (size_t joint_index, const math::mat4f&);
    const math::mat4f& JointTransformation    (size_t joint_index);
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Работа с уровнями детализации
///////////////////////////////////////////////////////////////////////////////////////////////////
    size_t LodsCount ();
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Работа с примитивом
///////////////////////////////////////////////////////////////////////////////////////////////////
    PrimitivePtr Primitive           (size_t level_of_detail);
    const char*  PrimitiveName       (size_t level_of_detail);  
    void         SetPrimitive        (const PrimitivePtr&, size_t level_of_detail);
    void         SetPrimitive        (const char* name, size_t level_of_detail);
    void         ResetPrimitive      (size_t level_of_detail);
    bool         HasPrimitive        (size_t level_of_detail);
    void         ResetAllPrimitives  ();
    
///////////////////////////////////////////////////////////////////////////////////////////////////
///Точка в локальной системе координат объекта для расчёта удаленности от камеры
///////////////////////////////////////////////////////////////////////////////////////////////////
    void               SetLodPoint (const math::vec3f&);
    const math::vec3f& LodPoint    ();
   
///////////////////////////////////////////////////////////////////////////////////////////////////
///Управление областью отсечения объекта
///////////////////////////////////////////////////////////////////////////////////////////////////
    void           SetWorldScissor (const BoxArea& scissor);
    const BoxArea& WorldScissor    ();
    void           SetScissorState (bool state);
    bool           ScissorState    ();

///////////////////////////////////////////////////////////////////////////////////////////////////
///Получение информации об уровне детализации
///////////////////////////////////////////////////////////////////////////////////////////////////
    const EntityLodDesc& GetLod (size_t level_of_detail, bool find_nearest = false);

///////////////////////////////////////////////////////////////////////////////////////////////////
///Управление кэшированием
///////////////////////////////////////////////////////////////////////////////////////////////////
    void UpdateCache ();
    void ResetCache  ();

  private:
    struct Impl;
    stl::auto_ptr<Impl> impl;
};
