Столкнулся с задачей столкновения
От: Glagolev Россия  
Дата: 10.04.08 12:02
Оценка:
Есть 2 объекта:
1. Геометрическая фигура, скажем прямоугольник, который задан 4-мя точками.
2. Даже не фигура а набор точек, т.е. 2-х мерная матрица поверхности, на которой предположим единицей задан твердый участок, а нулями — пустота. И образовать "это" может что угодно.

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

Как вариант я думал о разбиении этого чуда на геометрические примитивы, но уж больно затратная операция выходит. Очень был бы благодарен даже за подсказку в каком направлении думать.
Спасибо.
Re: Столкнулся с задачей столкновения
От: NikeByNike Россия  
Дата: 10.04.08 12:12
Оценка:
Здравствуйте, Glagolev, Вы писали:

Задача не самая тривиальная, в общем случае
Практически — лучше взять уже готовый движок.
Начать можно отсюда: http://code.google.com/p/physics2d/
Нужно разобрать угил.
Re[2]: Столкнулся с задачей столкновения
От: Glagolev Россия  
Дата: 10.04.08 12:30
Оценка:
Здравствуйте, NikeByNike, Вы писали:


NBN>Задача не самая тривиальная, в общем случае

NBN>Практически — лучше взять уже готовый движок.
NBN>Начать можно отсюда: http://code.google.com/p/physics2d/

Спасибо, я обязательно посижжу над его кодом в поисках решения (правда пишу не на си++), но всё-же был бы рад услашать конкретные предложения/алгоритмы/идеи/наводки по решению задачи.
Re[3]: Столкнулся с задачей столкновения
От: o.kostya  
Дата: 10.04.08 13:09
Оценка:
Здравствуйте, Glagolev, Вы писали:

G>Спасибо, я обязательно посижжу над его кодом в поисках решения (правда пишу не на си++), но всё-же был бы рад услашать конкретные предложения/алгоритмы/идеи/наводки по решению задачи.


Подсмотреть можешь здесь
... << RSDN@Home 1.1.3 stable >>
Re[4]: Столкнулся с задачей столкновения
От: Glagolev Россия  
Дата: 11.04.08 10:55
Оценка:
Здравствуйте, o.kostya, Вы писали:

OK>Подсмотреть можешь здесь


Ты пробовал нарисовать там невыпуклую фигуру? Если нет, то попробуй, она просто её не сделает, т.к. расщитать пересечение выпуклого многоугольника очень просто. У меня задача иного плана, да и на плоскости разбивать я бы тоже не хотел.
Re: Столкнулся с задачей столкновения
От: Krovosos  
Дата: 11.04.08 13:39
Оценка: 15 (1)
Здравствуйте, Glagolev, Вы писали:

G>Есть 2 объекта:

G>1. Геометрическая фигура, скажем прямоугольник, который задан 4-мя точками.
G>2. Даже не фигура а набор точек, т.е. 2-х мерная матрица поверхности, на которой предположим единицей задан твердый участок, а нулями — пустота. И образовать "это" может что угодно.

G>Нужно расщитать поведение 1-й фигуры при столкновении об 2-ю, причем желательно более или менее реалистичное столкновение (или хоть образование грамотного вектора выталкивания). Так что она не просто упрется, а начнет скользить, если есть возможность, т.е. узнать силу кручения конечно желательно, но не критично.


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

G>Спасибо.

В свое время я делал игрушку и написал статью на этот счет:

http://gamedev.ru/articles/?id=70124
Re: Столкнулся с задачей столкновения
От: Рома Мик Россия http://romamik.com
Дата: 14.04.08 19:34
Оценка:
Здравствуйте, Glagolev, Вы писали:

G>2. Даже не фигура а набор точек, т.е. 2-х мерная матрица поверхности, на которой предположим единицей задан твердый участок, а нулями — пустота. И образовать "это" может что угодно.

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

