2013-10-15 2 views
0

J'ai un système de particules de base en JavaScript (en utilisant canvas pour le rendu), et j'essaie de trouver la meilleure façon de gérer les collisions entre particules. Le système de particules peut traiter environ 70 000 particules à un FPS assez décent.Traitement des collisions dans un système de particules JavaScript/canvas

Il s'agit d'un tableau contenant tous les objets Particle. Chaque objet Particle contient 3 objets Vector (un pour le déplacement, la vélocité et l'accélération) contenant une variable x et une variable y. Avant chaque trame, des vecteurs d'accélération sont appliqués aux vecteurs de vitesse, et des vecteurs de vitesse sont appliqués aux vecteurs de déplacement pour chaque objet Particule. Le moteur de rendu parcourt ensuite chaque particule, puis dessine un carré de 1 x 1 pixel à l'emplacement de chaque vecteur de déplacement. Le système de particules possède également des champs «magnétiques» qui peuvent provoquer l'accélération/l'éloignement des particules à partir d'un point donné. J'ai essayé d'appliquer un champ «magnétique» à chaque particule, mais les calculs que j'utilise pour obtenir les vecteurs d'accélération mis à jour pour chaque particule sont trop inefficaces, et cette méthode a considérablement réduit le FPS.

est sous le code que j'utilise pour recalcule vecteurs d'accélération des particules, par rapport à des champs magnétiques à proximité (Cette fonction est appelée avant chaque image):

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); 
} 

Il est évident pourquoi la méthode ci-dessus réduit la performance de manière drastique - le nombre de calculs augmente exponentiellement avec chaque nouvelle particule ajoutée. Y at-il une autre méthode de détection de collision de particules qui aura de bonnes performances avec des milliers de particules? Ces méthodes fonctionneront-elles avec ma structure d'objet actuelle?

+1

Les systèmes de particules en eux-mêmes sont très gourmands en ressources et si vous faites en plus la détection de collision de particules de 70k +, j'ai peur que JavaScript ne vous aide beaucoup. Même avec des macro-optimisations (qui peuvent être importantes dans un cas comme celui-ci), vous verrez une lutte pour la performance. Typiquement, ces choses sont faites en utilisant un code de bas niveau (assembleur ou c/C++) combiné avec des cartes 3D accélérées matériellement - événement alors parfois les choses doivent être rendues (ce qui est normal dans le monde de la vidéo professionnelle). Vous pouvez évaluer si vous êtes prêt à faire un compromis sur le nombre de particules que je pense est la meilleure chance .. – K3N

+0

Si possible, je vous suggère de nous fournir un violon avec lequel nous pouvons jouer et faire des optimisations avec et nous peut voir ce que le résultat sera à partir de là (même si elle va varier en fonction de la configuration matérielle) – K3N

Répondre

1

Ne pas créer un nouveau vecteur ici. Cela signifie que vous créez 70 000 nouveaux vecteurs à chaque image. Il suffit de changer les valeurs de vecteur:

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

Si cela ne permet pas assez, vous devrez utiliser un WebWorker.

Questions connexes