Skip to content

Commit

Permalink
Work arounded crash in CEGUI/ogre open gl renderer when some entities…
Browse files Browse the repository at this point in the history
… were removed

+ dehardcoded the dirt tile used as a workaround for lightning issues

fixes OpenDungeons#700
  • Loading branch information
hwoarangmy committed Aug 3, 2015
1 parent 81902ff commit 2e6052c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
6 changes: 6 additions & 0 deletions source/gamemap/GameMap.cpp
Expand Up @@ -3030,6 +3030,12 @@ std::vector<Spell*> GameMap::getSpellsBySeatAndType(Seat* seat, SpellType type)
return ret;
}

const std::string& GameMap::getMeshForDefaultTile() const
{
// 0 means tile not linked to any neighboor
return mTileSet->getTileValues(TileVisual::dirtFull).at(0).getMeshName();
}

const TileSetValue& GameMap::getMeshForTile(const Tile* tile) const
{
int index = 0;
Expand Down
5 changes: 5 additions & 0 deletions source/gamemap/GameMap.h
Expand Up @@ -517,7 +517,12 @@ friend class ODServer;
inline const std::string& getTileSetName() const
{ return mTileSetName; }

//! \brief getMeshForDefaultTile returns a mesh for some default dirt tile. This
//! is used as a workaround to avoid lightning issues
const std::string& getMeshForDefaultTile() const;
//! \brief get the tileset infos for the given tile
const TileSetValue& getMeshForTile(const Tile* tile) const;
//! \brief get the tileset global scale
const Ogre::Vector3& getTileSetScale() const;

void playerSelects(std::vector<EntityBase*>& entities, int tileX1, int tileY1, int tileX2,
Expand Down
3 changes: 2 additions & 1 deletion source/network/ODClient.cpp
Expand Up @@ -370,7 +370,8 @@ bool ODClient::processOneClientSocketMessage()
}

// We reset the renderer
RenderManager::getSingleton().clearRenderer();
RenderManager::getSingleton().initRendererForNewGame(gameMap);

// Move camera to starting position
Ogre::Real startX = static_cast<Ogre::Real>(tempSeat->mStartingX);
Ogre::Real startY = static_cast<Ogre::Real>(tempSeat->mStartingY);
Expand Down
59 changes: 47 additions & 12 deletions source/render/RenderManager.cpp
Expand Up @@ -105,9 +105,55 @@ RenderManager::~RenderManager()
{
}

void RenderManager::clearRenderer()
void RenderManager::initRendererForNewGame(GameMap* gameMap)
{
mCreatureTextOverlayDisplayed = false;

for(Ogre::SceneNode* dummyNode : mDummyEntities)
{
Ogre::Entity* dummyEnt = mSceneManager->getEntity(dummyNode->getName() + "Ent");
if(dummyEnt != nullptr)
{
dummyNode->detachObject(dummyEnt);
mSceneManager->destroyEntity(dummyEnt);
}
mHandKeeperNode->removeChild(dummyNode);
mSceneManager->destroySceneNode(dummyNode);
}
mDummyEntities.clear();

//Add a too small to be visible dummy dirt tile to the hand node
//so that there will always be a dirt tile "visible"
//This is an ugly workaround for issue where destroying some entities messes
//up the lighing for some of the rtshader materials.
Ogre::SceneNode* dummyNode;
Ogre::Entity* dummyEnt;
dummyNode = mHandKeeperNode->createChildSceneNode("DummyNodeTile");
dummyNode->setScale(Ogre::Vector3(0.00000001f, 0.00000001f, 0.00000001f));
const std::string& defaultTileMesh = gameMap->getMeshForDefaultTile();
dummyEnt = mSceneManager->createEntity(dummyNode->getName() + "Ent", defaultTileMesh);
dummyEnt->setLightMask(0);
dummyEnt->setCastShadows(false);
dummyNode->attachObject(dummyEnt);
mDummyEntities.push_back(dummyNode);

// We load every creature class and attach them to the keeper hand.

This comment has been minimized.

Copy link
@Bertram25

Bertram25 Aug 3, 2015

Oh my. :S This will have to definitely be told to upstream.
Have you got a bt, so that I maybe post that to one of the two?

This comment has been minimized.

Copy link
@hwoarangmy

hwoarangmy Aug 3, 2015

Author Owner

That happens when we call CEGUI::System::getSingleton().renderAllGUIContexts();
There are some calls about drawing the screen that end up in the Ogre OpenGL renderer and it crashes when calling some OpenGL function. If you are interested, I will comment the workaround and post the bt

This comment has been minimized.

Copy link
@Bertram25

Bertram25 Aug 3, 2015

Thanks. I'll open a topic on Ogre with that.

// That's an ugly workaround to avoid a crash that occurs when CEGUI refreshes
// ogre open gl renderer after removing some creatures
// Note that from what I've seen, loading only one creature like "Troll.mesh" should be
// enough. However, it doesn't work with other creatures (like "Kobold.mesh"). Since we
// don't really know why, it is safer to load every creature
for(uint32_t i = 0; i < gameMap->numClassDescriptions(); ++i)
{
const CreatureDefinition* def = gameMap->getClassDescription(i);
dummyNode = mHandKeeperNode->createChildSceneNode("Dummy_" + def->getClassName());
dummyNode->setScale(Ogre::Vector3(0.00000001f, 0.00000001f, 0.00000001f));
dummyEnt = mSceneManager->createEntity(dummyNode->getName() + "Ent", def->getMeshName());
dummyEnt->setLightMask(0);
dummyEnt->setCastShadows(false);
dummyNode->attachObject(dummyEnt);
mDummyEntities.push_back(dummyNode);
}
}

void RenderManager::triggerCompositor(const std::string& compositorName)
Expand Down Expand Up @@ -165,17 +211,6 @@ void RenderManager::createScene(Ogre::Viewport* nViewport)
handKeeperOverlay->add3D(mHandKeeperNode);
handKeeperOverlay->show();

//Add a too small to be visible dummy dirt tile to the hand node
//so that there will allways be a dirt tile "visible"
//This is an ugly workaround for issue where destroying some entities messes
//up the lighing for some of the rtshader materials.
Ogre::SceneNode* dummyNode = mHandKeeperNode->createChildSceneNode("Dummy_node");
dummyNode->setScale(Ogre::Vector3(0.00000001f, 0.00000001f, 0.00000001f));
Ogre::Entity* dummyEnt = mSceneManager->createEntity("Dirt_fl_0000.mesh");
dummyEnt->setLightMask(0);
dummyEnt->setCastShadows(false);
dummyNode->attachObject(dummyEnt);

// Create the light which follows the single tile selection mesh
mHandLight = mSceneManager->createLight("MouseLight");
mHandLight->setType(Ogre::Light::LT_POINT);
Expand Down
9 changes: 7 additions & 2 deletions source/render/RenderManager.h
Expand Up @@ -67,8 +67,8 @@ class RenderManager: public Ogre::Singleton<RenderManager>
//! \brief Loop through the render requests in the queue and process them
void updateRenderAnimations(Ogre::Real timeSinceLastFrame);

//! \brief Resets the renderer
void clearRenderer();
//! \brief Initialize the renderer when a new game (Game or Editor) is launched
void initRendererForNewGame(GameMap* gameMap);

//! \brief starts the compositor compositorName.
void triggerCompositor(const std::string& compositorName);
Expand Down Expand Up @@ -181,6 +181,11 @@ class RenderManager: public Ogre::Singleton<RenderManager>
Ogre::Real mFactorWidth;
Ogre::Real mFactorHeight;

// As a workaround for some issues, we create dummy entities too small to be seen
// and attach them to the keeper hand. This vector allows to keep a track and delete
// them/recreate when loading a new game
std::vector<Ogre::SceneNode*> mDummyEntities;

//! \brief True if the creatures are currently displaying their text overlay
bool mCreatureTextOverlayDisplayed;

Expand Down

4 comments on commit 2e6052c

@hwoarangmy
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bertram25 Here is the bt:

#0  Ogre::GLRenderSystem::_render (this=0x11828b80, op=...) at ..\..\..\..\RenderSystems\GL\src\OgreGLRenderSystem.cpp:2922
#1  0x04af1d97 in CEGUI::OgreGeometryBuffer::draw (this=0x1bdf7178) at C:\devMinGW\cegui-0.8.4\cegui\src\RendererModules\Ogre\GeometryBuffer.cpp:169
#2  0x63b342fc in CEGUI::RenderQueue::draw (this=0x1d7b807c) at C:\devMinGW\cegui-0.8.4\cegui\src\RenderQueue.cpp:40
#3  0x04b02f27 in CEGUI::OgreRenderTarget<CEGUI::RenderTarget>::draw (this=0xfffc900, queue=...) at C:/devMinGW/cegui-0.8.4/cegui/src/RendererModules/Ogre/RenderTarget.inl:74
#4  0x63b3313f in CEGUI::RenderingSurface::draw (this=0x1b346158, queue=..., args=...) at C:\devMinGW\cegui-0.8.4\cegui\src\RenderingSurface.cpp:128
#5  0x63b330b8 in CEGUI::RenderingSurface::drawContent (this=0x1b346158) at C:\devMinGW\cegui-0.8.4\cegui\src\RenderingSurface.cpp:118
#6  0x63b20bb3 in CEGUI::GUIContext::drawContent (this=0x1b346158) at C:\devMinGW\cegui-0.8.4\cegui\src\GUIContext.cpp:293
#7  0x63b33011 in CEGUI::RenderingSurface::draw (this=0x1b346158) at C:\devMinGW\cegui-0.8.4\cegui\src\RenderingSurface.cpp:102
#8  0x63b20b9c in CEGUI::GUIContext::draw (this=0x1b346158) at C:\devMinGW\cegui-0.8.4\cegui\src\GUIContext.cpp:287
#9  0x63b3bc1d in CEGUI::System::renderAllGUIContexts (this=0xfffce78) at C:\devMinGW\cegui-0.8.4\cegui\src\System.cpp:413
#10 0x00504e0f in ODFrameListener::renderQueueStarted (this=0x28ed90, queueGroupId=101 'e', invocation=..., skipThisInvocation=@0x28e9a7: false) at C:\devMinGW\od-gh-src\source\render\ODFrameListener.cpp:219
#11 0x04f2d9b4 in Ogre::SceneManager::fireRenderQueueStarted (this=0x118d5978, id=101 'e', invocation=...) at ..\..\..\OgreMain\src\OgreSceneManager.cpp:4092
#12 0x04f27e53 in Ogre::SceneManager::renderVisibleObjectsDefaultSequence (this=0x118d5978) at ..\..\..\OgreMain\src\OgreSceneManager.cpp:2339
#13 0x04f27c0e in Ogre::SceneManager::_renderVisibleObjects (this=0x118d5978) at ..\..\..\OgreMain\src\OgreSceneManager.cpp:2264
#14 0x04f2432b in Ogre::SceneManager::_renderScene (this=0x118d5978, camera=0x118e02a8, vp=0x12ad4778, includeOverlays=true) at ..\..\..\OgreMain\src\OgreSceneManager.cpp:1561
#15 0x04de9fc0 in Ogre::Camera::_renderScene (this=0x118e02a8, vp=0x12ad4778, includeOverlays=true) at ..\..\..\OgreMain\src\OgreCamera.cpp:427
#16 0x04fbd6e6 in Ogre::Viewport::update (this=0x12ad4778) at ..\..\..\OgreMain\src\OgreViewport.cpp:224
#17 0x04f02087 in Ogre::RenderTarget::_updateViewport (this=0x1182d9e0, viewport=0x12ad4778, updateStatistics=true) at ..\..\..\OgreMain\src\OgreRenderTarget.cpp:200
#18 0x04f01fe8 in Ogre::RenderTarget::_updateAutoUpdatedViewports (this=0x1182d9e0, updateStatistics=true) at ..\..\..\OgreMain\src\OgreRenderTarget.cpp:178
#19 0x04f01f10 in Ogre::RenderTarget::updateImpl (this=0x1182d9e0) at ..\..\..\OgreMain\src\OgreRenderTarget.cpp:155
#20 0x04f038b4 in Ogre::RenderTarget::update (this=0x1182d9e0, swap=false) at ..\..\..\OgreMain\src\OgreRenderTarget.cpp:613
#21 0x04eefd6c in Ogre::RenderSystem::_updateAllRenderTargets (this=0x11828b80, swapBuffers=false) at ..\..\..\OgreMain\src\OgreRenderSystem.cpp:126
#22 0x04f1c5b1 in Ogre::Root::_updateAllRenderTargets (this=0x28f5b4) at ..\..\..\OgreMain\src\OgreRoot.cpp:1399
#23 0x04f1a55f in Ogre::Root::renderOneFrame (this=0x28f5b4) at ..\..\..\OgreMain\src\OgreRoot.cpp:972
#24 0x04f1a52b in Ogre::Root::startRendering (this=0x28f5b4) at ..\..\..\OgreMain\src\OgreRoot.cpp:962
#25 0x005863b5 in ODApplication::startClient (this=0x28fd88) at C:\devMinGW\od-gh-src\source\ODApplication.cpp:163
#26 0x005853bf in ODApplication::startGame (this=0x28fd88, options=...) at C:\devMinGW\od-gh-src\source\ODApplication.cpp:55
#27 0x0058716b in WinMain@16 (hInst=0x400000, strCmdLine=0x49f5ad5 "") at C:\devMinGW\od-gh-src\source\main.cpp:86
#28 0x006e519d in main ()

By running debugger, the crash seems to happen here:
OgreGLRenderSystem.cpp:2988 => glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData);
primType = 4
op.indexData->indexCount = 1329
indexType = 5123

But when playing step by step, it doesn't always crash. However, by randomly putting breakpoints and see where I could get before crashing I always ended up around OgreGLRenderSystem.cpp:2988

@Bertram25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect!

@Bertram25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, the bug comes indeed from CEGUI. I'll check that with them. :)

@hwoarangmy
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this bug is probably pretty nasty as when it occurs, I get no callstack at all, be it with MinGW or MSVS2013. Even when running with gdb. It breaks but there is no callstack and it doesn't show where it stopped.
However, if they want, I have found a systematic way to reproduce so if they need something, I can do some tests.
Note that I'm running OD with CEGUI 0.8.4, Ogre 1.9, SFML 2.3.1, boost 1.55 (BTW, it might be a good thing to add something about it in the release notes, no ?)

Please sign in to comment.