Sirikata
|
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