Войти
ПрограммированиеФорумФизика

Помогите написать физический движок :) (36 стр)

Страницы: 132 33 34 35 36 37 Следующая »
#525
(Правка: 12:28) 12:27, 20 мар. 2019

vindast
я не вижу никаких проблем с жёсткостью солвера. и проблема точно не из-за псевдоскоростей. если ты про сгибающиеся оси у колёс, то проблема чисто из-за недостаточно высокой частоты обновления. так как 120Гц — это уже достаточно высокая скорость, имеет смысл задуматься о том, чтобы в твоём случае сделать частоту обновления физики для разных объектов разной. ни одно тело за один такт физики не должно пролетать расстоение, больше (грубо) 5% своего характерного размера и не должно поворачиваться на угол больше 2*pi*5%. но вообще на таких скоростях не удивительно, что у тебя начинаются проблема с честным расчётом колёс. у рейкаста такой проблемы нет, потому что лучи не вращаются.


#526
(Правка: 17:58) 16:51, 20 мар. 2019

Suslik, идею я понял, но вот что делать если вдруг соприкоснулись тела у которых разные частоты обновления? Ну на пример у машины с ее элементами 1500 герц, у коробки на дороге 60 герц.
Оба считать по 1500  герц?

Suslik
> но вообще на таких скоростях не удивительно, что у тебя начинаются проблема с
> честным расчётом колёс. у рейкаста такой проблемы нет, потому что лучи не
> вращаются.

Да блин, все равно есть ощущение что я не правильно сделал петельное соединение.

#527
22:44, 20 мар. 2019

vindast
Посмотрел видео с канала, очень классно. По каким материалам работаете с коллизией? Книги/статьи? Можете скинуть, очень поможет)

#528
(Правка: 5:25) 5:19, 21 мар. 2019

sampl_e
> По каким материалам работаете с коллизией?
Можешь начинать от сюда. https://gamedev.ru/code/forum/?id=235421&page=25

Suslik, сделал я тут ассиметричный тензор инерции. Ты кубики хочешь сталкивать?

float getInvInertialMoment(const vec3 point, const vec3 axis) const
  {
    //Проекция направления в собственные координаты тела
    vec3 axisProj = projectVector(axis);

    //Коэффициент масштабирования относительно основных моментов инерции
    float scaleK = 1.0f 
          / (
             axisProj.x * axisProj.x / (_Inertia.x *_Inertia.x)
             + axisProj.y * axisProj.y / (_Inertia.y *_Inertia.y)
             + axisProj.z * axisProj.z / (_Inertia.z *_Inertia.z)
          );

    //d - расстояние от оси до центра тела
    float d = length(cross(_WorldPosition - point, axis)) / length(axis);
    float i = length(axisProj * sqrt(scaleK)) + d * d * _mass;

    return 1.0f / i;
  }

Все работает отлично если убрать теорему штайнера. Что я не так сделал? Она вообще применяется? Я наверное туплю с тем, что тут и сам джоинт должен меняться.

#529
5:29, 21 мар. 2019

vindast
тебе нужна теорема штейнера в тензорном виде, она выглядит не так.

#530
(Правка: 5:36) 5:35, 21 мар. 2019

Блин. Жесть. Нашел статью на википедии.  Придется разбираться что такое тензор.

#531
(Правка: 6:12) 6:10, 21 мар. 2019

Suslik, если я правильно все понял:

float getInvInertialMoment(const vec3 point, const vec3 axis) const
  {
    //Проекция направления в собственные  координаты тела
    vec3 axisProj = projectVector(axis);
    
    vec3  a = point - _WorldPosition; //Вектор смещения относительно центра масс
    float l = length(_WorldPosition - point);

    //Перерасчитаный эллипсойд инерции 
    vec3 currentInertia = _Inertia + _mass * vec3(l * l - a.x * a.x, l * l - a.y * a.y, l * l - a.z * a.z);

    //Коэффициент масштабирования относительно основных моментов инерции
    float scaleK = 1.0f 
          / (
                axisProj.x * axisProj.x / (currentInertia.x * currentInertia.x)
             + axisProj.y * axisProj.y / (currentInertia.y * currentInertia.y)
             + axisProj.z * axisProj.z / (currentInertia.z * currentInertia.z)
          );

    return 1.0f / length(axisProj * sqrt(scaleK));
  }

Правильно? По ощущению работает как надо.

#532
6:25, 21 мар. 2019

vindast
там вообще нигде не должно быть ни функций sqrt, ни length, если я правильно понимаю. должны быть только векторные и тензорные произведения.

#533
(Правка: 16:45) 15:37, 21 мар. 2019

Suslik, перечитал википедию, а там эта задача уже решена:

осевой момент инерции | Помогите написать физический движок :) (1).

Без учета теоремы Штейнера будет так:

float getInvInertialMoment(const vec3 point, const vec3 axis) const
  {
    //Проекция направления в собственные  координаты тела
    vec3 axisProj = normalize(projectVector(axis));

    float i = _Inertia.x * axisProj.x * axisProj.x + _Inertia.y * axisProj.y * axisProj.y + _Inertia.z * axisProj.z * axisProj.z;

    return 1.0f / i;
  }

теорема штейнера в тензорной форме | Помогите написать физический движок :) (2)

Если я правильно понял, для теоремы Штейнера нужно:

Мне из моего тензора инерции (_Inertia это его диагональ) нужно получить новый тензор, по формуле 2.
Затем мне нужно получить собственные числа этого тензора. (Можно ли проще? Без собственных чисел)
Затем мне нужно по формуле 1 получить инерцию.

Только вот Вы говорили про векторное произведение, но я так и не понял при чем оно тут  )

