Sirikata
libogre/src/PriorityDownloadPlanner.hpp
Go to the documentation of this file.
00001 // Copyright (c) 2009 Sirikata Authors. All rights reserved.
00002 // Use of this source code is governed by a BSD-style license that can
00003 // be found in the LICENSE file.
00004 
00005 #ifndef _SIRIKATA_OGRE_PRIORITY_DOWNLOAD_PLANNER_HPP
00006 #define _SIRIKATA_OGRE_PRIORITY_DOWNLOAD_PLANNER_HPP
00007 
00008 #include <sirikata/ogre/ResourceDownloadPlanner.hpp>
00009 #include <sirikata/ogre/resourceManager/AssetDownloadTask.hpp>
00010 #include <sirikata/ogre/Util.hpp>
00011 #include <sirikata/mesh/Meshdata.hpp>
00012 #include <sirikata/mesh/Billboard.hpp>
00013 #include <sirikata/core/util/Liveness.hpp>
00014 #include <sirikata/core/command/Commander.hpp>
00015 
00016 namespace Sirikata {
00017 namespace Graphics {
00018 
00019 class WebView;
00020 
00022 class PriorityDownloadPlannerMetric {
00023 public:
00024     virtual ~PriorityDownloadPlannerMetric() {}
00025     virtual double calculatePriority(Graphics::Camera *camera, ProxyObjectPtr proxy) = 0;
00026     virtual String name() const = 0;
00027 };
00028 typedef std::tr1::shared_ptr<PriorityDownloadPlannerMetric> PriorityDownloadPlannerMetricPtr;
00029 
00030 class DistanceDownloadPlannerMetric : public PriorityDownloadPlannerMetric {
00031 public:
00032     virtual ~DistanceDownloadPlannerMetric() {}
00033     virtual double calculatePriority(Graphics::Camera *camera, ProxyObjectPtr proxy);
00034     virtual String name() const { return "distance"; }
00035 };
00036 
00037 class SolidAngleDownloadPlannerMetric : public PriorityDownloadPlannerMetric {
00038 public:
00039     virtual ~SolidAngleDownloadPlannerMetric() {}
00040     virtual double calculatePriority(Graphics::Camera *camera, ProxyObjectPtr proxy);
00041     virtual String name() const { return "solid_angle"; }
00042 };
00043 
00044 
00049 class PriorityDownloadPlanner : public ResourceDownloadPlanner,
00050                                 public virtual Liveness
00051 {
00052 public:
00053     PriorityDownloadPlanner(Context* c, OgreRenderer* renderer, PriorityDownloadPlannerMetricPtr metric);
00054     ~PriorityDownloadPlanner();
00055 
00056     virtual void addNewObject(Graphics::Entity *ent, const Transfer::URI& mesh);
00057     virtual void addNewObject(ProxyObjectPtr p, Graphics::Entity *mesh);
00058     virtual void updateObject(ProxyObjectPtr p);
00059     virtual void removeObject(ProxyObjectPtr p);
00060     virtual void removeObject(Graphics::Entity* ent);
00061 
00062     //PollingService interface
00063     virtual void poll();
00064     virtual void stop();
00065 
00066     PriorityDownloadPlannerMetricPtr prioritizationMetric() {
00067         return mMetric;
00068     }
00069     void setPrioritizationMetric(PriorityDownloadPlannerMetricPtr metric) {
00070         mMetric = metric;
00071     }
00072 
00073     virtual Stats stats();
00074 protected:
00075     bool mStopped;
00076     PriorityDownloadPlannerMetricPtr mMetric;
00077     struct Object;
00078 
00079     void iUpdateObject(ProxyObjectPtr p,Liveness::Token lt);
00080     void iRemoveObject(const String& name, Liveness::Token alive);
00081     void iAddObject(Object* r, Liveness::Token alive);
00082     void addObject(Object* r);
00083     Object* findObject(const String& sporef);
00084     void removeObject(const String& sporef);
00085 
00086     double calculatePriority(ProxyObjectPtr proxy);
00087 
00088     void commandGetData(
00089         const Command::Command& cmd, Command::Commander* cmdr, Command::CommandID cmdid);
00090     void commandGetStats(
00091         const Command::Command& cmd, Command::Commander* cmdr, Command::CommandID cmdid);
00092 
00093     void checkShouldLoadNewObject(Object* r);
00094 
00095     // Checks if changes just due to budgets are possible,
00096     // e.g. regardless of priorities, we have waiting objects and free
00097     // spots for them.
00098     bool budgetRequiresChange() const;
00099 
00100     void loadObject(Object* r);
00101     void unloadObject(Object* r);
00102 
00103     struct Object {
00104         Object(Graphics::Entity *m, const Transfer::URI& mesh_uri, ProxyObjectPtr _proxy = ProxyObjectPtr());
00105         virtual ~Object(){
00106         }
00107 
00108         const String& id() const { return name; }
00109 
00110         Transfer::URI file;
00111         Graphics::Entity *mesh;
00112         String name;
00113         bool loaded;
00114         float32 priority;
00115         ProxyObjectPtr proxy;
00116 
00117         class Hasher {
00118         public:
00119             size_t operator() (const Object& r) const {
00120                 return std::tr1::hash<String>()(r.name);
00121             }
00122         };
00123 
00124         struct MaxHeapComparator {
00125             bool operator()(Object* lhs, Object* rhs) {
00126                 return lhs->priority < rhs->priority;
00127             }
00128         };
00129         struct MinHeapComparator {
00130             bool operator()(Object* lhs, Object* rhs) {
00131                 return lhs->priority > rhs->priority;
00132             }
00133         };
00134 
00135     };
00136 
00137     typedef std::tr1::unordered_set<String> ObjectSet;
00138     typedef std::tr1::unordered_map<String, Object*> ObjectMap;
00139     // The full list
00140     ObjectMap mObjects;
00141     // Loading has started for these
00142     ObjectMap mLoadedObjects;
00143     // Waiting to be important enough to load
00144     ObjectMap mWaitingObjects;
00145 
00146 
00147     // Heap storage for Objects. Choice between min/max heap is at call time.
00148     typedef std::vector<Object*> ObjectHeap;
00149 
00150 
00151     typedef std::vector<WebView*> WebMaterialList;
00152 
00153     // Assets represent a single graphical asset that needs to be downloaded
00154     // from the CDN and loaded into memory. Since a single asset can be loaded
00155     // many times by different 'Objects' (i.e. objects in the world) we track
00156     // them separately and make sure we only issue single requests for them.
00157     struct Asset : public Liveness
00158     {
00159         Transfer::URI uri;
00160         AssetDownloadTaskPtr downloadTask;
00161         // Objects that want this asset to be loaded and are waiting for it
00162         ObjectSet waitingObjects;
00163         // Objects that are using this asset
00164         ObjectSet usingObjects;
00165         // Filled in by the loader with the name of the asset that's actually
00166         // used when creating an instance (unique name for mesh, billboard
00167         // texture, etc).
00168         String ogreAssetName;
00169 
00170 
00171         //Can get into a situation where we fire a callback associated with a
00172         //transfer uri, then we delete the associated asset, then create a new
00173         //asset with the same uri.  The callback assumes that internal state
00174         //for the asset is valid and correct (in particular, downloadTask).
00175         //However, in these cases, the data wouldn't be valid.  Use internalId
00176         //to check that the callback that is being serviced corresponds to the
00177         //correct asset that we have in memory.
00178         uint64 internalId;
00179 
00180         TextureBindingsMapPtr textureFingerprints;
00181         std::set<String> animations;
00182 
00183         WebMaterialList webMaterials;
00184 
00185         // # of resources we're still waiting to finish loading
00186         uint16 loadingResources;
00187         // Sets of resources this Asset has loaded so we can get
00188         // ResourceLoader to unload them. Ordered list so we can
00189         // unload in reverse order we loaded in.
00190         typedef std::vector<String > ResourceNameList;
00191         ResourceNameList loadedResources;
00192 
00193         // Store a copy so we can release the download task but still
00194         // get at the data if another object uses this mesh.
00195         Mesh::VisualPtr visual;
00196 
00197         Asset(const Transfer::URI& name);
00198         ~Asset();
00199     };
00200     typedef std::tr1::unordered_map<Transfer::URI, Asset*, Transfer::URI::Hasher> AssetMap;
00201 
00202 
00203     AssetMap mAssets;
00204 
00205 
00206     // Because we aggregate all Asset requests so we only generate one
00207     // AssetDownloadTask, we need to aggregate some priorities
00208     // ourselves. Aggregation will still also be performed by other parts of the
00209     // system on a per-Resource basis (TransferPool for multiple requests by
00210     // different Assets, TransferMediator for requests across multiple Pools).
00211     Transfer::PriorityAggregationAlgorithm* mAggregationAlgorithm;
00212 
00213     // These are a sequence of async operations that take a URI for a
00214     // resource/asset pair and gets it loaded. Some paths will terminate early
00215     // since multiple resources that share an asset can share many of these
00216     // steps.
00217     void requestAssetForObject(Object*);
00218     void downloadAsset(Asset* asset, Object* forObject);
00219     void loadAsset(Transfer::URI asset_uri,uint64 assetId);
00220     void finishLoadAsset(Asset* asset, bool success);
00221 
00222     void loadMeshdata(Asset* asset, const Mesh::MeshdataPtr& mdptr, bool usingDefault);
00223     void loadBillboard(Asset* asset, const Mesh::BillboardPtr& bbptr, bool usingDefault);
00224     void loadDependentTextures(Asset* asset, bool usingDefault);
00225 
00226     // Helper, notifies when resource has finished loading allowing us
00227     // to figure out when the entire asset has loaded
00228     void handleLoadedResource(Asset* asset,Liveness::Token assetAlive);
00229 
00230     // Update the priority for an asset from all it's requestors
00231     void updateAssetPriority(Asset* asset);
00232 
00233     // Removes the resource's need for the asset, potentially allowing it to be
00234     // unloaded.
00235     void unrequestAssetForObject(Object*);
00236 
00237     // Helper to check if it's safe to remove an asset and does so if
00238     // possible. Properly handles current
00239     void checkRemoveAsset(Asset* asset,Liveness::Token lt);
00240 
00241     bool mActiveCDNArchive;
00242     unsigned int mCDNArchive;
00243 
00244     void iStop(Liveness::Token dpAlive);
00245     void iPoll(Liveness::Token dpAlive);
00246 };
00247 
00248 } // namespace Graphics
00249 } // namespace Sirikata
00250 
00251 #endif //_SIRIKATA_OGRE_PRIORITY_DOWNLOAD_PLANNER_HPP