Merge pull request #145 from OpenMW/master while resolving conflicts

# Conflicts:
#	CMakeLists.txt
coverity_scan^2
David Cernat 8 years ago
commit ae23c6d6a5

@ -165,10 +165,10 @@ else()
endif() endif()
IF(BUILD_OPENMW OR BUILD_OPENCS) IF(BUILD_OPENMW OR BUILD_OPENCS)
# Sound setup # Sound setup
find_package(FFmpeg REQUIRED COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE) find_package(FFmpeg REQUIRED COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE)
# Required for building the FFmpeg headers # Required for building the FFmpeg headers
add_definitions(-D__STDC_CONSTANT_MACROS) add_definitions(-D__STDC_CONSTANT_MACROS)
# TinyXML # TinyXML
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF) option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
@ -252,10 +252,15 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
endif() endif()
endif() endif()
set(REQUIRED_BULLET_VERSION 286) # Bullet 286 required due to runtime bugfixes for btCapsuleShape
if (DEFINED ENV{TRAVIS_BRANCH} OR DEFINED ENV{APPVEYOR})
set(REQUIRED_BULLET_VERSION 283) # but for build testing, 283 is fine
endif()
find_package(MyGUI 3.2.1 REQUIRED) find_package(MyGUI 3.2.1 REQUIRED)
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet 283 REQUIRED COMPONENTS BulletCollision LinearMath) find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath)
ENDIF(BUILD_OPENMW OR BUILD_OPENCS) ENDIF(BUILD_OPENMW OR BUILD_OPENCS)

@ -675,8 +675,6 @@ void OMW::Engine::go()
} }
else if (!mSkipMenu) else if (!mSkipMenu)
{ {
mEnvironment.getWorld()->preloadCommonAssets();
// start in main menu // start in main menu
mEnvironment.getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); mEnvironment.getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
try try

@ -95,8 +95,6 @@ namespace MWBase
virtual ~World() {} virtual ~World() {}
virtual void preloadCommonAssets() = 0;
virtual void startNewGame (bool bypass) = 0; virtual void startNewGame (bool bypass) = 0;
///< \param bypass Bypass regular game start. ///< \param bypass Bypass regular game start.

@ -268,12 +268,12 @@ namespace MWPhysics
( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length2() > 35*35 ( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length2() > 35*35
|| !isWalkableSlope(tracer.mPlaneNormal))) || !isWalkableSlope(tracer.mPlaneNormal)))
{ {
actor->setOnSlope(isWalkableSlope(resultCallback1.m_hitNormalWorld)); actor->setOnSlope(!isWalkableSlope(resultCallback1.m_hitNormalWorld));
return toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, 1.f); return toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, 1.f);
} }
else else
{ {
actor->setOnSlope(isWalkableSlope(tracer.mPlaneNormal)); actor->setOnSlope(!isWalkableSlope(tracer.mPlaneNormal));
} }
return tracer.mEndPos; return tracer.mEndPos;

@ -543,7 +543,7 @@ namespace MWRender
size_t blendMask = detectBlendMask(node); size_t blendMask = detectBlendMask(node);
// clone the controller, because each Animation needs its own ControllerSource // clone the controller, because each Animation needs its own ControllerSource
osg::ref_ptr<NifOsg::KeyframeController> cloned = osg::clone(it->second.get(), osg::CopyOp::DEEP_COPY_ALL); osg::ref_ptr<NifOsg::KeyframeController> cloned = new NifOsg::KeyframeController(*it->second, osg::CopyOp::SHALLOW_COPY);
cloned->setSource(mAnimationTimePtr[blendMask]); cloned->setSource(mAnimationTimePtr[blendMask]);
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned)); animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
@ -1272,7 +1272,7 @@ namespace MWRender
writableStateSet = node->getOrCreateStateSet(); writableStateSet = node->getOrCreateStateSet();
else else
{ {
writableStateSet = osg::clone(node->getStateSet(), osg::CopyOp::SHALLOW_COPY); writableStateSet = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
node->setStateSet(writableStateSet); node->setStateSet(writableStateSet);
} }
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON); writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);

@ -231,13 +231,51 @@ void LocalMap::setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int
segment.mMapTexture = texture; segment.mMapTexture = texture;
} }
bool needUpdate(std::set<std::pair<int, int> >& renderedGrid, std::set<std::pair<int, int> >& currentGrid, int cellX, int cellY)
{
// if all the cells of the current grid are contained in the rendered grid then we can keep the old render
for (int dx=-1;dx<2;dx+=1)
{
for (int dy=-1;dy<2;dy+=1)
{
bool haveInRenderedGrid = renderedGrid.find(std::make_pair(cellX+dx,cellY+dy)) != renderedGrid.end();
bool haveInCurrentGrid = currentGrid.find(std::make_pair(cellX+dx,cellY+dy)) != currentGrid.end();
if (haveInCurrentGrid && !haveInRenderedGrid)
return true;
}
}
return false;
}
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells) void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells)
{ {
std::set<std::pair<int, int> > grid;
for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
{
const MWWorld::CellStore* cell = *it;
if (cell->isExterior())
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
}
for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it) for (std::set<const MWWorld::CellStore*>::iterator it = cells.begin(); it != cells.end(); ++it)
{ {
const MWWorld::CellStore* cell = *it; const MWWorld::CellStore* cell = *it;
if (cell->isExterior()) if (cell->isExterior())
requestExteriorMap(cell); {
int cellX = cell->getCell()->getGridX();
int cellY = cell->getCell()->getGridY();
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
{
continue;
}
else
{
segment.mGrid = grid;
requestExteriorMap(cell);
}
}
else else
requestInteriorMap(cell); requestInteriorMap(cell);
} }

@ -124,6 +124,8 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture; osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
osg::ref_ptr<osg::Image> mFogOfWarImage; osg::ref_ptr<osg::Image> mFogOfWarImage;
std::set<std::pair<int, int> > mGrid; // the grid that was active at the time of rendering this segment
bool mHasFogState; bool mHasFogState;
}; };

