Map rendering

c++11
scrawl 10 years ago
parent 76dd3e4034
commit 3dcb167066

@ -596,7 +596,7 @@ void OMW::Engine::go()
{ {
double dt = frameTimer.time_s(); double dt = frameTimer.time_s();
frameTimer.setStartTick(); frameTimer.setStartTick();
//dt = std::min(dt, 0.2); dt = std::min(dt, 0.2);
double simulationTime = frame(dt); double simulationTime = frame(dt);
mViewer->frame(simulationTime); mViewer->frame(simulationTime);

@ -178,12 +178,6 @@ namespace MWBase
virtual void changeCell(MWWorld::CellStore* cell) = 0; virtual void changeCell(MWWorld::CellStore* cell) = 0;
///< change the active cell ///< change the active cell
virtual void setPlayerPos(int cellX, int cellY, const float x, const float y) = 0;
///< set player position in map space
virtual void setPlayerDir(const float x, const float y) = 0;
///< set player view direction in map space
virtual void setFocusObject(const MWWorld::Ptr& focus) = 0; virtual void setFocusObject(const MWWorld::Ptr& focus) = 0;
virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0; virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0;
@ -358,6 +352,9 @@ namespace MWBase
virtual std::string correctIconPath(const std::string& path) = 0; virtual std::string correctIconPath(const std::string& path) = 0;
virtual std::string correctBookartPath(const std::string& path, int width, int height) = 0; virtual std::string correctBookartPath(const std::string& path, int width, int height) = 0;
virtual std::string correctTexturePath(const std::string& path) = 0; virtual std::string correctTexturePath(const std::string& path) = 0;
virtual void requestMap(std::set<MWWorld::CellStore*> cells) = 0;
virtual void removeCell(MWWorld::CellStore* cell) = 0;
}; };
} }

@ -142,21 +142,12 @@ namespace MWBase
virtual bool isCellQuasiExterior() const = 0; virtual bool isCellQuasiExterior() const = 0;
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0; virtual osg::Vec2f getNorthVector (MWWorld::CellStore* cell) = 0;
///< get north vector for given interior cell ///< get north vector for given interior cell
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0; virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
///< get a list of teleport door markers for a given cell, to be displayed on the local map ///< get a list of teleport door markers for a given cell, to be displayed on the local map
virtual void worldToInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
///< see MWRender::LocalMap::worldToInteriorMapPosition
virtual Ogre::Vector2 interiorMapToWorldPosition (float nX, float nY, int x, int y) = 0;
///< see MWRender::LocalMap::interiorMapToWorldPosition
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0;
///< see MWRender::LocalMap::isPositionExplored
virtual void setGlobalInt (const std::string& name, int value) = 0; virtual void setGlobalInt (const std::string& name, int value) = 0;
///< Set value independently from real type. ///< Set value independently from real type.

@ -70,9 +70,9 @@ namespace MWGui
}; };
HUD::HUD(CustomMarkerCollection &customMarkers, bool showFps, DragAndDrop* dragAndDrop) HUD::HUD(CustomMarkerCollection &customMarkers, bool showFps, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
: Layout("openmw_hud.layout") : Layout("openmw_hud.layout")
, LocalMapBase(customMarkers) , LocalMapBase(customMarkers, localMapRender)
, mHealth(NULL) , mHealth(NULL)
, mMagicka(NULL) , mMagicka(NULL)
, mStamina(NULL) , mStamina(NULL)

@ -19,7 +19,7 @@ namespace MWGui
class HUD : public Layout, public LocalMapBase class HUD : public Layout, public LocalMapBase
{ {
public: public:
HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop); HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
virtual ~HUD(); virtual ~HUD();
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setFPS(float fps); void setFPS(float fps);

@ -35,7 +35,6 @@ namespace MWGui
, mLastRenderTime(0.0) , mLastRenderTime(0.0)
, mLoadingOnTime(0.0) , mLoadingOnTime(0.0)
, mProgress(0) , mProgress(0)
, mVSyncWasEnabled(false)
{ {
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());

@ -67,8 +67,6 @@ namespace MWGui
std::vector<std::string> mSplashScreens; std::vector<std::string> mSplashScreens;
bool mVSyncWasEnabled;
void changeWallpaper(); void changeWallpaper();
void draw(); void draw();

@ -26,6 +26,7 @@
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwrender/globalmap.hpp" #include "../mwrender/globalmap.hpp"
#include "../mwrender/localmap.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "confirmationdialog.hpp" #include "confirmationdialog.hpp"
@ -142,8 +143,9 @@ namespace MWGui
// ------------------------------------------------------ // ------------------------------------------------------
LocalMapBase::LocalMapBase(CustomMarkerCollection &markers) LocalMapBase::LocalMapBase(CustomMarkerCollection &markers, MWRender::LocalMap* localMapRender)
: mCurX(0) : mLocalMapRender(localMapRender)
, mCurX(0)
, mCurY(0) , mCurY(0)
, mInterior(false) , mInterior(false)
, mLocalMap(NULL) , mLocalMap(NULL)
@ -260,8 +262,8 @@ namespace MWGui
else else
{ {
int cellX, cellY; int cellX, cellY;
Ogre::Vector2 worldPos (worldX, worldY); osg::Vec2f worldPos (worldX, worldY);
MWBase::Environment::get().getWorld ()->worldToInteriorMapPosition (worldPos, nX, nY, cellX, cellY); mLocalMapRender->worldToInteriorMapPosition(worldPos, nX, nY, cellX, cellY);
markerPos.cellX = cellX; markerPos.cellX = cellX;
markerPos.cellY = cellY; markerPos.cellY = cellY;
@ -301,7 +303,7 @@ namespace MWGui
continue; continue;
} }
MarkerUserData markerPos; MarkerUserData markerPos (mLocalMapRender);
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos); MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 8, MyGUI::IntCoord widgetCoord(widgetPos.left - 8,
@ -342,24 +344,30 @@ namespace MWGui
mDoorMarkerWidgets.clear(); mDoorMarkerWidgets.clear();
// Update the map textures // Update the map textures
#if 0 std::vector<boost::shared_ptr<MyGUI::ITexture> > textures;
for (int mx=0; mx<3; ++mx) for (int mx=0; mx<3; ++mx)
{ {
for (int my=0; my<3; ++my) for (int my=0; my<3; ++my)
{ {
// map int mapX = x + (mx-1);
std::string image = mPrefix+"_"+ MyGUI::utility::toString(x + (mx-1)) + "_" int mapY = y + (-1*(my-1));
+ MyGUI::utility::toString(y + (-1*(my-1)));
MyGUI::ImageBox* box = mMapWidgets[my + 3*mx]; MyGUI::ImageBox* box = mMapWidgets[my + 3*mx];
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(mInterior, mapX, mapY);
box->setImageTexture(image); if (texture)
{
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));
}
else else
box->setImageTexture("black"); box->setRenderItemTexture(NULL);
} }
} }
#endif mMapTextures.swap(textures);
MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::World* world = MWBase::Environment::get().getWorld();
// Retrieve the door markers we want to show // Retrieve the door markers we want to show
@ -394,7 +402,7 @@ namespace MWGui
destNotes.push_back(it->mNote); destNotes.push_back(it->mNote);
} }
MarkerUserData data; MarkerUserData data (mLocalMapRender);
data.notes = destNotes; data.notes = destNotes;
data.caption = marker.name; data.caption = marker.name;
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, data); MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, data);
@ -490,7 +498,7 @@ namespace MWGui
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it) for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
{ {
const ESM::Position& worldPos = it->getRefData().getPosition(); const ESM::Position& worldPos = it->getRefData().getPosition();
MarkerUserData markerPos; MarkerUserData markerPos (mLocalMapRender);
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos); MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4, MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4, widgetPos.top - 4,
@ -535,7 +543,7 @@ namespace MWGui
if (markedCell && markedCell->isExterior() == !mInterior if (markedCell && markedCell->isExterior() == !mInterior
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->mName, mPrefix))) && (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->mName, mPrefix)))
{ {
MarkerUserData markerPos; MarkerUserData markerPos (mLocalMapRender);
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos); MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4, MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4, widgetPos.top - 4,
@ -553,9 +561,9 @@ namespace MWGui
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, const std::string& cacheDir) MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender)
: WindowPinnableBase("openmw_map_window.layout") : WindowPinnableBase("openmw_map_window.layout")
, LocalMapBase(customMarkers) , LocalMapBase(customMarkers, localMapRender)
, NoDrop(drag, mMainWidget) , NoDrop(drag, mMainWidget)
, mGlobalMap(0) , mGlobalMap(0)
, mGlobalMapTexture(NULL) , mGlobalMapTexture(NULL)
@ -662,19 +670,19 @@ namespace MWGui
x += mCurX; x += mCurX;
y += mCurY; y += mCurY;
Ogre::Vector2 worldPos; osg::Vec2f worldPos;
if (mInterior) if (mInterior)
{ {
worldPos = MWBase::Environment::get().getWorld()->interiorMapToWorldPosition(nX, nY, x, y); worldPos = mLocalMapRender->interiorMapToWorldPosition(nX, nY, x, y);
} }
else else
{ {
worldPos.x = (x + nX) * cellSize; worldPos.x() = (x + nX) * cellSize;
worldPos.y = (y + (1.0f-nY)) * cellSize; worldPos.y() = (y + (1.0f-nY)) * cellSize;
} }
mEditingMarker.mWorldX = worldPos.x; mEditingMarker.mWorldX = worldPos.x();
mEditingMarker.mWorldY = worldPos.y; mEditingMarker.mWorldY = worldPos.y();
mEditingMarker.mCell.mPaged = !mInterior; mEditingMarker.mCell.mPaged = !mInterior;
if (mInterior) if (mInterior)
@ -993,4 +1001,9 @@ namespace MWGui
eventDeleteClicked(); eventDeleteClicked();
} }
bool LocalMapBase::MarkerUserData::isPositionExplored() const
{
return mLocalMapRender->isPositionExplored(nX, nY, cellX, cellY, interior);
}
} }

