Support for loading .osg mesh format

openmw-38
scrawl 9 years ago
parent 21e25f4756
commit eb2f16d682

@ -19,7 +19,9 @@ void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
mVFS = vfs;
mResources.clear();
static const char * const sMeshTypes[] = { "nif", 0 };
// maybe we could go over the osgDB::Registry to list all supported node formats
static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2", 0 };
addResources (Resources (vfs, "meshes", UniversalId::Type_Mesh, sMeshTypes));
addResources (Resources (vfs, "icons", UniversalId::Type_Icon));

@ -975,7 +975,7 @@ namespace MWPhysics
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh)
{
osg::ref_ptr<NifBullet::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh);
if (!shapeInstance->getCollisionShape())
if (!shapeInstance || !shapeInstance->getCollisionShape())
return;
Object *obj = new Object(ptr, shapeInstance);
@ -1114,9 +1114,10 @@ namespace MWPhysics
}
}
void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh)
{
void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh) {
osg::ref_ptr<NifBullet::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh);
if (!shapeInstance)
return;
Actor* actor = new Actor(ptr, shapeInstance, mCollisionWorld);
mActors.insert(std::make_pair(ptr, actor));

@ -402,7 +402,7 @@ namespace MWRender
animsrc.reset(new AnimSource);
animsrc->mKeyframes = mResourceSystem->getSceneManager()->getKeyframes(kfname);
if (animsrc->mKeyframes->mTextKeys.empty() || animsrc->mKeyframes->mKeyframeControllers.empty())
if (!animsrc->mKeyframes || animsrc->mKeyframes->mTextKeys.empty() || animsrc->mKeyframes->mKeyframeControllers.empty())
return;
for (NifOsg::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin();

@ -30,6 +30,13 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
Files::IStreamPtr file = mVFS->get(normalized);
// TODO: add support for non-NIF formats
size_t extPos = normalized.find_last_of('.');
std::string ext;
if (extPos != std::string::npos && extPos+1 < normalized.size())
ext = normalized.substr(extPos+1);
if (ext != "nif")
return NULL;
BulletNifLoader loader;
// might be worth sharing NIFFiles with SceneManager in some way

@ -20,6 +20,8 @@
#include <components/sceneutil/clone.hpp>
#include <components/sceneutil/util.hpp>
#include "texturemanager.hpp"
namespace
{
@ -112,6 +114,73 @@ namespace Resource
SceneManager::~SceneManager()
{
// this has to be defined in the .cpp file as we can't delete incomplete types
}
/// @brief Callback to read image files from the VFS.
class ImageReadCallback : public osgDB::ReadFileCallback
{
public:
ImageReadCallback(Resource::TextureManager* textureMgr)
: mTextureManager(textureMgr)
{
}
virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
{
try
{
mTextureManager->getTexture2D(filename, osg::Texture::CLAMP_TO_EDGE, osg::Texture::CLAMP_TO_EDGE);
return osgDB::ReaderWriter::ReadResult(mTextureManager->getImage(filename), osgDB::ReaderWriter::ReadResult::FILE_LOADED);
}
catch (std::exception& e)
{
return osgDB::ReaderWriter::ReadResult(e.what());
}
}
private:
Resource::TextureManager* mTextureManager;
};
std::string getFileExtension(const std::string& file)
{
size_t extPos = file.find_last_of('.');
if (extPos != std::string::npos && extPos+1 < file.size())
return file.substr(extPos+1);
return std::string();
}
osg::ref_ptr<osg::Node> load (Files::IStreamPtr file, const std::string& normalizedFilename, Resource::TextureManager* textureMgr)
{
std::string ext = getFileExtension(normalizedFilename);
if (ext == "nif")
return NifOsg::Loader::load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalizedFilename)), textureMgr);
else
{
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
if (!reader)
{
std::stringstream errormsg;
errormsg << "Error loading " << normalizedFilename << ": no readerwriter for '" << ext << "' found" << std::endl;
throw std::runtime_error(errormsg.str());
}
osg::ref_ptr<osgDB::Options> options (new osgDB::Options);
// Set a ReadFileCallback so that image files referenced in the model are read from our virtual file system instead of the osgDB.
// Note, for some formats (.obj/.mtl) that reference other (non-image) files a findFileCallback would be necessary.
// but findFileCallback does not support virtual files, so we can't implement it.
options->setReadFileCallback(new ImageReadCallback(textureMgr));
osgDB::ReaderWriter::ReadResult result = reader->readNode(*file, options);
if (!result.success())
{
std::stringstream errormsg;
errormsg << "Error loading " << normalizedFilename << ": " << result.message() << " code " << result.status() << std::endl;
throw std::runtime_error(errormsg.str());
}
return result.getNode();
}
}
osg::ref_ptr<const osg::Node> SceneManager::getTemplate(const std::string &name)
@ -122,19 +191,19 @@ namespace Resource
Index::iterator it = mIndex.find(normalized);
if (it == mIndex.end())
{
// TODO: add support for non-NIF formats
osg::ref_ptr<osg::Node> loaded;
try
{
Files::IStreamPtr file = mVFS->get(normalized);
loaded = NifOsg::Loader::load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)), mTextureManager);
loaded = load(file, normalized, mTextureManager);
}
catch (std::exception& e)
{
std::cerr << "Failed to load '" << name << "': " << e.what() << ", using marker_error.nif instead" << std::endl;
Files::IStreamPtr file = mVFS->get("meshes/marker_error.nif");
loaded = NifOsg::Loader::load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)), mTextureManager);
normalized = "meshes/marker_error.nif";
loaded = load(file, normalized, mTextureManager);
}
osgDB::Registry::instance()->getOrCreateSharedStateManager()->share(loaded.get());
@ -174,6 +243,11 @@ namespace Resource
{
Files::IStreamPtr file = mVFS->get(normalized);
std::string ext = getFileExtension(normalized);
if (ext != "nif" && ext != "kf")
return NULL;
osg::ref_ptr<NifOsg::KeyframeHolder> loaded (new NifOsg::KeyframeHolder);
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)), *loaded.get());

