Xpoint
13-09-2006 21:22:20
Hey all,
I'm trying to implant some kind of gravity source, so objects which get close to a specific point will get pulled to that point. For now, it worked great!! But I noticed that at low frame rates that force gets less strong, meaning that at to low frame rates the global scene gravity will win it from the other... (still get it??
)
Anyway, this is what I'm doing:
void CAreaGravityAffector::update(const float fTimestep)
{
// Get the default scene.
nxOgre::scene* pScene = CWorldManager::getSingleton().getDefaultNxOgreScene();
// Iterate through all the bodies.
nxOgre::bodyIterator bodyIt(pScene);
nxOgre::body* pBody = NULL;
while(pBody = bodyIt.next())
{
// Check if this body is static or dynamic.
// Check if this body is in the correct scene.
// Check if this body has gravity.
if(pBody->isStatic() ||
pBody->owner != pScene ||
pBody->isIgnoringGravity())
continue;
// If the body is in range, apply the forces.
Ogre::Vector3 vDistance = pBody->getGlobalPosition() - m_pSceneNode->getWorldPosition();
if(vDistance.squaredLength() <= m_fSquaredRadius)
{
float fRatio = vDistance.normalise() / m_fRadius;
float fGravity = (fRatio * m_fOuterGravity) + ((1.0f - fRatio) * m_fInnerGravity);
Ogre::Vector3 vForce = ((-vDistance) * fGravity);
pBody->addForce(vForce, NxForceMode::NX_ACCELERATION);
}
}
}
How do I fix this problem, so that forces will be the same at lower and higher frame rates?
Thanks in advance!
betajaen
14-09-2006 11:00:04
Sounds like a cool project, I wanted to do a very similar thing with magnets. Anyway, I noticed you have "fTimestep" there, but no use for it.
So if you do:
Ogre::Vector3 vForce = ((-vDistance) * fGravity) * fTimestep;
The force should be fairly the same between frames, if you want a stronger gravity "field" because effectly the force is being divided by a 100 to 1000 then just turn up fGravity.
Xpoint
14-09-2006 12:20:28
Ok, that worked!
Didn't used that timestep because it didn't work for me, but after doing this:
Ogre::Vector3 vForce = (((-vDistance) * fGravity) * fTimestep) / (1.0f / 60.0f);
it worked nice.
Xpoint
14-09-2006 12:33:43
If the above advice is not sufficient then lock the framerate with:
'renderOneFrame()'.
Using the information in these threads:
http://www.ogre3d.org/phpBB2addons/view ... t=addforce
http://www.ogre3d.org/phpBB2/viewtopic. ... nt&start=0
It already works for me now.
But locking the framerate will only be a solution if you stay at that framerate, but you can't prevent getting lower frame rates.
Yes, I saw that it worked for you, my reply was for others with similar problems.
An added benefit for using the 'renderOneFrame()' method is that the application can run without actually rendering to screen and still be accurate in terms of its 'virtual' time (ie. the application will behave as if it is running at a certain framerate but infact is running faster to the user).
Xpoint
14-09-2006 13:00:05
I see what you mean, and I hope it will be usefull for other users.
I've created a video of my current progress, so if you like to see me results:
Video (~17.1MB)
betajaen
14-09-2006 13:21:28
Hahaha thats my NxOgre
I'm doing something incredibly similar but with magnetics using the state system.
via:
mMagenticBody->addState(STATE_MAGNET);
mIronBall->addState(STATE_MAGNETIC);
It works fairly well so far although I need to turn of the magnetic properties after it leaves a field of radius.
Xpoint
14-09-2006 14:20:26
Hahaha thats my NxOgre
I'm doing something incredibly similar but with magnetics using the state system.
via:
mMagenticBody->addState(STATE_MAGNET);
mIronBall->addState(STATE_MAGNETIC);
It works fairly well so far although I need to turn of the magnetic properties after it leaves a field of radius.
That looks cool, but I won't be using the state manager for it since it is easier for me to create my own kind of system. I will use the state machine to tell that objects are magnetic though.
betajaen
14-09-2006 14:22:39
Well it's your code, either way yours is more like a mini-moveable non-deadly blackhole, than my ultra-strong magnetic.
But I just posted the
video if you're intrested.
Xpoint
14-09-2006 14:36:06
that video looks awsome!
Imaging that you make the same effects like that video of CellFactor: Revolution on the Ageia home page.
And betajaen, thanks for your great library, very easy to use!! My compliments.
Btw, I'm thinking of creating some bad ass effects for that gravity sphere so it looks like a weapon, so stay tuned.
I can only agree.
Very nice to see that the state system can be easily extended and the result so easy to use.
betajaen
14-09-2006 15:02:57
I think I just cracked gravity; there are no words except the grunts of lifting my jaw off the floor.
Watch the
the video! (5 meg)
Betajaen, do you think physX can allow this to scale up?
Where the large cube is massively larger, actual planet size, while the satellites remain small?
betajaen
14-09-2006 15:16:11
In theory yes, Wyx and I simulated collisions of planets using that scale and it worked fine, however you would get some floating point errors or rounding off at that range.
So it would be better to scale it down, although if you make it look correct people won't notice.
Xpoint
14-09-2006 18:52:30
Now the problem is reversed!!! With higher framerate the forces get weaker... Any solution for that??
Xpoint
14-09-2006 21:56:18
I think I've fixed the problem now!
I've changed my code to this:
void CAreaGravityAffector::update(const float fTimestep)
{
// Get the default scene.
nxOgre::scene* pScene = CWorldManager::getSingleton().getDefaultNxOgreScene();
// Calculate the right timestep.
NxReal fMaxTimestep;
NxU32 dummy2;
NxTimeStepMethod dummy3;
pScene->mScene->getTiming(fMaxTimestep, dummy2, dummy3);
float fFinalTimestep = fTimestep > fMaxTimestep ? fMaxTimestep : fTimestep;
// Iterate through all the bodies.
nxOgre::bodyIterator bodyIt(pScene);
nxOgre::body* pBody = NULL;
while(pBody = bodyIt.next())
{
// Check if this body is static or dynamic.
// Check if this body is in the correct scene.
// Check if this body has gravity.
if(pBody->isStatic() ||
pBody->owner != pScene ||
pBody->isIgnoringGravity())
continue;
// If the body is in range, apply the forces.
Ogre::Vector3 vDistance = pBody->getGlobalPosition() - m_pSceneNode->getWorldPosition();
if(vDistance.squaredLength() <= m_fSquaredRadius)
{
float fRatio = vDistance.normalise() / m_fRadius;
float fGravity = (fRatio * m_fOuterGravity) + ((1.0f - fRatio) * m_fInnerGravity);
pBody->addForce(((-vDistance) * fGravity) * fFinalTimestep / fMaxTimestep, NX_ACCELERATION);
}
}
}
Just be sure the timestep doesn't get to big. The problem was that at lower framerates the force gets to large, so limit it with the max timestep.
betajaen
14-09-2006 22:27:08
Excellent
You could base fMaxTimestep of the best frame count from Ogre so it changes dynamically.
I can only agree again, Good going Xpoint!
Nice to see this problem solved in most ways
Xpoint
15-09-2006 13:54:03
One more video of this:
video (~5MB)
It shows the same, but now those balls are just as heavy as the gravitional balls, wich gives a funny effect.
Next thing for me will be implanting magnets, but that will be done next week because I'll be gone for the weekend.
betajaen
15-09-2006 13:58:16
Haha, very nice. I'd be intrested to see your full code of it all, perhaps it could be a prefab?
I sort of messed up the magnet code in NxOgre and can't get it back like I had before, still working on it though, but I'm on a break and working on the opposite - Explosions.
Xpoint
15-09-2006 14:39:45
There isn't realy more code to show exept for that function.
But I'll look if I can create a prefab for it next week. I'll be gone till sunday now, so good luck with your magnets.
Cya.
Xpoint
19-09-2006 22:28:16
Currently busy with other things, so not sure if I can work on that prefab..
Anyway, I'll let you know.