@ -20,6 +20,7 @@
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/resource/imagemanager.hpp> #include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp> #include <components/resource/scenemanager.hpp>
#include <components/resource/keyframemanager.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -140,14 +141,24 @@ namespace MWRender
virtual void doWork() virtual void doWork()
{ {
for (std::vector<std::string>::const_iterator it = mModels.begin(); it != mModels.end(); ++it) try
mResourceSystem->getSceneManager()->getTemplate(*it); {
for (std::vector<std::string>::const_iterator it = mTextures.begin(); it != mTextures.end(); ++it) for (std::vector<std::string>::const_iterator it = mModels.begin(); it != mModels.end(); ++it)
mResourceSystem->getImageManager()->getImage(*it); mResourceSystem->getSceneManager()->cacheInstance(*it);
for (std::vector<std::string>::const_iterator it = mTextures.begin(); it != mTextures.end(); ++it)
mResourceSystem->getImageManager()->getImage(*it);
for (std::vector<std::string>::const_iterator it = mKeyframes.begin(); it != mKeyframes.end(); ++it)
mResourceSystem->getKeyframeManager()->get(*it);
}
catch (std::exception&)
{
// ignore error (will be shown when these are needed proper)
}
} }
std::vector<std::string> mModels; std::vector<std::string> mModels;
std::vector<std::string> mTextures; std::vector<std::string> mTextures;
std::vector<std::string> mKeyframes;
private: private:
Resource::ResourceSystem* mResourceSystem; Resource::ResourceSystem* mResourceSystem;
@ -308,6 +319,13 @@ namespace MWRender
mSky->listAssetsToPreload(workItem->mModels, workItem->mTextures); mSky->listAssetsToPreload(workItem->mModels, workItem->mTextures);
mWater->listAssetsToPreload(workItem->mTextures); mWater->listAssetsToPreload(workItem->mTextures);
const char* basemodels[] = {"xbase_anim", "xbase_anim.1st", "xbase_anim_female", "xbase_animkna"};
for (size_t i=0; i<sizeof(basemodels)/sizeof(basemodels[0]); ++i)
{
workItem->mModels.push_back(std::string("meshes/") + basemodels[i] + ".nif");
workItem->mKeyframes.push_back(std::string("meshes/") + basemodels[i] + ".kf");
}
workItem->mTextures.push_back("textures/_land_default.dds"); workItem->mTextures.push_back("textures/_land_default.dds");
mWorkQueue->addWorkItem(workItem); mWorkQueue->addWorkItem(workItem);
@ -435,14 +453,6 @@ namespace MWRender
mViewer->getCamera()->setCullMask(mask); mViewer->getCamera()->setCullMask(mask);
return enabled; return enabled;
} }
/*
else //if (mode == Render_BoundingBoxes)
{
bool show = !mRendering.getScene()->getShowBoundingBoxes();
mRendering.getScene()->showBoundingBoxes(show);
return show;
}
*/
return false; return false;
} }

@ -9,7 +9,6 @@ namespace MWRender
Render_CollisionDebug, Render_CollisionDebug,
Render_Wireframe, Render_Wireframe,
Render_Pathgrid, Render_Pathgrid,
Render_BoundingBoxes,
Render_Water, Render_Water,
Render_Scene Render_Scene
}; };

@ -55,7 +55,7 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
osg::ref_ptr<osg::StateSet> stateset; osg::ref_ptr<osg::StateSet> stateset;
if (node->getStateSet()) if (node->getStateSet())
stateset = osg::clone(node->getStateSet(), osg::CopyOp::SHALLOW_COPY); stateset = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
else else
stateset = new osg::StateSet; stateset = new osg::StateSet;

@ -278,10 +278,10 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
bool enabled = bool enabled =
MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_BoundingBoxes); MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_CollisionDebug);
runtime.getContext().report (enabled ? runtime.getContext().report (enabled ?
"Bounding Box Rendering -> On" : "Bounding Box Rendering -> Off"); "Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
} }
}; };