@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
#include <boost/shared_ptr.hpp>
#include "windowpinnablebase.hpp" #include "windowpinnablebase.hpp"
#include <components/esm/cellid.hpp> #include <components/esm/cellid.hpp>
@ -12,6 +14,7 @@
namespace MWRender namespace MWRender
{ {
class GlobalMap; class GlobalMap;
class LocalMap;
} }
namespace ESM namespace ESM
@ -52,7 +55,7 @@ namespace MWGui
class LocalMapBase class LocalMapBase
{ {
public: public:
LocalMapBase(CustomMarkerCollection& markers); LocalMapBase(CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender);
virtual ~LocalMapBase(); virtual ~LocalMapBase();
void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int mapWidgetSize); void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int mapWidgetSize);
@ -67,6 +70,14 @@ namespace MWGui
struct MarkerUserData struct MarkerUserData
{ {
MarkerUserData(MWRender::LocalMap* map)
: mLocalMapRender(map)
{
}
bool isPositionExplored() const;
MWRender::LocalMap* mLocalMapRender;
bool interior; bool interior;
int cellX; int cellX;
int cellY; int cellY;
@ -77,6 +88,8 @@ namespace MWGui
}; };
protected: protected:
MWRender::LocalMap* mLocalMapRender;
int mCurX, mCurY; int mCurX, mCurY;
bool mInterior; bool mInterior;
MyGUI::ScrollView* mLocalMap; MyGUI::ScrollView* mLocalMap;
@ -93,6 +106,8 @@ namespace MWGui
std::vector<MyGUI::ImageBox*> mMapWidgets; std::vector<MyGUI::ImageBox*> mMapWidgets;
std::vector<MyGUI::ImageBox*> mFogWidgets; std::vector<MyGUI::ImageBox*> mFogWidgets;
std::vector<boost::shared_ptr<MyGUI::ITexture> > mMapTextures;
// Keep track of created marker widgets, just to easily remove them later. // Keep track of created marker widgets, just to easily remove them later.
std::vector<MyGUI::Widget*> mDoorMarkerWidgets; std::vector<MyGUI::Widget*> mDoorMarkerWidgets;
std::vector<MyGUI::Widget*> mMagicMarkerWidgets; std::vector<MyGUI::Widget*> mMagicMarkerWidgets;
@ -153,7 +168,7 @@ namespace MWGui
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
{ {
public: public:
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, const std::string& cacheDir); MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender);
virtual ~MapWindow(); virtual ~MapWindow();
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);

@ -169,7 +169,7 @@ namespace MWGui
{ {
LocalMapBase::MarkerUserData data = *focus->getUserData<LocalMapBase::MarkerUserData>(); LocalMapBase::MarkerUserData data = *focus->getUserData<LocalMapBase::MarkerUserData>();
if (!MWBase::Environment::get().getWorld ()->isPositionExplored (data.nX, data.nY, data.cellX, data.cellY, data.interior)) if (!data.isPositionExplored())
return; return;
ToolTipInfo info; ToolTipInfo info;

@ -53,6 +53,8 @@
#include "../mwmechanics/stat.hpp" #include "../mwmechanics/stat.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "../mwrender/localmap.hpp"
#include "../mwsound/soundmanagerimp.hpp" #include "../mwsound/soundmanagerimp.hpp"
#include "console.hpp" #include "console.hpp"
@ -115,6 +117,7 @@ namespace MWGui
, mCurrentModals() , mCurrentModals()
, mHud(NULL) , mHud(NULL)
, mMap(NULL) , mMap(NULL)
, mLocalMapRender(NULL)
, mMenu(NULL) , mMenu(NULL)
, mToolTips(NULL) , mToolTips(NULL)
, mStatsWindow(NULL) , mStatsWindow(NULL)
@ -266,7 +269,8 @@ namespace MWGui
mRecharge = new Recharge(); mRecharge = new Recharge();
mMenu = new MainMenu(w, h, mResourceSystem->getVFS()); mMenu = new MainMenu(w, h, mResourceSystem->getVFS());
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, ""); mLocalMapRender = new MWRender::LocalMap(mViewer);
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender);
trackWindow(mMap, "map"); trackWindow(mMap, "map");
mStatsWindow = new StatsWindow(mDragAndDrop); mStatsWindow = new StatsWindow(mDragAndDrop);
trackWindow(mStatsWindow, "stats"); trackWindow(mStatsWindow, "stats");
@ -284,7 +288,7 @@ namespace MWGui
trackWindow(mDialogueWindow, "dialogue"); trackWindow(mDialogueWindow, "dialogue");
mContainerWindow = new ContainerWindow(mDragAndDrop); mContainerWindow = new ContainerWindow(mDragAndDrop);
trackWindow(mContainerWindow, "container"); trackWindow(mContainerWindow, "container");
mHud = new HUD(mCustomMarkers, Settings::Manager::getInt("fps", "HUD"), mDragAndDrop); mHud = new HUD(mCustomMarkers, Settings::Manager::getInt("fps", "HUD"), mDragAndDrop, mLocalMapRender);
mToolTips = new ToolTips(); mToolTips = new ToolTips();
mScrollWindow = new ScrollWindow(); mScrollWindow = new ScrollWindow();
mBookWindow = new BookWindow(); mBookWindow = new BookWindow();
@ -383,6 +387,7 @@ namespace MWGui
delete mMessageBoxManager; delete mMessageBoxManager;
delete mHud; delete mHud;
delete mMap; delete mMap;
delete mLocalMapRender;
delete mMenu; delete mMenu;
delete mStatsWindow; delete mStatsWindow;
delete mJournal; delete mJournal;
@ -886,6 +891,31 @@ namespace MWGui
return default_; return default_;
} }
void WindowManager::updateMap()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPosition = player.getRefData().getPosition().asVec3();
osg::Quat playerOrientation (-player.getRefData().getPosition().rot[2], osg::Vec3(0,0,1));
osg::Vec3f playerdirection;
int x,y;
float u,v;
mLocalMapRender->updatePlayer(playerPosition, playerOrientation, u, v, x, y, playerdirection);
if (!player.getCell()->isExterior())
{
mMap->setActiveCell(x, y, true);
mHud->setActiveCell(x, y, true);
}
// else: need to know the current grid center, call setActiveCell from MWWorld::Scene
mMap->setPlayerDir(playerdirection.x(), playerdirection.y());
mMap->setPlayerPos(x, y, u, v);
mHud->setPlayerDir(playerdirection.x(), playerdirection.y());
mHud->setPlayerPos(x, y, u, v);
}
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
{ {
mMessageBoxManager->onFrame(frameDuration); mMessageBoxManager->onFrame(frameDuration);
@ -894,6 +924,9 @@ namespace MWGui
mMenu->update(frameDuration); mMenu->update(frameDuration);
if (mLocalMapRender)
mLocalMapRender->cleanupCameras();
if (MWBase::Environment::get().getStateManager()->getState()== if (MWBase::Environment::get().getStateManager()->getState()==
MWBase::StateManager::State_NoGame) MWBase::StateManager::State_NoGame)
return; return;
@ -908,6 +941,8 @@ namespace MWGui
mInventoryWindow->onFrame(); mInventoryWindow->onFrame();
updateMap();
mStatsWindow->onFrame(frameDuration); mStatsWindow->onFrame(frameDuration);
mMap->onFrame(frameDuration); mMap->onFrame(frameDuration);
mSpellWindow->onFrame(frameDuration); mSpellWindow->onFrame(frameDuration);
@ -968,29 +1003,10 @@ namespace MWGui
void WindowManager::setActiveMap(int x, int y, bool interior) void WindowManager::setActiveMap(int x, int y, bool interior)
{ {
if (!interior)
{
mMap->setCellPrefix("Cell");
mHud->setCellPrefix("Cell");
}
mMap->setActiveCell(x,y, interior); mMap->setActiveCell(x,y, interior);
mHud->setActiveCell(x,y, interior); mHud->setActiveCell(x,y, interior);
} }
void WindowManager::setPlayerPos(int cellX, int cellY, const float x, const float y)
{
mMap->setPlayerPos(cellX, cellY, x, y);
mHud->setPlayerPos(cellX, cellY, x, y);
}
void WindowManager::setPlayerDir(const float x, const float y)
{
mMap->setPlayerDir(x,y);
mMap->setGlobalMapPlayerDir(x, y);
mHud->setPlayerDir(x,y);
}
void WindowManager::setDrowningBarVisibility(bool visible) void WindowManager::setDrowningBarVisibility(bool visible)
{ {
mHud->setDrowningBarVisible(visible); mHud->setDrowningBarVisible(visible);
@ -1990,4 +2006,14 @@ namespace MWGui
tex->unlock(); tex->unlock();
} }
void WindowManager::requestMap(std::set<MWWorld::CellStore*> cells)
{
mLocalMapRender->requestMap(cells);
}
void WindowManager::removeCell(MWWorld::CellStore *cell)
{
mLocalMapRender->removeCell(cell);
}
} }

