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

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

Страницы: 129 30 31 32 33 34 Следующая »
#465

А ты вращаеш ось w1 за первым телом, а  ось w2 за вторым.
Типа такого
w1 *= QuternionBody1
w2 *= QuternionBody2
......?

25 дек. 2018, 23:22

#466

После 10 часов дебага, выяснил что проблема в неустойчивости контактной площадки, заменил все на  рейкаст ( решил что дорогу все таки пока-что сделаю тримешем, объектов много не планирую) и проблема прошла.

Я тут уже спрашивал, но ответа тогда не последовало.
Как сделать полноценную пружину?

https://gamedev.ru/code/forum/?id=235421&page=23#m344


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

Якобиан для  пружины устанавливается так:

void setupSpring(
    Jacobian& j,
    const vec3& SpringAxis, //Ось пружины
    const vec3& worldPos1,  //точка прикрепления тела один к пружине
    RigidBody* body1,
    const vec3& worldPos2,  //точка прикрепления тела два к пружине
    RigidBody* body2,
    const float& defL //положение равновесия
  )  
  {
    float p = dot(SpringAxis, worldPos1 - worldPos2);

    float d = p - defL; // d - величина отклонения от положения равновесия

    j.n1 = -SpringAxis;
    j.n2 =  SpringAxis;
    j.depth = d;
    j.w1 = cross(j.n1, body1->getWorldPosition() - worldPos1);
    j.w2 = cross(j.n2, body2->getWorldPosition() - worldPos2);
  }
Решается он так:
void solveJointSpring(Jacobian& j, const float& dT)
  {
    float a = dot(j.n1, _body1->_linearVelosity) + dot(j.w1, _body1->_angularVelosity) +
            dot(j.n2, _body2->_linearVelosity) + dot(j.w2, _body2->_angularVelosity);

    float b = dot(j.n1, j.n1) * _body1->_invMass + dot(j.w1, j.w1) * _body1->_invInertia +
            dot(j.n2, j.n2) * _body2->_invMass + dot(j.w2, j.w2) * _body2->_invInertia;


    float l = (j.depth * _maxFrequency - a) / b;

    l = min(abs(l), _rigidityKoef * abs(j.depth) * dT) * sign(l);

    _body1->_linearVelosity += j.n1 * _body1->_invMass * l;
    _body2->_linearVelosity += j.n2 * _body2->_invMass * l;

    _body1->_angularVelosity += j.w1 * _body1->_invInertia * l;
    _body2->_angularVelosity += j.w2 * _body2->_invInertia * l;
  }

Я правильно посчитал?

5 янв. 2019, 14:20

#467

vindast
> Я правильно посчитал?
похоже на правду. когда отлаживаешь, отлаживай так:
сначала установи _maxFrequency -> inf, _rigidityCoef = x; при этом пружина должна себя вести как обычная пружина по закону гука с жёсткостью x. далее попробуй _maxFrequency = x, rigidityCoef -> inf. при этом пружина должна возвращаться по асимптоте к положению равновесия без колебаний вообще.

ну или видео выложи, что у тебя не так работает.

UPD: а, чуть не забыл. вот эта формула:

 l = min(abs(l), _rigidityKoef * abs(j.depth) * dT) * sign(l);
должна ограничивать полный импульс в пружине. а ты фактически ограничиваешь дельту. то есть у тебя результат будет зависеть от количества итераций солвера в пределе, хотя такого быть не должно. короче, нормально это можно записать, только реализовав нормальный warmstarting.

5 янв. 2019, 15:53 (Правка: 15:56)

#468

Suslik
> ну или видео выложи, что у тебя не так работает.
Проблема у меня с камерой а не с автомобильной подвеской)
Для камеры не хватает устойчивости, иногда она резко смещается.


Могу повыкладывать как отрабатывает подвеска с разными значениями. На первый взгляд все ок.

Вармстатинг только для оси пружины понятно как реализовать. Не будет же проблем что он есть только в пружине, а в остальных джоинтах нет?

5 янв. 2019, 16:08

#469

vindast
> Вармстатинг только для оси пружины понятно как реализовать. Не будет же проблем
> что он есть только в пружине, а в остальных джоинтах нет?
звучит, если честно, не очень. я никогда так не пробовал, но что-то мне подсказывает, что что-то упадёт.

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

