CenterOfGravity on MotionState?

Post Reply
pixartist
Posts: 8
Joined: Thu Jan 15, 2015 5:07 pm

CenterOfGravity on MotionState?

Post by pixartist »

So the default motion state in BulletSharp has a field called CenterOfGravity. Now how would the value of this be communicated to the engine ? How would I go about implementing this myself in my own motion state?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: CenterOfGravity on MotionState?

Post by drleviathan »

You can see how the CenterOfGravity data is used by the btDefaultMotionState by looking at the code:

http://bulletphysics.org/Bullet/BulletF ... ource.html

As far as I can tell it allows the center of mass of the btRigidBody to be different from the "center" of the game object. Remember, the MotionState is an API of sorts that makes it easy to communicate transform changes between a game object and a btRigidObject. Bullet will call MotionState::setWorldTransform() each full-step on a DYNAMIC object and will call MotionState::getWorldTransform() each full-step on a KINEMATIC object.

It appears that bulletsharp provides access to btDefaultMotionState. I dunno how you would make your own MotionState in bulletsharp.
pixartist
Posts: 8
Joined: Thu Jan 15, 2015 5:07 pm

Re: CenterOfGravity on MotionState?

Post by pixartist »

But wouldn't that translate the entire collision shape, not just the center of the object ?

Edit: my class looks like this:

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using BulletSharp;
namespace SharpGL.Components.BulletPhysics
{
    public class RbMotionState : MotionState
    {
        private Transform objectTransform;
        public Vector3 Center { get; set; }
        public Vector3 CenterOfGravity { get; set; }
        public override Matrix4 WorldTransform
        {
            get
            {
                return objectTransform.GetMatrixInverse() * Matrix4.CreateTranslation(Center);
            }
            set
            {
                objectTransform.Rotation = value.ExtractRotation();
                objectTransform.Position = value.ExtractTranslation() - Vector3.Transform(Center, objectTransform.Rotation);
            }
        }
        public RbMotionState(Transform tranform, Vector3 center, Vector3 centerOfGravity)
        {
            Center = center;
            CenterOfGravity = centerOfGravity;
            objectTransform = tranform;
            WorldTransform = tranform.GetMatrixInverse();
        }
    }
}
As you can see, "Center" is the translation between the collider and the visual mesh. But I don't know where CenterOfMass comes in here.
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: CenterOfGravity on MotionState?

Post by Basroil »

pixartist wrote:But wouldn't that translate the entire collision shape, not just the center of the object ?
...

As you can see, "Center" is the translation between the collider and the visual mesh. But I don't know where CenterOfMass comes in here.
Well, objects are defined by their collision shape, so you should expect the entire thing to move when the center of gravity (also called center of mass) moves. It might not matter too much on kinematic objects where the center is, but dynamic objects have forces act on that center of gravity and moving it will change the dynamic response. Think of a boomerang, depending on if the CoG is in the shape's mesh at the symetric line, in the symetric line outside the shape (but inside the convex hull), or offset from that line (again inside the hull), it will either spin on it's point, wobble back and forth, or actually act like a boomerang!
pixartist
Posts: 8
Joined: Thu Jan 15, 2015 5:07 pm

Re: CenterOfGravity on MotionState?

Post by pixartist »

I don't expect the entire thing to move when I move the center of gravity. For example if I have a cube mesh going from 0 to 1 on all axis, this would require to move the center of gravity to 0.5 in order to make the cube behave as expected.
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: CenterOfGravity on MotionState?

Post by Basroil »

pixartist wrote:I don't expect the entire thing to move when I move the center of gravity. For example if I have a cube mesh going from 0 to 1 on all axis, this would require to move the center of gravity to 0.5 in order to make the cube behave as expected.
Looks like you don't understand what a center of gravity is. The center of gravity is a physical definition of the mass distribution within an object. If you were to pin an object's center of gravity in space, it would not rotate due to gravity or forces passing though the center of gravity. By moving the center of gravity with respect to a collision object, you are shifting the mass distribution, as if there were a cube half-filled with water sloshing around. While some physics with that are cool to do, it's not normal! :wink:

In bullet the center of gravity for a collision object defines where the mass is and how it rotates, and for built in types the center of gravity is analogous to the shape center. Moving the CoG is equivalent to moving the object simply because that's the easiest definition for a rigid body.
pixartist
Posts: 8
Joined: Thu Jan 15, 2015 5:07 pm

Re: CenterOfGravity on MotionState?

Post by pixartist »

I very well understand what the center of gravity is, you misunderstood my question, twice. The center of gravity variable in the motion state OBVIOUSLY does not contain information about the location of the center of gravity of the object in world coordinates. This information is already contained in the worldTranform of the motionState. What it should contain, is the location of the center of gravity in the local space of the collision mesh, thus making it possible to change the center of mass. Why else would there be a constructor with matrix containing the start-tranformation and a variable centerOfGravity.
anthrax11
Posts: 72
Joined: Wed Feb 24, 2010 9:49 pm