@ -143,6 +143,57 @@ namespace Resource
return true;
}
osg::ref_ptr<osg::Image> TextureManager::getImage(const std::string &filename)
{
std::string normalized = filename;
mVFS->normalizeFilename(normalized);
std::map<std::string, osg::ref_ptr<osg::Image> >::iterator found = mImages.find(normalized);
if (found != mImages.end())
return found->second;
else
{
Files::IStreamPtr stream;
try
{
stream = mVFS->get(normalized.c_str());
}
catch (std::exception& e)
{
std::cerr << "Failed to open image: " << e.what() << std::endl;
return NULL;
}
osg::ref_ptr<osgDB::Options> opts (new osgDB::Options);
opts->setOptionString("dds_dxt1_detect_rgba"); // tx_creature_werewolf.dds isn't loading in the correct format without this option
size_t extPos = normalized.find_last_of('.');
std::string ext;
if (extPos != std::string::npos && extPos+1 < normalized.size())
ext = normalized.substr(extPos+1);
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
if (!reader)
{
std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl;
return NULL;
}
osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, opts);
if (!result.success())
{
std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl;
return NULL;
}
osg::Image* image = result.getImage();
if (!checkSupported(image, filename))
{
return NULL;
}
mImages.insert(std::make_pair(normalized, image));
return image;
}
}
osg::ref_ptr<osg::Texture2D> TextureManager::getTexture2D(const std::string &filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT)
{
std::string normalized = filename;

@ -34,7 +34,7 @@ namespace Resource
osg::ref_ptr<osg::Texture2D> getTexture2D(const std::string& filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT);
/// Create or retrieve an Image
//osg::ref_ptr<osg::Image> getImage(const std::string& filename);
osg::ref_ptr<osg::Image> getImage(const std::string& filename);
const VFS::Manager* getVFS() { return mVFS; }
@ -49,7 +49,7 @@ namespace Resource
typedef std::pair<std::pair<int, int>, std::string> MapKey;
std::map<std::string, osg::observer_ptr<osg::Image> > mImages;
std::map<std::string, osg::ref_ptr<osg::Image> > mImages;
std::map<MapKey, osg::ref_ptr<osg::Texture2D> > mTextures;

Loading…
Cancel
Save