5 янв. 2019, 16:41

#470

Я явно что-то не так подсчитал.
При _maxFrequency -> inf, _rigidityCoef = x система бесконечно ускоряется.


Пытаюсь прикрутить вармстатинг.

 void solveJointSpring(WJacobian& j, const float& dT)
  {
    float a = dot(j.n1, _body1->_linearVelosity) + dot(j.w1, _body1->_angularVelosity) +
              dot(j.n2, _body2->_linearVelosity) + dot(j.w2, _body2->_angularVelosity);

    float b = dot(j.n1, j.n1) * _body1->_invMass + dot(j.w1, j.w1) * _body1->_invInertia +
              dot(j.n2, j.n2) * _body2->_invMass + dot(j.w2, j.w2) * _body2->_invInertia;
 

    float l = (j.depth * _maxFrequency - a) / b;

    float maxLambda = _rigidityKoef * abs(j.depth) * dT;

    j.accumulatedLambda += l;

    if (abs(j.accumulatedLambda) > maxLambda)
    {
      l += sign(j.accumulatedLambda) * maxLambda - j.accumulatedLambda;
      j.accumulatedLambda = maxLambda * sign(j.accumulatedLambda);
    }

    _body1->_linearVelosity += j.n1 * _body1->_invMass * l;
    _body2->_linearVelosity += j.n2 * _body2->_invMass * l;

    _body1->_angularVelosity += j.w1 * _body1->_invInertia * l;
    _body2->_angularVelosity += j.w2 * _body2->_invInertia * l;
  }

И добавилось это:

void accept()
  {
    acсeptAccumulatedLambda(suspJ);
  }

  void acсeptAccumulatedLambda(WJacobian& j)
  {
    _body1->_linearVelosity  += j.n1 * _body1->_invMass    * j.accumulatedLambda;
    _body1->_angularVelosity += j.w1 * _body1->_invInertia * j.accumulatedLambda;

    _body2->_linearVelosity  += j.n2 * _body2->_invMass    * j.accumulatedLambda;
    _body2->_angularVelosity += j.w2 * _body2->_invInertia * j.accumulatedLambda;
 
  }

Правильно посчитал? Я просто не понял понял ли я логику работы ) ))

6 янв. 2019, 18:06 (Правка: 18:07)

#471

vindast
> При _maxFrequency -> inf, _rigidityCoef = x система бесконечно ускоряется.
это неправильно, потому что джойнт должен просто каждый dt передавать импульс, равный импульсу обычной гуковской пружины.

7 янв. 2019, 1:56

#472

Вот значит как машинка выглядит при f = 5000000000000.0, k =  100000 (я отключил псевдоскорости вдоль оси пружины)

f = 0.5, k = 500000000.0

Тут при увеличении параметров система уже не устойчива.

vindast
> if (abs(j.accumulatedLambda) > maxLambda)
> {
> l += sign(j.accumulatedLambda) * maxLambda - j.accumulatedLambda;
> j.accumulatedLambda = maxLambda * sign(j.accumulatedLambda);
> }
Я тут правильно лямбду ограничил?

7 янв. 2019, 6:06

#473

Я убрал применение накопленного импульса, и вроде все заработало, он стал теперь только  ограничивать суммарный импульс, и зануляется перед входом в солвер. На видео есть только один артефакт, и тот только после взаимодействия со стеной.

f = 10, k = 10000000000

f = 100000000000.0, k = 10000

Можно этим удовлетворится?

7 янв. 2019, 10:21

#474

vindast
> Вот значит как машинка выглядит при f = 5000000000000.0, k =  100000 (я
> отключил псевдоскорости вдоль оси пружины)
проверь, что от увеличения количества итераций солвера, визуально жёсткость пружин не меняется. ещё можешь даже проверить, что [cht]mg = kx[/cht], то есть реально подставь сжатие всех пружин, возьми массу и ускорение свободного падения и сравни.

> Я убрал применение накопленного импульса, и вроде все заработало, он стал теперь только ограничивать суммарный импульс, и зануляется перед входом в солвер.
лол, это значит, что ты считаешь где-то ерунду. в смысле может у тебя пружина и заработает визуально лучше из-за этого, но что-то другое — обязательно упадёт.

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

