From bb32c761df2d08e65128998e6dd68bcfe7737bca Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 28 Mar 2015 02:20:20 +0100 Subject: [PATCH] *very* early texture manager, need a lot more thought to design this properly --- apps/nifosgtest/test.cpp | 5 +- apps/opencs/view/render/scenewidget.cpp | 2 +- components/CMakeLists.txt | 2 +- components/nifosg/controller.cpp | 9 +--- components/nifosg/controller.hpp | 6 +-- components/nifosg/nifloader.cpp | 59 ++++++++++------------ components/nifosg/nifloader.hpp | 9 ++-- components/resource/resourcesystem.cpp | 4 +- components/resource/resourcesystem.hpp | 4 ++ components/resource/scenemanager.cpp | 7 ++- components/resource/scenemanager.hpp | 8 ++- components/resource/texturemanager.cpp | 66 +++++++++++++++++++++++++ components/resource/texturemanager.hpp | 48 ++++++++++++++++++ 13 files changed, 176 insertions(+), 53 deletions(-) create mode 100644 components/resource/texturemanager.cpp create mode 100644 components/resource/texturemanager.hpp diff --git a/apps/nifosgtest/test.cpp b/apps/nifosgtest/test.cpp index dec038825..332867be5 100644 --- a/apps/nifosgtest/test.cpp +++ b/apps/nifosgtest/test.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include @@ -124,7 +126,8 @@ int main(int argc, char** argv) //osgDB::writeNodeFile(*newNode, "out.osg"); osg::Group* newNode = new osg::Group; NifOsg::Loader loader; - loader.resourceManager = &resourceMgr; + Resource::TextureManager texMgr(&resourceMgr); + loader.mTextureManager = &texMgr; newNode->addChild(loader.load(nif)); osg::PositionAttitudeTransform* trans = new osg::PositionAttitudeTransform; diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 16ad2e68a..d7a85410b 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -109,7 +109,7 @@ CompositeViewer::CompositeViewer() setRunFrameScheme(osgViewer::ViewerBase::CONTINUOUS); connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) ); - mTimer.start( 10 ); + mTimer.start( 0 ); } CompositeViewer &CompositeViewer::get() diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 161c9ce4a..47fcf2499 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -39,7 +39,7 @@ add_component_dir (vfs ) add_component_dir (resource - scenemanager resourcesystem + scenemanager texturemanager resourcesystem ) add_component_dir (sceneutil diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 6aa920553..eca5a7d79 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -416,7 +416,7 @@ void MaterialColorController::operator() (osg::Node* node, osg::NodeVisitor* nv) traverse(node, nv); } -FlipController::FlipController(const Nif::NiFlipController *ctrl, std::vector > textures) +FlipController::FlipController(const Nif::NiFlipController *ctrl, std::vector > textures) : mTexSlot(ctrl->mTexSlot) , mDelta(ctrl->mDelta) , mTextures(textures) @@ -442,12 +442,7 @@ void FlipController::operator() (osg::Node* node, osg::NodeVisitor* nv) { osg::StateSet* stateset = node->getStateSet(); int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); - osg::Texture2D* tex = dynamic_cast(stateset->getTextureAttribute(mTexSlot, osg::StateAttribute::TEXTURE)); - if (tex) - tex->setImage(mTextures[curTexture].get()); - else - std::cout << "FlipController: can't find target slot" << std::endl; - + stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]); } traverse(node, nv); } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 7579735ca..0e5885333 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -13,7 +13,7 @@ #include //UVController // FlipController -#include +#include #include #include @@ -265,10 +265,10 @@ namespace NifOsg private: int mTexSlot; float mDelta; - std::vector > mTextures; + std::vector > mTextures; public: - FlipController(const Nif::NiFlipController* ctrl, std::vector > textures); + FlipController(const Nif::NiFlipController* ctrl, std::vector > textures); FlipController(); FlipController(const FlipController& copy, const osg::CopyOp& copyop); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 7e1c27b0e..ace14c669 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -6,12 +6,12 @@ #include #include -// resource -#include -#include #include + +// resource #include #include +#include // skel #include @@ -510,11 +510,11 @@ namespace NifOsg class LoaderImpl { public: - const VFS::Manager* mResourceManager; + Resource::TextureManager* mTextureManager; bool mShowMarkers; - LoaderImpl(const VFS::Manager* resourceManager, bool showMarkers) - : mResourceManager(resourceManager) + LoaderImpl(Resource::TextureManager* textureManager, bool showMarkers) + : mTextureManager(textureManager) , mShowMarkers(showMarkers) { } @@ -846,22 +846,26 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiFlipController) { const Nif::NiFlipController* flipctrl = static_cast(ctrl.getPtr()); - std::vector > textures; + std::vector > textures; for (unsigned int i=0; imSources.length(); ++i) { Nif::NiSourceTexturePtr st = flipctrl->mSources[i]; if (st.empty()) continue; - std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, mResourceManager); + // inherit wrap settings from the target slot + osg::Texture2D* inherit = dynamic_cast(stateset->getTextureAttribute(flipctrl->mTexSlot, osg::StateAttribute::TEXTURE)); + osg::Texture2D::WrapMode wrapS = osg::Texture2D::CLAMP; + osg::Texture2D::WrapMode wrapT = osg::Texture2D::CLAMP; + if (inherit) + { + wrapS = inherit->getWrap(osg::Texture2D::WRAP_S); + wrapT = inherit->getWrap(osg::Texture2D::WRAP_T); + } - // TODO: replace with texture manager - // tx_creature_werewolf.dds isn't loading in the correct format without this option - osgDB::Options* opts = new osgDB::Options; - opts->setOptionString("dds_dxt1_detect_rgba"); - osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("dds"); - osgDB::ReaderWriter::ReadResult result = reader->readImage(*mResourceManager->get(filename.c_str()), opts); - textures.push_back(osg::ref_ptr(result.getImage())); + std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, mTextureManager->getVFS()); + osg::ref_ptr texture = mTextureManager->getTexture2D(filename, wrapS, wrapT); + textures.push_back(texture); } osg::ref_ptr callback(new FlipController(flipctrl, textures)); setupController(ctrl.getPtr(), callback, animflags); @@ -1398,26 +1402,15 @@ namespace NifOsg continue; } - std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, mResourceManager); - - // TODO: replace with texture manager - // tx_creature_werewolf.dds isn't loading in the correct format without this option - osgDB::Options* opts = new osgDB::Options; - opts->setOptionString("dds_dxt1_detect_rgba"); - osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("dds"); - osgDB::ReaderWriter::ReadResult result = reader->readImage(*mResourceManager->get(filename.c_str()), opts); - osg::Image* image = result.getImage(); - osg::Texture2D* texture2d = new osg::Texture2D; - // Can be enabled for single-context, i.e. in openmw - //texture2d->setUnRefImageDataAfterApply(true); - texture2d->setImage(image); + std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, mTextureManager->getVFS()); unsigned int clamp = static_cast(tex.clamp); int wrapT = (clamp) & 0x1; int wrapS = (clamp >> 1) & 0x1; - texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP); - texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); + osg::Texture2D* texture2d = mTextureManager->getTexture2D(filename, + wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP, + wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); stateset->setTextureAttributeAndModes(i, texture2d, osg::StateAttribute::ON); @@ -1544,19 +1537,19 @@ namespace NifOsg osg::ref_ptr Loader::load(Nif::NIFFilePtr file, TextKeyMap *textKeys) { - LoaderImpl loader(resourceManager, sShowMarkers); + LoaderImpl loader(mTextureManager, sShowMarkers); return loader.load(file, textKeys); } osg::ref_ptr Loader::loadAsSkeleton(Nif::NIFFilePtr file, TextKeyMap *textKeys) { - LoaderImpl loader(resourceManager, sShowMarkers); + LoaderImpl loader(mTextureManager, sShowMarkers); return loader.loadAsSkeleton(file, textKeys); } void Loader::loadKf(Nif::NIFFilePtr kf, osg::Node *rootNode, int sourceIndex, TextKeyMap &textKeys) { - LoaderImpl loader(resourceManager, sShowMarkers); + LoaderImpl loader(mTextureManager, sShowMarkers); loader.loadKf(kf, rootNode, sourceIndex, textKeys); } diff --git a/components/nifosg/nifloader.hpp b/components/nifosg/nifloader.hpp index 87d1a0a99..716cd1957 100644 --- a/components/nifosg/nifloader.hpp +++ b/components/nifosg/nifloader.hpp @@ -5,8 +5,6 @@ #include // NIFFilePtr -#include - #include namespace osg @@ -14,6 +12,11 @@ namespace osg class Node; } +namespace Resource +{ + class TextureManager; +} + namespace NifOsg { typedef std::multimap TextKeyMap; @@ -41,7 +44,7 @@ namespace NifOsg /// Default: false. static void setShowMarkers(bool show); - const VFS::Manager* resourceManager; + Resource::TextureManager* mTextureManager; private: diff --git a/components/resource/resourcesystem.cpp b/components/resource/resourcesystem.cpp index e87ef6f10..215b1a67c 100644 --- a/components/resource/resourcesystem.cpp +++ b/components/resource/resourcesystem.cpp @@ -1,6 +1,7 @@ #include "resourcesystem.hpp" #include "scenemanager.hpp" +#include "texturemanager.hpp" namespace Resource { @@ -8,7 +9,8 @@ namespace Resource ResourceSystem::ResourceSystem(const VFS::Manager *vfs) : mVFS(vfs) { - mSceneManager.reset(new SceneManager(vfs)); + mTextureManager.reset(new TextureManager(vfs)); + mSceneManager.reset(new SceneManager(vfs, mTextureManager.get())); } SceneManager* ResourceSystem::getSceneManager() diff --git a/components/resource/resourcesystem.hpp b/components/resource/resourcesystem.hpp index b696a2376..a91f3cab3 100644 --- a/components/resource/resourcesystem.hpp +++ b/components/resource/resourcesystem.hpp @@ -12,8 +12,11 @@ namespace Resource { class SceneManager; + class TextureManager; /// @brief Wrapper class that constructs and provides access to the various resource subsystems. + /// @par Resource subsystems can be used with multiple OpenGL contexts, just like the OSG equivalents, but + /// are built around the use of a single virtual file system. class ResourceSystem { public: @@ -25,6 +28,7 @@ namespace Resource private: std::auto_ptr mSceneManager; + std::auto_ptr mTextureManager; const VFS::Manager* mVFS; }; diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index c7fd5065e..c44cbd2ae 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include namespace @@ -61,8 +63,9 @@ namespace namespace Resource { - SceneManager::SceneManager(const VFS::Manager *vfs) + SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager) : mVFS(vfs) + , mTextureManager(textureManager) { } @@ -79,7 +82,7 @@ namespace Resource // TODO: add support for non-NIF formats NifOsg::Loader loader; - loader.resourceManager = mVFS; + loader.mTextureManager = mTextureManager; osg::ref_ptr loaded = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized))); // TODO: provide way for the user to get textKeys (attach to the node?) diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 76b69be6e..3d439c186 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -7,6 +7,11 @@ #include #include +namespace Resource +{ + class TextureManager; +} + namespace VFS { class Manager; @@ -19,7 +24,7 @@ namespace Resource class SceneManager { public: - SceneManager(const VFS::Manager* vfs); + SceneManager(const VFS::Manager* vfs, Resource::TextureManager* textureManager); /// Get a read-only copy of this scene "template" osg::ref_ptr getTemplate(const std::string& name); @@ -38,6 +43,7 @@ namespace Resource private: const VFS::Manager* mVFS; + Resource::TextureManager* mTextureManager; // observer_ptr? typedef std::map > Index; diff --git a/components/resource/texturemanager.cpp b/components/resource/texturemanager.cpp new file mode 100644 index 000000000..8347d5f04 --- /dev/null +++ b/components/resource/texturemanager.cpp @@ -0,0 +1,66 @@ +#include "texturemanager.hpp" + +#include + +#include + +#include + +namespace Resource +{ + + TextureManager::TextureManager(const VFS::Manager *vfs) + : mVFS(vfs) + { + + } + + /* + osg::ref_ptr TextureManager::getImage(const std::string &filename) + { + + } + */ + + osg::ref_ptr TextureManager::getTexture2D(const std::string &filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT) + { + std::string normalized = filename; + mVFS->normalizeFilename(normalized); + MapKey key = std::make_pair(std::make_pair(wrapS, wrapT), normalized); + std::map >::iterator found = mTextures.find(key); + if (found != mTextures.end()) + { + return found->second; + } + else + { + osg::ref_ptr 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); + osgDB::ReaderWriter::ReadResult result = reader->readImage(*mVFS->get(normalized.c_str()), opts); + if (!result.success()) + { + // TODO: use "notfound" default texture + throw std::runtime_error("Error loading"); + //std::cerr << "Error loading " << filename << ": " << result.message() << std::endl; + } + + osg::Image* image = result.getImage(); + osg::ref_ptr texture(new osg::Texture2D); + texture->setImage(image); + texture->setWrap(osg::Texture::WRAP_S, wrapS); + texture->setWrap(osg::Texture::WRAP_T, wrapT); + + // Can be enabled for single-context, i.e. in openmw + //texture->setUnRefImageDataAfterApply(true); + + mTextures.insert(std::make_pair(key, texture)); + return texture; + } + } + +} diff --git a/components/resource/texturemanager.hpp b/components/resource/texturemanager.hpp new file mode 100644 index 000000000..c0b36f7cf --- /dev/null +++ b/components/resource/texturemanager.hpp @@ -0,0 +1,48 @@ +#ifndef OPENMW_COMPONENTS_RESOURCE_TEXTUREMANAGER_H +#define OPENMW_COMPONENTS_RESOURCE_TEXTUREMANAGER_H + +#include +#include + +#include +#include +#include + +namespace VFS +{ + class Manager; +} + +namespace Resource +{ + + /// @brief Handles loading/caching of Images and Texture StateAttributes. + class TextureManager + { + public: + TextureManager(const VFS::Manager* vfs); + + // TODO: texture filtering settings + + /// Create or retrieve a Texture2D using the specified image filename, and wrap parameters. + osg::ref_ptr getTexture2D(const std::string& filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT); + + /// Create or retrieve an Image + //osg::ref_ptr getImage(const std::string& filename); + + const VFS::Manager* getVFS() { return mVFS; } + + private: + const VFS::Manager* mVFS; + + typedef std::pair, std::string> MapKey; + + std::map > mImages; + + std::map > mTextures; + + }; + +} + +#endif