From c065a4b203ec53906477aa77e0e205351d83523e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 19:01:03 +0200 Subject: [PATCH] Add ManualResourceLoader for global map overlay (Fixes #1736) --- apps/openmw/mwgui/mapwindow.cpp | 8 +--- apps/openmw/mwrender/globalmap.cpp | 70 ++++++++++++++++++++---------- apps/openmw/mwrender/globalmap.hpp | 6 ++- apps/openmw/mwrender/localmap.cpp | 1 + 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 39df4d03e..1f2794be3 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -544,15 +544,9 @@ namespace MWGui void MapWindow::open() { - // force markers to foreground - for (unsigned int i=0; igetChildCount (); ++i) - { - if (mGlobalMapOverlay->getChildAt (i)->getName().substr(0,4) == "Door") - mGlobalMapOverlay->getChildAt (i)->castType()->setImageResource("DoorMarker"); - } - globalMapUpdatePlayer(); + mPlayerArrowGlobal->setImageTexture (""); mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds"); } diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 1ccfd9527..d543308ff 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -31,6 +31,10 @@ namespace MWRender { } + GlobalMap::~GlobalMap() + { + Ogre::TextureManager::getSingleton().remove(mOverlayTexture->getName()); + } void GlobalMap::render (Loading::Listener* loadingListener) { @@ -168,9 +172,8 @@ namespace MWRender tex->load(); - mOverlayTexture = Ogre::TextureManager::getSingleton().createManual("GlobalMapOverlay", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC_WRITE_ONLY); + Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC, this); clear(); @@ -194,9 +197,11 @@ namespace MWRender void GlobalMap::exploreCell(int cellX, int cellY) { - float originX = (cellX - mMinX) * 24; + const int size = 24; + + float originX = (cellX - mMinX) * size; // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is - float originY = mHeight - (cellY+1 - mMinY) * 24; + float originY = mHeight - (cellY+1 - mMinY) * size; if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; @@ -204,31 +209,47 @@ namespace MWRender Ogre::TexturePtr localMapTexture = Ogre::TextureManager::getSingleton().getByName("Cell_" + boost::lexical_cast(cellX) + "_" + boost::lexical_cast(cellY)); - // mipmap version - can't get ogre to generate automips.. - /*if (!localMapTexture.isNull()) - { - assert(localMapTexture->getBuffer(0, 4)->getWidth() == 64); // 1024 / 2^4 - - mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(0, 4), Ogre::Image::Box(0,0,64, 64), - Ogre::Image::Box(originX,originY,originX+24,originY+24)); - }*/ - if (!localMapTexture.isNull()) { + mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512), - Ogre::Image::Box(originX,originY,originX+24,originY+24)); + Ogre::Image::Box(originX,originY,originX+size,originY+size)); + + Ogre::Image backup; + std::vector data; + data.resize(size*size*4, 0); + backup.loadDynamicImage(&data[0], size, size, Ogre::PF_A8B8G8R8); + + localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,512,512), backup.getPixelBox()); + + for (int x=0; x buffer; - // initialize to (0,0,0,0) - buffer.resize(mWidth * mHeight, 0); + Ogre::uchar* buffer = OGRE_ALLOC_T(Ogre::uchar, mWidth * mHeight * 4, Ogre::MEMCATEGORY_GENERAL); + memset(buffer, 0, mWidth * mHeight * 4); - Ogre::PixelBox pb(mWidth, mHeight, 1, Ogre::PF_A8B8G8R8, &buffer[0]); + mOverlayImage.loadDynamicImage(&buffer[0], mWidth, mHeight, 1, Ogre::PF_A8B8G8R8, true); // pass ownership of buffer to image - mOverlayTexture->getBuffer()->blitFromMemory(pb); + mOverlayTexture->load(); + } + + void GlobalMap::loadResource(Ogre::Resource *resource) + { + Ogre::Texture* tex = dynamic_cast(resource); + Ogre::ConstImagePtrList list; + list.push_back(&mOverlayImage); + tex->_loadImages(list); } void GlobalMap::write(ESM::GlobalMap& map) @@ -238,9 +259,7 @@ namespace MWRender map.mBounds.mMinY = mMinY; map.mBounds.mMaxY = mMaxY; - Ogre::Image image; - mOverlayTexture->convertToImage(image); - Ogre::DataStreamPtr encoded = image.encode("png"); + Ogre::DataStreamPtr encoded = mOverlayImage.encode("png"); map.mImageData.resize(encoded->size()); encoded->read(&map.mImageData[0], encoded->size()); } @@ -303,8 +322,15 @@ namespace MWRender image.getHeight(), 0, Ogre::PF_A8B8G8R8); tex->loadImage(image); + mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); + if (srcBox.left == destBox.left && srcBox.right == destBox.right + && srcBox.top == destBox.top && srcBox.bottom == destBox.bottom) + mOverlayImage = image; + else + mOverlayTexture->convertToImage(mOverlayImage); + Ogre::TextureManager::getSingleton().remove("@temp"); } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 6075d042e..050da8e7f 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -18,10 +18,11 @@ namespace ESM namespace MWRender { - class GlobalMap + class GlobalMap : public Ogre::ManualResourceLoader { public: GlobalMap(const std::string& cacheDir); + ~GlobalMap(); void render(Loading::Listener* loadingListener); @@ -36,6 +37,8 @@ namespace MWRender void exploreCell (int cellX, int cellY); + virtual void loadResource(Ogre::Resource* resource); + /// Clears the overlay void clear(); @@ -48,6 +51,7 @@ namespace MWRender std::vector< std::pair > mExploredCells; Ogre::TexturePtr mOverlayTexture; + Ogre::Image mOverlayImage; // Backup in system memory int mWidth; int mHeight; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 50dec8950..ace105b2d 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -324,6 +324,7 @@ void LocalMap::createFogOfWar(const std::string& texturePrefix) buffer.resize(sFogOfWarResolution*sFogOfWarResolution, 0xFF000000); // upload to the texture + tex->load(); memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); tex->getBuffer()->unlock();