#534
22:04, 21 мар. 2019

upd.
билиненйное представление | Помогите написать физический движок :)
А можно же сразу посчитать момент смещенного тензора относительно оси в билиненейном представлении, и не искать собственные числа.

#535
(Правка: 1:45) 1:37, 22 мар. 2019

Suslik, не работает. Я не могу понять что такое a^2 в формуле два. Так же не могу понять что такое I(i,j). 
I(i,j) - это элементы начального тензора инерции? Ничего что он диагональный?

float getInvInertialMoment(const vec3 point, const vec3 axis) const
  {
    //Проекция направления оси в собственные  координаты тела
    vec3 axisProj = normalize(projectVector(axis));
    
    //a  - вектор смещения относительно центра масс в собсвтенных координатах
    vec3 a   = projectVector(point - _WorldPosition);
    float a2 = length(a);
    a2 *= a2;

    //Начальный тензор инерции, диагональный.
    mat3 inertia(0.0f);
    inertia[0][0] = _Inertia[0];
    inertia[1][1] = _Inertia[1];
    inertia[2][2] = _Inertia[2];

    mat3 currentInertia(0.0f);

    //Перерасчет тензора
    for (int i = 0; i < 3; i++)
    {
      for (int j = 0; j < 3; j++)
      {
        currentInertia[i][j] = inertia[i][j] + _mass * (a2 * (i == j ? 1.0f : 0.0f) - a[i] * a[j]);
      }
    }

    //Перемножение transpose(axis) * currentInertia * axis - билиненейная форма
    //transpose(axis) * currentInertia = c
    float c1 = axisProj[0] * currentInertia[0][0] + axisProj[1] * currentInertia[1][0] + axisProj[2] * currentInertia[2][0];
    float c2 = axisProj[0] * currentInertia[0][1] + axisProj[1] * currentInertia[1][1] + axisProj[2] * currentInertia[2][1];
    float c3 = axisProj[0] * currentInertia[0][2] + axisProj[1] * currentInertia[1][2] + axisProj[2] * currentInertia[2][2];
 
    //c * axis
    float i = c1 * axisProj.x + c2 * axisProj.y + c3 * axisProj.z;
    return 1.0f / i;
  }
Получается слишком мало инерции.
Что я делаю не так?
#536
(Правка: 3:11) 2:39, 22 мар. 2019

Suslik, я проверил правильность самого решения.
Если принять a = vec3(0.0f), то результат вычислений соответствует  _Inertia.x * axisProj.x * axisProj.x + _Inertia.y * axisProj.y * axisProj.y + _Inertia.z * axisProj.z * axisProj.z. То есть дело в (скорей всего )  в этой части:
_mass * (a2 * (i == j ? 1.0f : 0.0f) - a * a[j])

upd: мне начало казаться что все правильно работает, но я не уверен.
upd: у меня возникло подозрение что нужно менять джоинт.

vL и vW угловая и линейная скорость соответственно.

Раньше, на пример, было так: l = -(dot(n, body->vL) + dot(w,body-> vW)) / (dot(n, n) * body->_invM + dot(w, w) * body->_invI)

invI = body->getInvInertialMoment(contactPoint, I);

А сейчас:  l = -(dot(n, body->vL) + dot(w, body->vW)) / (dot(n, n) * body->_invM + invI)

Тут явно что-то не так. Но я не понимаю что. Тут тоже dot(w, w)  нужен?

#537
3:10, 22 мар. 2019

vindast
я не могу чиать этот ужас из кучи индексов. сделай нормальный класс тензора, перегрузи операции вроде умножения на вектор слева и справа, итп. потом проверяй простые случаи вроде плоского тензора инерции и другие случаи с известным и простым решением. ещё я не понимаю, чего ты пытаешься добиться, используя точно рассчитанные тензоры. самый стабильный тензор — сфера, так как не порождает прецесии при вращении. любое отклонение от сферы устойчивости тебе не добавит. поэтому для колёс часто полагают именно сферический тензор.

#538
9:37, 22 мар. 2019

vindast
> перечитал википедию, а там эта задача уже решена
Возможно, следует скачать учебник по теоретической механике.
Именно эта дисциплина изучает всё это безобразие с моментами инерции и как они влияют на вращение тел. При том с практической точки зрения, вопреки своему названию.
Например:
http://stu.sernam.ru/book_stm.php?id=103 со 161 странице и далее.

Вообще для написания физики для собственного движка настоятельно рекомендую хотя бы пролистать всю книгу, чтобы понять, что в ней есть. А лучше прочитать.

Иначе рискуешь начать протаптывать собственную тропинку там, где есть уже проложенное шоссе.

#539
22:39, 24 мар. 2019

Dmitrrr
> Возможно, следует скачать учебник по теоретической механике.
Почитаю на досуге. Тензор уже проверил, все правильно. Ошибка была в другом месте.

Остался вопрос только вопрос:
> в соединения очень легко добавляется эластичность через constraint force mixing
Что это за зверек такой?

Я нашел статью у ODE: http://ode.org/ode-latest-userguide.html#sec_3_8_1

Я так понял, что основная идея в том, чтобы прикладывать силу к телу внутри джоинта, похоже что именно этим способом Вы моделируете пружину. Вроде как там лямбда найдена даже, но я не понял что такое h.

Уровнение контакта. | Помогите написать физический движок :)

Если честно, я до сих пор не понял как был совершен переход от первой строчки ко второй. Я до этого пользовался Вашим решением и все.
Как этот переход был совершен?

Страницы: 132 33 34 35 36 37 Следующая »
ПрограммированиеФорумФизика