Re: CenterOfGravity on MotionState?

Post by anthrax11 »

CenterOfGravity is maybe not the best name for that variable, but I guess you can think of it as the local center of gravity in visual coordinates. The value of CenterOfGravity here depends only on the visual mesh. It doesn't make sense to change it after setting it initially. If your visual mesh is already centered at the physical center of gravity, then CenterOfGravity is just the identity matrix. Otherwise, for example, if you have a model of a cube for rendering where the center point (0,0,0) is at one of the 8 corners, then in WorldTransform.get you would transform the graphics transform by some CenterOfGravity to tell Bullet that the center of gravity is different from the center of the visual mesh.

With a custom motion state, you can use GraphicsTransform to render your mesh while Bullet keeps using WorldTransform. Maybe this makes more sense:

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using BulletSharp;
namespace SharpGL.Components.BulletPhysics
{
    public class RbMotionState : MotionState
    {
        public Transform GraphicsTransform { get; set; }
        public Transform CenterOfGravityOffset { get; set; }
        
        public override Matrix4 WorldTransform
        {
            get
            {
                return CenterOfGravityOffset.GetMatrixInverse() * GraphicsTransform;
            }
            set
            {
                GraphicsTransform = CenterOfGravityOffset * value;
            }
        }
        public RbMotionState(Transform graphicsTranform, Transform centerOfGravityOffset)
        {
            GraphicsTransform = graphicsTranform;
            CenterOfGravityOffset = centerOfGravityOffset;
        }
    }
}
It's easier to store the center of gravity offset as a transform, so you don't have to do extra work every time WorldTransform is called.

Edit:
To clarify, the center of gravity is already determined by the collision shape. For example, if you want to make one side of a collision object heavier, then there are ways to do it (http://www.bulletphysics.org/Bullet/php ... f=9&t=2209).

The motion state is just a hook for when the object's world transform is updated. The code above is an extension to MotionState that gives the world transform also in visual coordinates (like if the visual mesh is offset from the center of gravity). There is no way to actually change the center of gravity in the simulation using motion states.
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: CenterOfGravity on MotionState?

Post by Basroil »

pixartist wrote:The center of gravity variable in the motion state OBVIOUSLY does not contain information about the location of the center of gravity of the object in world coordinates.

The motion state doesn't contain anything other than a transform. The transform however, is defined as the world coordinates of the center of gravity. Here's the motion state code that shows there is no secondary center of gravity necessary in a motion state:

Code: Select all

#include "btTransform.h"

///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
class	btMotionState
{
	public:
		
		virtual ~btMotionState()
		{
			
		}
		
		virtual void	getWorldTransform(btTransform& worldTrans ) const =0;

		//Bullet only calls the update of worldtransform for active objects
		virtual void	setWorldTransform(const btTransform& worldTrans)=0;
		
	
};

#endif //BT_MOTIONSTATE_H
pixartist wrote:What it [The motion state] should contain, is the location of the center of gravity in the local space of the collision mesh, thus making it possible to change the center of mass.

btDefaultMotionState allows you to have a graphics world to physics world offset, but the value you feed into it is the "center of mass transform", i.e. the mass center of your collision shape. At no point do you change the actual center of mass in respect to the collision shape. As I stated before, changing the location of the center of gravity will cause serious issues unless you're careful and recompute the inertia and velocity vectors (you need conservation of momentum and angular momentum after all).
pixartist wrote:Why else would there be a constructor with matrix containing the start-tranformation and a variable centerOfGravity.
There is no centerOfGravity in either btMotionState or btDefaultMotionState, rather you have a "m_centerOfMassOffset" which lets you define graphics world and physics worlds as different world axis (i.e. your physics says [1,0,0,0][0,1,0,0][0,0,1,0][0,0,0,1] but in the graphics world you rotate about an angle and shift by 2 and the function will return [1,0,0,2][0,0,1,0][0,-1,0,0][0,0,0,1] without needing to do the calculations yourself!). Both constructor arguments are optional, and are there to allow you to pre-load the transform start data in case you want to allow the system to revert to an old value (and set up your offset if needed)
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: CenterOfGravity on MotionState?

Post by Erwin Coumans »

The rigid body world transform is by definition at the center of gravity. Now your graphics and collision shapes might be at a different location, relative to the center of gravity. You can control this shift using two steps:

1) Shift the collision shape so that it matches the center of gravity, using the inverse center of mass offset (m_centerOfMassOffset in step 2)
2) Compensate for this shift in the motion state using the m_centerOfMassOffset, to compensate for the shift of collision shape (and graphics shape).

I'll create some demo to show how to do this.
Thanks!
Erwin
Post Reply