Обработка столкновений в системе частиц JavaScript/canvas

У меня есть базовая система частиц в JavaScript (использующая холст для рендеринга), и я пытаюсь найти лучший способ обработки столкновений между частицами. Система частиц может обрабатывать около 70 000 частиц с довольно приличным FPS.

Он состоит из массива, содержащего каждый объект Particle. Каждый объект Particle содержит 3 объекта Vector (по одному для смещения, скорости и ускорения), которые содержат переменные x и y. Перед каждым кадром векторы ускорения применяются к векторам скорости, а векторы скорости применяются к векторам смещения для каждого отдельного объекта Particle. Затем средство визуализации выполняет итерацию по каждой частице, а затем рисует квадрат размером 1x1 пиксель в месте расположения каждого вектора смещения.

Система частиц также имеет «магнитные» поля, которые могут вызывать ускорение частиц по направлению к заданной точке или от нее.

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

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

Particle.prototype.submitToFields = function (fields) {
    // our starting acceleration this frame
    var totalAccelerationX = 0;
    var totalAccelerationY = 0;

    // for each passed field
    for (var i = 0; i < fields.length; i++) {
        var field = fields[i];

        // find the distance between the particle and the field
        var vectorX = field.point.x - this.point.x;
        var vectorY = field.point.y - this.point.y;

        // calculate the force via MAGIC and HIGH SCHOOL SCIENCE!
        var force = field.mass / Math.pow(vectorX*vectorX+vectorY*vectorY,1.5);

        // add to the total acceleration the force adjusted by distance
        totalAccelerationX += vectorX * force;
        totalAccelerationY += vectorY * force;
    }

    // update our particle's acceleration
    this.acceleration = new Vector(totalAccelerationX, totalAccelerationY);
}

Очевидно, почему вышеупомянутый метод резко снизил производительность - количество вычислений растет экспоненциально с каждой добавленной новой частицей.

Существует ли другой метод обнаружения столкновений частиц, который будет хорошо работать с тысячами частиц? Будут ли эти методы работать с моей текущей структурой объекта?


person Sosumi    schedule 15.10.2013    source источник
comment
Системы частиц сами по себе очень требовательны к ресурсам, и если вы дополнительно выполняете обнаружение столкновений более 70 000 частиц, я боюсь, что JavaScript вам не сильно поможет. Даже с макрооптимизациями (что может быть важно в таком случае) вы увидите борьбу с производительностью. Обычно эти вещи создаются с использованием низкоуровневого кода (ассемблера или C/C++) в сочетании с аппаратно-ускоренными 3D-картами — иногда приходится рендерить вещи (что нормально в мире профессионального видео). Вы можете оценить, готовы ли вы пойти на компромисс в количестве частиц, что, я думаю, является лучшим шансом.   -  person    schedule 15.10.2013
comment
Если возможно, я бы посоветовал вам предоставить нам скрипку, с которой мы можем поиграть и провести некоторые оптимизации, и мы сможем увидеть, какой будет результат (даже если он будет варьироваться в зависимости от конфигурации оборудования).   -  person    schedule 15.10.2013


Ответы (1)


Не создавайте здесь новый вектор. Это означает, что вы создаете 70 000 новых векторов в каждом кадре. Просто измените значения вектора:

this.acceleration.x = totalAccelerationX; // or : this.acceleration[0] = totalAccelerationX;
this.acceleration.y = totalAccelerationY; // or : this.acceleration[1] = totalAccelerationY;

Если этого недостаточно, вам придется использовать WebWorker.

person Sebastien C.    schedule 15.10.2013