@ -67,6 +67,11 @@ namespace Gui
class FontLoader; class FontLoader;
} }
namespace MWRender
{
class LocalMap;
}
namespace MWGui namespace MWGui
{ {
class WindowBase; class WindowBase;
@ -191,8 +196,6 @@ namespace MWGui
virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty
virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell
virtual void setPlayerPos(int cellX, int cellY, const float x, const float y); ///< set player position in map space
virtual void setPlayerDir(const float x, const float y); ///< set player view direction in map space
virtual void setFocusObject(const MWWorld::Ptr& focus); virtual void setFocusObject(const MWWorld::Ptr& focus);
virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y);
@ -363,6 +366,9 @@ namespace MWGui
virtual std::string correctBookartPath(const std::string& path, int width, int height); virtual std::string correctBookartPath(const std::string& path, int width, int height);
virtual std::string correctTexturePath(const std::string& path); virtual std::string correctTexturePath(const std::string& path);
void requestMap(std::set<MWWorld::CellStore*> cells);
void removeCell(MWWorld::CellStore* cell);
private: private:
Resource::ResourceSystem* mResourceSystem; Resource::ResourceSystem* mResourceSystem;
@ -386,6 +392,7 @@ namespace MWGui
HUD *mHud; HUD *mHud;
MapWindow *mMap; MapWindow *mMap;
MWRender::LocalMap* mLocalMapRender;
MainMenu *mMenu; MainMenu *mMenu;
ToolTips *mToolTips; ToolTips *mToolTips;
StatsWindow *mStatsWindow; StatsWindow *mStatsWindow;
@ -473,6 +480,8 @@ namespace MWGui
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
void updateMap();
float mFPS; float mFPS;
std::map<std::string, std::string> mFallbackMap; std::map<std::string, std::string> mFallbackMap;

@ -1,5 +1,4 @@
#include "actor.hpp" #include "actor.hpp"
#include <osg/io_utils>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>

@ -8,7 +8,6 @@
#include <osg/TexEnvCombine> #include <osg/TexEnvCombine>
#include <osg/ComputeBoundsVisitor> #include <osg/ComputeBoundsVisitor>
#include <osg/MatrixTransform> #include <osg/MatrixTransform>
#include <osg/io_utils>
#include <osg/Geode> #include <osg/Geode>
#include <components/nifosg/nifloader.hpp> #include <components/nifosg/nifloader.hpp>

@ -16,6 +16,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
#include "vismask.hpp"
namespace MWRender namespace MWRender
{ {
@ -81,6 +82,8 @@ namespace MWRender
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture); mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture);
mCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext()); mCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
mCamera->setNodeMask(Mask_RenderToTexture);
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager; osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager;
lightManager->setStartLight(1); lightManager->setStartLight(1);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet; osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;

