Gravity in a Sphere for Small Planets

mammut87

04-06-2010 09:27:40

Hi,

for a Project i'm need place the gravity in the Center of a smaller or bigger spherical mash.
So that i can place objects around it, that they fall to the "planet" and not of the "planet" i've they move around it.
Like the game "Mario Galaxy".

Now i have the problem that i don't find any reference code for this.

I use Bloody Mess 1.5.5 and PhysX 9.10.0129 and i hope this is even possible here. Otherwise

Greats
Benni

betajaen

04-06-2010 10:26:05

PhysX doesn't support gravity like that, not natively anyway.

What you'll need to do is disable scene gravity, and apply a force vector to each actor to attract them to your planet. Luckily Newton got there before you with his law of gravitation. I've actually wrote some code ages ago based on the equation, if I find it -- I'll post it for you. But have a go at implementing it anyway.

mammut87

04-06-2010 13:48:53

Thanks for that fast response.

I will immediately try it out.
Hopefully I don't need to be a Newton to get behind the formular^^

Greats
Benjamin

betajaen

04-06-2010 14:19:57

It isn't to difficult to implement, and you only need to apply the force to the bodies and not the planet. Also remember to apply it to bodies that aren't sleeping.

mammut87

04-06-2010 18:14:56

... Also remember to apply it to bodies that aren't sleeping.

Yeah, instead i had to wake them up^^

mammut87

06-06-2010 17:35:52

Hi,

i had time to write the formular in Code, i thought to calculate every Axis for themself. But It throws me an Error which sais :
Assertion failed!
Expression:(min.x <= max.x && min.y <= max.y && min.z <= max.z) && "The minimum corner of the box must be less than or equal to maximum corner"

My Code ist this, the mSphere is representative for the Planet and the mCubeTwo for a simple Object.
The formular i used, was the Vector form of Gravitation that betajaen had postet here


mCubeTwo->addForce(
NxOgre::Vec3(
-mGravity * (mMass*mPlanetMass)/pow(abs(mCubeTwo->getGlobalPosition().x - mSphere->getGlobalPosition().x),2) * ((mCubeTwo->getGlobalPosition().x - mSphere->getGlobalPosition().x)/abs(mCubeTwo->getGlobalPosition().x - mSphere->getGlobalPosition().x)),
-mGravity * (mMass*mPlanetMass)/pow(abs(mCubeTwo->getGlobalPosition().y - mSphere->getGlobalPosition().y),2) * ((mCubeTwo->getGlobalPosition().y - mSphere->getGlobalPosition().y)/abs(mCubeTwo->getGlobalPosition().y - mSphere->getGlobalPosition().y)),
-mGravity * (mMass*mPlanetMass)/pow(abs(mCubeTwo->getGlobalPosition().z - mSphere->getGlobalPosition().z),2) * ((mCubeTwo->getGlobalPosition().z - mSphere->getGlobalPosition().z)/abs(mCubeTwo->getGlobalPosition().z - mSphere->getGlobalPosition().z))
),
NxOgre::Enums::ForceMode_Force, true);


In coordinates the mSphere has (0.300.0) and the mCubeTwo has (20, 1445, 0). Box Size is 100 and Cube size is 10.

Now I don't find the problem, maybe it's just a simple one, maybe i'am in the wrong path

Thanks for help

Greats
Benjamin

betajaen

06-06-2010 18:51:17

Your making things a bit to difficult.

Remember gravity is just an acceleration; like a car, so we can drop quite a bit of that equation. Newton's Second Law will help you out.

Anyway, I had a quick go at it myself, and it comes up fairly well. If the bodies are too far away from the planet then the attraction tends to over shoot, and you have mini-moons orbiting your planet, otherwise it's a good start.

This is Detritus/Haddock code, so if your using BM you'll have to adjust.

Create your Planet and Bodies. I'm using a square planet, because I don't have a sphere mesh handy, but it's still the same.

Critter::BodyDescription bodyDescription;
bodyDescription.mMass = 1000;
bodyDescription.mDynamicRigidbodyFlags += DynamicRigidbodyFlags::FreezePosition;
bodyDescription.mDynamicRigidbodyFlags += DynamicRigidbodyFlags::FreezeRotation;

mPlanet = mRenderSystem->createBody(NxOgre::BoxDescription(5,5,5), NxOgre::Vec3(0,10,0), "cube.1m.mesh", bodyDescription);
mPlanet->getSceneNode()->scale(5,5,5);


Critter::BodyDescription desc;
desc.mMass = 10;
desc.mDynamicRigidbodyFlags += DynamicRigidbodyFlags::DisableGravity;

