AntonyCoder
31-03-2006 17:46:00
I don't mean framerate wise, it's chugging along at 26fps which is good for my ancient set up, but every body falls at a very slow rate, then bounces up and down really slowly.
It's as if they were on the moon rather than Earth.
I rewrote some of the basic frame listener so that I could call updateworld myself, and doing so yielded no results as no matter what number I pass from the insanely small to the humoungously huge seems to have any effect on the simulation.
Anything I'm missing? I'm using MomentOfInertia constants as you're supposed to, I've set automatic gravity on, i've generaed convex hulls..Dunno where else to go from here.
greyWiz
31-03-2006 21:04:36
Hi, AntonyCoder, I also had problems with it, and the people here in the forum helped me promptly. So, it doesn't hurt to return the kindness.
Anyway, here are things that might help you:
1. Are you setting OgreNewt's world to a framerate inferior to 60? By standard, Newton clamps framerates smaller than 60 or higher than 600, changing them to 60 and 600, respectively. In this way, if you use a value smaller than 60 with OgreNewt's BasicFrameListener, weird things might happen, mainly things falling down like if they were on moon... If you're using BasicFrameListener, the solution is to create it with a framerate between 60 and 600 (it's the constructor's last parameter);
2. What's the metric system you're using? When you create models in a 3d package, you must decide if, for instance, 1 unit from the modeling application means 1 meter, 1 kilometer, 1 centimeter... if you're using Body's setStandardForceCallback() method, you're agreeing on the stipulation of 1 unit = 1 meter. In this way, gravity has a value of 9.8 units/s^2.
What's the importance of it? Suppose you stated that one generic unit means one centimeter; if you create a model that measures 1.8 meter, it will occupy 180 generic units on Y axis. As a consequence, applying OgreNewt's standard force will take too long to fall down, since the force applied is much smaller than the scene's scale... There are two solutions here: first, you could scale down all your meshes in order to fit them in a scale of one generic unit = one meter; the second solution is to create your own callback with forces proprtional to your own scale.
I hope I could be of any help, I'm also a newbie on OgreNewt...
Good luck on your project!
Edgard
AntonyCoder
01-04-2006 13:05:08
Thanks for the information. Will prove useful.
But I actually solved the problem yesterday by doing this,
for(int frame=0;frame<4;frame++){
mWorld->update(0.2);
}
Instead of calling update once per frame, I called it four times per frame.
Of course I had to rewrite and rebuild ogrenewt's basic frame listener. In my humble opinon the basic frame limitier is broke and causes jerky slow movement whatever fps you request.
If anyone has similar problems, here's the update frame listener code. just replace yours and then call update yourselfs at a constant or frame limited rate.
#include "OgreNewt_BasicFrameListener.h"
#include "OgreNewt_Debugger.h"
namespace OgreNewt
{
BasicFrameListener::BasicFrameListener(RenderWindow* win, Camera* cam, SceneManager* mgr, OgreNewt::World* W, int update_framerate) :
ExampleFrameListener(win,cam)
{
m_World = W;
desired_framerate = update_framerate;
m_update = (Ogre::Real)(1.0f / (Ogre::Real)desired_framerate);
m_elapsed = 0.0f;
// add the standard debug viewer.
Debugger::getSingleton().init( mgr );
}
BasicFrameListener::~BasicFrameListener(void)
{
}
bool BasicFrameListener::frameStarted(const FrameEvent &evt)
{
m_elapsed += evt.timeSinceLastFrame;
//Ogre::LogManager::getSingleton().logMessage(" Newton Frame Listener... m_elapsed: "+Ogre::StringConverter::toString(m_elapsed)+
// " m_update:"+Ogre::StringConverter::toString(m_update));
// m_World->update( m_update );
int count = 0;
if ((m_elapsed > m_update) && (m_elapsed < (1.0f)) )
{
//while (m_elapsed > m_update)
//{
// m_World->update( m_update );
// m_elapsed -= m_update;
// count++;
//}
}
else
{
if (m_elapsed < (m_update))
{
// not enough time has passed this loop, so ignore for now.
}
else
{
//m_World->update( m_elapsed );
//count++;
}
}
// Ogre::LogManager::getSingleton().logMessage(" Newton updates this loop: "+Ogre::StringConverter::toString(count));
/////////////////////////////////////////////////////////////
// DEBUGGER
mInputDevice->capture();
if (mInputDevice->isKeyDown(Ogre::KC_F3))
{
Debugger::getSingleton().showLines( m_World );
}
else
{
Debugger::getSingleton().hideLines();
}
return true;
}
} // end NAMESPACE OgreNewt
That also removes the annoying constant logging of netwon updates.(Annoying for me because I use a ogre wrapper I wrote myself for blitzmax, and that uses a richedit output box. As you know they have a 4mb limit and slow down the more text is entered. So netwon really slowed it down for me.)
But overall OgreNewt is the most wonderful physics api I've used so no complaints here, just tips!
praetor
03-04-2006 05:34:00
Yeah, that may seem like a good idea, but it isn't. The reason you let OgreNewt handle updates is because Newton should be update at a constant rate. By calling the update 4 times per frame, you call it more often, but that still isn't constant. The technique is called time-slicing if you want to search about it, but it's the correct way of doing things.
nathanwilliams6
03-04-2006 11:13:06
i had the same problem, i found that using the standard time slicing method in combination with a multiplier (which i could adjust via an updateSpeed call to my listener) worked well.
basically whenever i updated the time that was passed since last frame, i multiplied the elapsed time by this multiplier, therby making the physics world, think that more time had passed than what had.
bool myPhysicsListener::frameStarted(const Ogre::FrameEvent &evt)
{
m_rElapsed += evt.timeSinceLastFrame * m_rSpeed; // <--- here i multiply the time passed by the multiplier
int count = 0;
if ((m_rElapsed > m_rUpdate) && (m_rElapsed < (1.0f)) )
{
while (m_rElapsed > m_rUpdate)
{
m_wWorld->update( m_rUpdate );
m_rElapsed -= m_rUpdate;
count++;
}
}
else
{
if (m_rElapsed < (m_rUpdate))
{
// not enough time has passed this loop, so ignore for now.
}
else
{
m_wWorld->update( m_rElapsed );
count++;
m_rElapsed = 0;
}
}
return true;
Ogre::LogManager::getSingleton().logMessage(" Newton updates this loop: "+Ogre::StringConverter::toString(count));
}
void myPhysicsListener::updateSpeed(const Ogre::Real &rSpeed)
{
m_rSpeed = rSpeed;
}
basically m_rSpeed, is a Ogre::Real which would contain the desired speed of the physics.
timeslicing is a far better way to go, for reasons mentioned earlier.
Vectrex
03-04-2006 12:09:52