Skip to content

Commit

Permalink
Load a default (white cube) if mesh cannot be downloaded.
Browse files Browse the repository at this point in the history
Provide a white cube mesh, to be included locally with the
installation, and have OgreSystem load it when an asset can't be
loaded. Fixes sirikata#250.
  • Loading branch information
ewencp committed Jun 1, 2011
1 parent 2fed65d commit c64ac6a
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 13 deletions.
5 changes: 5 additions & 0 deletions libogre/include/sirikata/ogre/OgreRenderer.hpp
Expand Up @@ -155,6 +155,10 @@ class SIRIKATA_OGRE_EXPORT OgreRenderer : public TimeSteppedQueryableSimulation,
*/
void parseMesh(const Transfer::URI& orig_uri, const Transfer::Fingerprint& fp, Transfer::DenseDataPtr data, ParseMeshCallback cb);

/** Get the default mesh to present if a model fails to load. This may
* return an empty MeshdataPtr if no default mesh is specified.
*/
virtual Mesh::MeshdataPtr defaultMesh() const { return Mesh::MeshdataPtr(); }

void screenshot(const String& filename);
void screenshotNextFrame(const String& filename);
Expand All @@ -177,6 +181,7 @@ class SIRIKATA_OGRE_EXPORT OgreRenderer : public TimeSteppedQueryableSimulation,


void parseMeshWork(const Transfer::URI& orig_uri, const Transfer::Fingerprint& fp, Transfer::DenseDataPtr data, ParseMeshCallback cb);
Mesh::MeshdataPtr parseMeshWorkSync(const Transfer::URI& orig_uri, const Transfer::Fingerprint& fp, Transfer::DenseDataPtr data);


