标签:
杂谈 |
分类: 物理引擎 |
Bullet中的常用数据类型包括: btScalar、btVector3、 btQuaternion、btMatrix3x3以及btTransform。
下面我们看看这些基本数据类型功能及用法:
1、btScalar
在bullet中,btScalar是单精度或双精度浮点数。如果我们定义了宏BT_USE_DOUBLE_PRECISION,则btScalar是double,否则是float。
btScalar的实现代码:
1 | #if defined(BT_USE_DOUBLE_PRECISION) |
2 | typedef double btScalar; |
3 | //this number could be bigger in double precision |
4 | #define BT_LARGE_FLOAT 1e30 |
5 | #else |
6 | typedef float btScalar; |
7 | //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX |
8 | #define BT_LARGE_FLOAT 1e18f |
9 | #endif |
2、btVector3
在Bullet中,3D位置和向量用btVector3表示。在btVector3中,实际上包含四个值:x, y, z, w,第四个分量w值恒为0。加第四个分量,主要是考虑SIMD对齐(通常SIMD指令可以处理四个浮点数)。
除了常用的加、减、点积、叉积、混合积、乘一个标量值,归一化等操作外,还包括几个特殊的函数或操作:
比如:angle返回当前向量和另一个向量的夹角。
1 | |
3 | SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const |
4 | { |
5 | btScalar s = btSqrt(length2() * v.length2()); |
6 | btFullAssert(s != btScalar(0.0)); |
7 | return btAcos(dot(v) / s); |
8 | } |
绕单位向量旋转一rotate个角度:
1 | SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) |
2 | { |
3 | // wAxis must be a unit lenght vector |
4 | |
5 | btVector3 o = wAxis * wAxis.dot( *this ); |
6 | btVector3 x = *this - o; |
7 | btVector3 y; |
8 | |
9 | y = wAxis.cross( *this ); |
10 | |
11 | return ( o + x * btCos( angle ) + y * btSin( angle ) ); |
12 | } |
在win32中,btVector3还会使用sse指令加速操作:
比如:
1 | #ifdef BT_USE_SSE // _WIN32 |
2 | union { |
3 | __m128 mVec128; |
4 | btScalar m_floats[4]; |
5 | }; |
6 | SIMD_FORCE_INLINE __m128 get128() const |
7 | { |
8 | return mVec128; |
9 | } |
10 | SIMD_FORCE_INLINE void set128(__m128 v128) |
11 | { |
12 | mVec128 = v128; |
13 | } |
14 | #else |
15 | btScalar m_floats[4]; |
16 | #endif |
3、 btQuaternion
这是bullet中四元数类。在3D数学中,四元数可以用来表示物体的方位和旋转。另外,也可以使用矩阵或欧拉角的方式表示旋转,它们之间可以相互转化。
我们知道四元数通过一个方向轴和一个旋转角表示物体的方位。
在Bullet中,我们常通过设置旋转方向和角度的方法来设置四元数,单位化的四元数表示为:
http://s14/middle/61feffe149736dc14902d&690
其中,u是旋转向量,alpha角是旋转角度。一个向量v被一个四元数q旋转的操作为:
http://s6/middle/61feffe149736dc8efa05&690
在btQuaternion中,通过函数SetRotation我们来设置某个方向,一定角度的四元数。
1 | |
4 | void setRotation(const btVector3& axis, const btScalar& angle) |
5 | { |
6 | btScalar d = axis.length(); |
7 | btAssert(d != btScalar(0.0)); |
8 | btScalar s = btSin(angle * btScalar(0.5)) / d; |
9 | setValue(axis.x() * s, axis.y() * s, axis.z() * s, |
10 | btCos(angle * btScalar(0.5))); |
11 | } |
另外,btQuaternion也包括了欧拉角和四元数的转化,我们通过void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)来直接设置欧拉角,函数内部会转化为相应的四元数值。【yaw表示绕y轴旋转角度,pich绕x轴旋转角度,roll绕z轴旋转角度】
另外一个重要的函数是slerp,它在两个四元数之间进行平滑插入操作,常用插值动画中使用该函数。
1 | |
5 | btQuaternion slerp(const btQuaternion& q, const btScalar& t) const |
6 | { |
7 | btScalar theta = angle(q); |
8 | if (theta != btScalar(0.0)) |
9 | { |
10 | btScalar d = btScalar(1.0) / btSin(theta); |
11 | btScalar s0 = btSin((btScalar(1.0) - t) * theta); |
12 | btScalar s1 = btSin(t * theta); |
13 | if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp |
14 | return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d, |
15 | (m_floats[1] * s0 + -q.y() * s1) * d, |
16 | (m_floats[2] * s0 + -q.z() * s1) * d, |
17 | (m_floats[3] * s0 + -q.m_floats[3] * s1) * d); |
18 | else |
19 | return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d, |
20 | (m_floats[1] * s0 + q.y() * s1) * d, |
21 | (m_floats[2] * s0 + q.z() * s1) * d, |
22 | (m_floats[3] * s0 + q.m_floats[3] * s1) * d); |
23 | |
24 | } |
25 | else |
26 | { |
27 | return *this; |
28 | } |
29 | } |
4、btMatrix3x3
btMatrix3x3是一个3*3的矩阵,它可以和欧拉角和四元数之间相互转化。
void setRotation(const btQuaternion& q)
void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ)
void getRotation(btQuaternion& q) const
void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
当然,也可以求转置矩阵、伴随矩阵等等。
另外,diagonalize计算旋转矩阵R,具体解释可以看下编写这个函数的人如何解释:
http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=2562&start=0
5、btTransform
该类同时表示位置和旋转。主要用于点或向量在不同坐标系统之间的转换。
Bullet中使用右手坐标系,和OpenGL是一致的。
http://s14/middle/61feffe149736dd21845d&690
在btTransform中,旋转用m_basis表示,平移通过m_origin表示:
///Storage for the
rotation
btMatrix3x3
m_basis;
///Storage for the
translation
btVector3 m_origin;
我们可以对btTransform实施平移、旋转操作。
btTransform可以返回四元数表示的旋转:getRotation
1 | void setFromOpenGLMatrix(const btScalar *m) |
2 | { |
3 | m_basis.setFromOpenGLSubMatrix(m); |
4 | m_origin.setValue(m[12],m[13],m[14]); |
5 | } |
6 | |
7 | |
9 | void getOpenGLMatrix(btScalar *m) const |
10 | { |
11 | m_basis.getOpenGLSubMatrix(m); |
12 | m[12] = m_origin.x(); |
13 | m[13] = m_origin.y(); |
14 | m[14] = m_origin.z(); |
15 | m[15] = btScalar(1.0); |
16 | } |
getOpenGLMatrix返回btTransform表示的OpenGL矩阵(4*4).