/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Cache of 3D model files.
 * @verbatim
 *
 * 3D model offset:
 * ----------------
 * Some 3D models need their origin to be moved for proper rotation.
 * The existence of a 3D model offset is handled by the function LoadModel()
 * which splices a transform node before it is passed to a Graph's ctor.
 * Thus, Object and Graph classes aren't aware.
 *
 * @endverbatim
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef GRAPH_MODEL_CACHE_HH
#define GRAPH_MODEL_CACHE_HH 1

#include <map>
#include "base/singleton.hh"
using namespace base;
#include "object/rotation_list.hh"
using namespace object;
#include "physics/types.hh"
using namespace physics;
#include "graph/graph_enablement.hh"
#include "graph/model_cache.hh"

#define GET_MODEL_CACHE() (ModelCache::GetInstance())

namespace graph {

class Graph;

////////////////////////////////////////////////////////////////////////////////
/// @brief Cache of 3D models (avoids re-loading the same 3D model files).
///
/// Since a 3D model may be cached, its osg::Node may be shared by multiple parents.
/// The reason a 3D model can exist in multiple locations
/// is because its shared node is placed under separate transform nodes.
///
class ModelCache
{
PREVENT_COPYING(ModelCache)
private:
    ModelCache( void );
    ~ModelCache();

public:
    enum { LOAD_SHARED, LOAD_COPY };  // for loadCopy arg

    DEFINE_GetInstance( ModelCache )  // Singleton

    // Load a cached 3D model according to physics parameters.
    shptr<Graph> LoadModel( const string&       modelFilename,  // sub-pathname
                            const Meter         modelLength,
                            const GeoVertex&    modelOffset,
                            const RotationList& rotationList,
                            const fp            modelScale = 1.0f,
                            const bool          loadCopy = false );

    // Directly load a cached 3D model.
    shptr<Graph> LoadModel( const string& modelFilename,
                            const fp      modelScale = 1.0f,
                            const bool    loadCopy = false );

    void         Flush( void );

private:
    RefPtr<osg::Node>               LoadModelIntoNode( const string& modelFilename, const bool loadCopy );
    RefPtr<osg::Node>               LoadModelIntoNode2( const string& modelFilename );
    RefPtr<osg::MatrixTransform>    LoadModelIntoTransform( const string& modelFilename, const bool loadCopy );
    RefPtr0<osg::Node>              ReadNodeFile( const string& pathname );

private:
    typedef std::map<string,RefPtr<osg::Node> > ModelMap;
    CLASS_VAR ModelCache*   msInstance;
    ModelMap                mModelMap;      ///< maps filename and node containing 3D model
};

} // namespace graph

#endif // GRAPH_MODEL_CACHE_HH
