void AssetDownloadTask::handleAssetParsed(Mesh::MeshdataPtr md) { mAsset = md; if (!md) { SILOG(ogre,error,"Failed to parse mesh " << mAssetURI.toString()); mCB(); return; } // This is a sanity check. There's no way Ogre can reasonably handle meshes // that require a ton of draw calls. Estimate them here and if its too high, // destroy the data and invoke the callback to make it look like failure. { // Draw calls = // Number of instances * number of primitives in instance uint32 draw_calls = 0; Meshdata::GeometryInstanceIterator geoinst_it = md->getGeometryInstanceIterator(); uint32 geoinst_idx; Matrix4x4f pos_xform; while( geoinst_it.next(&geoinst_idx, &pos_xform) ) draw_calls += md->geometry[ md->instances[geoinst_idx].geometryIndex ].primitives.size(); // Arbitrary number, but probably more than we should even allow given // that there are probably hundreds or thousands of other objects if (draw_calls > 500) { SILOG(ogre,error,"Excessively complicated mesh: " << mAssetURI.toString() << " has " << draw_calls << " draw calls. Ignoring this mesh."); mAsset = Mesh::MeshdataPtr(); mCB(); return; } } mRemainingDownloads = md->textures.size(); // Special case for no dependent downloads if (mRemainingDownloads == 0) { mCB(); return; } String assetURIString = mAssetURI.toString(); for(TextureList::const_iterator it = md->textures.begin(); it != md->textures.end(); it++) { String texURIString = assetURIString.substr(0, assetURIString.rfind("/")+1) + (*it); Transfer::URI texURI(texURIString); ResourceDownloadTaskPtr dl = ResourceDownloadTask::construct( texURI, mScene->transferPool(), mPriority, std::tr1::bind(&AssetDownloadTask::weakTextureDownloaded, getWeakPtr(), _1, _2) ); mActiveDownloads[texURI] = dl; dl->start(); } }
void AssetDownloadTask::textureDownloaded(Transfer::URI uri, ResourceDownloadTaskPtr taskptr, Transfer::TransferRequestPtr request, Transfer::DenseDataPtr response) { // This could be triggered by any CDN thread, protect access // (mActiveDownloads, mDependencies) boost::mutex::scoped_lock lok(mDependentDownloadMutex); if (!taskptr) { SILOG(ogre, warn, "failed request dependent callback"); failDownload(); return; } if (!request) { SILOG(ogre, warn, "failed request dependent callback " << taskptr->getIdentifier()); failDownload(); return; } // Clear the download task mActiveDownloads.erase(taskptr->getIdentifier()); mFinishedDownloads.push_back(taskptr->getIdentifier()); // Lack of response data means failure of some sort if (!response) { SILOG(ogre, warn, "failed response dependent callback " << taskptr->getIdentifier()); failDownload(); return; } // Store data for later use mDependencies[uri].request = request; mDependencies[uri].response = response; if (mActiveDownloads.size() == 0) mCB(); }
void AssetDownloadTask::failDownload() { // Cancel will stop the current download process. cancel(); // In this case, since it wasn't user requested, we also clear any parsed // data (e.g. if we failed on a texture download) and trigger a callback to // let them know about the failure. mAsset.reset(); mCB(); }
void AssetDownloadTask::textureDownloaded(std::tr1::shared_ptr<ChunkRequest> request, std::tr1::shared_ptr<const DenseData> response) { // Clear the download task mActiveDownloads.erase(request->getURI()); // Lack of response data means failure of some sort if (!response) { failDownload(); return; } // Store data for later use mDependencies[request->getURI()].request = request; mDependencies[request->getURI()].response = response; mRemainingDownloads--; if (mRemainingDownloads == 0) mCB(); }
void AssetDownloadTask::handleAssetParsed(Mesh::VisualPtr vis) { mAsset = vis; if (!vis) { SILOG(ogre,error,"Failed to parse mesh " << mAssetURI.toString()); mCB(); return; } // Now we need to handle downloads for each type of Visual. MeshdataPtr md( std::tr1::dynamic_pointer_cast<Meshdata>(vis) ); if (md) { // This is a sanity check. There's no way Ogre can reasonably handle meshes // that require a ton of draw calls. Estimate them here and if its too high, // destroy the data and invoke the callback to make it look like failure. { // Draw calls = // Number of instances * number of primitives in instance uint32 draw_calls = 0; Meshdata::GeometryInstanceIterator geoinst_it = md->getGeometryInstanceIterator(); uint32 geoinst_idx; Matrix4x4f pos_xform; while( geoinst_it.next(&geoinst_idx, &pos_xform) ) draw_calls += md->geometry[ md->instances[geoinst_idx].geometryIndex ].primitives.size(); // Arbitrary number, but probably more than we should even allow given // that there are probably hundreds or thousands of other objects if (draw_calls > 500) { SILOG(ogre,error,"Excessively complicated mesh: " << mAssetURI.toString() << " has " << draw_calls << " draw calls. Ignoring this mesh."); mAsset = Mesh::VisualPtr(); mCB(); return; } } // Another sanity check: if we have an excessive number of textures, // we're probably going to hit some memory constraints { // Complete arbitrary number if (md->textures.size() > 100) { SILOG(ogre,error, "Mesh with excessive number of textures: " << mAssetURI.toString() << " has " << md->textures.size() << " textures. Ignoring this mesh."); mAsset = Mesh::VisualPtr(); mCB(); return; } } // Special case for no dependent downloads if (md->textures.size() == 0) { mCB(); return; } for(TextureList::const_iterator it = md->textures.begin(); it != md->textures.end(); it++) { const std::string& texName = *it; Transfer::URI texURI( getURL(mAssetURI, texName) ); ProgressiveMipmapMap::const_iterator findProgTex; if (md->progressiveData) { findProgTex = md->progressiveData->mipmaps.find(texName); } if (md->progressiveData && findProgTex != md->progressiveData->mipmaps.end()) { const ProgressiveMipmaps& progMipmaps = findProgTex->second.mipmaps; uint32 mipmapLevel = 0; for ( ; mipmapLevel < progMipmaps.size(); mipmapLevel++) { if (progMipmaps.find(mipmapLevel)->second.width >= 128 || progMipmaps.find(mipmapLevel)->second.height >= 128) { break; } } uint32 offset = progMipmaps.find(mipmapLevel)->second.offset; uint32 length = progMipmaps.find(mipmapLevel)->second.length; Transfer::Fingerprint hash = findProgTex->second.archiveHash; addDependentDownload(texURI, Transfer::Chunk(hash, Transfer::Range(offset, length, Transfer::LENGTH))); } else { addDependentDownload(texURI); } } startDependentDownloads(); return; } BillboardPtr bboard( std::tr1::dynamic_pointer_cast<Billboard>(vis) ); if (bboard) { // For billboards, we have to download at least the image to display on // it Transfer::URI texURI( getURL(mAssetURI, bboard->image) ); addDependentDownload(texURI); startDependentDownloads(); return; } // If we've gotten here, then we haven't handled the specific type of visual // and we need to issue a warning and callback. SILOG(ogre, error, "Tried to use AssetDownloadTask for a visual type it doesn't handle (" << vis->type() << "). Not downloading dependent resources."); mCB(); }