@ -1,74 +1,82 @@
#include "localmap.hpp" #include "localmap.hpp"
#include <OgreMaterialManager.h> #include <iostream>
#include <OgreHardwarePixelBuffer.h>
#include <OgreSceneManager.h> #include <osg/LightModel>
#include <OgreSceneNode.h> #include <osg/Texture2D>
#include <OgreCamera.h> #include <osg/ComputeBoundsVisitor>
#include <OgreTextureManager.h>
#include <OgreRenderTexture.h> #include <osgViewer/Viewer>
#include <OgreViewport.h>
#include <components/esm/fogstate.hpp> #include <components/esm/fogstate.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/sceneutil/visitor.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "vismask.hpp"
namespace
{
class CameraUpdateCallback : public osg::NodeCallback
{
public:
CameraUpdateCallback(osg::Camera* cam, MWRender::LocalMap* parent)
: mCamera(cam), mParent(parent)
{
}
virtual void operator()(osg::Node*, osg::NodeVisitor*)
{
mParent->markForRemoval(mCamera);
// Note, we intentionally do not traverse children here. The map camera's scene data is the same as the master camera's,
// so it has been updated already.
//traverse(node, nv);
}
private:
osg::ref_ptr<osg::Camera> mCamera;
MWRender::LocalMap* mParent;
};
}
using namespace MWRender; namespace MWRender
using namespace Ogre; {
LocalMap::LocalMap() LocalMap::LocalMap(osgViewer::Viewer* viewer)
: mMapResolution(Settings::Manager::getInt("local map resolution", "Map")) : mViewer(viewer)
, mMapResolution(Settings::Manager::getInt("local map resolution", "Map"))
, mMapWorldSize(8192.f)
, mAngle(0.f) , mAngle(0.f)
, mInterior(false) , mInterior(false)
{ {
// mCellCamera = mRendering->getScene()->createCamera("CellCamera"); mRoot = mViewer->getSceneData()->asGroup();
mCellCamera->setProjectionType(PT_ORTHOGRAPHIC);
mCameraNode->attachObject(mCellCamera);
mLight->setType (Ogre::Light::LT_DIRECTIONAL);
mLight->setDirection (Ogre::Vector3(0.3f, 0.3f, -0.7f));
mLight->setVisible (false);
mLight->setDiffuseColour (ColourValue(0.7f,0.7f,0.7f));
mRenderTexture = TextureManager::getSingleton().createManual(
"localmap/rtt",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
TEX_TYPE_2D,
mMapResolution, mMapResolution,
0,
PF_R8G8B8,
TU_RENDERTARGET);
mRenderTarget = mRenderTexture->getBuffer()->getRenderTarget();
mRenderTarget->setAutoUpdated(false);
Viewport* vp = mRenderTarget->addViewport(mCellCamera);
vp->setOverlaysEnabled(false);
vp->setShadowsEnabled(false);
vp->setBackgroundColour(ColourValue(0, 0, 0));
vp->setMaterialScheme("local_map");
}
LocalMap::~LocalMap() SceneUtil::FindByNameVisitor find("Scene Root");
{ mRoot->accept(find);
mSceneRoot = find.mFoundNode;
if (!mSceneRoot)
throw std::runtime_error("no scene root found");
} }
const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle) LocalMap::~LocalMap()
{ {
return Vector2( Math::Cos(angle) * (p.x - c.x) - Math::Sin(angle) * (p.y - c.y) + c.x, for (CameraVector::iterator it = mActiveCameras.begin(); it != mActiveCameras.end(); ++it)
Math::Sin(angle) * (p.x - c.x) + Math::Cos(angle) * (p.y - c.y) + c.y); mRoot->removeChild(*it);
for (CameraVector::iterator it = mCamerasPendingRemoval.begin(); it != mCamerasPendingRemoval.end(); ++it)
mRoot->removeChild(*it);
} }
std::string LocalMap::coordStr(const int x, const int y) const osg::Vec2f LocalMap::rotatePoint(const osg::Vec2f& p, const osg::Vec2f& c, const float angle)
{ {
return StringConverter::toString(x) + "_" + StringConverter::toString(y); return osg::Vec2f( std::cos(angle) * (p.x() - c.x()) - std::sin(angle) * (p.y() - c.y()) + c.x(),
std::sin(angle) * (p.x() - c.x()) + std::cos(angle) * (p.y() - c.y()) + c.y());
} }
void LocalMap::clear() void LocalMap::clear()
@ -103,8 +111,8 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y); Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y);
Vector2 length = max-min; Vector2 length = max-min;
const int segsX = static_cast<int>(std::ceil(length.x / sSize)); const int segsX = static_cast<int>(std::ceil(length.x / mMapWorldSize));
const int segsY = static_cast<int>(std::ceil(length.y / sSize)); const int segsY = static_cast<int>(std::ceil(length.y / mMapWorldSize));
mInteriorName = cell->getCell()->mName; mInteriorName = cell->getCell()->mName;
@ -148,24 +156,145 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
*/ */
} }
void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax) osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, float width, float height, const osg::Vec3d& upVector, float zmin, float zmax)
{ {
mInterior = false; osg::ref_ptr<osg::Camera> camera (new osg::Camera);
camera->setProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10);
camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
camera->setViewMatrixAsLookAt(osg::Vec3d(x, y, zmax + 5), osg::Vec3d(x, y, zmin), upVector);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
camera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 1.f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setCullMask(MWRender::Mask_Scene);
camera->setNodeMask(Mask_RenderToTexture);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
stateset->setMode(GL_FOG, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel;
lightmodel->setAmbientIntensity(osg::Vec4(0.3f, 0.3f, 0.3f, 1.f));
stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::Light> light = new osg::Light;
light->setPosition(osg::Vec4(-0.3f, -0.3f, 0.7f, 0.f));
light->setDiffuse(osg::Vec4(0.7f, 0.7f, 0.7f, 1.f));
light->setAmbient(osg::Vec4(0,0,0,1));
light->setSpecular(osg::Vec4(0,0,0,0));
light->setLightNum(0);
light->setConstantAttenuation(1.f);
light->setLinearAttenuation(0.f);
light->setQuadraticAttenuation(0.f);
osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
lightSource->setLight(light);
lightSource->setStateSetModes(*stateset, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
camera->addChild(lightSource);
camera->setStateSet(stateset);
camera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
camera->setViewport(0, 0, mMapResolution, mMapResolution);
camera->setUpdateCallback(new CameraUpdateCallback(camera, this));
return camera;
}
mCameraRotNode->setOrientation(Quaternion::IDENTITY); void LocalMap::setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y)
mCellCamera->setOrientation(Quaternion(Ogre::Math::Cos(Ogre::Degree(0)/2.f), 0, 0, -Ogre::Math::Sin(Ogre::Degree(0)/2.f))); {
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
texture->setTextureSize(mMapResolution, mMapResolution);
texture->setInternalFormat(GL_RGB);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
camera->attach(osg::Camera::COLOR_BUFFER, texture);
camera->addChild(mSceneRoot);
mRoot->addChild(camera);
mActiveCameras.push_back(camera);
mTextures[std::make_pair(x, y)] = texture;
}
void LocalMap::requestMap(std::set<MWWorld::CellStore*> cells)
{
for (std::set<MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
{
MWWorld::CellStore* cell = *it;
if (cell->isExterior())
requestExteriorMap(cell);
else
requestInteriorMap(cell);
}
}
void LocalMap::removeCell(MWWorld::CellStore *cell)
{
if (cell->isExterior())
mTextures.erase(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
else
mTextures.clear();
}
osg::ref_ptr<osg::Texture2D> LocalMap::getMapTexture(bool interior, int x, int y)
{
TextureMap::iterator found = mTextures.find(std::make_pair(x, y));
if (found == mTextures.end())
return osg::ref_ptr<osg::Texture2D>();
else
return found->second;
}
void LocalMap::markForRemoval(osg::Camera *cam)
{
CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), cam);
if (found == mActiveCameras.end())
{
std::cerr << "trying to remove an inactive camera" << std::endl;
return;
}
mActiveCameras.erase(found);
mCamerasPendingRemoval.push_back(cam);
}
void LocalMap::cleanupCameras()
{
if (mCamerasPendingRemoval.empty())
return;
for (CameraVector::iterator it = mCamerasPendingRemoval.begin(); it != mCamerasPendingRemoval.end(); ++it)
{
(*it)->removeChildren(0, (*it)->getNumChildren());
(*it)->setGraphicsContext(NULL);
mRoot->removeChild(*it);
}
mCamerasPendingRemoval.clear();
}
void LocalMap::requestExteriorMap(MWWorld::CellStore* cell)
{
mInterior = false;
int x = cell->getCell()->getGridX(); int x = cell->getCell()->getGridX();
int y = cell->getCell()->getGridY(); int y = cell->getCell()->getGridY();
std::string name = "Cell_"+coordStr(x, y); osg::BoundingSphere bound = mViewer->getSceneData()->getBound();
float zmin = bound.center().z() - bound.radius();
float zmax = bound.center().z() + bound.radius();
mCameraPosNode->setPosition(Vector3(0,0,0)); osg::ref_ptr<osg::Camera> camera = createOrthographicCamera(x*mMapWorldSize + mMapWorldSize/2.f, y*mMapWorldSize + mMapWorldSize/2.f, mMapWorldSize, mMapWorldSize,
osg::Vec3d(0,1,0), zmin, zmax);
// Note: using force=true for exterior cell maps. setupRenderToTexture(camera, cell->getCell()->getGridX(), cell->getCell()->getGridY());
// They must be updated even if they were visited before, because the set of surrounding active cells might be different
// (and objects in a different cell can "bleed" into another cell's map if they cross the border)
render((x+0.5f)*sSize, (y+0.5f)*sSize, zMin, zMax, static_cast<float>(sSize), static_cast<float>(sSize), name, true);
/* /*
if (mBuffers.find(name) == mBuffers.end()) if (mBuffers.find(name) == mBuffers.end())
@ -178,12 +307,17 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax)
*/ */
} }
void LocalMap::requestMap(MWWorld::CellStore* cell, void LocalMap::requestInteriorMap(MWWorld::CellStore* cell)
AxisAlignedBox bounds)
{ {
osg::ComputeBoundsVisitor computeBoundsVisitor;
computeBoundsVisitor.setTraversalMask(Mask_Scene);
mSceneRoot->accept(computeBoundsVisitor);
osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox();
// If we're in an empty cell, bail out // If we're in an empty cell, bail out
// The operations in this function are only valid for finite bounds // The operations in this function are only valid for finite bounds
if (bounds.isNull ()) if (!bounds.valid() || bounds.radius2() == 0.0)
return; return;
mInterior = true; mInterior = true;
@ -191,41 +325,31 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
mBounds = bounds; mBounds = bounds;
// Get the cell's NorthMarker rotation. This is used to rotate the entire map. // Get the cell's NorthMarker rotation. This is used to rotate the entire map.
const Vector2& north = MWBase::Environment::get().getWorld()->getNorthVector(cell); osg::Vec2f north = MWBase::Environment::get().getWorld()->getNorthVector(cell);
Radian angle = Ogre::Math::ATan2 (north.x, north.y);
mAngle = angle.valueRadians(); mAngle = std::atan2(north.x(), north.y());
// Rotate the cell and merge the rotated corners to the bounding box // Rotate the cell and merge the rotated corners to the bounding box
Vector2 _center(bounds.getCenter().x, bounds.getCenter().y); osg::Vec2f _center(bounds.center().x(), bounds.center().y());
Vector3 _c1 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM); for (int i=0; i<8; ++i)
Vector3 _c2 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM); {
Vector3 _c3 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_TOP); osg::Vec3f corner = mBounds.corner(i);
Vector3 _c4 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_TOP); osg::Vec2f corner2d (corner.x(), corner.y());
corner2d = rotatePoint(corner2d, _center, mAngle);
Vector2 c1(_c1.x, _c1.y); mBounds.expandBy(osg::Vec3f(corner2d.x(), corner2d.y(), 0));
Vector2 c2(_c2.x, _c2.y); }
Vector2 c3(_c3.x, _c3.y);
Vector2 c4(_c4.x, _c4.y);
c1 = rotatePoint(c1, _center, mAngle);
c2 = rotatePoint(c2, _center, mAngle);
c3 = rotatePoint(c3, _center, mAngle);
c4 = rotatePoint(c4, _center, mAngle);
mBounds.merge(Vector3(c1.x, c1.y, 0));
mBounds.merge(Vector3(c2.x, c2.y, 0));
mBounds.merge(Vector3(c3.x, c3.y, 0));
mBounds.merge(Vector3(c4.x, c4.y, 0));
// Do NOT change padding! This will break older savegames. // Do NOT change padding! This will break older savegames.
// If the padding really needs to be changed, then it must be saved in the ESM::FogState and // If the padding really needs to be changed, then it must be saved in the ESM::FogState and
// assume the old (500) value as default for older savegames. // assume the old (500) value as default for older savegames.
const Ogre::Real padding = 500.0f; const float padding = 500.0f;
// Apply a little padding // Apply a little padding
mBounds.setMinimum (mBounds.getMinimum() - Vector3(padding,padding,0)); mBounds.set(mBounds._min - osg::Vec3f(padding,padding,0.f),
mBounds.setMaximum (mBounds.getMaximum() + Vector3(padding,padding,0)); mBounds._max + osg::Vec3f(padding,padding,0.f));
float zMin = mBounds.getMinimum().z; float zMin = mBounds.zMin();
float zMax = mBounds.getMaximum().z; float zMax = mBounds.zMax();
// If there is fog state in the CellStore (e.g. when it came from a savegame) we need to do some checks // If there is fog state in the CellStore (e.g. when it came from a savegame) we need to do some checks
// to see if this state is still valid. // to see if this state is still valid.
@ -244,8 +368,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
Ogre::Vector3 minDiff = newMin - mBounds.getMinimum(); Ogre::Vector3 minDiff = newMin - mBounds.getMinimum();
Ogre::Vector3 maxDiff = newMax - mBounds.getMaximum(); Ogre::Vector3 maxDiff = newMax - mBounds.getMaximum();
if (std::abs(minDiff.x) > 500 || std::abs(minDiff.y) > 500 if (std::abs(minDiff.x) > padding || std::abs(minDiff.y) > padding
|| std::abs(maxDiff.x) > 500 || std::abs(maxDiff.y) > 500 || std::abs(maxDiff.x) > padding || std::abs(maxDiff.y) > padding
|| std::abs(mAngle - fog->mNorthMarkerAngle) > Ogre::Degree(5).valueRadians()) || std::abs(mAngle - fog->mNorthMarkerAngle) > Ogre::Degree(5).valueRadians())
{ {
// Nuke it // Nuke it
@ -260,35 +384,35 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
} }
*/ */
Vector2 center(mBounds.getCenter().x, mBounds.getCenter().y); osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
osg::Vec2f max(mBounds.xMax(), mBounds.yMax());
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y);
Vector2 length = max-min; osg::Vec2f length = max-min;
mCellCamera->setOrientation(Quaternion::IDENTITY); osg::Vec2f center(bounds.center().x(), bounds.center().y());
mCameraRotNode->setOrientation(Quaternion(Math::Cos(mAngle/2.f), 0, 0, -Math::Sin(mAngle/2.f)));
mCameraPosNode->setPosition(Vector3(center.x, center.y, 0));
// divide into segments // divide into segments
const int segsX = static_cast<int>(std::ceil(length.x / sSize)); const int segsX = static_cast<int>(std::ceil(length.x() / mMapWorldSize));
const int segsY = static_cast<int>(std::ceil(length.y / sSize)); const int segsY = static_cast<int>(std::ceil(length.y() / mMapWorldSize));
mInteriorName = cell->getCell()->mName;
int i=0;
for (int x=0; x<segsX; ++x) for (int x=0; x<segsX; ++x)
{ {
for (int y=0; y<segsY; ++y) for (int y=0; y<segsY; ++y)
{ {
Vector2 start = min + Vector2(static_cast<Ogre::Real>(sSize*x), static_cast<Ogre::Real>(sSize*y)); osg::Vec2f start = min + osg::Vec2f(mMapWorldSize*x, mMapWorldSize*y);
Vector2 newcenter = start + sSize/2; osg::Vec2f newcenter = start + osg::Vec2f(mMapWorldSize/2.f, mMapWorldSize/2.f);
osg::Quat cameraOrient (mAngle, osg::Vec3d(0,0,-1));
osg::Vec2f a = newcenter - center;
osg::Vec3f rotatedCenter = cameraOrient * (osg::Vec3f(a.x(), a.y(), 0));
osg::Vec2f pos = osg::Vec2f(rotatedCenter.x(), rotatedCenter.y()) + center;
std::string texturePrefix = cell->getCell()->mName + "_" + coordStr(x,y); osg::ref_ptr<osg::Camera> camera = createOrthographicCamera(pos.x(), pos.y(),
mMapWorldSize, mMapWorldSize,
osg::Vec3f(north.x(), north.y(), 0.f), zMin, zMax);
render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, static_cast<float>(sSize), static_cast<float>(sSize), texturePrefix); setupRenderToTexture(camera, x, y);
/* /*
if (!cell->getFog()) if (!cell->getFog())
@ -305,14 +429,13 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
loadFogOfWar(texturePrefix, esm); loadFogOfWar(texturePrefix, esm);
} }
*/ */
++i;
} }
} }
} }
/*
void LocalMap::createFogOfWar(const std::string& texturePrefix) void LocalMap::createFogOfWar(const std::string& texturePrefix)
{ {
/*
const std::string texName = texturePrefix + "_fog"; const std::string texName = texturePrefix + "_fog";
TexturePtr tex = createFogOfWarTexture(texName); TexturePtr tex = createFogOfWarTexture(texName);
@ -328,34 +451,12 @@ void LocalMap::createFogOfWar(const std::string& texturePrefix)
tex->getBuffer()->unlock(); tex->getBuffer()->unlock();
mBuffers[texturePrefix] = buffer; mBuffers[texturePrefix] = buffer;
*/
}
Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName)
{
TexturePtr tex;// = TextureManager::getSingleton().getByName(texName);
/*
* if (tex.isNull())
{
tex = TextureManager::getSingleton().createManual(
texName,
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
TEX_TYPE_2D,
sFogOfWarResolution, sFogOfWarResolution,
0,
PF_A8R8G8B8,
TU_DYNAMIC_WRITE_ONLY,
this // ManualResourceLoader required if the texture contents are lost (due to lost devices nonsense that can occur with D3D)
);
}
*/
return tex;
} }
*/
/*
void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& esm) void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& esm)
{ {
/*
std::vector<char>& data = esm.mImageData; std::vector<char>& data = esm.mImageData;
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size())); Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
Ogre::Image image; Ogre::Image image;
@ -377,89 +478,35 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture&
memcpy(&buffer[0], image.getData(), image.getSize()); memcpy(&buffer[0], image.getData(), image.getSize());
mBuffers[texturePrefix] = buffer; mBuffers[texturePrefix] = buffer;
*/
}
void LocalMap::render(const float x, const float y,
const float zlow, const float zhigh,
const float xw, const float yw, const std::string& texture, bool force)
{
mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 );
mCellCamera->setNearClipDistance(50);
mCellCamera->setOrthoWindow(xw, yw);
mCameraNode->setPosition(Vector3(x, y, zhigh+1000));
// disable fog (only necessary for fixed function, the shader based
// materials already do this through local_map material configuration)
//mRendering->getScene()->setFog(FOG_NONE);
// set up lighting
//Ogre::ColourValue oldAmbient = mRendering->getScene()->getAmbientLight();
//mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3f, 0.3f, 0.3f));
//mRenderingManager->disableLights(true);
mLight->setVisible(true);
TexturePtr tex;
// try loading from memory
tex = TextureManager::getSingleton().getByName(texture);
if (tex.isNull())
{
// render
mRenderTarget->update();
// create a new texture and blit to it
Ogre::TexturePtr tex = TextureManager::getSingleton().createManual(
texture,
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
TEX_TYPE_2D,
mMapResolution, mMapResolution,
0,
PF_R8G8B8);
tex->getBuffer()->blit(mRenderTexture->getBuffer());
}
else if (force)
{
mRenderTarget->update();
tex->getBuffer()->blit(mRenderTexture->getBuffer());
}
//mRenderingManager->enableLights(true);
mLight->setVisible(false);
// re-enable fog
//mRendering->getScene()->setFog(FOG_LINEAR, oldFogColour, 0, oldFogStart, oldFogEnd);
//mRendering->getScene()->setAmbientLight(oldAmbient);
} }
*/
void LocalMap::worldToInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) void LocalMap::worldToInteriorMapPosition (osg::Vec2f pos, float& nX, float& nY, int& x, int& y)
{ {
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().y), mAngle); pos = rotatePoint(pos, osg::Vec2f(mBounds.center().x(), mBounds.center().y()), mAngle);
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
x = static_cast<int>(std::ceil((pos.x - min.x) / sSize) - 1); x = static_cast<int>(std::ceil((pos.x() - min.x()) / mMapWorldSize) - 1);
y = static_cast<int>(std::ceil((pos.y - min.y) / sSize) - 1); y = static_cast<int>(std::ceil((pos.y() - min.y()) / mMapWorldSize) - 1);
nX = (pos.x - min.x - sSize*x)/sSize; nX = (pos.x() - min.x() - mMapWorldSize*x)/mMapWorldSize;
nY = 1.0f-(pos.y - min.y - sSize*y)/sSize; nY = 1.0f-(pos.y() - min.y() - mMapWorldSize*y)/mMapWorldSize;
} }
Ogre::Vector2 LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int y) osg::Vec2f LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int y)
{ {
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
Ogre::Vector2 pos; osg::Vec2f pos (mMapWorldSize * (nX + x) + min.x(),
mMapWorldSize * (1.0f-nY + y) + min.y());
pos.x = sSize * (nX + x) + min.x; pos = rotatePoint(pos, osg::Vec2f(mBounds.center().x(), mBounds.center().y()), -mAngle);
pos.y = sSize * (1.0f-nY + y) + min.y;
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().y), -mAngle);
return pos; return pos;
} }
bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interior) bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interior)
{ {
return false; return true;
/* /*
std::string texName = (interior ? mInteriorName + "_" : "Cell_") + coordStr(x, y); std::string texName = (interior ? mInteriorName + "_" : "Cell_") + coordStr(x, y);
@ -478,33 +525,8 @@ bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interi
*/ */
} }
void LocalMap::loadResource(Ogre::Resource* resource) void LocalMap::updatePlayer (const osg::Vec3f& position, const osg::Quat& orientation,
{ float& u, float& v, int& x, int& y, osg::Vec3f& direction)
/*
std::string resourceName = resource->getName();
size_t pos = resourceName.find("_fog");
if (pos != std::string::npos)
resourceName = resourceName.substr(0, pos);
if (mBuffers.find(resourceName) == mBuffers.end())
{
// create a buffer to use for dynamic operations
std::vector<uint32> buffer;
// initialize to (0, 0, 0, 1)
buffer.resize(sFogOfWarResolution*sFogOfWarResolution, 0xFF000000);
mBuffers[resourceName] = buffer;
}
std::vector<uint32>& buffer = mBuffers[resourceName];
Ogre::Texture* tex = static_cast<Ogre::Texture*>(resource);
tex->createInternalResources();
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
tex->getBuffer()->unlock();
*/
}
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
{ {
/* /*
if (sFogOfWarSkip != 0) if (sFogOfWarSkip != 0)
@ -513,42 +535,32 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
if (++count % sFogOfWarSkip != 0) if (++count % sFogOfWarSkip != 0)
return; return;
} }
*/
// retrieve the x,y grid coordinates the player is in // retrieve the x,y grid coordinates the player is in
int x,y; osg::Vec2f pos(position.x(), position.y());
float u,v;
Vector2 pos(position.x, position.y);
if (mInterior) if (mInterior)
worldToInteriorMapPosition(pos, u,v, x,y);
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
if (!mInterior)
{ {
x = static_cast<int>(std::ceil(pos.x / sSize) - 1); worldToInteriorMapPosition(pos, u,v, x,y);
y = static_cast<int>(std::ceil(pos.y / sSize) - 1);
}
else
MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior);
// convert from world coordinates to texture UV coordinates osg::Quat cameraOrient (mAngle, osg::Vec3(0,0,-1));
std::string texBaseName; direction = orientation * cameraOrient.inverse() * osg::Vec3f(0,1,0);
if (!mInterior)
{
u = std::abs((pos.x - (sSize*x))/sSize);
v = 1.0f-std::abs((pos.y - (sSize*y))/sSize);
texBaseName = "Cell_";
} }
else else
{ {
texBaseName = mInteriorName + "_"; direction = orientation * osg::Vec3f(0,1,0);
x = static_cast<int>(std::ceil(pos.x() / mMapWorldSize) - 1);
y = static_cast<int>(std::ceil(pos.y() / mMapWorldSize) - 1);
// convert from world coordinates to texture UV coordinates
u = std::abs((pos.x() - (mMapWorldSize*x))/mMapWorldSize);
v = 1.0f-std::abs((pos.y() - (mMapWorldSize*y))/mMapWorldSize);
} }
MWBase::Environment::get().getWindowManager()->setPlayerPos(x, y, u, v);
MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y);
/*
// explore radius (squared) // explore radius (squared)
const float exploreRadius = (mInterior ? 0.1f : 0.3f) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1 const float exploreRadius = (mInterior ? 0.1f : 0.3f) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
const float sqrExploreRadius = Math::Sqr(exploreRadius); const float sqrExploreRadius = Math::Sqr(exploreRadius);
@ -614,3 +626,5 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
} }
*/ */
} }
}

