2
votes

Création d'une grille 2D arbitrairement déformée

Je souhaite déformer une grille 2D en fonction de l'emplacement des masses ponctuelles. La présence de masse, devrait contracter la grille comme suit:

 distorsion

Mais je veux le déformer avec un nombre arbitraire de particules sur la grille.

C'est, pour que je puisse visualiser l'effet de la gravité sur l'espace: déformé l'espace où de grandes masses sont présentes.

Ce que j'ai essayé jusqu'à présent, c'est d'ajuster de manière itérative les bords d'une cellule, en fonction du nombre de particules à l'intérieur. Une cellule contenant de nombreuses particules devrait rétrécir ses bords.

Cependant, le visuel qui en résulte est décevant et ne se présente pas vraiment comme un espace 2D déformé. Je pense que parce que la déformation devrait avoir un effet global, et pas seulement un effet sur une seule cellule?

Quel algorithme puis-je utiliser pour déformer un espace 2D avec des masses de particules?

 tentative


7 commentaires

Avez-vous des contraintes de temps de traitement ou de mémoire? Ou peut-être une estimation approximative du nombre de particules? Une méthode que je peux imaginer est simple mais lente, et une autre est potentiellement rapide mais pourrait être difficile à mettre en œuvre.


Ceci est pour une utilisation interactive, donc devrait certainement fonctionner à 60 Hz ou plus rapide.


D'accord. Je pense que je peux bricoler quelque chose dans les douze prochaines heures. En attendant, quelques questions supplémentaires. La plus petite masse occuperait-elle un pixel ou pourrait-elle occuper une fraction de pixel? Quelle est la résolution d'affichage maximale? Bien que vous ayez mentionné un nombre arbitraire de pixels, y a-t-il une limite pratique au nombre de masses / particules? Pouvons-nous supposer que les masses représentent des sphéroïdes, ou voulez-vous gérer des formes étranges? Auriez-vous la chance de travailler avec OpenGL (ou VTK) ou CUDA, ou simplement l'implémenter pour les cœurs de processeur?


Aussi: voulez-vous une description des «vrais» maths, ou simplement quelque chose qui semble réaliste? À partir de votre profil, je vous vois écrire en C, je vais donc proposer du code C ++; faites-moi savoir si vous voulez qu'il ressemble plus à C qu'à C ++.


Ce n'est pas une simulation basée sur des pixels. Il utilise des vecteurs et est un ordinateur sur CPU, pas GPU. Actuellement, j'utilise jusqu'à 50K particules ou plus, toutes avec la même masse. Vous pouvez essayer la version existante sans distorsion d'espace ici: bram.itch.io/sprinkle- saupoudrer-petite-étoile


Merci. L'application est jolie! Je vais essayer quelques idées et je vous répondrai.


Désolé, j'ai fini par être si fatigué que j'ai eu du mal avec l'implémentation naïve (pour des raisons de démonstration) et je n'ai même pas réussi à l'implémentation rapide. Pour faire court, je pense qu'il existe un moyen rapide de gérer la superposition des forces gravitationnelles de toutes les masses, mais j'ai besoin d'un cerveau plus frais pour l'écrire. Je vous recontacterai dès que je pourrai.


3 Réponses :


1
votes

Je modéliserais le plan 2D comme étant constitué d'un matériau élastique, de sorte que vous puissiez le déformer en appliquant des forces qui simulent le poids d'un objet donné.

Puisque vous souhaitez visualiser un effet physique, je pense qu'une visualisation physique peut être un choix adéquat.

Un moyen relativement simple de simuler un tel comportement élastique consiste à créer un système masse-ressort:

https://en.m.wikipedia.org/wiki/Soft-body_dynamics

Cependant, l'application de ce type de techniques nécessite une bonne compréhension de la physique hookéenne, des ODE, de l'intégration et d'autres éléments mathématiques connexes.


0 commentaires

2
votes

J'ai créé un violon où chaque particule affecte chaque intersection de la grille en fonction de la règle du carré inverse utilisée par la gravité. https://jsfiddle.net/1nrjcsqa/2/

    dx = points[i][0] - x;
    dy = points[i][1] - y;
    d = Math.sqrt(dx * dx + dy * dy);
    f = gravity_force / Math.pow(d, falloff);

Parce que la gravité tombe comme un carré de la distance, les points n'ont un effet visible que sur la grille la plus proche d'eux. Vous pouvez faire en sorte que les points affectent la grille plus loin en réduisant l'atténuation, mais cela ressemblerait moins à la gravité.

Vous devrez peut-être ajuster gravity_force pour que les choses vous semblent bien.


0 commentaires

0
votes

Je publierai quelques suggestions rapides pour le moment, puis j'y reviendrai lorsque je le pourrai.

Bien que vous ayez dit explicitement dans votre message et vos commentaires que cela serait traité sur le CPU, faire cela sur le GPU et utiliser OpenGL pour l'affichage pourrait beaucoup aider. Traiter les effets de dizaines de milliers de points à 60 Hz (~ 16 ms par passage) demande beaucoup à un CPU même s'il a huit cœurs.

