Vec3 минимального размера, который перемещает физический объект, чтобы сделать проникновение = 0 - PullRequest
5 голосов
/ 21 мая 2019

Вот пример (см. Изображение): -

  • 2 красноватых прямоугольника являются статическими объектами (т.е. он не может двигаться).
  • Голубоватый шар - это динамический объект.

Пока мне удается получить всю проникающую информацию.Давайте рассмотрим это как наш ввод: -

  • Чтобы разрешить проникновение между A и мячом, я могу переместить шар либо на Vec3(1,0,0) ИЛИ Vec3(0,2,0).
  • Чтобы разрешить проникновение между B и мячом, я могу переместить мяч на Vec3(0,1,0).

^ Я сохраняю его как двумерный массив Vec3 problem = {{Vec3{1,0,0},Vec3{0,2,0}},{Vec3{0,1,0}}}.

Как найти наилучшее движение (минимальный размер) физического объекта (например, шара)в примере), чтобы минимизировать как можно большее проникновение?

Лучшее решение в этом примере - «переместить шар на Vec3(1,1,0): размер = 1,414».

enter image description here

В реальном случае ситуация может быть более сложной и безобразной,
например, возможно, что и A & B (и другиеФизика объекта) попробуйте толкнуть мяч в почти противоположном направлении.(изображения ниже)

enter image description here

^ В некоторых сценах двумерный массив problem может не обладать некоторыми деталями, но для простоты, давайте представим, что это объясняет всю информацию точно.

C ++ Код

Вот мой MCVE (coliru) : -

#include<iostream>
#include <utility>
#include <vector>
#include <array>
#include <math.h>

using Vec3=std::array<float, 3>;
float dotProduct(Vec3 vec1,Vec3 vec2){
    return vec1[0]*vec2[0]+vec1[1]*vec2[1]+vec1[2]*vec2[2];
}
float size2(Vec3 vec1){
    return vec1[0]*vec1[0]+vec1[1]*vec1[1]+vec1[2]*vec1[2];
}
Vec3 mulFloat(Vec3 vec1,float m){
    return Vec3{vec1[0]*m,vec1[1]*m,vec1[2]*m};
}
Vec3 normalize(Vec3 vec1){
    return mulFloat(vec1,1/sqrt(size2(vec1)));
}

Вот main(): -

int main() {
    std::vector<std::vector<Vec3>> problem;
    std::vector<Vec3> location1;
    location1.push_back(Vec3{0,2,0});
    location1.push_back(Vec3{1,0,0});
    problem.push_back(location1);
    std::vector<Vec3> location2;
    location2.push_back(Vec3{0,1,0});
    problem.push_back(location2);
    //^ INPUT
    //----- insert YOUR ALGORITHM here  ------
    Vec3 solution=Vec3{0,2,0};

    float totalResidual=0;
    for(auto& location : problem){
        float residualRemainMin=1000000;//numerical limit
        for(auto& orgResidual : location){
            Vec3 orgResidualNormalize=normalize(orgResidual);
            float orgResidualSize=sqrt(size2(orgResidual));
            float residualModifyBy=-dotProduct(orgResidualNormalize,solution);//#1
            //"residualModifyBy" is usually negative
            float remainResidual=std::max(0.0f,orgResidualSize+residualModifyBy);
            //^ "max" because it has no advantage to reduce residual to < 0
            residualRemainMin=std::min(residualRemainMin,remainResidual);
            //^ "min" because the "OR" word
        }
        totalResidual+=residualRemainMin;
    }
    std::cout<<"totalResidual="<<totalResidual;
    return 0;
}

Примечание (#1) в коде: остаток уменьшается на dotProduct(solution,normalize(orgResidual) ).
Мой вывод этой формулы происходит из этого изображения: -
enter image description here

Примечание:

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

Мне просто нужна инструкция;Я не возражаю против ответа без кода.

Редактировать (29 июня 2019 г.)

Больше тестов: -

{{(0,3,0)},{(2,2,0)}}            ===> (1,3,0)       
{{(0,1,1),(10,0,0)},{(0,2,3)}}   ===> (0,2,3)  
{{(99,1,0),(99,-1,0),(100,0,0)}} ===> (99,1,0) OR (99,-1,0)    (equally good)

1 Ответ

0 голосов
/ 21 мая 2019

Я думаю, что реализация, которая дает вам правильный / лучший ответ только на шаге, будет очень сложной.

Мой подход будет такой:

  1. , если нет пересечений слюбой из объектов, переместите шар в направлении объектов (не в направлении объектов, уже соприкасающихся) перейти к 0;
  2. обнаружить все недопустимые пересечения с объектами
  3. для каждого пересечения вычислитьнаправление, в котором вам нужно, чтобы шарик двигался, чтобы устранить пересечение (простейший случай - это перемещение по вертикали относительно поверхности объекта на величину глубины пересечения)
  4. перемещайте шарик в направлениях, рассчитанных в 2.
  5. goto 0

Завершение цикла либо в том случае, если положение мяча больше не меняется (или после ограниченного числа итераций)

В первомНапример, это позволит найти лучшее решение за одну итерацию.
Во втором примере мяч будет медленно подниматься вверх в каждой итерации.пока пересечения больше не существует)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...