mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 13:15:32 +00:00
Support for loading .osg mesh format
This commit is contained in:
parent
21e25f4756
commit
eb2f16d682
7 changed files with 145 additions and 10 deletions
|
@ -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…
Reference in a new issue