kallaspriit
20-06-2009 10:40:29
I am trying to get Newton multi-threading work to with OgreNewt and as much as I have learned about the subject, the problem is the default transform callback, because multiple threads will try to set transformation of the same object, causing a crash (same problem in newton forum).
Default transformcallback implementation:
So I tried making a transformation request in the callback and applying the transformations in my main loop, but the crash persists when using world->setThreadCount(2);
My extensions/changes to OgreNewt are following:
OgreNewt_TransformRequest.h
OgreNewt_TransformRequest.cpp
OgreNewt_TransformAccumulator.h
OgreNewt_TransformAccumulator.cpp
The TransformAccumulator belongs to the OgreNewt World, the new transformcallback is as follows:
And finally, in the main loop or actually in the OgreNewt::World::update(), I call applyAll() on the accumulator:
Hoped this would work but what am I missing or doing wrong?
Default transformcallback implementation:
void Body::standardTransformCallback( OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, int threadIndex )
{
me->m_node->setOrientation( orient );
me->m_node->setPosition( pos );
}So I tried making a transformation request in the callback and applying the transformations in my main loop, but the crash persists when using world->setThreadCount(2);
My extensions/changes to OgreNewt are following:
OgreNewt_TransformRequest.h
/*
OgreNewt Library
Ogre implementation of Newton Game Dynamics SDK
OgreNewt basically has no license, you may use any or all of the library however you desire... I hope it can help you in any way.
please note that the "boost" library files included here are not of my creation, refer to those files and boost.org for information.
by Walaber
some changes by melven
this class by kallaspriit
*/
#ifndef _INCLUDE_OGRENEWT_TRANSFORMREQUEST
#define _INCLUDE_OGRENEWT_TRANSFORMREQUEST
#include "OgreNewt_Body.h"
#include <OgreVector3.h>
#include <OgreQuaternion.h>
// OgreNewt namespace. all functions and classes use this namespace.
namespace OgreNewt
{
/*
CLASS DEFINITION:
TransformRequest
USE:
this class represents a transformation of a ogrenewt body. This
is neccesary for using Newton in multiple threads. The requests should be
accumulated and applied in the main loop.
*/
//! OgreNewt body transformation request
class TransformRequest
{
public:
//! constructor.
/*!
creates the request object for given body with given transformations
\param body pointer to transformed body
\param position new position
\param orientation new orientation
*/
TransformRequest(OgreNewt::Body* body, const Ogre::Vector3& position, const Ogre::Quaternion& orientation);
//! Applies the transformations
void apply();
OgreNewt::Body* getBody() { return m_body; }
Ogre::Vector3 getPosition() { return m_position; }
Ogre::Quaternion getOrientation() { return m_orientation; }
protected:
//! The body
OgreNewt::Body* m_body;
//! New position
Ogre::Vector3 m_position;
//! New orientation
Ogre::Quaternion m_orientation;
};
}
#endif
// _INCLUDE_OGRENEWT_TRANSFORMREQUEST
OgreNewt_TransformRequest.cpp
#include "OgreNewt_TransformRequest.h"
namespace OgreNewt
{
TransformRequest::TransformRequest(OgreNewt::Body* body, const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
{
m_body = body;
m_position = position;
m_orientation = orientation;
}
void TransformRequest::apply()
{
if(m_body != NULL)
{
m_body->getOgreNode()->setOrientation(m_orientation);
m_body->getOgreNode()->setPosition(m_position);
}
}
}
OgreNewt_TransformAccumulator.h
/*
OgreNewt Library
Ogre implementation of Newton Game Dynamics SDK
OgreNewt basically has no license, you may use any or all of the library however you desire... I hope it can help you in any way.
please note that the "boost" library files included here are not of my creation, refer to those files and boost.org for information.
by Walaber
some changes by melven
this class by kallaspriit
*/
#ifndef _INCLUDE_OGRENEWT_TRANSFORMACCUMULATOR
#define _INCLUDE_OGRENEWT_TRANSFORMACCUMULATOR
#include "OgreNewt_TransformRequest.h"
#include "OgreNewt_Body.h"
#include <map>
// OgreNewt namespace. all functions and classes use this namespace.
namespace OgreNewt
{
/*
CLASS DEFINITION:
TransformAccumulator
USE:
this class accumulates OgreNewt::TransformRequest objects and enables
to apply them in main loop
*/
//! OgreNewt transform accumulator
class TransformAccumulator
{
public:
//! Registers new request
/*!
Registers new transform request. These will be accumulated and
applied by calling applyAll().
\param request The request
*/
void add(TransformRequest request);
//! Applies all accumulated transformations
void applyAll();
protected:
//! Map of transform requests
/*!
A map is used so there wouldnt be several requests for a
single body.
*/
std::map<Body*, TransformRequest> requests;
};
}
#endif
// _INCLUDE_TRANSFORMACCUMULATOR
OgreNewt_TransformAccumulator.cpp
#include "OgreNewt_TransformAccumulator.h"
#include "OgreNewt_World.h"
namespace OgreNewt
{
void TransformAccumulator::add(TransformRequest request)
{
std::map<Body*, TransformRequest>::iterator search = requests.find(request.getBody());
if(search != requests.end())
{
requests.erase(search);
}
requests.insert(std::make_pair(request.getBody(), request));
}
void TransformAccumulator::applyAll()
{
std::map<Body*, TransformRequest>::iterator iter;
for(iter = requests.begin(); iter != requests.end(); iter++)
{
iter->second.apply();
}
}
}
The TransformAccumulator belongs to the OgreNewt World, the new transformcallback is as follows:
void Body::standardTransformCallback( OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, int threadIndex )
{
TransformRequest request(me, pos, orient);
me->getWorld()->getTransformAccumulator().add(request);
}And finally, in the main loop or actually in the OgreNewt::World::update(), I call applyAll() on the accumulator:
void World::update( Ogre::Real t_step )
{
NewtonUpdate( m_world, (float)t_step );
m_transformAccumulator->applyAll();
}Hoped this would work but what am I missing or doing wrong?