@ -242,6 +242,10 @@ void FFmpeg_Decoder::open(const std::string &fname)
} }
catch(std::exception&) catch(std::exception&)
{ {
if(mStream)
avcodec_close((*mStream)->codec);
mStream = NULL;
if (mFormatCtx->pb->buffer != NULL) if (mFormatCtx->pb->buffer != NULL)
{ {
av_free(mFormatCtx->pb->buffer); av_free(mFormatCtx->pb->buffer);

@ -55,6 +55,7 @@ namespace MWWorld
, mKeyframeManager(keyframeManager) , mKeyframeManager(keyframeManager)
, mTerrain(terrain) , mTerrain(terrain)
, mPreloadInstances(preloadInstances) , mPreloadInstances(preloadInstances)
, mAbort(false)
{ {
ListModelsVisitor visitor (mMeshes); ListModelsVisitor visitor (mMeshes);
if (cell->getState() == MWWorld::CellStore::State_Loaded) if (cell->getState() == MWWorld::CellStore::State_Loaded)
@ -76,11 +77,30 @@ namespace MWWorld
} }
} }
virtual void abort()
{
mAbort = true;
}
/// Preload work to be called from the worker thread. /// Preload work to be called from the worker thread.
virtual void doWork() virtual void doWork()
{ {
if (mIsExterior)
{
try
{
mPreloadedObjects.push_back(mTerrain->cacheCell(mX, mY));
}
catch(std::exception& e)
{
}
}
for (MeshList::const_iterator it = mMeshes.begin(); it != mMeshes.end(); ++it) for (MeshList::const_iterator it = mMeshes.begin(); it != mMeshes.end(); ++it)
{ {
if (mAbort)
break;
try try
{ {
std::string mesh = *it; std::string mesh = *it;
@ -119,17 +139,6 @@ namespace MWWorld
// error will be shown when visiting the cell // error will be shown when visiting the cell
} }
} }
if (mIsExterior)
{
try
{
mPreloadedObjects.push_back(mTerrain->cacheCell(mX, mY));
}
catch(std::exception& e)
{
}
}
} }
private: private:
@ -144,6 +153,8 @@ namespace MWWorld
Terrain::World* mTerrain; Terrain::World* mTerrain;
bool mPreloadInstances; bool mPreloadInstances;
volatile bool mAbort;
// keep a ref to the loaded objects to make sure it stays loaded as long as this cell is in the preloaded state // keep a ref to the loaded objects to make sure it stays loaded as long as this cell is in the preloaded state
std::vector<osg::ref_ptr<const osg::Object> > mPreloadedObjects; std::vector<osg::ref_ptr<const osg::Object> > mPreloadedObjects;
}; };
@ -187,7 +198,10 @@ namespace MWWorld
CellPreloader::~CellPreloader() CellPreloader::~CellPreloader()
{ {
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();++it) for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();++it)
{
it->second.mWorkItem->abort();
it->second.mWorkItem->waitTillDone(); it->second.mWorkItem->waitTillDone();
}
mPreloadCells.clear(); mPreloadCells.clear();
} }
@ -228,7 +242,10 @@ namespace MWWorld
} }
if (oldestTimestamp + threshold < timestamp) if (oldestTimestamp + threshold < timestamp)
{
oldestCell->second.mWorkItem->abort();
mPreloadCells.erase(oldestCell); mPreloadCells.erase(oldestCell);
}
else else
return; return;
} }
@ -246,18 +263,42 @@ namespace MWWorld
{ {
// do the deletion in the background thread // do the deletion in the background thread
if (found->second.mWorkItem) if (found->second.mWorkItem)
{
found->second.mWorkItem->abort();
mUnrefQueue->push(mPreloadCells[cell].mWorkItem); mUnrefQueue->push(mPreloadCells[cell].mWorkItem);
}
mPreloadCells.erase(found); mPreloadCells.erase(found);
} }
} }
void CellPreloader::clear()
{
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();)
{
if (it->second.mWorkItem)
{
it->second.mWorkItem->abort();
mUnrefQueue->push(it->second.mWorkItem);
}
mPreloadCells.erase(it++);
}
}
void CellPreloader::updateCache(double timestamp) void CellPreloader::updateCache(double timestamp)
{ {
for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();) for (PreloadMap::iterator it = mPreloadCells.begin(); it != mPreloadCells.end();)
{ {
if (mPreloadCells.size() >= mMinCacheSize && it->second.mTimeStamp < timestamp - mExpiryDelay) if (mPreloadCells.size() >= mMinCacheSize && it->second.mTimeStamp < timestamp - mExpiryDelay)
{
if (it->second.mWorkItem)
{
it->second.mWorkItem->abort();
mUnrefQueue->push(it->second.mWorkItem);
}
mPreloadCells.erase(it++); mPreloadCells.erase(it++);
}
else else
++it; ++it;
} }

@ -37,6 +37,8 @@ namespace MWWorld
void notifyLoaded(MWWorld::CellStore* cell); void notifyLoaded(MWWorld::CellStore* cell);
void clear();
/// Removes preloaded cells that have not had a preload request for a while. /// Removes preloaded cells that have not had a preload request for a while.
void updateCache(double timestamp); void updateCache(double timestamp);

@ -205,9 +205,9 @@ namespace MWWorld
if (mPreloadEnabled) if (mPreloadEnabled)
{ {
mPreloadTimer += duration; mPreloadTimer += duration;
if (mPreloadTimer > 0.25f) if (mPreloadTimer > 0.1f)
{ {
preloadCells(); preloadCells(0.1f);
mPreloadTimer = 0.f; mPreloadTimer = 0.f;
} }
} }
@ -328,13 +328,15 @@ namespace MWWorld
mPreloader->notifyLoaded(cell); mPreloader->notifyLoaded(cell);
} }
void Scene::changeToVoid() void Scene::clear()
{ {
CellStoreCollection::iterator active = mActiveCells.begin(); CellStoreCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end()) while (active!=mActiveCells.end())
unloadCell (active++); unloadCell (active++);
assert(mActiveCells.empty()); assert(mActiveCells.empty());
mCurrentCell = NULL; mCurrentCell = NULL;
mPreloader->clear();
} }
void Scene::playerMoved(const osg::Vec3f &pos) void Scene::playerMoved(const osg::Vec3f &pos)
@ -481,6 +483,8 @@ namespace MWWorld
mechMgr->watchActor(player); mechMgr->watchActor(player);
MWBase::Environment::get().getWorld()->adjustSky(); MWBase::Environment::get().getWorld()->adjustSky();
mLastPlayerPos = pos.asVec3();
} }
Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics) Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics)
@ -675,17 +679,24 @@ namespace MWWorld
return Ptr(); return Ptr();
} }
void Scene::preloadCells() void Scene::preloadCells(float dt)
{ {
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
osg::Vec3f moved = playerPos - mLastPlayerPos;
osg::Vec3f predictedPos = playerPos + moved / dt;
mLastPlayerPos = playerPos;
if (mPreloadDoors) if (mPreloadDoors)
preloadTeleportDoorDestinations(); preloadTeleportDoorDestinations(playerPos, predictedPos);
if (mPreloadExteriorGrid) if (mPreloadExteriorGrid)
preloadExteriorGrid(); preloadExteriorGrid(playerPos, predictedPos);
if (mPreloadFastTravel) if (mPreloadFastTravel)
preloadFastTravelDestinations(); preloadFastTravelDestinations(playerPos, predictedPos);
} }
void Scene::preloadTeleportDoorDestinations() void Scene::preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos)
{ {
std::vector<MWWorld::ConstPtr> teleportDoors; std::vector<MWWorld::ConstPtr> teleportDoors;
for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); for (CellStoreCollection::const_iterator iter (mActiveCells.begin());
@ -703,11 +714,11 @@ namespace MWWorld
} }
} }
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
for (std::vector<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it) for (std::vector<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it)
{ {
const MWWorld::ConstPtr& door = *it; const MWWorld::ConstPtr& door = *it;
float sqrDistToPlayer = (player.getRefData().getPosition().asVec3() - door.getRefData().getPosition().asVec3()).length2(); float sqrDistToPlayer = (playerPos - door.getRefData().getPosition().asVec3()).length2();
sqrDistToPlayer = std::min(sqrDistToPlayer, (predictedPos - door.getRefData().getPosition().asVec3()).length2());
if (sqrDistToPlayer < mPreloadDistance*mPreloadDistance) if (sqrDistToPlayer < mPreloadDistance*mPreloadDistance)
{ {
@ -730,15 +741,13 @@ namespace MWWorld
} }
} }
void Scene::preloadExteriorGrid() void Scene::preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos)
{ {
if (!MWBase::Environment::get().getWorld()->isCellExterior()) if (!MWBase::Environment::get().getWorld()->isCellExterior())
return; return;
int halfGridSizePlusOne = mHalfGridSize + 1; int halfGridSizePlusOne = mHalfGridSize + 1;
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
int cellX,cellY; int cellX,cellY;
getGridCenter(cellX,cellY); getGridCenter(cellX,cellY);
@ -757,6 +766,7 @@ namespace MWWorld
MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true); MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true);
float dist = std::max(std::abs(thisCellCenterX - playerPos.x()), std::abs(thisCellCenterY - playerPos.y())); float dist = std::max(std::abs(thisCellCenterX - playerPos.x()), std::abs(thisCellCenterY - playerPos.y()));
dist = std::min(dist,std::max(std::abs(thisCellCenterX - predictedPos.x()), std::abs(thisCellCenterY - predictedPos.y())));
float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance; float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance;
if (dist < loadDist) if (dist < loadDist)
@ -816,7 +826,7 @@ namespace MWWorld
std::vector<ESM::Transport::Dest> mList; std::vector<ESM::Transport::Dest> mList;
}; };
void Scene::preloadFastTravelDestinations() void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/) // ignore predictedPos here since opening dialogue with travel service takes extra time
{ {
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3()); ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3());