7 янв. 2019, 10:53 (Правка: 10:56)

#475

Suslik, я из этой формулы рассчитывал жесткость изначально. И это работает. На вид именно так как я жду.

От числа итераций не зависит.

Вернул как было (накопленный импульс применяется, не зануляется):

f = 5000000000.0, k = 80000

Suslik
> при этом пружина должна себя вести как обычная пружина по закону гука с
> жёсткостью x.


Выполняется.

f = 5.0, k = 800000000

Suslik
> далее попробуй _maxFrequency = x, rigidityCoef -> inf. при этом пружина должна
> возвращаться по асимптоте к положению равновесия без колебаний вообще.


Выполняется. Получается что все верно было?

Можно забить тогда.

Встала остро проблема необходимости завести дифференциал. Сейчас колеса на мертво связаны с коробкой.

Если расмотреть дифференциал по отдельности от коробки, то он получается джоинтом трения с коэффициентом от 0 (полностью свободный) до 1 (заваренный) без ограничения импульса связывающим оси колес. Тут в одной статье было описано подобное.

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

Как сделать такую штуку? Я сам не справлюсь.
Очень не хочется моделировать планетарный редуктор в лоб ) )
Такой джоинт должен связать три тела, и для меня это разрыв шаблона.

7 янв. 2019, 11:13 (Правка: 15:24)

#476

vindast
просто делай джойнт на три тела. вместо n1, n2, w1, w2, получается n[3], w[3]. все три n будут равны нулю, поэтому остаются только w. точно так же находишь импульс и применяешь ко всем трём телам. уравнение на угловые скорости в дифференциале такое:
[cht]
\vec e_{\text{engine}} \cdot \vec \omega_{\text{engine}} = \alpha \vec e_{\text{wheels}} (\vec \omega_{\text{wheel1}}+\vec \omega_{\text{wheel2}})
[/cht]
здесь [cht]\vec e_{\text{engine}}[/cht] — ось разрешённого вращения двигателя, [cht] \vec e_{\text{wheels}}[/cht] — ось разрешённого вращения колёс, [cht]\alpha[/cht] — передаточное число. из этого прямым образом берётся массив трёх векторов w[3]. если есть сцепление, то ограничение [cht]|\lambda|<k[/cht].

7 янв. 2019, 16:31

#477

k тут что? Максимальный импульс трения в сцеплении? Я не понял как регулировать степень его свободы.

Я пока пошел делать это )

7 янв. 2019, 17:25 (Правка: 17:29)

#478

Я тут насчитал что:

float a = _gearbox->_angularVelocity - //Тут _angularVelocity  скаляр
              _k * dot(_wheel1->_angularVelosity, _wheel1->getXAxis()) -
              _k * dot(_wheel2->_angularVelosity, _wheel2->getXAxis()); //ось икс - ось вращения колеса

      float b = _gearbox->_invInertia + _k * _k * (_wheel1->_invInertia + _wheel2->_invInertia);

      float l = -a / b;

Вроде эту часть насчитал правильно.

Но тут вроде ошибка:

_gearbox->_angularVelocity += _gearbox->_invInertia * l;
      _wheel1->_angularVelosity  -= _wheel1->_invInertia * l *_wheel1->getXAxis() * _k;
      _wheel2->_angularVelosity  -= _wheel2->_invInertia * l *_wheel2->getXAxis() * _k;

Вышло так что передача короче раза в два чем должна быть.

Руководствовался формулами вот от сюда https://gamedev.ru/code/forum/?id=235421&page=19#m272

7 янв. 2019, 18:30 (Правка: 18:32)

#479

Suslik
> уравнение на угловые скорости в дифференциале такое:
А почему там сумма скоростей? Ведь тогда и получается что скорость вращения вала равна сумме скоростей вращения колес, от туда и разность в длине передачи в два раза (состоянии какого-никакого равновесия)? Нет? Или я что-то путаю?

7 янв. 2019, 18:37 (Правка: 18:42)

Страницы: 129 30 31 32 33 34 Следующая »
ПрограммированиеФорумФизика