NxOgre::BoxDescription box(1,1,1);

for (unsigned int i=0;i < 20;i++)
{
Body* body = mRenderSystem->createBody(box, Vec3(8,i,0), "cube.1m.mesh", desc);
mBodies.push_back(body);
}


Next up is applying the calculate force, each frame to each body affected:

Vec3 force; // F = m*A

for (NxOgre::vector_iterator<Body*> body = mBodies.elements(); body != body.end(); body++)
{
// Calculate the acceleration first (the A in the equation)
// Calculate the distance between the two bodies.
force = mPlanet->getGlobalPosition() - body->getGlobalPosition();
// Normalise the vector to create a direction.
force.normalise();
// Multiply it by the magnitude of acceleration, so we have acceleration and direction.
force *= 9.8f;

// Multiply it by the planets mass. (Remember: heavy and light things always fall at the same speed)
force *= mPlanet->getMass();

// Add the force to our body. time is involved because Newton's second law, is measured in per second
// and NxOgre/Ogre increments in microsecond intervals, so we have to lower the force by the time interval
// for it to be correctly spread across the second.
body->addForce(force * evt.timeSinceLastFrame);
// Done!
}


You still need to implement sleeping, and making the gravity proportional to distance between the planet and body (a spherical trigger could do), but hopefully if you understand my code and comments, you'll come up with something like this ;)

[attachment=0]Clipboard Image.png[/attachment]

mammut87

06-06-2010 19:09:13

Ok, it is very much to lock at.
I will do this later or tomorrow.

But a short question to the picture. Is there a new Version of Bloddy Mess where the Visual Debugger is activated?
Because we are using Bloody Mess 1.5.5 where the Visual Debugger is deactived, so it is written in here http://www.ogre3d.org/wiki/index.php/Bl ... Tutorial_3

Greats
Benjamin

mammut87

06-06-2010 19:30:53

I had try to implement your code pieces fix, to test the small errors.

And this line here is not working as yours

NxOgre::Vec3* gravForce;
gravForce = mSphere->getGlobalPosition() - mCubeTwo->getGlobalPosition();


It says : cannot convert from 'bml::Vector3<Type>' to 'Ogre::Vector3 *'

Now i don't know what there is the main difference between this and :

Vec3 force; // F = m*A
.....
force = mPlanet->getGlobalPosition() - body->getGlobalPosition();


It only seems that you are using the namespace method.

Greats
Benjamin

betajaen

06-06-2010 19:36:16

NxOgre::Vec3*

Is a pointer, you don't want that.

mammut87

06-06-2010 20:05:53

Okay, it's working with this.

You added the addForce to the FrameListener didn't you? Because of the evt.timeSinceLastFrame.

For testing i added the Force in createScene() and the Object is moving to the Planet, great.
But when the object collides with the Planet the object then driftes away and never comes back.

Is this normal? Does the addForce has to be in the FrameListener so it will work?

Greats
Benjamin

betajaen

06-06-2010 20:15:50

Yep, has to be in the frame listener on the frame started event, just before you call the TimeController.

If the object that comes towards the planet and misses, and drifts away, then the the gravity isn't strong enough to pull it back, it's reached escape velocity if you will.

mammut87

08-06-2010 23:54:20

The FrameListener and so is now working, with one Body.

I'd now wanted to add a Vector Type , so i think did you as you are using a Vector Iterator here:

for (NxOgre::vector_iterator<Body*> body = mBodies.elements(); body != body.end(); body++)
{


And mBodies seems to be the Vector Type.
But what is <Body*> for a Type? Is this the OGRE3DBody Type? And when Yes, why only Body?

The other case, I don't find the Vector Type or the Vector Iterator in NxOgre and now i'm thinking "from where you are getting them".

Maybe is there something i have to include befor it will work?

Greats
Benjamin

betajaen

09-06-2010 00:01:20

You don't have the new NxOgre vector in Bloody Mess, it was recently added in Detritus. Just use a normal stl vector to store your bodies.

std::vector<Body*> mBodies

mammut87

09-06-2010 01:36:54

The Gravity with multiple Objects is now working and it was hopefully the Ende of this Part^^

Thanks for fast help even at times where i didn't thought that there is anybody out else there who is now working on this kind of crab^^

Greats
Benjamin

betajaen

09-06-2010 10:51:45

The Gravity with multiple Objects is now working and it was hopefully the Ende of this Part^^

Thanks for fast help even at times where i didn't thought that there is anybody out else there who is now working on this kind of crab^^

Greats
Benjamin


Good to hear! ;)