@ -68,6 +68,8 @@ namespace MWWorld
bool mPreloadDoors; bool mPreloadDoors;
bool mPreloadFastTravel; bool mPreloadFastTravel;
osg::Vec3f mLastPlayerPos;
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener);
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
@ -75,12 +77,10 @@ namespace MWWorld
void getGridCenter(int& cellX, int& cellY); void getGridCenter(int& cellX, int& cellY);
void preloadCells(); void preloadCells(float dt);
void preloadTeleportDoorDestinations(); void preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadExteriorGrid(); void preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadFastTravelDestinations(); void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
public: public:
@ -88,6 +88,8 @@ namespace MWWorld
~Scene(); ~Scene();
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
void unloadCell (CellStoreCollection::iterator iter); void unloadCell (CellStoreCollection::iterator iter);
void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn); void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn);
@ -111,7 +113,7 @@ namespace MWWorld
///< Move to exterior cell. ///< Move to exterior cell.
/// @param changeEvent Set cellChanged flag? /// @param changeEvent Set cellChanged flag?
void changeToVoid(); void clear();
///< Change into a void ///< Change into a void
void markCellAsUnchanged(); void markCellAsUnchanged();

@ -164,6 +164,8 @@ namespace MWWorld
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath); mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath);
mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics)); mProjectileManager.reset(new ProjectileManager(mRendering->getLightRoot(), resourceSystem, mRendering, mPhysics));
mRendering->preloadCommonAssets();
mEsm.resize(contentFiles.size()); mEsm.resize(contentFiles.size());
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener->loadingOn(); listener->loadingOn();
@ -303,7 +305,7 @@ namespace MWWorld
mProjectileManager->clear(); mProjectileManager->clear();
mLocalScripts.clear(); mLocalScripts.clear();
mWorldScene->changeToVoid(); mWorldScene->clear();
mStore.clearDynamic(); mStore.clearDynamic();
mStore.setUp(); mStore.setUp();
@ -359,9 +361,9 @@ namespace MWWorld
mStore.write (writer, progress); // dynamic Store must be written (and read) before Cells, so that mStore.write (writer, progress); // dynamic Store must be written (and read) before Cells, so that
// references to custom made records will be recognized // references to custom made records will be recognized
mPlayer->write (writer, progress);
mCells.write (writer, progress); mCells.write (writer, progress);
mGlobalVariables.write (writer, progress); mGlobalVariables.write (writer, progress);
mPlayer->write (writer, progress);
mWeatherManager->write (writer, progress); mWeatherManager->write (writer, progress);
mProjectileManager->write (writer, progress); mProjectileManager->write (writer, progress);
@ -387,10 +389,13 @@ namespace MWWorld
reader.getHNT(mTeleportEnabled, "TELE"); reader.getHNT(mTeleportEnabled, "TELE");
reader.getHNT(mLevitationEnabled, "LEVT"); reader.getHNT(mLevitationEnabled, "LEVT");
return; return;
case ESM::REC_PLAY:
mPlayer->readRecord(reader, type);
mWorldScene->preloadCell(getPlayerPtr().getCell(), true);
break;
default: default:
if (!mStore.readRecord (reader, type) && if (!mStore.readRecord (reader, type) &&
!mGlobalVariables.readRecord (reader, type) && !mGlobalVariables.readRecord (reader, type) &&
!mPlayer->readRecord (reader, type) &&
!mWeatherManager->readRecord (reader, type) && !mWeatherManager->readRecord (reader, type) &&
!mCells.readRecord (reader, type, contentFileMap) !mCells.readRecord (reader, type, contentFileMap)
&& !mProjectileManager->readRecord (reader, type) && !mProjectileManager->readRecord (reader, type)
@ -1468,8 +1473,6 @@ namespace MWWorld
} }
if(player != results.end()) if(player != results.end())
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false); moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
mPhysics->debugDraw();
} }
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2) bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
@ -1643,6 +1646,8 @@ namespace MWWorld
if (!paused) if (!paused)
doPhysics (duration); doPhysics (duration);
mPhysics->debugDraw();
mWorldScene->update (duration, paused); mWorldScene->update (duration, paused);
updateWindowManager (); updateWindowManager ();
@ -2200,6 +2205,8 @@ namespace MWWorld
scaleObject(getPlayerPtr(), 1.f); // apply race height scaleObject(getPlayerPtr(), 1.f); // apply race height
rotateObject(getPlayerPtr(), 0.f, 0.f, 0.f, true);
MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr()); MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr());
MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr()); MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr());
@ -3429,9 +3436,4 @@ namespace MWWorld
return mPhysics->getHitDistance(weaponPos, target) - halfExtents.y(); return mPhysics->getHitDistance(weaponPos, target) - halfExtents.y();
} }
void World::preloadCommonAssets()
{
mRendering->preloadCommonAssets();
}
} }

