mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 08:15:37 +00:00
Map rendering
This commit is contained in:
parent
76dd3e4034
commit
3dcb167066
31 changed files with 535 additions and 458 deletions
|
@ -596,7 +596,7 @@ void OMW::Engine::go()
|
|||
{
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
//dt = std::min(dt, 0.2);
|
||||
dt = std::min(dt, 0.2);
|
||||
|
||||
double simulationTime = frame(dt);
|
||||
mViewer->frame(simulationTime);
|
||||
|
|
|
@ -178,12 +178,6 @@ namespace MWBase
|
|||
virtual void changeCell(MWWorld::CellStore* cell) = 0;
|
||||
///< 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 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 correctBookartPath(const std::string& path, int width, int height) = 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 Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
virtual osg::Vec2f getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< get north vector for given interior cell
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
///< 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")
|
||||
, LocalMapBase(customMarkers)
|
||||
, LocalMapBase(customMarkers, localMapRender)
|
||||
, mHealth(NULL)
|
||||
, mMagicka(NULL)
|
||||
, mStamina(NULL)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace MWGui
|
|||
class HUD : public Layout, public LocalMapBase
|
||||
{
|
||||
public:
|
||||
HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop);
|
||||
HUD(CustomMarkerCollection& customMarkers, bool fpsVisible, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
|
||||
virtual ~HUD();
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setFPS(float fps);
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace MWGui
|
|||
, mLastRenderTime(0.0)
|
||||
, mLoadingOnTime(0.0)
|
||||
, mProgress(0)
|
||||
, mVSyncWasEnabled(false)
|
||||
{
|
||||
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
|
||||
|
||||
|
|
|
@ -67,8 +67,6 @@ namespace MWGui
|
|||
|
||||
std::vector<std::string> mSplashScreens;
|
||||
|
||||
bool mVSyncWasEnabled;
|
||||
|
||||
void changeWallpaper();
|
||||
|
||||
void draw();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwrender/globalmap.hpp"
|
||||
#include "../mwrender/localmap.hpp"
|
||||
|
||||
#include "widgets.hpp"
|
||||
#include "confirmationdialog.hpp"
|
||||
|
@ -142,8 +143,9 @@ namespace MWGui
|
|||
|
||||
// ------------------------------------------------------
|
||||
|
||||
LocalMapBase::LocalMapBase(CustomMarkerCollection &markers)
|
||||
: mCurX(0)
|
||||
LocalMapBase::LocalMapBase(CustomMarkerCollection &markers, MWRender::LocalMap* localMapRender)
|
||||
: mLocalMapRender(localMapRender)
|
||||
, mCurX(0)
|
||||
, mCurY(0)
|
||||
, mInterior(false)
|
||||
, mLocalMap(NULL)
|
||||
|
@ -260,8 +262,8 @@ namespace MWGui
|
|||
else
|
||||
{
|
||||
int cellX, cellY;
|
||||
Ogre::Vector2 worldPos (worldX, worldY);
|
||||
MWBase::Environment::get().getWorld ()->worldToInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
|
||||
osg::Vec2f worldPos (worldX, worldY);
|
||||
mLocalMapRender->worldToInteriorMapPosition(worldPos, nX, nY, cellX, cellY);
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
@ -301,7 +303,7 @@ namespace MWGui
|
|||
continue;
|
||||
}
|
||||
|
||||
MarkerUserData markerPos;
|
||||
MarkerUserData markerPos (mLocalMapRender);
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos);
|
||||
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 8,
|
||||
|
@ -342,24 +344,30 @@ namespace MWGui
|
|||
mDoorMarkerWidgets.clear();
|
||||
|
||||
// Update the map textures
|
||||
#if 0
|
||||
std::vector<boost::shared_ptr<MyGUI::ITexture> > textures;
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
{
|
||||
// map
|
||||
std::string image = mPrefix+"_"+ MyGUI::utility::toString(x + (mx-1)) + "_"
|
||||
+ MyGUI::utility::toString(y + (-1*(my-1)));
|
||||
int mapX = x + (mx-1);
|
||||
int mapY = y + (-1*(my-1));
|
||||
|
||||
MyGUI::ImageBox* box = mMapWidgets[my + 3*mx];
|
||||
|
||||
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
|
||||
box->setImageTexture(image);
|
||||
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(mInterior, mapX, mapY);
|
||||
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
|
||||
box->setImageTexture("black");
|
||||
box->setRenderItemTexture(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mMapTextures.swap(textures);
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// Retrieve the door markers we want to show
|
||||
|
@ -394,7 +402,7 @@ namespace MWGui
|
|||
destNotes.push_back(it->mNote);
|
||||
}
|
||||
|
||||
MarkerUserData data;
|
||||
MarkerUserData data (mLocalMapRender);
|
||||
data.notes = destNotes;
|
||||
data.caption = marker.name;
|
||||
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)
|
||||
{
|
||||
const ESM::Position& worldPos = it->getRefData().getPosition();
|
||||
MarkerUserData markerPos;
|
||||
MarkerUserData markerPos (mLocalMapRender);
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
|
@ -535,7 +543,7 @@ namespace MWGui
|
|||
if (markedCell && markedCell->isExterior() == !mInterior
|
||||
&& (!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::IntCoord widgetCoord(widgetPos.left - 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")
|
||||
, LocalMapBase(customMarkers)
|
||||
, LocalMapBase(customMarkers, localMapRender)
|
||||
, NoDrop(drag, mMainWidget)
|
||||
, mGlobalMap(0)
|
||||
, mGlobalMapTexture(NULL)
|
||||
|
@ -662,19 +670,19 @@ namespace MWGui
|
|||
x += mCurX;
|
||||
y += mCurY;
|
||||
|
||||
Ogre::Vector2 worldPos;
|
||||
osg::Vec2f worldPos;
|
||||
if (mInterior)
|
||||
{
|
||||
worldPos = MWBase::Environment::get().getWorld()->interiorMapToWorldPosition(nX, nY, x, y);
|
||||
worldPos = mLocalMapRender->interiorMapToWorldPosition(nX, nY, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
worldPos.x = (x + nX) * cellSize;
|
||||
worldPos.y = (y + (1.0f-nY)) * cellSize;
|
||||
worldPos.x() = (x + nX) * cellSize;
|
||||
worldPos.y() = (y + (1.0f-nY)) * cellSize;
|
||||
}
|
||||
|
||||
mEditingMarker.mWorldX = worldPos.x;
|
||||
mEditingMarker.mWorldY = worldPos.y;
|
||||
mEditingMarker.mWorldX = worldPos.x();
|
||||
mEditingMarker.mWorldY = worldPos.y();
|
||||
|
||||
mEditingMarker.mCell.mPaged = !mInterior;
|
||||
if (mInterior)
|
||||
|
@ -993,4 +1001,9 @@ namespace MWGui
|
|||
eventDeleteClicked();
|
||||
}
|
||||
|
||||
bool LocalMapBase::MarkerUserData::isPositionExplored() const
|
||||
{
|
||||
return mLocalMapRender->isPositionExplored(nX, nY, cellX, cellY, interior);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "windowpinnablebase.hpp"
|
||||
|
||||
#include <components/esm/cellid.hpp>
|
||||
|
@ -12,6 +14,7 @@
|
|||
namespace MWRender
|
||||
{
|
||||
class GlobalMap;
|
||||
class LocalMap;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
|
@ -52,7 +55,7 @@ namespace MWGui
|
|||
class LocalMapBase
|
||||
{
|
||||
public:
|
||||
LocalMapBase(CustomMarkerCollection& markers);
|
||||
LocalMapBase(CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender);
|
||||
virtual ~LocalMapBase();
|
||||
void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int mapWidgetSize);
|
||||
|
||||
|
@ -67,6 +70,14 @@ namespace MWGui
|
|||
|
||||
struct MarkerUserData
|
||||
{
|
||||
MarkerUserData(MWRender::LocalMap* map)
|
||||
: mLocalMapRender(map)
|
||||
{
|
||||
}
|
||||
|
||||
bool isPositionExplored() const;
|
||||
|
||||
MWRender::LocalMap* mLocalMapRender;
|
||||
bool interior;
|
||||
int cellX;
|
||||
int cellY;
|
||||
|
@ -77,6 +88,8 @@ namespace MWGui
|
|||
};
|
||||
|
||||
protected:
|
||||
MWRender::LocalMap* mLocalMapRender;
|
||||
|
||||
int mCurX, mCurY;
|
||||
bool mInterior;
|
||||
MyGUI::ScrollView* mLocalMap;
|
||||
|
@ -93,6 +106,8 @@ namespace MWGui
|
|||
std::vector<MyGUI::ImageBox*> mMapWidgets;
|
||||
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.
|
||||
std::vector<MyGUI::Widget*> mDoorMarkerWidgets;
|
||||
std::vector<MyGUI::Widget*> mMagicMarkerWidgets;
|
||||
|
@ -153,7 +168,7 @@ namespace MWGui
|
|||
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
|
||||
{
|
||||
public:
|
||||
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, const std::string& cacheDir);
|
||||
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender);
|
||||
virtual ~MapWindow();
|
||||
|
||||
void setCellName(const std::string& cellName);
|
||||
|
|
|
@ -169,7 +169,7 @@ namespace MWGui
|
|||
{
|
||||
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;
|
||||
|
||||
ToolTipInfo info;
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "../mwmechanics/stat.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "../mwrender/localmap.hpp"
|
||||
|
||||
#include "../mwsound/soundmanagerimp.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
|
@ -115,6 +117,7 @@ namespace MWGui
|
|||
, mCurrentModals()
|
||||
, mHud(NULL)
|
||||
, mMap(NULL)
|
||||
, mLocalMapRender(NULL)
|
||||
, mMenu(NULL)
|
||||
, mToolTips(NULL)
|
||||
, mStatsWindow(NULL)
|
||||
|
@ -266,7 +269,8 @@ namespace MWGui
|
|||
|
||||
mRecharge = new Recharge();
|
||||
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");
|
||||
mStatsWindow = new StatsWindow(mDragAndDrop);
|
||||
trackWindow(mStatsWindow, "stats");
|
||||
|
@ -284,7 +288,7 @@ namespace MWGui
|
|||
trackWindow(mDialogueWindow, "dialogue");
|
||||
mContainerWindow = new ContainerWindow(mDragAndDrop);
|
||||
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();
|
||||
mScrollWindow = new ScrollWindow();
|
||||
mBookWindow = new BookWindow();
|
||||
|
@ -383,6 +387,7 @@ namespace MWGui
|
|||
delete mMessageBoxManager;
|
||||
delete mHud;
|
||||
delete mMap;
|
||||
delete mLocalMapRender;
|
||||
delete mMenu;
|
||||
delete mStatsWindow;
|
||||
delete mJournal;
|
||||
|
@ -886,6 +891,31 @@ namespace MWGui
|
|||
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)
|
||||
{
|
||||
mMessageBoxManager->onFrame(frameDuration);
|
||||
|
@ -894,6 +924,9 @@ namespace MWGui
|
|||
|
||||
mMenu->update(frameDuration);
|
||||
|
||||
if (mLocalMapRender)
|
||||
mLocalMapRender->cleanupCameras();
|
||||
|
||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||
MWBase::StateManager::State_NoGame)
|
||||
return;
|
||||
|
@ -908,6 +941,8 @@ namespace MWGui
|
|||
|
||||
mInventoryWindow->onFrame();
|
||||
|
||||
updateMap();
|
||||
|
||||
mStatsWindow->onFrame(frameDuration);
|
||||
mMap->onFrame(frameDuration);
|
||||
mSpellWindow->onFrame(frameDuration);
|
||||
|
@ -968,29 +1003,10 @@ namespace MWGui
|
|||
|
||||
void WindowManager::setActiveMap(int x, int y, bool interior)
|
||||
{
|
||||
if (!interior)
|
||||
{
|
||||
mMap->setCellPrefix("Cell");
|
||||
mHud->setCellPrefix("Cell");
|
||||
}
|
||||
|
||||
mMap->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)
|
||||
{
|
||||
mHud->setDrowningBarVisible(visible);
|
||||
|
@ -1990,4 +2006,14 @@ namespace MWGui
|
|||
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;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class LocalMap;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowBase;
|
||||
|
@ -191,8 +196,6 @@ namespace MWGui
|
|||
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 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 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 correctTexturePath(const std::string& path);
|
||||
|
||||
void requestMap(std::set<MWWorld::CellStore*> cells);
|
||||
void removeCell(MWWorld::CellStore* cell);
|
||||
|
||||
private:
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
|
@ -386,6 +392,7 @@ namespace MWGui
|
|||
|
||||
HUD *mHud;
|
||||
MapWindow *mMap;
|
||||
MWRender::LocalMap* mLocalMapRender;
|
||||
MainMenu *mMenu;
|
||||
ToolTips *mToolTips;
|
||||
StatsWindow *mStatsWindow;
|
||||
|
@ -473,6 +480,8 @@ namespace MWGui
|
|||
|
||||
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
|
||||
|
||||
void updateMap();
|
||||
|
||||
float mFPS;
|
||||
|
||||
std::map<std::string, std::string> mFallbackMap;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "actor.hpp"
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <osg/TexEnvCombine>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "npcanimation.hpp"
|
||||
#include "vismask.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
@ -81,6 +82,8 @@ namespace MWRender
|
|||
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture);
|
||||
mCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
|
||||
|
||||
mCamera->setNodeMask(Mask_RenderToTexture);
|
||||
|
||||
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager;
|
||||
lightManager->setStartLight(1);
|
||||
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||
|
|
|
@ -1,74 +1,82 @@
|
|||
#include "localmap.hpp"
|
||||
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreTextureManager.h>
|
||||
#include <OgreRenderTexture.h>
|
||||
#include <OgreViewport.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/LightModel>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <components/esm/fogstate.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
|
||||
#include "vismask.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
namespace
|
||||
{
|
||||
|
||||
LocalMap::LocalMap()
|
||||
: mMapResolution(Settings::Manager::getInt("local map resolution", "Map"))
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
LocalMap::LocalMap(osgViewer::Viewer* viewer)
|
||||
: mViewer(viewer)
|
||||
, mMapResolution(Settings::Manager::getInt("local map resolution", "Map"))
|
||||
, mMapWorldSize(8192.f)
|
||||
, mAngle(0.f)
|
||||
, mInterior(false)
|
||||
{
|
||||
// mCellCamera = mRendering->getScene()->createCamera("CellCamera");
|
||||
mCellCamera->setProjectionType(PT_ORTHOGRAPHIC);
|
||||
mRoot = mViewer->getSceneData()->asGroup();
|
||||
|
||||
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");
|
||||
SceneUtil::FindByNameVisitor find("Scene Root");
|
||||
mRoot->accept(find);
|
||||
mSceneRoot = find.mFoundNode;
|
||||
if (!mSceneRoot)
|
||||
throw std::runtime_error("no scene root found");
|
||||
}
|
||||
|
||||
LocalMap::~LocalMap()
|
||||
{
|
||||
for (CameraVector::iterator it = mActiveCameras.begin(); it != mActiveCameras.end(); ++it)
|
||||
mRoot->removeChild(*it);
|
||||
for (CameraVector::iterator it = mCamerasPendingRemoval.begin(); it != mCamerasPendingRemoval.end(); ++it)
|
||||
mRoot->removeChild(*it);
|
||||
}
|
||||
|
||||
const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle)
|
||||
const osg::Vec2f LocalMap::rotatePoint(const osg::Vec2f& p, const osg::Vec2f& c, const float angle)
|
||||
{
|
||||
return Vector2( Math::Cos(angle) * (p.x - c.x) - Math::Sin(angle) * (p.y - c.y) + c.x,
|
||||
Math::Sin(angle) * (p.x - c.x) + Math::Cos(angle) * (p.y - c.y) + c.y);
|
||||
}
|
||||
|
||||
std::string LocalMap::coordStr(const int x, const int y)
|
||||
{
|
||||
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()
|
||||
|
@ -103,8 +111,8 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
|
|||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y);
|
||||
Vector2 length = max-min;
|
||||
const int segsX = static_cast<int>(std::ceil(length.x / sSize));
|
||||
const int segsY = static_cast<int>(std::ceil(length.y / sSize));
|
||||
const int segsX = static_cast<int>(std::ceil(length.x / mMapWorldSize));
|
||||
const int segsY = static_cast<int>(std::ceil(length.y / mMapWorldSize));
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void LocalMap::setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y)
|
||||
{
|
||||
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;
|
||||
|
||||
mCameraRotNode->setOrientation(Quaternion::IDENTITY);
|
||||
mCellCamera->setOrientation(Quaternion(Ogre::Math::Cos(Ogre::Degree(0)/2.f), 0, 0, -Ogre::Math::Sin(Ogre::Degree(0)/2.f)));
|
||||
|
||||
int x = cell->getCell()->getGridX();
|
||||
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));
|
||||
|
||||
// Note: using force=true for exterior cell maps.
|
||||
// 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);
|
||||
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);
|
||||
setupRenderToTexture(camera, cell->getCell()->getGridX(), cell->getCell()->getGridY());
|
||||
|
||||
/*
|
||||
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,
|
||||
AxisAlignedBox bounds)
|
||||
void LocalMap::requestInteriorMap(MWWorld::CellStore* cell)
|
||||
{
|
||||
osg::ComputeBoundsVisitor computeBoundsVisitor;
|
||||
computeBoundsVisitor.setTraversalMask(Mask_Scene);
|
||||
mSceneRoot->accept(computeBoundsVisitor);
|
||||
|
||||
osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox();
|
||||
|
||||
// If we're in an empty cell, bail out
|
||||
// The operations in this function are only valid for finite bounds
|
||||
if (bounds.isNull ())
|
||||
if (!bounds.valid() || bounds.radius2() == 0.0)
|
||||
return;
|
||||
|
||||
mInterior = true;
|
||||
|
@ -191,41 +325,31 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
|
|||
mBounds = bounds;
|
||||
|
||||
// Get the cell's NorthMarker rotation. This is used to rotate the entire map.
|
||||
const Vector2& north = MWBase::Environment::get().getWorld()->getNorthVector(cell);
|
||||
Radian angle = Ogre::Math::ATan2 (north.x, north.y);
|
||||
mAngle = angle.valueRadians();
|
||||
osg::Vec2f north = MWBase::Environment::get().getWorld()->getNorthVector(cell);
|
||||
|
||||
mAngle = std::atan2(north.x(), north.y());
|
||||
|
||||
// Rotate the cell and merge the rotated corners to the bounding box
|
||||
Vector2 _center(bounds.getCenter().x, bounds.getCenter().y);
|
||||
Vector3 _c1 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM);
|
||||
Vector3 _c2 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM);
|
||||
Vector3 _c3 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_TOP);
|
||||
Vector3 _c4 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_TOP);
|
||||
|
||||
Vector2 c1(_c1.x, _c1.y);
|
||||
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));
|
||||
osg::Vec2f _center(bounds.center().x(), bounds.center().y());
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
osg::Vec3f corner = mBounds.corner(i);
|
||||
osg::Vec2f corner2d (corner.x(), corner.y());
|
||||
corner2d = rotatePoint(corner2d, _center, mAngle);
|
||||
mBounds.expandBy(osg::Vec3f(corner2d.x(), corner2d.y(), 0));
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
mBounds.setMinimum (mBounds.getMinimum() - Vector3(padding,padding,0));
|
||||
mBounds.setMaximum (mBounds.getMaximum() + Vector3(padding,padding,0));
|
||||
mBounds.set(mBounds._min - osg::Vec3f(padding,padding,0.f),
|
||||
mBounds._max + osg::Vec3f(padding,padding,0.f));
|
||||
|
||||
float zMin = mBounds.getMinimum().z;
|
||||
float zMax = mBounds.getMaximum().z;
|
||||
float zMin = mBounds.zMin();
|
||||
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
|
||||
// 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 maxDiff = newMax - mBounds.getMaximum();
|
||||
|
||||
if (std::abs(minDiff.x) > 500 || std::abs(minDiff.y) > 500
|
||||
|| std::abs(maxDiff.x) > 500 || std::abs(maxDiff.y) > 500
|
||||
if (std::abs(minDiff.x) > padding || std::abs(minDiff.y) > padding
|
||||
|| std::abs(maxDiff.x) > padding || std::abs(maxDiff.y) > padding
|
||||
|| std::abs(mAngle - fog->mNorthMarkerAngle) > Ogre::Degree(5).valueRadians())
|
||||
{
|
||||
// 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);
|
||||
osg::Vec2f length = max-min;
|
||||
|
||||
Vector2 length = max-min;
|
||||
|
||||
mCellCamera->setOrientation(Quaternion::IDENTITY);
|
||||
mCameraRotNode->setOrientation(Quaternion(Math::Cos(mAngle/2.f), 0, 0, -Math::Sin(mAngle/2.f)));
|
||||
|
||||
mCameraPosNode->setPosition(Vector3(center.x, center.y, 0));
|
||||
osg::Vec2f center(bounds.center().x(), bounds.center().y());
|
||||
|
||||
// divide into segments
|
||||
const int segsX = static_cast<int>(std::ceil(length.x / sSize));
|
||||
const int segsY = static_cast<int>(std::ceil(length.y / sSize));
|
||||
const int segsX = static_cast<int>(std::ceil(length.x() / mMapWorldSize));
|
||||
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 y=0; y<segsY; ++y)
|
||||
{
|
||||
Vector2 start = min + Vector2(static_cast<Ogre::Real>(sSize*x), static_cast<Ogre::Real>(sSize*y));
|
||||
Vector2 newcenter = start + sSize/2;
|
||||
osg::Vec2f start = min + osg::Vec2f(mMapWorldSize*x, mMapWorldSize*y);
|
||||
osg::Vec2f newcenter = start + osg::Vec2f(mMapWorldSize/2.f, mMapWorldSize/2.f);
|
||||
|
||||
std::string texturePrefix = cell->getCell()->mName + "_" + coordStr(x,y);
|
||||
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));
|
||||
|
||||
render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, static_cast<float>(sSize), static_cast<float>(sSize), texturePrefix);
|
||||
osg::Vec2f pos = osg::Vec2f(rotatedCenter.x(), rotatedCenter.y()) + center;
|
||||
|
||||
osg::ref_ptr<osg::Camera> camera = createOrthographicCamera(pos.x(), pos.y(),
|
||||
mMapWorldSize, mMapWorldSize,
|
||||
osg::Vec3f(north.x(), north.y(), 0.f), zMin, zMax);
|
||||
|
||||
setupRenderToTexture(camera, x, y);
|
||||
|
||||
/*
|
||||
if (!cell->getFog())
|
||||
|
@ -305,14 +429,13 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
|
|||
loadFogOfWar(texturePrefix, esm);
|
||||
}
|
||||
*/
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void LocalMap::createFogOfWar(const std::string& texturePrefix)
|
||||
{
|
||||
/*
|
||||
const std::string texName = texturePrefix + "_fog";
|
||||
TexturePtr tex = createFogOfWarTexture(texName);
|
||||
|
||||
|
@ -328,34 +451,12 @@ void LocalMap::createFogOfWar(const std::string& texturePrefix)
|
|||
tex->getBuffer()->unlock();
|
||||
|
||||
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)
|
||||
{
|
||||
/*
|
||||
std::vector<char>& data = esm.mImageData;
|
||||
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||
Ogre::Image image;
|
||||
|
@ -377,89 +478,35 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture&
|
|||
memcpy(&buffer[0], image.getData(), image.getSize());
|
||||
|
||||
mBuffers[texturePrefix] = buffer;
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
void LocalMap::worldToInteriorMapPosition (osg::Vec2f pos, float& nX, float& nY, int& x, int& y)
|
||||
{
|
||||
pos = rotatePoint(pos, osg::Vec2f(mBounds.center().x(), mBounds.center().y()), mAngle);
|
||||
|
||||
osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
|
||||
|
||||
x = static_cast<int>(std::ceil((pos.x() - min.x()) / mMapWorldSize) - 1);
|
||||
y = static_cast<int>(std::ceil((pos.y() - min.y()) / mMapWorldSize) - 1);
|
||||
|
||||
nX = (pos.x() - min.x() - mMapWorldSize*x)/mMapWorldSize;
|
||||
nY = 1.0f-(pos.y() - min.y() - mMapWorldSize*y)/mMapWorldSize;
|
||||
}
|
||||
|
||||
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)
|
||||
osg::Vec2f LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int y)
|
||||
{
|
||||
mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 );
|
||||
mCellCamera->setNearClipDistance(50);
|
||||
osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
|
||||
osg::Vec2f pos (mMapWorldSize * (nX + x) + min.x(),
|
||||
mMapWorldSize * (1.0f-nY + y) + min.y());
|
||||
|
||||
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)
|
||||
{
|
||||
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().y), mAngle);
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
|
||||
x = static_cast<int>(std::ceil((pos.x - min.x) / sSize) - 1);
|
||||
y = static_cast<int>(std::ceil((pos.y - min.y) / sSize) - 1);
|
||||
|
||||
nX = (pos.x - min.x - sSize*x)/sSize;
|
||||
nY = 1.0f-(pos.y - min.y - sSize*y)/sSize;
|
||||
}
|
||||
|
||||
Ogre::Vector2 LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int y)
|
||||
{
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
Ogre::Vector2 pos;
|
||||
|
||||
pos.x = sSize * (nX + x) + min.x;
|
||||
pos.y = sSize * (1.0f-nY + y) + min.y;
|
||||
|
||||
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().y), -mAngle);
|
||||
pos = rotatePoint(pos, osg::Vec2f(mBounds.center().x(), mBounds.center().y()), -mAngle);
|
||||
return pos;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -478,33 +525,8 @@ bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interi
|
|||
*/
|
||||
}
|
||||
|
||||
void LocalMap::loadResource(Ogre::Resource* resource)
|
||||
{
|
||||
/*
|
||||
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)
|
||||
void LocalMap::updatePlayer (const osg::Vec3f& position, const osg::Quat& orientation,
|
||||
float& u, float& v, int& x, int& y, osg::Vec3f& direction)
|
||||
{
|
||||
/*
|
||||
if (sFogOfWarSkip != 0)
|
||||
|
@ -513,42 +535,32 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
if (++count % sFogOfWarSkip != 0)
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// retrieve the x,y grid coordinates the player is in
|
||||
int x,y;
|
||||
float u,v;
|
||||
|
||||
Vector2 pos(position.x, position.y);
|
||||
osg::Vec2f pos(position.x(), position.y());
|
||||
|
||||
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);
|
||||
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
|
||||
std::string texBaseName;
|
||||
if (!mInterior)
|
||||
{
|
||||
u = std::abs((pos.x - (sSize*x))/sSize);
|
||||
v = 1.0f-std::abs((pos.y - (sSize*y))/sSize);
|
||||
texBaseName = "Cell_";
|
||||
osg::Quat cameraOrient (mAngle, osg::Vec3(0,0,-1));
|
||||
direction = orientation * cameraOrient.inverse() * osg::Vec3f(0,1,0);
|
||||
}
|
||||
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)
|
||||
const float exploreRadius = (mInterior ? 0.1f : 0.3f) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
|
||||
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
|
||||
#define GAME_RENDER_LOCALMAP_H
|
||||
|
||||
#include <OgreAxisAlignedBox.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreResource.h>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <osg/BoundingBox>
|
||||
#include <osg/Quat>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -15,52 +19,57 @@ namespace ESM
|
|||
struct FogTexture;
|
||||
}
|
||||
|
||||
namespace osgViewer
|
||||
{
|
||||
class Viewer;
|
||||
}
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Texture2D;
|
||||
class Camera;
|
||||
class Group;
|
||||
class Node;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class RenderingManager;
|
||||
|
||||
///
|
||||
/// \brief Local map rendering
|
||||
///
|
||||
class LocalMap
|
||||
{
|
||||
public:
|
||||
LocalMap();
|
||||
LocalMap(osgViewer::Viewer* viewer);
|
||||
~LocalMap();
|
||||
|
||||
virtual void loadResource(Ogre::Resource* resource);
|
||||
|
||||
/**
|
||||
* Clear all savegame-specific data (i.e. fog of war textures)
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Request the local map for an exterior cell.
|
||||
* @remarks It will either be loaded from a disk cache,
|
||||
* or rendered if it is not already cached.
|
||||
* @param cell exterior cell
|
||||
* @param zMin min height of objects or terrain in cell
|
||||
* @param zMax max height of objects or terrain in cell
|
||||
*/
|
||||
void requestMap (MWWorld::CellStore* cell, float zMin, float zMax);
|
||||
void requestMap (std::set<MWWorld::CellStore*> cells);
|
||||
|
||||
void removeCell (MWWorld::CellStore* cell);
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> getMapTexture (bool interior, int x, int y);
|
||||
|
||||
void markForRemoval(osg::Camera* cam);
|
||||
|
||||
/**
|
||||
* Request the local map for an interior cell.
|
||||
* @remarks It will either be loaded from a disk cache,
|
||||
* or rendered if it is not already cached.
|
||||
* @param cell interior cell
|
||||
* @param bounds bounding box of the cell
|
||||
* Removes cameras that have already been rendered. Should be called every frame to ensure that
|
||||
* we do not render the same map more than once. Note, this cleanup is difficult to implement in an
|
||||
* automated fashion, since we can't alter the scene graph structure from within an update callback.
|
||||
*/
|
||||
void requestMap (MWWorld::CellStore* cell,
|
||||
Ogre::AxisAlignedBox bounds);
|
||||
void cleanupCameras();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
|
@ -72,9 +81,9 @@ namespace MWRender
|
|||
* Get the interior map texture index and normalized 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)
|
||||
|
@ -82,6 +91,20 @@ namespace MWRender
|
|||
bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
|
||||
|
||||
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;
|
||||
|
||||
// the dynamic texture is a bottleneck, so don't set this too high
|
||||
|
@ -91,46 +114,34 @@ namespace MWRender
|
|||
static const int sFogOfWarSkip = 2;
|
||||
|
||||
// size of a map segment (for exteriors, 1 cell)
|
||||
static const int sSize = 8192;
|
||||
|
||||
Ogre::Camera* mCellCamera;
|
||||
Ogre::SceneNode* mCameraNode;
|
||||
Ogre::SceneNode* mCameraPosNode;
|
||||
Ogre::SceneNode* mCameraRotNode;
|
||||
|
||||
// directional light from a fixed angle
|
||||
Ogre::Light* mLight;
|
||||
float mMapWorldSize;
|
||||
|
||||
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 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=false);
|
||||
void requestExteriorMap(MWWorld::CellStore* cell);
|
||||
void requestInteriorMap(MWWorld::CellStore* cell);
|
||||
|
||||
osg::ref_ptr<osg::Camera> createOrthographicCamera(float left, float top, float width, float height, const osg::Vec3d& upVector, float zmin, float zmax);
|
||||
void setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y);
|
||||
|
||||
// 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
|
||||
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);
|
||||
//void loadFogOfWar(const std::string& texturePrefix, ESM::FogTexture& esm); // FogTexture not const because MemoryDataStream doesn't accept it
|
||||
|
||||
// A buffer for the "fog of war" textures of the current cell.
|
||||
// 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
|
||||
Ogre::TexturePtr mRenderTexture;
|
||||
Ogre::RenderTarget* mRenderTarget;
|
||||
//Ogre::TexturePtr mRenderTexture;
|
||||
//Ogre::RenderTarget* mRenderTarget;
|
||||
|
||||
bool mInterior;
|
||||
Ogre::AxisAlignedBox mBounds;
|
||||
std::string mInteriorName;
|
||||
osg::BoundingBox mBounds;
|
||||
//std::string mInteriorName;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Group>
|
||||
#include <osg/Geode>
|
||||
#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)
|
||||
{
|
||||
osg::Node* objectNode = cur.getRefData().getBaseNode();
|
||||
if (!objectNode)
|
||||
return;
|
||||
|
||||
MWWorld::CellStore *newCell = cur.getCell();
|
||||
|
||||
osg::Group* cellnode;
|
||||
|
@ -217,8 +220,6 @@ void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
|
|||
cellnode = mCellSceneNodes[newCell];
|
||||
}
|
||||
|
||||
osg::Node* objectNode = cur.getRefData().getBaseNode();
|
||||
|
||||
osg::UserDataContainer* userDataContainer = objectNode->getUserDataContainer();
|
||||
if (userDataContainer)
|
||||
for (unsigned int i=0; i<userDataContainer->getNumUserObjects(); ++i)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Light>
|
||||
#include <osg/LightModel>
|
||||
#include <osg/Fog>
|
||||
|
@ -111,6 +110,7 @@ namespace MWRender
|
|||
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
||||
|
||||
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
||||
source->setNodeMask(SceneUtil::Mask_Lit);
|
||||
mSunLight = new osg::Light;
|
||||
source->setLight(mSunLight);
|
||||
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
|
||||
|
@ -123,6 +123,7 @@ namespace MWRender
|
|||
lightRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
||||
|
||||
lightRoot->setNodeMask(Mask_Scene);
|
||||
lightRoot->setName("Scene Root");
|
||||
|
||||
mSky.reset(new SkyManager(lightRoot, resourceSystem->getSceneManager()));
|
||||
|
||||
|
@ -342,8 +343,12 @@ namespace MWRender
|
|||
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST);
|
||||
|
||||
osgUtil::IntersectionVisitor intersectionVisitor(intersector);
|
||||
int mask = intersectionVisitor.getTraversalMask();
|
||||
mask &= ~(Mask_RenderToTexture|Mask_Sky|Mask_Debug|Mask_Effect);
|
||||
if (ignorePlayer)
|
||||
intersectionVisitor.setTraversalMask(intersectionVisitor.getTraversalMask() & (~Mask_Player));
|
||||
mask &= ~(Mask_Player);
|
||||
|
||||
intersectionVisitor.setTraversalMask(mask);
|
||||
|
||||
mViewer->getCamera()->accept(intersectionVisitor);
|
||||
|
||||
|
@ -451,12 +456,8 @@ namespace MWRender
|
|||
|
||||
void RenderingManager::updateProjectionMatrix()
|
||||
{
|
||||
double fovy, aspect, zNear, zFar;
|
||||
mViewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
|
||||
fovy = mFieldOfView;
|
||||
zNear = mNearClip;
|
||||
zFar = mViewDistance;
|
||||
mViewer->getCamera()->setProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
|
||||
double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
|
||||
mViewer->getCamera()->setProjectionMatrixAsPerspective(mFieldOfView, aspect, mNearClip, mViewDistance);
|
||||
}
|
||||
|
||||
void RenderingManager::updateTextureFiltering()
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
#include <osg/Geometry>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <osg/TexEnvCombine>
|
||||
#include <osg/TexMat>
|
||||
|
||||
|
@ -34,7 +30,7 @@
|
|||
|
||||
#include "../mwworld/fallback.hpp"
|
||||
|
||||
#include "renderingmanager.hpp"
|
||||
#include "vismask.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -506,6 +502,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
|
|||
, mSecundaEnabled(true)
|
||||
{
|
||||
osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform);
|
||||
skyroot->setNodeMask(Mask_Sky);
|
||||
parentNode->addChild(skyroot);
|
||||
|
||||
mRootNode = skyroot;
|
||||
|
@ -652,7 +649,7 @@ void SkyManager::setEnabled(bool enabled)
|
|||
if (!enabled)
|
||||
clearRain();
|
||||
|
||||
mRootNode->setNodeMask(enabled ? ~((unsigned int)(0)) : 0);
|
||||
mRootNode->setNodeMask(enabled ? Mask_Sky : 0);
|
||||
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,16 @@ namespace MWRender
|
|||
Mask_Debug = (1<<2),
|
||||
Mask_Actor = (1<<3),
|
||||
Mask_Player = (1<<4),
|
||||
Mask_Sky = (1<<5),
|
||||
|
||||
// top level masks
|
||||
Mask_Scene = (1<<5),
|
||||
Mask_GUI = (1<<6)
|
||||
Mask_Scene = (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
|
||||
// (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)
|
||||
//mRendering.requestMap(*active);
|
||||
std::set<MWWorld::CellStore*> cellsToUpdate;
|
||||
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
|
||||
{
|
||||
cellsToUpdate.insert(*active);
|
||||
}
|
||||
MWBase::Environment::get().getWindowManager()->requestMap(cellsToUpdate);
|
||||
|
||||
mNeedMapUpdate = false;
|
||||
|
||||
if (mCurrentCell->isExterior())
|
||||
|
@ -213,6 +218,7 @@ namespace MWWorld
|
|||
MWBase::Environment::get().getMechanicsManager()->drop (*iter);
|
||||
|
||||
mRendering.removeCell(*iter);
|
||||
MWBase::Environment::get().getWindowManager()->removeCell(*iter);
|
||||
|
||||
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);
|
||||
|
||||
|
|
|
@ -162,14 +162,11 @@ namespace MWWorld
|
|||
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
|
||||
{
|
||||
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
||||
//mPhysEngine = mPhysics->getEngine();
|
||||
#if 0
|
||||
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
|
||||
#endif
|
||||
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem);
|
||||
|
||||
//mPhysEngine->setSceneManager(renderer.getScene());
|
||||
|
||||
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
|
||||
|
||||
mEsm.resize(contentFiles.size());
|
||||
|
@ -1591,24 +1588,38 @@ namespace MWWorld
|
|||
updateWindowManager ();
|
||||
|
||||
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));
|
||||
}
|
||||
*/
|
||||
|
||||
if (player.getClass().getNpcStats(player).isWerewolf())
|
||||
MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mRendering->getCamera()->isFirstPerson());
|
||||
|
||||
// Sink the camera while sneaking
|
||||
bool sneaking = getPlayerPtr().getClass().getCreatureStats(getPlayerPtr()).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
||||
bool inair = !isOnGround(getPlayerPtr());
|
||||
bool swimming = isSwimming(getPlayerPtr());
|
||||
bool sneaking = player.getClass().getCreatureStats(getPlayerPtr()).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
||||
bool inair = !isOnGround(player);
|
||||
bool swimming = isSwimming(player);
|
||||
|
||||
static const float i1stPersonSneakDelta = getStore().get<ESM::GameSetting>().find("i1stPersonSneakDelta")->getFloat();
|
||||
if(!paused && sneaking && !(swimming || inair))
|
||||
mRendering->getCamera()->setSneakOffset(i1stPersonSneakDelta);
|
||||
else
|
||||
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()
|
||||
|
@ -1701,16 +1712,16 @@ namespace MWWorld
|
|||
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::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
|
||||
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);
|
||||
Ogre::Vector3 dir = orient * Ogre::Vector3(0,1,0);
|
||||
Ogre::Vector2 d = Ogre::Vector2(dir.x, dir.y);
|
||||
osg::Quat orient (-ref->mData.getPosition().rot[2], osg::Vec3f(0,0,1));
|
||||
osg::Vec3f dir = orient * osg::Vec3f(0,1,0);
|
||||
osg::Vec2f d (dir.x(), dir.y());
|
||||
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)
|
||||
{
|
||||
//mPhysics->setWaterHeight(height);
|
||||
mPhysics->setWaterHeight(height);
|
||||
//mRendering->setWaterHeight(height);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,7 @@ namespace MWWorld
|
|||
|
||||
void updateSoundListener();
|
||||
void updateWindowManager ();
|
||||
void updatePlayer(bool paused);
|
||||
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
|
||||
|
||||
void removeContainerScripts(const Ptr& reference);
|
||||
|
@ -218,21 +219,12 @@ namespace MWWorld
|
|||
|
||||
virtual bool isCellQuasiExterior() const;
|
||||
|
||||
virtual Ogre::Vector2 getNorthVector (CellStore* cell);
|
||||
virtual osg::Vec2f getNorthVector (CellStore* cell);
|
||||
///< get north vector for given interior cell
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
///< Set value independently from real type.
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace osgMyGUI
|
|||
if (!mTextureManager)
|
||||
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
|
||||
mFormat = MyGUI::PixelFormat::R8G8B8;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <osg/TexMat>
|
||||
#include <osg/Material>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/UserDataContainer>
|
||||
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
#include <osg/ShapeDrawable>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
// resource
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <components/nif/controlled.hpp>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include "userdata.hpp"
|
||||
|
||||
namespace NifOsg
|
||||
|
|
|
@ -226,6 +226,7 @@ namespace SceneUtil
|
|||
LightSource::LightSource()
|
||||
: mRadius(0.f)
|
||||
{
|
||||
setNodeMask(Mask_Lit);
|
||||
setUpdateCallback(new CollectLightCallback);
|
||||
}
|
||||
|
||||
|
@ -233,6 +234,12 @@ namespace SceneUtil
|
|||
{
|
||||
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
||||
|
||||
if (!(cv->getCurrentCamera()->getCullMask()&Mask_Lit))
|
||||
{
|
||||
traverse(node, nv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mLightManager)
|
||||
{
|
||||
for (unsigned int i=0;i<nv->getNodePath().size(); ++i)
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
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.
|
||||
class LightSource : public osg::Node
|
||||
{
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <cstdlib>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include "skeleton.hpp"
|
||||
#include "util.hpp"
|
||||
|
|
Loading…
Reference in a new issue