Hello, searching in src/BulletDynamics/Dynamics/btRigidBody.cpp, it seems that bullet use a 3D vector for rotation, representing the axis of rotation and the angle with the norm.It seems very practical because it's directly given by a cross product when applying an impulse ,and we can add them to combine them.

What is the name of this,and how can we make a rotation matrix from it?

## rotation format in bullet physics

- drleviathan
**Posts:**699**Joined:**Tue Sep 30, 2014 6:03 pm**Location:**San Francisco

### Re: rotation format in bullet physics

Bullet stores both position and rotation in a

Quaternions are useful because it is relatively easy to do rotation math with them to obtain other rotations. Once you're done with rotation math you would take the

There are many tutorials about Quaternions online, however I will offer a crash course on them here:

There are some common "gotchas" when working with

If you're going to use the result then discard it, don't normalize, but if you're going to save the

The question becomes: Which rotation should operate first? That one always goes RIGHT-most, and subsequent rotations operate from RIGHT to LEFT order.

**btTransform**which is a 4x4 matrix under the hood. You can extract just the rotation part into a normalized**btQuaternion**which is a 4D "vector". The components of a Quaternion are NOT the normalized_axis + angle, however with some practice you can "eyeball" a Quaternion to get an idea of what the axis and rotation are.Quaternions are useful because it is relatively easy to do rotation math with them to obtain other rotations. Once you're done with rotation math you would take the

**finalQuaternion**and do something like this:Code: Select all

```
transform.setRotation(finalQuaternion);
body->setTransform(transform);
```

**(1)**Quaternions in general span all of 4D space, however when it comes to rotations we are only concerned with those Quaternions which live on the surface of the unit hypersphere: centered at the origin with radius = 1.**(2)**The subset of Quaternions on the unit hypersphere form a "Group" (research "Group Theory" for more about what this means) under some operator we will call "multiplication". In other words, when you "multiply" two elements in the Group the result is another element of the Group.**(3)**There is an isomorphism (sorta) between the Group of unit Quaternions and the Group of Rotations in 3D. In other words, the two Groups behave in the same way under the multiplication operator. This is why unitary Quaternions are so useful in 3D math.**(4)**The "sorta" qualifier is there because really there is a 2-to-1 mapping from Quaternion space to Rotations. For each valid Rotation there are two Quaternions that represent it, and these Quaternions are at opposite ends of the hypersphere: Q and -Q. This fact matters sometimes when you're doing interpolation from one Quaternion to another, but usually you can forget about it.**(5)**Internally the Quaternion has four elements:**<x,y,z,w>**. In code: some Quaternion implementations might order them**<w,x,y,z>**but the**btQuaternion**ctor which takes four floats orders them**<x,y,z,w>**. The**<x,y,z>**components are called the "imaginary" part, similar to the "imaginary number '**i**' you learned in high school) but in this case there are three distinct imaginary axes and they are often referred to as**<i,j,k>**. The**<w>**component is known as the "real part".**(6)**The identity**btQuaternion**(zero rotation) has the form:**<0,0,0,1>****(7)**For a rotation of**A**radians about a normalized axis**<X,Y,Z>**the corresponding**btQuaternion**has components:**<sX, sY, sZ, c>**(and its negative as per item**(4)**) where:**s = sin(A/2)**and**c=cos(A/2)**. Knowing this, with some practice you can "eyeball" the components of a**btQuaternion**to get an idea as to what sort of rotation it represents. For example:**<1,0,0,0>**= pi radians about X-axis**<0,1,0,0>**= pi radians about Y-axis**<sqrt(2)/2, 0, 0, sqrt(2)/2>**= pi/2 radians about X-axisThere are some common "gotchas" when working with

**btQuaternions**in code. Here are some:**(8)**Due to floating point error a**btQuaternion**probably doesn't lie on the unit hypersphere, but it is close. Consequently the product of two**btQuaternions**:**Q1*Q2**can drift even further from the sphere. Normally this isn't a problem, but if you ever find yourself recycling a**btQuaternion**to compute its next value then it will eventually explode off the sphere... unless you constantly normalize. In other words:Code: Select all

```
Q = Q * deltaQ; // BAD!
Q = (Q * deltaQ).normalize(); // GOOD!
```

**btQuaternion**for the next loop then normalize it every loop. Note, this is not a problem if you're "storing" the**btQuaternion**in a**btTrasnform**because normalization automatically happens when storing the rotation into the 4x4 matrix.**(9)**Bullet does not provide a convenient operator between**btQuaternion**and**btVector3**. It is implemented but probably doesn't do what you think: it doesn't just rotate the vector. To rotate a**btVector3**in Bullet first store the rotation into a**btTransform**and use that.**(10)**Rotations do not commute, so order matters. When doing rotation math you need to figure out if it is**Q1*Q2**or**Q2*Q1**. My advice for this is to always imagine the rotations operating from the LEFT on a hypothetical vector on the RIGHT. So: consider it like so:**Q1 * Q2 * v**The question becomes: Which rotation should operate first? That one always goes RIGHT-most, and subsequent rotations operate from RIGHT to LEFT order.

### Re: rotation format in bullet physics

in btRigidBody.h,angles seem to be stored in a btVector3:
also in this function:
computation are made on a btVector3

how is stored for example m_angularVelocity?

Code: Select all

```
btVector3 m_linearVelocity;
btVector3 m_angularVelocity;
```

Code: Select all

```
void applyTorqueImpulse(const btVector3& torque)
{
m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
clampVelocity(m_angularVelocity);
#endif
```

how is stored for example m_angularVelocity?

- drleviathan
**Posts:**699**Joined:**Tue Sep 30, 2014 6:03 pm**Location:**San Francisco

### Re: rotation format in bullet physics

**AngularVelocity**is indeed a

**btVector3**, however its units are

**radians/second**. It represents the rate of change of the rotation... not the rotation. Perhaps you had a question about

**AngularVelocity**?

### Re: rotation format in bullet physics

so if I understand well,"adding" angular velocities is commutative,in contrary to rotations,and we can use for that a vector collinear to the axis of the rotation,with the norm the velocity in radians(as i understand in the code)

ok,I just found that:https://en.wikipedia.org/wiki/Angular_v ... ty_vectors so it seems to be that

is there a way to efficiently integrate the rotation(with a rotation matrix because it's a school project and i want to stay on the program) with this vector?

ok,I just found that:https://en.wikipedia.org/wiki/Angular_v ... ty_vectors so it seems to be that

is there a way to efficiently integrate the rotation(with a rotation matrix because it's a school project and i want to stay on the program) with this vector?

- drleviathan
**Posts:**699**Joined:**Tue Sep 30, 2014 6:03 pm**Location:**San Francisco

### Re: rotation format in bullet physics

Do you mean: "Given some initial rotationis there a way to efficiently integrate the rotation with this vector?

**Q0**and a non-zero angular velocity

**W**... is it possible to compute the rotation

**Q(t)**as time progresses forward?"

If so then: yes. In fact, that is what Bullet does: RigidBody dynamics. It has an integration step which computes future rotations. The details there are a bit more complicated than my paraphrased and hypothetical question since you also need to know the body's

**InertiaTensor**(angular mass distribution). Depending on the symmetry of the Body the

**AngularVelocity**might not be uniform over time for a freely tumbling object but the

**AngularMomentum**would be conserved (e.g. would be invariant).

Perhaps you should describe what you really want to do and then then your questions might become more clear.