В Box2D, как мне создать бесконечно колеблющуюся пружину?

Как создать идеальную пружину, которая может неограниченно осциллировать с помощью Box2D?

A b2DistanceJoint работает почти отлично, но в конечном итоге он замедляется до остановки, даже с демпфированием, равным 0. Я думаю, это потому, что b2DistanceJoint не предназначен для создания пружин, а для сохранения расстояния между двумя телами путем коррекции нарушенного расстояния с похожей на пружину поведением. Следовательно, он должен иметь затухание, чтобы в конечном итоге вернуть тела в исходное состояние и остановиться в какой-то момент.

3 голоса | спросил Narek 19 PMpSun, 19 Apr 2015 20:41:38 +030041Sunday 2015, 20:41:38

1 ответ


1

Если вам нужно четко определенное поведение, вы должны подумать о том, чтобы увековечить колебания самостоятельно. Для простоты я предполагаю, что мы работаем с простым spring-mass-damper , где поведение пружины и демпфера инкапсулируется в b2DistanceJoint.

Основная идея состоит в том, чтобы оценить полную энергию (кинетический + потенциал) системы и применить силу, если она ниже определенного порога. Полная энергия системы в любой момент времени определяется выражением:

spring_mass_energy

spring_mass_energy2

где m - масса тела в конце весны, k - коэффициент пружины, а x - смещение от остальной длины. k может быть связано с частотой совместного соединения через уравнение:

spring_coeff

Включение этого и упрощения дает:

spring_mass_energy3

Все переменные с правой стороны можно оценить (с помощью box2d). Как только вы вычислили энергию, сравните ее с разумным пороговым значением. Если он превышает этот порог, то ваша пружина находится под значительным натяжением или сжатием и /или масса имеет высокую скорость; в этом случае нам не нужно ничего делать. Если энергия падает ниже порогового значения, примените небольшую силу dF вдоль оси пружины в направлении перемещения массы.

Вот как я могу реализовать его (в c ++)

/* ... */

b2Body springBody;
b2DistanceJoint spring;
double restLength;
double Ethresh;          //Threshold energy. Set to reasonable value.
double dFM;              //Small force. Set to reasonable value.

// in time loop

/* ... */

/* Assign spring body and distance joint */

double m = springBody.GetMass();
b2Vec2 vel = springBody.GetLinearVelocity();
double vmag = vel.Length();            //Assuming the body is traveling along the spring axis
double w = spring.GetFrequency();
double x = spring.GetLength() - restLength;
double E = 0.5*m*(vmag*vmag + w*w*x*x);

if(E < Ethresh){
    b2Vec2 dF = (vel/vmag)*dFM;
    springBody.applyForce(dF);
}

/* ... */

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

ответил NauticalMile 20 AMpMon, 20 Apr 2015 03:57:42 +030057Monday 2015, 03:57:42

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132