Hi,
I have a seperate thread to calculate positions of about 50 nodes. But calling setPosition of the nodes creates an vs error message:
Assertion failed!
Programm: OgreMain_d.dll
File: OgreNode.h
Line: 653
Expression: !mCachedTransformOutOfDate
Is setPosition not thread safe? I can move setPosition/setOrientation to an other place, if neccesary. Where is the best place to update positions?
Thanks,
Transporter
Thread safe positions
-
- Minaton
- Posts: 933
- Joined: Mon Mar 05, 2012 11:37 am
- Location: Germany
- x 110
-
- OGRE Team Member
- Posts: 5476
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1358
Re: Thread safe positions
More information on how your threads are running and the hierarchy setup is needed.
Updating and retrieving positions can be done in a thread safe manner, but no lock inside is performed, thus care must be taken.
I'll link as a reminder my comment on the same issue.
Note this code how it updates all nodes from multiple threads.
Updating and retrieving positions can be done in a thread safe manner, but no lock inside is performed, thus care must be taken.
I'll link as a reminder my comment on the same issue.
Note this code how it updates all nodes from multiple threads.
-
- Minaton
- Posts: 933
- Joined: Mon Mar 05, 2012 11:37 am
- Location: Germany
- x 110
Re: Thread safe positions
Thanks a lot! I'm very sorry but I forget about https://ogre3d.atlassian.net/browse/OGRE-406. 
I'll create a thread safe queue where I can save rotations/translation and update the nodes in frameStart.
Edit: Example for 64 threads
TutorialApplication.h
TutorialApplication.cpp
I've added a virtual function bool updateFrame(const Ogre::FrameEvent& evt) to BaseApplication and call it from frameStart
This is just to reduce changes on BaseApplication.

I'll create a thread safe queue where I can save rotations/translation and update the nodes in frameStart.
Edit: Example for 64 threads
TutorialApplication.h
Code: Select all
#include "BaseApplication.h"
#include <boost/lockfree/queue.hpp>
#define TESTTHREADING 8
class TutorialApplication : public BaseApplication
{
private:
typedef struct
{
Ogre::SceneNode* node;
Ogre::Real w, x, y, z;
} ROTATION;
boost::shared_ptr<boost::thread> mThreads[TESTTHREADING * TESTTHREADING];
boost::lockfree::queue<ROTATION, boost::lockfree::fixed_sized<false>> mQueue;
public:
TutorialApplication(void);
virtual ~TutorialApplication(void);
protected:
virtual void createScene(void);
virtual bool updateFrame(const Ogre::FrameEvent& evt);
void threadProc(Ogre::SceneNode* pNode);
};
Code: Select all
void TutorialApplication::createScene(void)
{
srand(time(NULL));
Ogre::LogManager::getSingletonPtr()->logMessage("Working Threads: " + Ogre::StringConverter::toString(TESTTHREADING * TESTTHREADING));
Ogre::MeshPtr sinbad;
for(size_t i = 0; i < TESTTHREADING; i++)
{
for(size_t j = 0; j < TESTTHREADING; j++)
{
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode(Ogre::SCENE_DYNAMIC)->createChildSceneNode(Ogre::SCENE_DYNAMIC);
Ogre::Entity* entity = mSceneMgr->createEntity("Sinbad.mesh", Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, Ogre::SCENE_DYNAMIC);
if(sinbad.isNull()) sinbad = entity->getMesh();
node->attachObject(entity);
node->setPosition((Ogre::Real)i * 3.0f * sinbad->getBoundingSphereRadius(), 0.0f, (Ogre::Real)j * 3.0f * sinbad->getBoundingSphereRadius());
mThreads[i * TESTTHREADING + j] = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&TutorialApplication::threadProc, this, node)));
}
}
mCamera->setPosition(0.0f, (Ogre::Real)TESTTHREADING * 5.0f, 0.0f);
mCamera->lookAt((Ogre::Real)TESTTHREADING * 1.5f * sinbad->getBoundingSphereRadius(), 0.0f, (Ogre::Real)TESTTHREADING * 1.5f * sinbad->getBoundingSphereRadius());
mSceneMgr->setAmbientLight(Ogre::ColourValue::White);
}
bool TutorialApplication::updateFrame(const Ogre::FrameEvent& evt)
{
ROTATION rot;
while(mQueue.pop(rot))
{
rot.node->setOrientation(rot.w, rot.x, rot.y, rot.z);
}
return true;
}
void TutorialApplication::threadProc(Ogre::SceneNode* pNode)
{
srand((unsigned int)(void*)pNode);
ROTATION rot = { pNode, 0.0f, 0.0f, 0.0f, 0.0f };
while(!mShutDown)
{
Ogre::Quaternion r(Ogre::Degree((Ogre::Real)(rand() % 360)), Ogre::Vector3::UNIT_Y);
rot.w = r.w;
rot.x = r.x;
rot.y = r.y;
rot.z = r.z;
mQueue.push(rot);
int wait = rand() % 100 + 1;
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
Sleep(wait);
#else
usleep(wait * 1000);
#endif
}
}
Code: Select all
bool BaseApplication::frameStarted(const Ogre::FrameEvent& evt)
{
return updateFrame(evt);
}