@ -1,9 +1,13 @@
#ifndef GAME_RENDER_LOCALMAP_H #ifndef GAME_RENDER_LOCALMAP_H
#define GAME_RENDER_LOCALMAP_H #define GAME_RENDER_LOCALMAP_H
#include <OgreAxisAlignedBox.h> #include <set>
#include <OgreColourValue.h> #include <vector>
#include <OgreResource.h> #include <map>
#include <osg/BoundingBox>
#include <osg/Quat>
#include <osg/ref_ptr>
namespace MWWorld namespace MWWorld
{ {
@ -15,52 +19,57 @@ namespace ESM
struct FogTexture; struct FogTexture;
} }
namespace MWRender namespace osgViewer
{ {
class RenderingManager; class Viewer;
}
namespace osg
{
class Texture2D;
class Camera;
class Group;
class Node;
}
namespace MWRender
{
/// ///
/// \brief Local map rendering /// \brief Local map rendering
/// ///
class LocalMap class LocalMap
{ {
public: public:
LocalMap(); LocalMap(osgViewer::Viewer* viewer);
~LocalMap(); ~LocalMap();
virtual void loadResource(Ogre::Resource* resource);
/** /**
* Clear all savegame-specific data (i.e. fog of war textures) * Clear all savegame-specific data (i.e. fog of war textures)
*/ */
void clear(); void clear();
/** void requestMap (std::set<MWWorld::CellStore*> cells);
* Request the local map for an exterior cell.
* @remarks It will either be loaded from a disk cache, void removeCell (MWWorld::CellStore* cell);
* or rendered if it is not already cached.
* @param cell exterior cell osg::ref_ptr<osg::Texture2D> getMapTexture (bool interior, int x, int y);
* @param zMin min height of objects or terrain in cell
* @param zMax max height of objects or terrain in cell void markForRemoval(osg::Camera* cam);
*/
void requestMap (MWWorld::CellStore* cell, float zMin, float zMax);
/** /**
* Request the local map for an interior cell. * Removes cameras that have already been rendered. Should be called every frame to ensure that
* @remarks It will either be loaded from a disk cache, * we do not render the same map more than once. Note, this cleanup is difficult to implement in an
* or rendered if it is not already cached. * automated fashion, since we can't alter the scene graph structure from within an update callback.
* @param cell interior cell
* @param bounds bounding box of the cell
*/ */
void requestMap (MWWorld::CellStore* cell, void cleanupCameras();
Ogre::AxisAlignedBox bounds);
/** /**
* Set the position & direction of the player. * Set the position & direction of the player, and returns the position in map space through the reference parameters.
* @remarks This is used to draw a "fog of war" effect * @remarks This is used to draw a "fog of war" effect
* to hide areas on the map the player has not discovered yet. * to hide areas on the map the player has not discovered yet.
*/ */
void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation); void updatePlayer (const osg::Vec3f& position, const osg::Quat& orientation,
float& u, float& v, int& x, int& y, osg::Vec3f& direction);
/** /**
* Save the fog of war for this cell to its CellStore. * Save the fog of war for this cell to its CellStore.
@ -72,9 +81,9 @@ namespace MWRender
* Get the interior map texture index and normalized position * Get the interior map texture index and normalized position
* on this texture, given a world position * on this texture, given a world position
*/ */
void worldToInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y); void worldToInteriorMapPosition (osg::Vec2f pos, float& nX, float& nY, int& x, int& y);
Ogre::Vector2 interiorMapToWorldPosition (float nX, float nY, int x, int y); osg::Vec2f interiorMapToWorldPosition (float nX, float nY, int x, int y);
/** /**
* Check if a given position is explored by the player (i.e. not obscured by fog of war) * Check if a given position is explored by the player (i.e. not obscured by fog of war)
@ -82,6 +91,20 @@ namespace MWRender
bool isPositionExplored (float nX, float nY, int x, int y, bool interior); bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
private: private:
osg::ref_ptr<osgViewer::Viewer> mViewer;
osg::ref_ptr<osg::Group> mRoot;
osg::ref_ptr<osg::Node> mSceneRoot;
typedef std::vector< osg::ref_ptr<osg::Camera> > CameraVector;
CameraVector mActiveCameras;
CameraVector mCamerasPendingRemoval;
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Texture2D> > TextureMap;
TextureMap mTextures;
int mMapResolution; int mMapResolution;
// the dynamic texture is a bottleneck, so don't set this too high // the dynamic texture is a bottleneck, so don't set this too high
@ -91,46 +114,34 @@ namespace MWRender
static const int sFogOfWarSkip = 2; static const int sFogOfWarSkip = 2;
// size of a map segment (for exteriors, 1 cell) // size of a map segment (for exteriors, 1 cell)
static const int sSize = 8192; float mMapWorldSize;
Ogre::Camera* mCellCamera;
Ogre::SceneNode* mCameraNode;
Ogre::SceneNode* mCameraPosNode;
Ogre::SceneNode* mCameraRotNode;
// directional light from a fixed angle
Ogre::Light* mLight;
float mAngle; float mAngle;
const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle); const osg::Vec2f rotatePoint(const osg::Vec2f& p, const osg::Vec2f& c, const float angle);
/// @param force Always render, even if we already have a cached map void requestExteriorMap(MWWorld::CellStore* cell);
void render(const float x, const float y, void requestInteriorMap(MWWorld::CellStore* cell);
const float zlow, const float zhigh,
const float xw, const float yw, osg::ref_ptr<osg::Camera> createOrthographicCamera(float left, float top, float width, float height, const osg::Vec3d& upVector, float zmin, float zmax);
const std::string& texture, bool force=false); void setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y);
// Creates a fog of war texture and initializes it to full black // Creates a fog of war texture and initializes it to full black
void createFogOfWar(const std::string& texturePrefix); //void createFogOfWar(const std::string& texturePrefix);
// Loads a fog of war texture from its ESM struct // Loads a fog of war texture from its ESM struct
void loadFogOfWar(const std::string& texturePrefix, ESM::FogTexture& esm); // FogTexture not const because MemoryDataStream doesn't accept it //void loadFogOfWar(const std::string& texturePrefix, ESM::FogTexture& esm); // FogTexture not const because MemoryDataStream doesn't accept it
Ogre::TexturePtr createFogOfWarTexture(const std::string& name);
std::string coordStr(const int x, const int y);
// A buffer for the "fog of war" textures of the current cell. // A buffer for the "fog of war" textures of the current cell.
// Both interior and exterior maps are possibly divided into multiple textures. // Both interior and exterior maps are possibly divided into multiple textures.
std::map <std::string, std::vector<Ogre::uint32> > mBuffers; //std::map <std::string, std::vector<Ogre::uint32> > mBuffers;
// The render texture we will use to create the map images // The render texture we will use to create the map images
Ogre::TexturePtr mRenderTexture; //Ogre::TexturePtr mRenderTexture;
Ogre::RenderTarget* mRenderTarget; //Ogre::RenderTarget* mRenderTarget;
bool mInterior; bool mInterior;
Ogre::AxisAlignedBox mBounds; osg::BoundingBox mBounds;
std::string mInteriorName; //std::string mInteriorName;
}; };
} }

@ -2,7 +2,6 @@
#include <cmath> #include <cmath>
#include <osg/io_utils>
#include <osg/Group> #include <osg/Group>
#include <osg/Geode> #include <osg/Geode>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
@ -206,6 +205,10 @@ void Objects::removeCell(const MWWorld::CellStore* store)
void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur) void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
{ {
osg::Node* objectNode = cur.getRefData().getBaseNode();
if (!objectNode)
return;
MWWorld::CellStore *newCell = cur.getCell(); MWWorld::CellStore *newCell = cur.getCell();
osg::Group* cellnode; osg::Group* cellnode;
@ -217,8 +220,6 @@ void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
cellnode = mCellSceneNodes[newCell]; cellnode = mCellSceneNodes[newCell];
} }
osg::Node* objectNode = cur.getRefData().getBaseNode();
osg::UserDataContainer* userDataContainer = objectNode->getUserDataContainer(); osg::UserDataContainer* userDataContainer = objectNode->getUserDataContainer();
if (userDataContainer) if (userDataContainer)
for (unsigned int i=0; i<userDataContainer->getNumUserObjects(); ++i) for (unsigned int i=0; i<userDataContainer->getNumUserObjects(); ++i)

@ -2,7 +2,6 @@
#include <stdexcept> #include <stdexcept>
#include <osg/io_utils>
#include <osg/Light> #include <osg/Light>
#include <osg/LightModel> #include <osg/LightModel>
#include <osg/Fog> #include <osg/Fog>
@ -111,6 +110,7 @@ namespace MWRender
mViewer->setLightingMode(osgViewer::View::NO_LIGHT); mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
osg::ref_ptr<osg::LightSource> source = new osg::LightSource; osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
source->setNodeMask(SceneUtil::Mask_Lit);
mSunLight = new osg::Light; mSunLight = new osg::Light;
source->setLight(mSunLight); source->setLight(mSunLight);
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1)); mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
@ -123,6 +123,7 @@ namespace MWRender
lightRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); lightRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
lightRoot->setNodeMask(Mask_Scene); lightRoot->setNodeMask(Mask_Scene);
lightRoot->setName("Scene Root");
mSky.reset(new SkyManager(lightRoot, resourceSystem->getSceneManager())); mSky.reset(new SkyManager(lightRoot, resourceSystem->getSceneManager()));
@ -342,8 +343,12 @@ namespace MWRender
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST); intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST);
osgUtil::IntersectionVisitor intersectionVisitor(intersector); osgUtil::IntersectionVisitor intersectionVisitor(intersector);
int mask = intersectionVisitor.getTraversalMask();
mask &= ~(Mask_RenderToTexture|Mask_Sky|Mask_Debug|Mask_Effect);
if (ignorePlayer) if (ignorePlayer)
intersectionVisitor.setTraversalMask(intersectionVisitor.getTraversalMask() & (~Mask_Player)); mask &= ~(Mask_Player);
intersectionVisitor.setTraversalMask(mask);
mViewer->getCamera()->accept(intersectionVisitor); mViewer->getCamera()->accept(intersectionVisitor);
@ -451,12 +456,8 @@ namespace MWRender
void RenderingManager::updateProjectionMatrix() void RenderingManager::updateProjectionMatrix()
{ {
double fovy, aspect, zNear, zFar; double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
mViewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar); mViewer->getCamera()->setProjectionMatrixAsPerspective(mFieldOfView, aspect, mNearClip, mViewDistance);
fovy = mFieldOfView;
zNear = mNearClip;
zFar = mViewDistance;
mViewer->getCamera()->setProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
} }
void RenderingManager::updateTextureFiltering() void RenderingManager::updateTextureFiltering()

@ -8,10 +8,6 @@
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
#include <osg/io_utils>
#include <osgUtil/CullVisitor>
#include <osg/TexEnvCombine> #include <osg/TexEnvCombine>
#include <osg/TexMat> #include <osg/TexMat>
@ -34,7 +30,7 @@
#include "../mwworld/fallback.hpp" #include "../mwworld/fallback.hpp"
#include "renderingmanager.hpp" #include "vismask.hpp"
namespace namespace
{ {
@ -506,6 +502,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
, mSecundaEnabled(true) , mSecundaEnabled(true)
{ {
osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform); osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform);
skyroot->setNodeMask(Mask_Sky);
parentNode->addChild(skyroot); parentNode->addChild(skyroot);
mRootNode = skyroot; mRootNode = skyroot;
@ -652,7 +649,7 @@ void SkyManager::setEnabled(bool enabled)
if (!enabled) if (!enabled)
clearRain(); clearRain();
mRootNode->setNodeMask(enabled ? ~((unsigned int)(0)) : 0); mRootNode->setNodeMask(enabled ? Mask_Sky : 0);
mEnabled = enabled; mEnabled = enabled;
} }

@ -14,10 +14,16 @@ namespace MWRender
Mask_Debug = (1<<2), Mask_Debug = (1<<2),
Mask_Actor = (1<<3), Mask_Actor = (1<<3),
Mask_Player = (1<<4), Mask_Player = (1<<4),
Mask_Sky = (1<<5),
// top level masks // top level masks
Mask_Scene = (1<<5), Mask_Scene = (1<<6),
Mask_GUI = (1<<6) Mask_GUI = (1<<7),
// Set on cameras within the main scene graph
Mask_RenderToTexture = (1<<8)
// reserved: (1<<16) for SceneUtil::Mask_Lit
}; };
} }

@ -172,8 +172,13 @@ namespace MWWorld
{ {
// Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different // Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different
// (and objects in a different cell can "bleed" into another cells map if they cross the border) // (and objects in a different cell can "bleed" into another cells map if they cross the border)
//for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) std::set<MWWorld::CellStore*> cellsToUpdate;
//mRendering.requestMap(*active); for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
{
cellsToUpdate.insert(*active);
}
MWBase::Environment::get().getWindowManager()->requestMap(cellsToUpdate);
mNeedMapUpdate = false; mNeedMapUpdate = false;
if (mCurrentCell->isExterior()) if (mCurrentCell->isExterior())
@ -213,6 +218,7 @@ namespace MWWorld
MWBase::Environment::get().getMechanicsManager()->drop (*iter); MWBase::Environment::get().getMechanicsManager()->drop (*iter);
mRendering.removeCell(*iter); mRendering.removeCell(*iter);
MWBase::Environment::get().getWindowManager()->removeCell(*iter);
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter); MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);

@ -162,14 +162,11 @@ namespace MWWorld
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
{ {
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode); mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
//mPhysEngine = mPhysics->getEngine();
#if 0 #if 0
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine)); mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
#endif #endif
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem); mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem);
//mPhysEngine->setSceneManager(renderer.getScene());
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback); mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
mEsm.resize(contentFiles.size()); mEsm.resize(contentFiles.size());
@ -1591,24 +1588,38 @@ namespace MWWorld
updateWindowManager (); updateWindowManager ();
updateSoundListener(); updateSoundListener();
/*
if (!paused && mPlayer->getPlayer().getCell()->isExterior()) updatePlayer(paused);
}
void World::updatePlayer(bool paused)
{
MWWorld::Ptr player = getPlayerPtr();
// TODO: move to MWWorld::Player
if (player.getCell()->isExterior())
{ {
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition(); ESM::Position pos = player.getRefData().getPosition();
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos)); mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos));
} }
*/
if (player.getClass().getNpcStats(player).isWerewolf())
MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mRendering->getCamera()->isFirstPerson());
// Sink the camera while sneaking // Sink the camera while sneaking
bool sneaking = getPlayerPtr().getClass().getCreatureStats(getPlayerPtr()).getStance(MWMechanics::CreatureStats::Stance_Sneak); bool sneaking = player.getClass().getCreatureStats(getPlayerPtr()).getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool inair = !isOnGround(getPlayerPtr()); bool inair = !isOnGround(player);
bool swimming = isSwimming(getPlayerPtr()); bool swimming = isSwimming(player);
static const float i1stPersonSneakDelta = getStore().get<ESM::GameSetting>().find("i1stPersonSneakDelta")->getFloat(); static const float i1stPersonSneakDelta = getStore().get<ESM::GameSetting>().find("i1stPersonSneakDelta")->getFloat();
if(!paused && sneaking && !(swimming || inair)) if(!paused && sneaking && !(swimming || inair))
mRendering->getCamera()->setSneakOffset(i1stPersonSneakDelta); mRendering->getCamera()->setSneakOffset(i1stPersonSneakDelta);
else else
mRendering->getCamera()->setSneakOffset(0.f); mRendering->getCamera()->setSneakOffset(0.f);
int blind = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude());
MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind)));
} }
void World::updateSoundListener() void World::updateSoundListener()
@ -1701,16 +1712,16 @@ namespace MWWorld
mWeatherManager->modRegion(regionid, chances); mWeatherManager->modRegion(regionid, chances);
} }
Ogre::Vector2 World::getNorthVector (CellStore* cell) osg::Vec2f World::getNorthVector (CellStore* cell)
{ {
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>(); MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();
MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker"); MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
if (!ref) if (!ref)
return Ogre::Vector2(0, 1); return osg::Vec2f(0, 1);
Ogre::Quaternion orient (Ogre::Radian(-ref->mData.getPosition().rot[2]), Ogre::Vector3::UNIT_Z); osg::Quat orient (-ref->mData.getPosition().rot[2], osg::Vec3f(0,0,1));
Ogre::Vector3 dir = orient * Ogre::Vector3(0,1,0); osg::Vec3f dir = orient * osg::Vec3f(0,1,0);
Ogre::Vector2 d = Ogre::Vector2(dir.x, dir.y); osg::Vec2f d (dir.x(), dir.y());
return d; return d;
} }
@ -1756,24 +1767,9 @@ namespace MWWorld
} }
} }
void World::worldToInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
{
//mRendering->worldToInteriorMapPosition(position, nX, nY, x, y);
}
Ogre::Vector2 World::interiorMapToWorldPosition(float nX, float nY, int x, int y)
{
return Ogre::Vector2();//mRendering->interiorMapToWorldPosition(nX, nY, x, y);
}
bool World::isPositionExplored (float nX, float nY, int x, int y, bool interior)
{
return 0;//mRendering->isPositionExplored(nX, nY, x, y, interior);
}
void World::setWaterHeight(const float height) void World::setWaterHeight(const float height)
{ {
//mPhysics->setWaterHeight(height); mPhysics->setWaterHeight(height);
//mRendering->setWaterHeight(height); //mRendering->setWaterHeight(height);
} }

