Войти
Физика для игрСтатьи

ARBD. Шаг0. Твердое тело, свойства и понятия

Автор:

Твердое тело, свойства и понятия

Твердое тело, вернее, Абсолютно Твердое Тело ( АТТ ) – тело, расстояние между любыми двумя точками которого одинаково для всех этапов моделирования. Т. е. в процессе никаких, даже малейших, деформаций не происходит.

Свойства АТТ:
Линейные    Угловые
Положение  Ориентация
Скорость      Угловая скорость
Ускорение    Вращающий момент
Масса            Тензор инерции

Итак, положение тела ( position; x ) – вектор от начала мировых координат ( world coordinate system или global space) до начала координат в системе тела ( body coordinate system, так же local space ). Под мировыми координатами подразумевается координаты системы, в котором находится тело; обычно начало координат мировой системы – (0, 0, 0). Под системой координат тела представляется система, в которой все точки тела неподвижны, и обычно понимается связка: его положение и ориентация. Ориентация – это матрица ( R ) или кватернион ( Q ) ( или и то, и другое ), показывающий, как отличается базис тела от базиса системы в котором оно находится. Матрица ориентации представляет собой 3х3 матрицу, колонками которой являются 3 вектора базиса тела. На примере, тело находится в изначальной ориентации. Тогда базис e1 ( соответствует оси X ) = ( 1, 0, 0 ), базис e2 ( ось Y ) = ( 0, 1, 0 ), e3 ( ось Z ) = ( 0, 0, 1 ). Матрица ориентации такого тела будет иметь вид:
e1.x | e2.x | e3.x
e1.y | e2.y | e3.y
e1.z | e2.z | e3.z
т. е.
1 | 0 | 0
0 | 1 | 0
0 | 0 | 1
Кватернион, по сути, есть скаляр – величина поворота, и вектор – ось, вокруг которой поворот и совершается ( хранится это в таком виде: [ cos(theta / 2.0), sin(theta / 2.0) * v ], где theta – угол поворота, а вектор v - ось ). Преимущества использования кватернионов: проще интегрировать, а так же смежное, простота нормализации. Есть так же и преимущество в хранении – матрица ориентации это 9 скаляров, тогда как кватернион – всего 4. Однако, обычно матрица хранится вместе с кватернионом, для того чтобы не делать постоянные переводы ( например, отобразить моделируемое тело ).
Положение и ориентация тела меняются. Изменение этих величин называют линейной ( velocity; v ) и угловой ( angular velocity; греческая буква омега, обозначать будем латинской w ) скоростями. Угловая скорость есть вектор, модуль которого и есть фактическое значение угловой скорости, а нормированное направление – ось.
Движение АТТ в симуляторе можно назвать равноускоренным ( до тех пор, пока не произойдет столкновение или не нарушится любое другое ограничение ); это значит что скорости так же изменяются. Величины изменения скоростей называются линейным и угловым ускорениями. Хранить эти величины не стоит, обычно для этого хранят аккумулятор силы ( force; F ) и вращающего момента ( torque; греческая буква тау, обозначать ее будем латинской T ), которые обнуляются после каждого шага моделирования.
T = r x F,
где r – радиус-вектор от точки приложения силы ( мировая система координат ) до положения тела.
Характеристики сопротивления тела воздействию внешних сил, называются характеристиками инертности. Для линейного движения это скаляр – масса ( mass; m ). Для углового движения это тензор инерции ( inertia tensor; I ). Тензор инерции это матрица 3х3, которая вычисляется в локальных координатах тела и хранится; а затем, когда требуется, переводится в мировую систему координат ( в случае частого использования, следует хранить и начальный тензор, рассчитанный в локальных координатах тела, и один раз за шаг вычесленный тензор в мировых координатах ). После вычисления в локальных координатах матрицу обычно инвертируют и хранят именно в таком виде. Для перевода в мировую систему координат используется формула:
I-1 = R * Ib-1 * RT;
где R – ориентация тела в мировой системе координат, Ib – тензор инерции, рассчитанный в локальной системе координат тела.

