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

Физический движок. Идентификатор контакта. Точки взаимодействия тел

#0
11:45, 28 окт. 2018

Доброго времени суток!
Пишу физ двиг для выпуклых многоугольников, на данном этапе работает сносно и я постепенно перехожу к оптимизации.
Образовалось несколько вопросов:
-для warstarting мы ищем контакты с прошлой итерации, но всё-таки контакт можно считать тем же, если совпадают тела или тела и нормаль?
-точек взаимодействия может быть 2, если многоугольник лежит плашмя, решаем импульсы для каждой из них или сводим 2 к одной?
-принимаю за точки взаимодействия те, что лежат внутри многоугольника с "наименьшей" нормалью. Взял у Randy Gaul, правильный ли подход?

скрин | Физический движок. Идентификатор контакта. Точки взаимодействия тел

#1
16:51, 28 окт. 2018

aptem336
> -для warstarting мы ищем контакты с прошлой итерации, но всё-таки контакт можно
> считать тем же, если совпадают тела или тела и нормаль?
должны как минимум либо почти совпадать либо точка и нормаль, либо совпадать фичи (например, номер ребра на одном теле и треугольника на другом)
aptem336
> -точек взаимодействия может быть 2, если многоугольник лежит плашмя, решаем
> импульсы для каждой из них или сводим 2 к одной?
в 2д необходимо 2 точки контакта, в 3д обычно обходятся четырьмя точками

aptem336
> -принимаю за точки взаимодействия те, что лежат внутри многоугольника с
> "наименьшей" нормалью. Взял у Randy Gaul, правильный ли подход?
>
я не знаю, что это значит, поясни.

#2
18:46, 28 окт. 2018

Suslik
> я не знаю, что это значит, поясни.
для поиска коллизий использую ТРО, следовательно находим проекции на каждую ось каждого полигона. Та ось, пересечение проекций на которую наименьшее, используется для дальнейших вычислений.
Ребро давшее эту ось называем reference face, ребро зашедшее внутрь и при этом наиболее параллельное к reference называем incident face.
Точки взаимодействия будут находиться на incident face, но для начала нужно обрезать его сначала используя крайние точки refence face слева и справа (1-2), а затем используя саму refence face (3), то бишь внутри refence полигона
точки | Физический движок. Идентификатор контакта. Точки взаимодействия тел
Наверху скрины из программы, может быть там даже понятнее будет
Такое способ заслуживает быть?
После решаю импульсы для найденных точек одной или двух

for (int i = 0; i < contactPointCount; i++) {
     double dLambda = calcLambda(linearA, linearB, angularA.getValue(), angularB.getValue(), dstVelocity[i], i) / contactPointCount;
     if (dLambda + accumLambda[i].getValue() < 0d) {
        dLambda = -accumLambda[i].getValue();
     }
     applyImpulse(linearA, linearB, angularA, angularB, dLambda, i);
     accumLambda[i].plus(dLambda);
}
protected double calcLambda(Vector linearA, Vector linearB, double angularA, double angularB, double distanseVelocity, int num) {
    double lambda = 0;
    lambda -= Vector.dotProduct(normal, linearA);
    lambda += Vector.dotProduct(normal, linearB);
    lambda -= raCrossN[num] * angularA;
    lambda -= rbCrossN[num] * angularB;
    lambda -= distanseVelocity;
    return lambda * invSumInvMass[num];
}
protected void applyImpulse(Vector linearA, Vector linearB, MutableDouble angularA, MutableDouble angularB, double lambda, int num) {
     linearA.plus(linearProjectorA, lambda);
     linearB.plus(linearProjectorB, lambda);
     angularA.plus(lambda * angularProjectorA[num]);
     angularB.plus(lambda * angularProjectorB[num]);
}
при этом предварительно для каждой точки нахожу всяческие "ангулярные" параметры и все от них зависящее
for (int i = 0; i < contactPointCount; i++) {
     raCrossN[i] = Vector.crossProduct(Vector.getDiff(contactPoint[i], a.centerMass), normal);
     rbCrossN[i] = -Vector.crossProduct(Vector.getDiff(contactPoint[i], b.centerMass), normal);

     angularProjectorA[i] = raCrossN[i] * a.iInertia;
     angularProjectorB[i] = rbCrossN[i] * b.iInertia;

     invSumInvMass[i] = 1d / (a.iMass + b.iMass + raCrossN[i] * raCrossN[i] * a.iInertia + rbCrossN[i] * rbCrossN[i] * b.iInertia);
}
Мне не очень нравится этот подход с циклами и делением импульса на количество точек, может быть есть альтернатива?
Надеюсь я понятно изложил)
#3
1:44, 29 окт. 2018