Первая часть тебе нужно столкновения не геометрических фигур, что обычно делают в физических движках, а попиксельное. Это не так уж сложно реализовать и не так уж медленно работает. Общая идея, вначале смотришь, пересекаются ли OOB (описывающие прямоугольники вращающиеся вместе с телом, т.е. для спрайта — это просто прямоугольник который получиться если картинку залить одним цветом) спрайтов. Потом в области пересечения OOB проходишься по всем "единицам" одного тела и смотришь нет ли там "единицы" другого тела. Лучше, если разрешение карт столкновений поменьше, тогда и проверять точек можно поменьше.
Вот код, он конечно содержит всякую специфику, но алгоритм из него ясен:
bool Image::CheckCollisions(Rect &pos, Image rImage, Rect &rPos, float * px, float * py)
{
    if(!impl_ || !rImage.impl_)
        return false;
    impl_->MakeCollMap();
    rImage.impl_->MakeCollMap();

// Проверяем AAB
    Rect const &q1 = pos;
    Rect const &q2 = rPos;
    float lx1 = q1.v[0].x, lx2 = q1.v[0].x;
    float ly1 = q1.v[0].y, ly2 = q1.v[0].y;
    float rx1 = q2.v[0].x, rx2 = q2.v[0].x;
    float ry1 = q2.v[0].y, ry2 = q2.v[0].y;
    for(int i = 1; i < 4; ++i) 
    {
        lx1 = std::min(lx1, q1.v[i].x);
        lx2 = std::max(lx2, q1.v[i].x);
        ly1 = std::min(ly1, q1.v[i].y);
        ly2 = std::max(ly2, q1.v[i].y);
        rx1 = std::min(rx1, q2.v[i].x);
        rx2 = std::max(rx2, q2.v[i].x);
        ry1 = std::min(ry1, q2.v[i].y);
        ry2 = std::max(ry2, q2.v[i].y);
    }
    if(lx1 > rx2 || lx2 < rx1 || ly1 > ry2 || ly2 < ry1)
        return false;

// Проходимся по области пересечения AAB, сразу откидывая места, где OOB не пересекаются. 
// Наверное это не самое быстрое, но тогда когда писал, написал так и работает вполне сносно
    int x1 = int(lx1 > rx1 ? lx1 : rx1);
    int x2 = int(lx2 < rx2 ? lx2 : rx2);
    int y1 = int(ly1 > ry1 ? ly1 : ry1) + 1;
    int y2 = int(ly2 < ry2 ? ly2 : ry2) + 1;

    std::vector<bool> &m1 = impl_->record_->collMap_;
    int m1W = impl_->record_->collWidth_;
    int m1H = impl_->record_->collHeight_;
    std::vector<bool> &m2 = rImage.impl_->record_->collMap_;
    int m2W = rImage.impl_->record_->collWidth_;
    int m2H = rImage.impl_->record_->collHeight_;

    int nCollisions = 0;
    for(int y = y1; y < y2; y += 3)
    {
        for(int x = x1; x < x2; x += 3)
        {
            int tx1 = int(((x - q1.v[0].x) * (q1.v[1].x - q1.v[0].x) + 
                (y - q1.v[0].y) * (q1.v[1].y - q1.v[0].y)) * m1W / (q1.w_*q1.w_));
            if(tx1 < 0 || tx1 >= m1W) 
                continue;
            int ty1 = int(((x - q1.v[0].x) * (q1.v[3].x - q1.v[0].x) + 
                (y - q1.v[0].y) * (q1.v[3].y - q1.v[0].y)) * m1H / (q1.h_*q1.h_));
            if(ty1 < 0 || ty1 >= m1H) 
                continue;
            int tx2 = int(((x - q2.v[0].x) * (q2.v[1].x - q2.v[0].x) + 
                (y - q2.v[0].y) * (q2.v[1].y - q2.v[0].y)) * m2W / (q2.w_*q2.w_));
            if(tx2 < 0 || tx2 >= m2W)
                continue;
            int ty2 = int(((x - q2.v[0].x) * (q2.v[3].x - q2.v[0].x) + 
                (y - q2.v[0].y) * (q2.v[3].y - q2.v[0].y)) * m2H / (q2.h_*q2.h_));
            if(ty2 < 0 || ty2 >= m2H)
                continue;

// здесь находится среднее всех от всех точек пересечения, это не всегда то, что надо. 
            if(m1[tx1 + ty1 * m1W] && m2[tx2 + ty2 * m2W])
            {
                if(px) 
                    ((*px *= nCollisions) += 1.f * x) /= nCollisions + 1;
                if(py) 
                    ((*py *= nCollisions) += 1.f * y) /= nCollisions + 1;
                ++nCollisions;
            }
        }
    }
    if(nCollisions)
        return true;
    return false;
}

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

Вторая часть задачи имеет несколько разных вариантов решения. Прочитай ссылку, что дал Кровосос, в принципе там много про нахождение столкновений, а про их обработку несколько более сумбурно, но понять можно. Почитай вообще про физические движки.
Мне в свое время хватило куда более простого, но и менее точного алгоритма: как реагирует тело на приложение к нему силы можно узнать из учебника физики. На каждом шаге, в точках столкновения тела действуют друг на друга по нормали к поверхности выталкивая друг друга константной силой...
Re: Столкнулся с задачей столкновения
От: johny5 Новая Зеландия
Дата: 19.05.08 03:58
Оценка:
Мы в своё время к "набору точек, 2-мерная матрица поверхности", т.е. битмапу отдельно извне подрисовывали окантовывающую форму... Так и быстрее работать будет и вообще ИМХО более универсально — можно рисовать на картинке всякие усики и тени — и это не будет автоматически участвовать в коллизиях.

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

Евгений.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.