[добавить про формулы для примитивов - сфера, капсула, бокс, ... и рассказать про метод Mirtich'а]

Для управления телом требуется создать несколько методов, с помощью которых можно применить силу к телу. Неплохо бы сделать применение сил как в глобальной, так и в локальной системах координат. Так же, для более быстрого влияния на движение тел необходимо сделать приложение импульсов ( impulse; p ). В классической механике, импульс равен произведению массы тела на его скорость, p = m * v. Приложение так же необходимо сделать в двух координатных системах. Модифицировать напрямую положение/ориентацию тела не следует, так как это повлечет за собой сильные визуально заметные неточности в моделировании.

Вот как это выглядит примерно в C++:

/***************************************
  Заголовок
***************************************/
// Базовый класс для АТТ
class RigidBody
{
public:

  // Положение тела
  Vec3 x;
  // Матрица ориентации и транспонированная матрица ориентации
  Mat33 R, R_T;
  // Кватернион, содержащий ориентацию
  Quat Q;

  // Скорости: линейная и угловая
  Vec3 v, w;
  
  // Сила и вращающий момент
  Vec3 F, T;     

  // Инвертированный тензор инерции ( I^-1 ): система координат тела [Ib_1] и мировая система координат [I_1]
  Mat33 Ib_1, I_1;
  // Масса тела
  float m;

  RigidBody(float _m): x(0), v(0), w(0), F(0), T(0), m(_m)
  {
  }

  // Применение силы
  //  Point - точка приложения силы
  //  Force - вектор силы

  // Мировая система координат ( WCS - world coordinate system )
  void ApplyForceWCS(const Vec3 &Point, const Vec3 &Force);
  // Система координат тела ( BCS - body coordinate system )
  void ApplyForceBCS(const Vec3 &Point, const Vec3 &Force);

  // Построить R, R_T по пересчитанному кватерниону Q, а затем пересчитать I_1 ( т. к. ориентация тела поменялась - предполагается )
  void UpdateOrientation();

  // Обнулить аккумуляторы тела ( сил и вращающих моментов )
  void ZeroAccums();

  // Посчитать тензор инерции для тела, чисто виртуальная функция
  // т. к. это зависит от типа тела
  virtual void CalcInertia() = 0;
};

// Производный класс, реализующий конкретный тип твердого тела - сферу
class RigidSphere : public RigidBody
{
public:

  float Rad;    // Радиус сферы

  RigidSphere(float _m, float _Rad): RigidBody(_m), Rad(_Rad)
  {
  }
  ~RigidSphere()
  {
  }

  // Функция для рассчета тензора инерции
  void CalcInertia();
};


/***************************************
  Реализация
***************************************/
void RigidBody::ApplyForceWCS(const Vec3 &Point, const Vec3 &Force)
{
  F += Force;
  // T = r x F
  T += Vec3::Cross((Point - x), Force);
}

void RigidBody::ApplyForceBCS(const Vec3 &Point, const Vec3 &Force)
{
  // Сила в мировой системе координат
  Vec3 wcsForce(R * Force);

  F += wcsForce;
  // Вычисление момента ( точка в BCS - нада только умножить на R чтоб получить P_wcs - x )
  T += Vec3::Cross(R * Point, wcsForce);
}

void RigidBody::UpdateOrientation()
{
  // Перевод кватерниона в матрицу
  R = Quat::ToMatrix(Q);
  // Транспонирование
  R_T = ~R;

  // Вычисление тензора инерции
  I_1 = R * Ib_1 * R_T;
}

void RigidBody::ZeroAccums()
{
  F = NULL_VEC;
  T = NULL_VEC;
}

void RigidSphere::CalcInertia()
{
  Mat33 Ib;

  // В диагонали тензора (2 / 5) * m * R^2
  Ib.v[0][0] = Ib.v[1][1] = Ib.v[2][2] = 0.4f * m * sqrf(Rad);
  // Инвертирование матрицы
  Ib_1 = !Ib;
}

Страницы: 1 2 Следующая »

#dynamics, #физика, #rigid body

29 ноября 2007 (Обновление: 9 дек. 2007)

Комментарии [16]