@ -121,6 +121,7 @@ namespace MWWorld
void updateSoundListener(); void updateSoundListener();
void updateWindowManager (); void updateWindowManager ();
void updatePlayer(bool paused);
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true); MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
void removeContainerScripts(const Ptr& reference); void removeContainerScripts(const Ptr& reference);
@ -218,21 +219,12 @@ namespace MWWorld
virtual bool isCellQuasiExterior() const; virtual bool isCellQuasiExterior() const;
virtual Ogre::Vector2 getNorthVector (CellStore* cell); virtual osg::Vec2f getNorthVector (CellStore* cell);
///< get north vector for given interior cell ///< get north vector for given interior cell
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out); virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out);
///< get a list of teleport door markers for a given cell, to be displayed on the local map ///< get a list of teleport door markers for a given cell, to be displayed on the local map
virtual void worldToInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
///< see MWRender::LocalMap::worldToInteriorMapPosition
virtual Ogre::Vector2 interiorMapToWorldPosition (float nX, float nY, int x, int y);
///< see MWRender::LocalMap::interiorMapToWorldPosition
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
///< see MWRender::LocalMap::isPositionExplored
virtual void setGlobalInt (const std::string& name, int value); virtual void setGlobalInt (const std::string& name, int value);
///< Set value independently from real type. ///< Set value independently from real type.

