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.
This commit is contained in:
scrawl 2016-02-05 20:23:41 +01:00
parent 6ac688c0e2
commit e8662bea31
14 changed files with 41 additions and 32 deletions

View file

@ -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)

View file

@ -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);

View file

@ -254,7 +254,7 @@ namespace MWGui
{
boost::shared_ptr<MyGUI::ITexture> 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<MyGUI::ITexture> 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()

View file

@ -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);

View file

@ -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));
}
}

View file

@ -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()

View file

@ -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();
}

View file

@ -9,6 +9,7 @@
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Texture2D>
#include <osg/TexMat>
#include <osgViewer/Viewer>
@ -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 &copy, const osg::CopyOp &copyop=osg::CopyOp::SHALLOW_COPY)
: osg::Drawable(copy, copyop)

View file

@ -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<osg::Texture2D> newTexture = new osg::Texture2D;
newTexture->setTextureSize(getWidth(), getHeight());

View file

@ -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; uv<list->size(); ++uv)
{
(*list)[uv] = osg::Vec2((*list)[uv].x(), 1.f - (*list)[uv].y());
}
}
}
}

View file

@ -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<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())
@ -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<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())
@ -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<osg::Texture2D> texture(new osg::Texture2D);
texture->setImage(image);
texture->setWrap(osg::Texture::WRAP_S, wrapS);

View file

@ -18,6 +18,11 @@ namespace VFS
class Manager;
}
namespace osgDB
{
class Options;
}
namespace Resource
{
@ -49,6 +54,7 @@ namespace Resource
std::map<MapKey, osg::ref_ptr<osg::Texture2D> > mTextures;
osg::ref_ptr<osg::Texture2D> mWarningTexture;
osg::ref_ptr<osgDB::Options> mOptions;
TextureManager(const TextureManager&);
void operator = (const TextureManager&);

View file

@ -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);

View file

@ -23,13 +23,13 @@
<Property key="Point" value="17 15"/>
<Property key="Size" value="32 32"/>
<Property key="Resource" value="HResizePointerImage"/>
<Property key="Rotation" value="45"/>
<Property key="Rotation" value="-45"/>
</Resource>
<Resource type="ResourceImageSetPointer" name="dresize2">
<Property key="Point" value="15 15"/>
<Property key="Size" value="32 32"/>
<Property key="Resource" value="HResizePointerImage"/>
<Property key="Rotation" value="-45"/>
<Property key="Rotation" value="45"/>
</Resource>
<Resource type="ResourceImageSetPointer" name="drop_ground">
<Property key="Point" value="0 24"/>