static Ogre::Root* sRoot;
Expand Down
Expand Up @@ -82,6 +82,11 @@ class AssetDownloadTask : public SelfWeakPtr<AssetDownloadTask>{
void textureDownloaded(std::tr1::shared_ptr<Transfer::ChunkRequest> request,
std::tr1::shared_ptr<const Transfer::DenseData> response);


// Fails the entire process as a result of one dependency (or the original
// asset) failing to download.
void failDownload();

Graphics::OgreRenderer *const mScene;
Transfer::URI mAssetURI;
double mPriority; // FIXME this should really be a function or functor to
Expand Down
26 changes: 16 additions & 10 deletions libogre/src/Entity.cpp
Expand Up @@ -1135,10 +1135,15 @@ bool Entity::tryInstantiateExistingMesh(const String& meshname) {


void Entity::createMesh() {
bool usingDefault = false;
MeshdataPtr mdptr = mAssetDownload->asset();
if (!mdptr) {
notify(&EntityListener::entityLoaded, this, false);
return;
usingDefault = true;
mdptr = mScene->defaultMesh();
if (!mdptr) {
notify(&EntityListener::entityLoaded, this, false);
return;
}
}

SHA256 sha = mdptr->hash;
Expand All @@ -1147,19 +1152,20 @@ void Entity::createMesh() {
// If we already have it, just load the existing one
if (tryInstantiateExistingMesh(hash)) return;

for(AssetDownloadTask::Dependencies::const_iterator tex_it = mAssetDownload->dependencies().begin(); tex_it != mAssetDownload->dependencies().end(); tex_it++) {
const AssetDownloadTask::ResourceData& tex_data = tex_it->second;
if (mActiveCDNArchive && mTextureFingerprints->find(tex_data.request->getURI().toString()) == mTextureFingerprints->end() ) {
String id = tex_data.request->getURI().toString() + tex_data.request->getMetadata().getFingerprint().toString();
if (!usingDefault) { // we currently assume no dependencies for default
for(AssetDownloadTask::Dependencies::const_iterator tex_it = mAssetDownload->dependencies().begin(); tex_it != mAssetDownload->dependencies().end(); tex_it++) {
const AssetDownloadTask::ResourceData& tex_data = tex_it->second;
if (mActiveCDNArchive && mTextureFingerprints->find(tex_data.request->getURI().toString()) == mTextureFingerprints->end() ) {
String id = tex_data.request->getURI().toString() + tex_data.request->getMetadata().getFingerprint().toString();

(*mTextureFingerprints)[tex_data.request->getURI().toString()] = id;
(*mTextureFingerprints)[tex_data.request->getURI().toString()] = id;

fixOgreURI(id);
CDNArchiveFactory::getSingleton().addArchiveData(mCDNArchive,id,SparseData(tex_data.response));
fixOgreURI(id);
CDNArchiveFactory::getSingleton().addArchiveData(mCDNArchive,id,SparseData(tex_data.response));
}
}
}


if (!mdptr->instances.empty()) {
Ogre::MaterialManager& matm = Ogre::MaterialManager::getSingleton();
int index=0;
Expand Down
7 changes: 6 additions & 1 deletion libogre/src/OgreRenderer.cpp
Expand Up @@ -891,6 +891,11 @@ void OgreRenderer::parseMesh(const Transfer::URI& orig_uri, const Transfer::Fing
}

void OgreRenderer::parseMeshWork(const Transfer::URI& orig_uri, const Transfer::Fingerprint& fp, Transfer::DenseDataPtr data, ParseMeshCallback cb) {
Mesh::MeshdataPtr parsed = parseMeshWorkSync(orig_uri, fp, data);
mContext->mainStrand->post(std::tr1::bind(cb, parsed));
}

Mesh::MeshdataPtr OgreRenderer::parseMeshWorkSync(const Transfer::URI& orig_uri, const Transfer::Fingerprint& fp, Transfer::DenseDataPtr data) {
Mesh::MeshdataPtr parsed = mModelParser->load(orig_uri, fp, data);
if (parsed && mModelFilter) {
Mesh::MutableFilterDataPtr input_data(new Mesh::FilterData);
Expand All @@ -899,7 +904,7 @@ void OgreRenderer::parseMeshWork(const Transfer::URI& orig_uri, const Transfer::
assert(output_data->single());
parsed = output_data->get();
}
mContext->mainStrand->post(std::tr1::bind(cb, parsed));
return parsed;
}

void OgreRenderer::screenshot(const String& filename) {
Expand Down
23 changes: 23 additions & 0 deletions libogre/src/resourceManager/AssetDownloadTask.cpp
Expand Up @@ -88,6 +88,12 @@ void AssetDownloadTask::assetFileDownloaded(std::tr1::shared_ptr<ChunkRequest> r
assert(mActiveDownloads.size() == 1);
mActiveDownloads.erase(mAssetURI);

// Lack of response data means failure of some sort
if (!response) {
failDownload();
return;
}

// FIXME here we could have another callback which lets them get
// at the hash to try to use an existing copy. Even with the
// eventual centralized loading we want, this may still be
Expand Down Expand Up @@ -170,6 +176,12 @@ void AssetDownloadTask::textureDownloaded(std::tr1::shared_ptr<ChunkRequest> req
// 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;
Expand All @@ -179,4 +191,15 @@ void AssetDownloadTask::textureDownloaded(std::tr1::shared_ptr<ChunkRequest> req
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();
}

} // namespace Sirikata
8 changes: 6 additions & 2 deletions libogre/src/resourceManager/ResourceDownloadTask.cpp
Expand Up @@ -72,11 +72,14 @@ void ResourceDownloadTask::chunkFinished(std::tr1::shared_ptr<ResourceDownloadTa
std::tr1::shared_ptr<ChunkRequest> request,
std::tr1::shared_ptr<const DenseData> response)
{
if (response != NULL && cb) {
// Nothing to do with no callback
if (!cb) return;

if (response != NULL) {
cb(request, response);
}
else {
SILOG(ogre,error,"Failed chunk download");
cb(request, Transfer::DenseDataPtr());
}
}

Expand All @@ -97,6 +100,7 @@ void ResourceDownloadTask::metadataFinished(std::tr1::shared_ptr<ResourceDownloa
}
else {
SILOG(ogre,error,"Failed metadata download");
if (cb) cb(ChunkRequestPtr(), Transfer::DenseDataPtr());
}
}

Expand Down
28 changes: 28 additions & 0 deletions libproxyobject/plugins/ogre/OgreSystem.cpp
Expand Up @@ -126,6 +126,28 @@ void OgreSystem::instantiateAllObjects(ProxyManagerPtr pman)
}
}

namespace {
Transfer::DenseDataPtr read_file(const String& filename)
{
ifstream myfile;
myfile.open (filename.c_str());
if (!myfile.is_open()) return Transfer::DenseDataPtr();

myfile.seekg(0, ios::end);
int length = myfile.tellg();
myfile.seekg(0, ios::beg);

Transfer::MutableDenseDataPtr output(new Transfer::DenseData(Transfer::Range(true)));
output->setLength(length, true);

// read data as a block:
myfile.read((char*)output->writableData(), length);
myfile.close();

return output;
}
}

bool OgreSystem::initialize(VWObjectPtr viewer, const SpaceObjectReference& presenceid, const String& options) {
if(!OgreRenderer::initialize(options)) return false;

Expand All @@ -141,6 +163,12 @@ bool OgreSystem::initialize(VWObjectPtr viewer, const SpaceObjectReference& pres

allocMouseHandler();

// The default mesh is just loaded from a known local file
using namespace boost::filesystem;
String cube_path = (path(mResourcesDir) / "cube.dae").string();
Transfer::DenseDataPtr cube_data = read_file(cube_path);
mDefaultMesh = parseMeshWorkSync(Transfer::URI("file:///fake.dae"), Transfer::Fingerprint::null(), cube_data);

//finish instantiation here
instantiateAllObjects(proxyManager);

Expand Down
5 changes: 5 additions & 0 deletions libproxyobject/plugins/ogre/OgreSystem.hpp
Expand Up @@ -100,6 +100,8 @@ class OgreSystem: public OgreRenderer, protected SessionEventListener
int& returnSubMesh,
IntersectResult *returnIntersectResult, bool texcoord,
int which=0) const;

Mesh::MeshdataPtr mDefaultMesh;
public:

ProxyCamera *mPrimaryCamera;
Expand Down Expand Up @@ -177,6 +179,9 @@ class OgreSystem: public OgreRenderer, protected SessionEventListener
virtual void attachCamera(const String&renderTargetName,Camera*);
virtual void detachCamera(Camera*);


virtual Mesh::MeshdataPtr defaultMesh() const { return mDefaultMesh; }

// *******

// ConnectionEventListener Interface
Expand Down
92 changes: 92 additions & 0 deletions libproxyobject/plugins/ogre/data/cube.dae
@@ -0,0 +1,92 @@
<?xml version="1.0" ?><COLLADA version="1.5.1" xmlns="http://www.collada.org/2005/11/COLLADASchema">
<asset>
<unit meter="1.0" name="meter"/>
<up_axis>Y_UP</up_axis>
</asset>
<library_images>
</library_images>
<library_effects>
<effect id="nil_1" name="nil_1">
<profile_COMMON>
<technique sid="common">
<blinn>
<emission>
<color>0 0 0 1</color>
</emission>
<ambient>
<color>0 0 0 1</color>
</ambient>
<diffuse>
<color>1 1 1 1</color>
</diffuse>
<specular>
<color>1 1 1 1</color>
</specular>
<shininess>
<float>1.0</float>
</shininess>
</blinn>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_materials>
<material id="nil_1-material" name="nil_1">
<instance_effect url="#nil_1"/>
</material>
</library_materials>
<library_geometries>
<geometry id="cubedae_1-geometry" name="cubedae_1">
<mesh>
<source id="1_1-positions">
<float_array count="24" id="1_1-positions-array">
0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 1.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 1.0 </float_array>
<technique_common>
<accessor count="8" source="#1_1-positions-array" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="1_1-normals">
<float_array count="18" id="1_1-normals-array">
0.0 0.0 1.0 0.0 0.0 -1.0 0.0 1.0 0.0 0.0 -1.0 0.0 1.0 0.0 0.0 -1.0 0.0 0.0 </float_array>
<technique_common>
<accessor count="6" source="#1_1-normals-array" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="1_1-vertices">
<input semantic="POSITION" source="#1_1-positions"/>
</vertices>
<triangles count="12" material="nil_1-material">
<input offset="0" semantic="VERTEX" source="#1_1-vertices"/>
<input offset="1" semantic="NORMAL" source="#1_1-normals"/>
<p>0 1 6 1 4 1 0 1 2 1 6 1 0 5 3 5 2 5 0 5 1 5 3 5 2 2 7 2 6 2 2 2 3 2 7 2 4 4 6 4 7 4 4 4 7 4 5 4 0 3 4 3 5 3 0 3 5 3 1 3 1 0 5 0 7 0 1 0 7 0 3 0 </p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_visual_scenes>
<visual_scene id="main_scene_000" name="MainScene">
<node id="main_node_000" name="MainNode">
<instance_geometry url="#cubedae_1-geometry">
<bind_material>
<technique_common>
<instance_material symbol="nil_1-material" target="#nil_1-material">
<bind_vertex_input input_semantic="TEXCOORD" input_set="0" semantic="CHANNEL0"/>
</instance_material>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#main_scene_000"/>
</scene>
</COLLADA>

0 comments on commit c64ac6a

Please sign in to comment.