@ -86,7 +86,7 @@ namespace osgMyGUI
if (!mTextureManager) if (!mTextureManager)
throw std::runtime_error("No texturemanager set"); throw std::runtime_error("No texturemanager set");
mTexture = mTextureManager->getTexture2D(fname, osg::Texture2D::REPEAT, osg::Texture2D::REPEAT); mTexture = mTextureManager->getTexture2D(fname, osg::Texture2D::CLAMP_TO_EDGE, osg::Texture2D::CLAMP_TO_EDGE);
// FIXME // FIXME
mFormat = MyGUI::PixelFormat::R8G8B8; mFormat = MyGUI::PixelFormat::R8G8B8;

@ -4,7 +4,6 @@
#include <osg/TexMat> #include <osg/TexMat>
#include <osg/Material> #include <osg/Material>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/io_utils>
#include <osg/UserDataContainer> #include <osg/UserDataContainer>
#include <osgAnimation/MorphGeometry> #include <osgAnimation/MorphGeometry>

@ -9,8 +9,6 @@
#include <osg/ShapeDrawable> #include <osg/ShapeDrawable>
#include <osg/ComputeBoundsVisitor> #include <osg/ComputeBoundsVisitor>
#include <osg/io_utils>
// resource // resource
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>

@ -6,8 +6,6 @@
#include <components/nif/controlled.hpp> #include <components/nif/controlled.hpp>
#include <osg/io_utils>
#include "userdata.hpp" #include "userdata.hpp"
namespace NifOsg namespace NifOsg