Cela dit, quelques réflexions préparatoires:

  • Comme le fait remarquer l'utilisateur aptriangle, la gravité tombe comme le carré de la distance. À une certaine distance, vous pouvez ignorer les effets, d'autant plus que vos objets ont tous la même masse.
  • Étant donné que vous supporteriez un grand nombre de masses, il y a des problèmes de mise à l'échelle tout en maintenant de bons taux de mise à jour pour une interaction et une animation fluide.
  • Votre objectif est la visualisation, ce qui signifie que vous pourrez peut-être prendre des raccourcis vers lesquels une interprétation stricte des mathématiques pourrait autrement vous conduire. En fait, je pense qu'au moins certains raccourcis sont nécessaires pour fonctionner à la vitesse souhaitée.
  • L'itération des masses et de tous les points de quadrillage qu'elles affectent ne conduira probablement pas à une mise à jour graphique attrayante aux vitesses que vous souhaitez.
  • Vous devrez tenir compte de la superposition et des vecteurs de champ . (Je vais ici pour un sens général, pas une terminologie appropriée.) Chaque masse aura un effet sur tout l'espace qui l'entoure. De n'importe quel point de l'espace, il y aura un vecteur pointant vers cette masse, dont la longueur du vecteur représente la force d'attraction. À tout moment dans l'espace, vous additionnerez les vecteurs. Cela peut produire un "point mort" où deux corps différents tirent avec des forces qui s'annulent.
  • Avec de nombreux volumes, la visualisation des lignes de quadrillage courbes peut devenir si compliquée qu'elle déroute plutôt qu'elle n'éclaire l'utilisateur. Imaginez une feuille de caoutchouc extensible avec des milliers de poids en acier qui y sont attachés, parfois avec les poids regroupés: la forme de la surface peut sembler très complexe.
  • Comme l'a écrit Mauricio Cele Lopez Belon, vous pouvez modéliser la surface sous la forme d'un matériau élastique, c'est-à-dire implémenter directement une géométrie de surface «en caoutchouc». À moins d'utiliser CUDA et OpenGL sur le GPU, je ne pense pas que cela fonctionne.
  • Le principal obstacle est le temps de calcul.
  • Pour minimiser le temps de calcul, précalculez autant que possible.
  • Notez que puisque vos masses sont égales, les effets de ces masses à tout décalage donné (dx, dy) sont les mêmes.
  • Bien que les points représentant des masses puissent avoir des emplacements à valeur réelle, tels que (23.32342, -15.38963) ou autre, vous pouvez probablement (et devez probablement) calculer les effets sur une grille basée sur des nombres entiers pour simplifier le calcul.

Compte tenu de tout cela, j'ai à l'esprit une technique rapide qui définit le champ gravitationnel autour de chaque masse comme un morceau de mémoire qui est (plus ou moins) combiné avec une autre mémoire pour produire une carte finale des vecteurs de champ.

Ensuite, il y a la question du dessin. Encore une fois, utiliser OpenGL pour créer une véritable représentation 3D qui est ensuite projetée sur un écran 2D serait ma méthode préférée. OpenGL peut fonctionner sur des graphiques intégrés, et c'est ce que je recommanderais. Sinon, les calculs à effectuer pour modifier le quadrillage 2D en tant que figures 2D pourraient être compliqués.

Cela mis à part, il y a probablement des ajustements supplémentaires, des astuces et des solutions de contournement pour donner quelque chose de raisonnable qui aidera l'utilisateur à visualiser ce qui se passe, mais sans représenter les champs gravitationnels aussi précisément que certains pourraient le souhaiter.

À partir du code initial que j'ai écrit simplement pour montrer une manière lente et moins souhaitable de résoudre le problème, voici un échantillon très approximatif de quadrillages de flexion en les traitant comme des points pouvant être tirés individuellement vers chaque masse. Ce n'est PAS la manière de traiter le quadrillage de manière réaliste; le code a aussi quelques bugs.

 Exemple approximatif de quadrillage plié en masse


2 commentaires

Je pense que vous avez mal compris: j'ai déjà la simulation N-Body en cours d'exécution, avec des dizaines de milliers de particules, bien à moins de 16 ms sur le processeur. La simulation est terminée. Ce que je veux superposer, c'est une visualisation de la façon dont l'espace est déformé par la gravité. youtube.com/watch?v=YiAiEWqxLWg


J'ai compris ça. Calculer comment plier le quadrillage en fonction de tous les points sera difficile à insérer dans les mêmes 16 msec, d'autant plus que je ne suis toujours pas sûr des limites du nombre de masses, de mémoire, de cœurs, etc. Si vous avez un processeur inutilisé cœurs et / ou pourraient se décharger sur le GPU ou des graphiques intégrés aideraient. Si vous avez déjà défini le champ et / ou que vous avez une recherche rapide de point dans un espace à valeur entière ou à valeur réelle, il devrait y avoir un moyen de créer des lignes de quadrillage sous forme de courbes par morceaux nouées ensemble.