@ -191,8 +191,6 @@ namespace MWWorld
virtual void startNewGame (bool bypass); virtual void startNewGame (bool bypass);
///< \param bypass Bypass regular game start. ///< \param bypass Bypass regular game start.
virtual void preloadCommonAssets();
virtual void clear(); virtual void clear();
virtual int countSavedGameRecords() const; virtual int countSavedGameRecords() const;

@ -51,7 +51,7 @@ namespace ESM
esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS); esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS);
} }
if (mDataTypes & Land::DATA_VTEX) { if (mDataTypes & Land::DATA_VTEX) {
static uint16_t vtex[LAND_NUM_TEXTURES]; uint16_t vtex[LAND_NUM_TEXTURES];
transposeTextureData(mTextures, vtex); transposeTextureData(mTextures, vtex);
esm.writeHNT("VTEX", vtex, sizeof(vtex)); esm.writeHNT("VTEX", vtex, sizeof(vtex));
} }
@ -202,7 +202,7 @@ namespace ESM
} }
if (reader.isNextSub("VHGT")) { if (reader.isNextSub("VHGT")) {
static VHGT vhgt; VHGT vhgt;
if (condLoad(reader, flags, DATA_VHGT, &vhgt, sizeof(vhgt))) { if (condLoad(reader, flags, DATA_VHGT, &vhgt, sizeof(vhgt))) {
float rowOffset = vhgt.mHeightOffset; float rowOffset = vhgt.mHeightOffset;
for (int y = 0; y < LAND_SIZE; y++) { for (int y = 0; y < LAND_SIZE; y++) {
@ -227,7 +227,7 @@ namespace ESM
if (reader.isNextSub("VCLR")) if (reader.isNextSub("VCLR"))
condLoad(reader, flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS); condLoad(reader, flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS);
if (reader.isNextSub("VTEX")) { if (reader.isNextSub("VTEX")) {
static uint16_t vtex[LAND_NUM_TEXTURES]; uint16_t vtex[LAND_NUM_TEXTURES];
if (condLoad(reader, flags, DATA_VTEX, vtex, sizeof(vtex))) { if (condLoad(reader, flags, DATA_VTEX, vtex, sizeof(vtex))) {
LandData::transposeTextureData(vtex, mLandData->mTextures); LandData::transposeTextureData(vtex, mLandData->mTextures);
} }

@ -356,12 +356,24 @@ namespace NifOsg
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder); osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, imageManager, std::vector<int>(), 0, 0, false, &textkeys->mTextKeys); osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, imageManager, std::vector<int>(), 0, false, &textkeys->mTextKeys);
if (nif->getUseSkinning()) if (nif->getUseSkinning())
{ {
osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton; osg::ref_ptr<SceneUtil::Skeleton> skel = new SceneUtil::Skeleton;
skel->addChild(created);
osg::Group* root = created->asGroup();
if (root && root->getDataVariance() == osg::Object::STATIC)
{
skel->setStateSet(root->getStateSet());
skel->setName(root->getName());
for (unsigned int i=0; i<root->getNumChildren(); ++i)
skel->addChild(root->getChild(i));
root->removeChildren(0, root->getNumChildren());
created = skel;
}
else
skel->addChild(created);
created = skel; created = skel;
} }
@ -404,15 +416,6 @@ namespace NifOsg
toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl))); toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl)));
} }
void setupParticleController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int particleflags)
{
bool autoPlay = particleflags & Nif::NiNode::ParticleFlag_AutoPlay;
if (autoPlay)
toSetup->setSource(boost::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
toSetup->setFunction(boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl)));
}
void optimize (const Nif::Node* nifNode, osg::Group* node, bool skipMeshes) void optimize (const Nif::Node* nifNode, osg::Group* node, bool skipMeshes)
{ {
// For nodes with an identity transform, remove the redundant Transform node // For nodes with an identity transform, remove the redundant Transform node
@ -547,7 +550,7 @@ namespace NifOsg
} }
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager, osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
std::vector<int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL) std::vector<int> boundTextures, int animflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
{ {
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix()); osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
@ -617,10 +620,8 @@ namespace NifOsg
} }
} }
if (nifNode->recType == Nif::RC_NiBSAnimationNode) if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode)
animflags |= nifNode->flags; animflags = nifNode->flags;
if (nifNode->recType == Nif::RC_NiBSParticleNode)
particleflags |= nifNode->flags;
// Hide collision shapes, but don't skip the subgraph // Hide collision shapes, but don't skip the subgraph
// We still need to animate the hidden bones so the physics system can access them // We still need to animate the hidden bones so the physics system can access them
@ -663,7 +664,7 @@ namespace NifOsg
} }
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
handleParticleSystem(nifNode, node, composite, animflags, particleflags, rootNode); handleParticleSystem(nifNode, node, composite, animflags, rootNode);
if (composite->getNumControllers() > 0) if (composite->getNumControllers() > 0)
node->addUpdateCallback(composite); node->addUpdateCallback(composite);
@ -700,7 +701,7 @@ namespace NifOsg
for(size_t i = 0;i < children.length();++i) for(size_t i = 0;i < children.length();++i)
{ {
if(!children[i].empty()) if(!children[i].empty())
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode); handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, textKeys, rootNode);
} }
} }
@ -965,7 +966,7 @@ namespace NifOsg
return emitter; return emitter;
} }
void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags, int particleflags, osg::Node* rootNode) void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags, osg::Node* rootNode)
{ {
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem); osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT); partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
@ -986,7 +987,7 @@ namespace NifOsg
return; return;
} }
osgParticle::ParticleProcessor::ReferenceFrame rf = (particleflags & Nif::NiNode::ParticleFlag_LocalSpace) osgParticle::ParticleProcessor::ReferenceFrame rf = (animflags & Nif::NiNode::ParticleFlag_LocalSpace)
? osgParticle::ParticleProcessor::RELATIVE_RF ? osgParticle::ParticleProcessor::RELATIVE_RF
: osgParticle::ParticleProcessor::ABSOLUTE_RF; : osgParticle::ParticleProcessor::ABSOLUTE_RF;
@ -1032,10 +1033,10 @@ namespace NifOsg
emitterNode->addChild(emitter); emitterNode->addChild(emitter);
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl)); osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
setupParticleController(partctrl, callback, particleflags); setupController(partctrl, callback, animflags);
emitter->setUpdateCallback(callback); emitter->setUpdateCallback(callback);
if (!(particleflags & Nif::NiNode::ParticleFlag_AutoPlay)) if (!(animflags & Nif::NiNode::ParticleFlag_AutoPlay))
{ {
partsys->setFrozen(true); partsys->setFrozen(true);
// HACK: particle system will not render in Frozen state if there was no update // HACK: particle system will not render in Frozen state if there was no update
@ -1438,20 +1439,27 @@ namespace NifOsg
} }
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i];
if(tex.texture.empty()) if(tex.texture.empty() && texprop->controller.empty())
{ {
std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl; std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl;
continue; continue;
} }
const Nif::NiSourceTexture *st = tex.texture.getPtr();
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager); // create a new texture, will later attempt to share using the SharedStateManager
osg::ref_ptr<osg::Texture2D> texture2d;
if (!tex.texture.empty())
{
const Nif::NiSourceTexture *st = tex.texture.getPtr();
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
texture2d = new osg::Texture2D(image);
}
else
texture2d = new osg::Texture2D;
unsigned int clamp = static_cast<unsigned int>(tex.clamp); unsigned int clamp = static_cast<unsigned int>(tex.clamp);
int wrapT = (clamp) & 0x1; int wrapT = (clamp) & 0x1;
int wrapS = (clamp >> 1) & 0x1; int wrapS = (clamp >> 1) & 0x1;
// create a new texture, will later attempt to share using the SharedStateManager
osg::ref_ptr<osg::Texture2D> texture2d (new osg::Texture2D(image));
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP); texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);