@ -226,6 +226,7 @@ namespace SceneUtil
LightSource::LightSource() LightSource::LightSource()
: mRadius(0.f) : mRadius(0.f)
{ {
setNodeMask(Mask_Lit);
setUpdateCallback(new CollectLightCallback); setUpdateCallback(new CollectLightCallback);
} }
@ -233,6 +234,12 @@ namespace SceneUtil
{ {
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv); osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
if (!(cv->getCurrentCamera()->getCullMask()&Mask_Lit))
{
traverse(node, nv);
return;
}
if (!mLightManager) if (!mLightManager)
{ {
for (unsigned int i=0;i<nv->getNodePath().size(); ++i) for (unsigned int i=0;i<nv->getNodePath().size(); ++i)

@ -9,6 +9,9 @@
namespace SceneUtil namespace SceneUtil
{ {
// This mask should be included in the Cull and Update visitor's traversal mask if lighting is desired.
const int Mask_Lit = (1<<16);
/// LightSource managed by a LightManager. /// LightSource managed by a LightManager.
class LightSource : public osg::Node class LightSource : public osg::Node
{ {

@ -6,7 +6,6 @@
#include <cstdlib> #include <cstdlib>
#include <osg/MatrixTransform> #include <osg/MatrixTransform>
#include <osg/io_utils>
#include "skeleton.hpp" #include "skeleton.hpp"
#include "util.hpp" #include "util.hpp"

Loading…
Cancel
Save