From e8662bea3133ba9dbb09b86c3abb1af39425e90d Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 5 Feb 2016 20:23:41 +0100 Subject: [PATCH] Change the way that image origin is converted to OpenGL's lower-left convention Flip the texture coordinates instead of flipping textures. This simplifies the TextureManager (no need to worry if the caller wants flipping or not), should make it easier to generalize & multithread it. --- apps/openmw/mwgui/inventorywindow.cpp | 6 +++--- apps/openmw/mwgui/loadingscreen.cpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 8 ++++---- apps/openmw/mwgui/race.cpp | 2 +- apps/openmw/mwgui/savegamedialog.cpp | 2 +- apps/openmw/mwgui/videowidget.cpp | 2 +- apps/openmw/mwrender/characterpreview.cpp | 2 +- .../myguiplatform/myguirendermanager.cpp | 7 +++++++ components/myguiplatform/myguitexture.cpp | 2 ++ components/nif/data.cpp | 10 ++++++++-- components/resource/texturemanager.cpp | 18 +++--------------- components/resource/texturemanager.hpp | 6 ++++++ components/sdlutil/sdlcursormanager.cpp | 2 +- files/mygui/openmw_pointer.xml | 4 ++-- 14 files changed, 41 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index facb17d66..4599132e3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -87,7 +87,7 @@ namespace MWGui mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked); mAvatarImage->setRenderItemTexture(mPreviewTexture.get()); - mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); getWidget(mItemView, "ItemView"); mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected); @@ -403,8 +403,8 @@ namespace MWGui int height = std::min(mPreview->getTextureHeight(), size.height); mPreview->setViewport(width, height); - mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, height/float(mPreview->getTextureHeight()), - width/float(mPreview->getTextureWidth()), 0.f)); + mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, + width/float(mPreview->getTextureWidth()), height/float(mPreview->getTextureHeight()))); } void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index e32140cb3..6385eb2c6 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -164,7 +164,7 @@ namespace MWGui mBackgroundImage->setBackgroundImage(""); mBackgroundImage->setRenderItemTexture(mGuiTexture.get()); - mBackgroundImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mBackgroundImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); } setVisible(true); diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 362d2d9e0..1b8d5ab43 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -254,7 +254,7 @@ namespace MWGui { boost::shared_ptr myguitex (new osgMyGUI::OSGTexture(tex)); fog->setRenderItemTexture(myguitex.get()); - fog->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); + fog->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); fogTextures.push_back(myguitex); } else @@ -391,7 +391,7 @@ namespace MWGui boost::shared_ptr guiTex (new osgMyGUI::OSGTexture(texture)); textures.push_back(guiTex); box->setRenderItemTexture(guiTex.get()); - box->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + box->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); } else box->setRenderItemTexture(NULL); @@ -770,11 +770,11 @@ namespace MWGui mGlobalMapTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getBaseTexture())); mGlobalMapImage->setRenderItemTexture(mGlobalMapTexture.get()); - mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); mGlobalMapOverlayTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getOverlayTexture())); mGlobalMapOverlay->setRenderItemTexture(mGlobalMapOverlayTexture.get()); - mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); } MapWindow::~MapWindow() diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index a65379fca..aa229de72 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -142,7 +142,7 @@ namespace MWGui mPreviewTexture.reset(new osgMyGUI::OSGTexture(mPreview->getTexture())); mPreviewImage->setRenderItemTexture(mPreviewTexture.get()); - mPreviewImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mPreviewImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); const ESM::NPC& proto = mPreview->getPrototype(); setRaceId(proto.mRace); diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 53c280737..9de2374ad 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -422,6 +422,6 @@ namespace MWGui mScreenshotTexture.reset(new osgMyGUI::OSGTexture(texture)); mScreenshot->setRenderItemTexture(mScreenshotTexture.get()); - mScreenshot->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); + mScreenshot->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); } } diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp index d28ea0b66..5a4bb981f 100644 --- a/apps/openmw/mwgui/videowidget.cpp +++ b/apps/openmw/mwgui/videowidget.cpp @@ -50,7 +50,7 @@ void VideoWidget::playVideo(const std::string &video) mTexture.reset(new osgMyGUI::OSGTexture(texture)); setRenderItemTexture(mTexture.get()); - getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); + getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); } int VideoWidget::getVideoWidth() diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index a6f68b5d4..258854054 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -194,7 +194,7 @@ namespace MWRender sizeX = std::max(sizeX, 0); sizeY = std::max(sizeY, 0); - mCamera->setViewport(0, 0, std::min(mSizeX, sizeX), std::min(mSizeY, sizeY)); + mCamera->setViewport(0, mSizeY-sizeY, std::min(mSizeX, sizeX), std::min(mSizeY, sizeY)); redraw(); } diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index 5bd56dc8f..f5bebd560 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -189,6 +190,12 @@ public: mStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); mStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + + // need to flip tex coords since MyGUI uses DirectX convention of top left image origin + osg::Matrix flipMat; + flipMat.preMultTranslate(osg::Vec3f(0,1,0)); + flipMat.preMultScale(osg::Vec3f(1,-1,1)); + mStateSet->setTextureAttribute(0, new osg::TexMat(flipMat), osg::StateAttribute::ON); } Drawable(const Drawable ©, const osg::CopyOp ©op=osg::CopyOp::SHALLOW_COPY) : osg::Drawable(copy, copyop) diff --git a/components/myguiplatform/myguitexture.cpp b/components/myguiplatform/myguitexture.cpp index a42568cf8..3560a3ae3 100644 --- a/components/myguiplatform/myguitexture.cpp +++ b/components/myguiplatform/myguitexture.cpp @@ -145,6 +145,8 @@ namespace osgMyGUI if (!mLockedImage.valid()) throw std::runtime_error("Texture not locked"); + mLockedImage->flipVertical(); + // mTexture might be in use by the draw thread, so create a new texture instead and use that. osg::ref_ptr newTexture = new osg::Texture2D; newTexture->setTextureSize(getWidth(), getHeight()); diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 5a60ab8a5..08c268dde 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -65,8 +65,14 @@ void ShapeData::read(NIFStream *nif) uvlist.resize(uvs); for(int i = 0;i < uvs;i++) { - uvlist[i] = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); - nif->getVector2s(uvlist[i], verts); + osg::Vec2Array* list = uvlist[i] = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); + nif->getVector2s(list, verts); + + // flip the texture coordinates to convert them to the OpenGL convention of bottom-left image origin + for (unsigned int uv=0; uvsize(); ++uv) + { + (*list)[uv] = osg::Vec2((*list)[uv].x(), 1.f - (*list)[uv].y()); + } } } } diff --git a/components/resource/texturemanager.cpp b/components/resource/texturemanager.cpp index b49c6bb09..709b925f1 100644 --- a/components/resource/texturemanager.cpp +++ b/components/resource/texturemanager.cpp @@ -47,8 +47,8 @@ namespace Resource TextureManager::TextureManager(const VFS::Manager *vfs) : mVFS(vfs) , mWarningTexture(createWarningTexture()) + , mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba")) { - } TextureManager::~TextureManager() @@ -116,8 +116,6 @@ namespace Resource return NULL; } - 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()) @@ -129,7 +127,7 @@ namespace Resource return NULL; } - osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, opts); + osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); if (!result.success()) { std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl; @@ -170,8 +168,6 @@ namespace Resource return mWarningTexture; } - 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()) @@ -183,7 +179,7 @@ namespace Resource return mWarningTexture; } - osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, opts); + osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); if (!result.success()) { std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl; @@ -196,14 +192,6 @@ namespace Resource return mWarningTexture; } - // We need to flip images, because the Morrowind texture coordinates use the DirectX convention (top-left image origin), - // but OpenGL uses bottom left as the image origin. - // For some reason this doesn't concern DDS textures, which are already flipped when loaded. - if (ext != "dds") - { - image->flipVertical(); - } - osg::ref_ptr texture(new osg::Texture2D); texture->setImage(image); texture->setWrap(osg::Texture::WRAP_S, wrapS); diff --git a/components/resource/texturemanager.hpp b/components/resource/texturemanager.hpp index 61a727b5e..cb2711aa7 100644 --- a/components/resource/texturemanager.hpp +++ b/components/resource/texturemanager.hpp @@ -18,6 +18,11 @@ namespace VFS class Manager; } +namespace osgDB +{ + class Options; +} + namespace Resource { @@ -49,6 +54,7 @@ namespace Resource std::map > mTextures; osg::ref_ptr mWarningTexture; + osg::ref_ptr mOptions; TextureManager(const TextureManager&); void operator = (const TextureManager&); diff --git a/components/sdlutil/sdlcursormanager.cpp b/components/sdlutil/sdlcursormanager.cpp index 9ecef0483..afe240609 100644 --- a/components/sdlutil/sdlcursormanager.cpp +++ b/components/sdlutil/sdlcursormanager.cpp @@ -231,7 +231,7 @@ namespace SDLUtil return; } - SDL_Surface* surf = SDLUtil::imageToSurface(decompressed, false); + SDL_Surface* surf = SDLUtil::imageToSurface(decompressed, true); //set the cursor and store it for later SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y); diff --git a/files/mygui/openmw_pointer.xml b/files/mygui/openmw_pointer.xml index a55a5453c..4a2f81860 100644 --- a/files/mygui/openmw_pointer.xml +++ b/files/mygui/openmw_pointer.xml @@ -23,13 +23,13 @@ - + - +