@ -1,7 +1,6 @@
#include "keyframemanager.hpp" #include "keyframemanager.hpp"
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#include <components/nifosg/nifloader.hpp>
#include "objectcache.hpp" #include "objectcache.hpp"

@ -4,12 +4,9 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <string> #include <string>
#include "resourcemanager.hpp" #include <components/nifosg/nifloader.hpp>
namespace NifOsg #include "resourcemanager.hpp"
{
class KeyframeHolder;
}
namespace Resource namespace Resource
{ {

@ -13,6 +13,20 @@
namespace SceneUtil namespace SceneUtil
{ {
class LightStateCache
{
public:
osg::Light* lastAppliedLight[8];
};
LightStateCache* getLightStateCache(unsigned int contextid)
{
static std::vector<LightStateCache> cacheVector;
if (cacheVector.size() < contextid+1)
cacheVector.resize(contextid+1);
return &cacheVector[contextid];
}
// Resets the modelview matrix to just the view matrix before applying lights. // Resets the modelview matrix to just the view matrix before applying lights.
class LightStateAttribute : public osg::StateAttribute class LightStateAttribute : public osg::StateAttribute
{ {
@ -50,8 +64,17 @@ namespace SceneUtil
state.applyModelViewMatrix(state.getInitialViewMatrix()); state.applyModelViewMatrix(state.getInitialViewMatrix());
LightStateCache* cache = getLightStateCache(state.getContextID());
for (unsigned int i=0; i<mLights.size(); ++i) for (unsigned int i=0; i<mLights.size(); ++i)
applyLight((GLenum)((int)GL_LIGHT0 + i + mIndex), mLights[i].get()); {
osg::Light* current = cache->lastAppliedLight[i+mIndex];
if (current != mLights[i].get())
{
applyLight((GLenum)((int)GL_LIGHT0 + i + mIndex), mLights[i].get());
cache->lastAppliedLight[i+mIndex] = mLights[i].get();
}
}
state.applyModelViewMatrix(modelViewMatrix); state.applyModelViewMatrix(modelViewMatrix);
} }
@ -262,18 +285,64 @@ namespace SceneUtil
return it->second; return it->second;
} }
class DisableLight : public osg::StateAttribute
{
public:
DisableLight() : mIndex(0) {}
DisableLight(int index) : mIndex(index) {}
DisableLight(const DisableLight& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
: osg::StateAttribute(copy,copyop), mIndex(copy.mIndex) {}
virtual osg::Object* cloneType() const { return new DisableLight(mIndex); }
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new DisableLight(*this,copyop); }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const DisableLight *>(obj)!=NULL; }
virtual const char* libraryName() const { return "SceneUtil"; }
virtual const char* className() const { return "DisableLight"; }
virtual Type getType() const { return LIGHT; }
unsigned int getMember() const
{
return mIndex;
}
virtual bool getModeUsage(ModeUsage & usage) const
{
usage.usesMode(GL_LIGHT0 + mIndex);
return true;
}
virtual int compare(const StateAttribute &sa) const
{
throw std::runtime_error("DisableLight::compare: unimplemented");
}
virtual void apply(osg::State& state) const
{
int lightNum = GL_LIGHT0 + mIndex;
glLightfv( lightNum, GL_AMBIENT, mNull.ptr() );
glLightfv( lightNum, GL_DIFFUSE, mNull.ptr() );
glLightfv( lightNum, GL_SPECULAR, mNull.ptr() );
LightStateCache* cache = getLightStateCache(state.getContextID());
cache->lastAppliedLight[mIndex] = NULL;
}
private:
unsigned int mIndex;
osg::Vec4f mNull;
};
void LightManager::setStartLight(int start) void LightManager::setStartLight(int start)
{ {
mStartLight = start; mStartLight = start;
// Set default light state to zero // Set default light state to zero
// This is necessary because shaders don't respect glDisable(GL_LIGHTX) so in addition to disabling
// we'll have to set a light state that has no visible effect
for (int i=start; i<8; ++i) for (int i=start; i<8; ++i)
{ {
osg::ref_ptr<osg::Light> defaultLight (new osg::Light(i)); osg::ref_ptr<DisableLight> defaultLight (new DisableLight(i));
defaultLight->setAmbient(osg::Vec4());
defaultLight->setDiffuse(osg::Vec4());
defaultLight->setSpecular(osg::Vec4());
defaultLight->setConstantAttenuation(0.f);
getOrCreateStateSet()->setAttributeAndModes(defaultLight, osg::StateAttribute::OFF); getOrCreateStateSet()->setAttributeAndModes(defaultLight, osg::StateAttribute::OFF);
} }
} }
@ -299,7 +368,7 @@ namespace SceneUtil
mId = sLightId++; mId = sLightId++;
for (int i=0; i<2; ++i) for (int i=0; i<2; ++i)
mLight[i] = osg::clone(copy.mLight[i].get(), copyop); mLight[i] = new osg::Light(*copy.mLight[i].get(), copyop);
} }