aptem336
> Такое способ заслуживает быть?
такой способ работает только для многоугольников и только для 2д. например, для 3д эллипсоидов он работать не будет. ещё он неустойчив относительно тесселяции многоугольника — например, если добавить лишних точек на гранях кубов(такое случается, если геометрии составляются из кусков), то он выдаст другой результат, что неправильно.

#4
4:21, 29 окт. 2018

aptem336
> для поиска коллизий использую ТРО, следовательно находим проекции на каждую ось
> каждого полигона. Та ось, пересечение проекций на которую наименьшее,
> используется для дальнейших вычислений.
> Ребро давшее эту ось называем reference face, ребро зашедшее внутрь и при этом
> наиболее параллельное к reference называем incident face.
> Точки взаимодействия будут находиться на incident face, но для начала нужно
> обрезать его сначала используя крайние точки refence face слева и справа (1-2),
> а затем используя саму refence face (3), то бишь внутри refence полигона
А не легче просто ось с наименьшем проникновениям ,
то бишь ось коллизии (зелёный вектор ) просто немного наклонить в одну сторону ( в право ) на епсилон и взять самую дальнюю точку в этом направлении  ,
а потом наклонить ось (зелёный вектор ) в другую сторону на епсилон  (на лево ) и взять самую дальнюю точку уже в это направлении , все это сделать для квадрата .
Потом перевернуть ось ( зеленый вектор ) в другую сторону (axis = -axis) и сделать тоже самое для треугольника ,,,
а для коллизии брать все етеже точки спроецированные с одного тела на другое  ,
ну то бишь сделать AxisRoatation только в 2Д,,!?

#5
11:24, 29 окт. 2018

werasaimon
Нарисуй молю, я читал в статье Suslika про это, но так и не понял) туповат видимо

#6
11:28, 29 окт. 2018

Suslik
Ладно, пусть найду точки не важно каким способом, если их будет две, то как решать импульсы? Так и делить на количество точек найденный импульс? Или как-то пограмотнее всё-таки?

#7
11:29, 29 окт. 2018

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

#8
13:57, 29 окт. 2018

Suslik
То есть каждая точка это отдельный контакт?

#9
19:54, 29 окт. 2018

aptem336
> То есть каждая точка это отдельный контакт?
Да..! То есть тебе решать солвер для всех точек контакта

#10
20:20, 29 окт. 2018

werasaimon
Понял, благодарю

#11
23:10, 29 окт. 2018

aptem336
Те точки которые ты находиш не совсем правильные , их надо ещё спроецировать на контактную фичу другого тела !
Кароче найди просто глубину проникновения для каждой кнтактной точки в противопожарное тело , и всё поймёшь!

#12
23:26, 29 окт. 2018

werasaimon
Допустим спроецирую, и они окажутся на ребре квадрата, но чем ребро квадрата «лучше» ребра треугольника? Тем, что оно дало нормаль с минимальным проникновением? Чувствую, что что-то недогоняю)

#13
1:30, 30 окт. 2018

aptem336
> Допустим спроецирую, и они окажутся на ребре квадрата, но чем ребро квадрата
> «лучше» ребра треугольника? Тем, что оно дало нормаль с минимальным
> проникновением?
Да именно этим... ! Это тебе даст более стабильное ришения солвера .
Можеш для теста взять стек и 10-20 квадратов, и увидишь что без прецирования стек рано или позно упадёт и за ошыбок интегрирования, с проецированием будет намного лутше !

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

Тема в архиве.

Тема закрыта.