@ -64,7 +64,7 @@ namespace SceneUtil
void setLight(osg::Light* light) void setLight(osg::Light* light)
{ {
mLight[0] = light; mLight[0] = light;
mLight[1] = osg::clone(light); mLight[1] = new osg::Light(*light);
} }
/// Get the unique ID for this light source. /// Get the unique ID for this light source.

@ -15,7 +15,7 @@ namespace SceneUtil
for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first
// This can be done conveniently in user implementations of the setDefaults() method // This can be done conveniently in user implementations of the setDefaults() method
{ {
mStateSets[i] = osg::clone(src, osg::CopyOp::SHALLOW_COPY); mStateSets[i] = new osg::StateSet(*src, osg::CopyOp::SHALLOW_COPY);
setDefaults(mStateSets[i]); setDefaults(mStateSets[i]);
} }
} }

@ -31,6 +31,9 @@ namespace SceneUtil
/// Internal use by the WorkQueue. /// Internal use by the WorkQueue.
void signalDone(); void signalDone();
/// Set abort flag in order to return from doWork() as soon as possible. May not be respected by all WorkItems.
virtual void abort() {}
protected: protected:
OpenThreads::Atomic mDone; OpenThreads::Atomic mDone;
OpenThreads::Mutex mMutex; OpenThreads::Mutex mMutex;

@ -85,7 +85,7 @@ namespace Shader
if (!node.getStateSet()) if (!node.getStateSet())
return node.getOrCreateStateSet(); return node.getOrCreateStateSet();
osg::ref_ptr<osg::StateSet> newStateSet = osg::clone(node.getStateSet(), osg::CopyOp::SHALLOW_COPY); osg::ref_ptr<osg::StateSet> newStateSet = new osg::StateSet(*node.getStateSet(), osg::CopyOp::SHALLOW_COPY);
node.setStateSet(newStateSet); node.setStateSet(newStateSet);
return newStateSet.get(); return newStateSet.get();
} }
@ -152,7 +152,7 @@ namespace Shader
} }
} }
if (mAutoUseNormalMaps && diffuseMap != NULL && normalMap == NULL) if (mAutoUseNormalMaps && diffuseMap != NULL && normalMap == NULL && diffuseMap->getImage(0))
{ {
std::string normalMapFileName = diffuseMap->getImage(0)->getFileName(); std::string normalMapFileName = diffuseMap->getImage(0)->getFileName();
@ -194,7 +194,7 @@ namespace Shader
mRequirements.back().mNormalHeight = normalHeight; mRequirements.back().mNormalHeight = normalHeight;
} }
} }
if (mAutoUseSpecularMaps && diffuseMap != NULL && specularMap == NULL) if (mAutoUseSpecularMaps && diffuseMap != NULL && specularMap == NULL && diffuseMap->getImage(0))
{ {
std::string specularMapFileName = diffuseMap->getImage(0)->getFileName(); std::string specularMapFileName = diffuseMap->getImage(0)->getFileName();
boost::replace_last(specularMapFileName, ".", mSpecularMapPattern + "."); boost::replace_last(specularMapFileName, ".", mSpecularMapPattern + ".");
@ -272,6 +272,9 @@ namespace Shader
{ {
switch (reqs.mVertexColorMode) switch (reqs.mVertexColorMode)
{ {
case GL_AMBIENT:
defineMap["colorMode"] = "3";
break;
default: default:
case GL_AMBIENT_AND_DIFFUSE: case GL_AMBIENT_AND_DIFFUSE:
defineMap["colorMode"] = "2"; defineMap["colorMode"] = "2";

@ -59,7 +59,7 @@
<Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox"> <Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox">
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36"> <Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
<Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="WeapImage"> <Widget type="ItemWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="WeapImage">
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
</Widget> </Widget>
</Widget> </Widget>
@ -71,7 +71,7 @@
<!-- Selected spell box --> <!-- Selected spell box -->
<Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox"> <Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox">
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36"> <Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
<Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="SpellImage"/> <Widget type="ItemWidget" skin="MW_ItemIconNoShadow" position="-3 -3 42 42" align="Left Top" name="SpellImage"/>
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
</Widget> </Widget>
<Widget type="ProgressBar" skin="MW_EnergyBar_Magic" position="0 36 36 6" align="Left Bottom" name="SpellStatus"> <Widget type="ProgressBar" skin="MW_EnergyBar_Magic" position="0 36 36 6" align="Left Bottom" name="SpellStatus">

@ -128,6 +128,18 @@
</Widget> </Widget>
</Resource> </Resource>
<Resource type="ResourceLayout" name="MW_ItemIconNoShadow" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 42 42" name="Root">
<Widget type="ImageBox" skin="ImageBox" position="0 0 42 42" align="Stretch" name="Frame">
<Widget type="TextBox" skin="CountText" position="5 19 32 18" align="Right Bottom" name="Text">
<Property key="TextAlign" value="Right"/>
<Property key="TextShadow" value="true"/>
</Widget>
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Stretch" name="Item"/>
</Widget>
</Widget>
</Resource>
<Resource type="ResourceLayout" name="MW_ItemIconSmall" version="3.2.0"> <Resource type="ResourceLayout" name="MW_ItemIconSmall" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 32 32" name="Root"> <Widget type="Widget" skin="" position="0 0 32 32" name="Root">
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Frame"> <Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Frame">

@ -5,7 +5,10 @@ vec4 doLighting(vec3 viewPos, vec3 viewNormal, vec4 vertexColor)
vec3 lightDir; vec3 lightDir;
float d; float d;
#if @colorMode == 2 #if @colorMode == 3
vec4 diffuse = gl_FrontMaterial.diffuse;
vec3 ambient = vertexColor.xyz;
#elif @colorMode == 2
vec4 diffuse = vertexColor; vec4 diffuse = vertexColor;
vec3 ambient = vertexColor.xyz; vec3 ambient = vertexColor.xyz;
#else #else

Loading…
Cancel
Save