Przeglądaj źródła

NEW collsion detection and elastic choc algorythme which works nice with squares

Bachir Soussi Chiadmi 7 lat temu
rodzic
commit
123e3ad7c1

+ 64 - 52
sites/all/modules/figli/edlp_corpus/assets/dist/scripts/corpus.min.js

@@ -8,6 +8,8 @@
  * @License: GPL-V3
  */
 
+// JS performance improvement http://archive.oreilly.com/pub/a/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
+
 /**
   * depends on :
   *
@@ -520,75 +522,85 @@
     // https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
     function checkParticulesCollisions(){
       // pre create vars to save memory;
-      var d, full_rad, margin,
-          newVelX1, newVelY1, newVelX2, newVelY2,
-          makeup, angle;
+      var na,nb,
+          ma,mb,
+          w,h,dx,dy,
+          makeup,
+          newVelX1, newVelY1, newVelX2, newVelY2;
+          // , angle;
       // colisions between _particules
-      for (var n = 0; n < _nodes.length; n++) {
-
+      for (var n = 0, l = _nodes.length; n < l; n++) {
+        na = _nodes[n];
+        ma = na.p.mass;
         // avoid colliding for centered nodes
         // if(_nodes[n].center) continue;
 
         // avoid colliding for scrambling nodes
-        if(_nodes[n].scrambling) continue;
-
-        for (var q = n+1; q < _nodes.length; q++) {
-          if(q===n) continue;
+        if(na.scrambling) continue;
 
+        for (var q = n+1; q < l; q++) {
+          nb = _nodes[q];
+          mb = nb.p.mass;
           // avoid impact between center and aside particules
-          if((_nodes[n].center && _nodes[q].aside) || (_nodes[n].aside && _nodes[q].center))
+          if((na.center && nb.aside) || (na.aside && nb.center))
             continue;
 
-          margin = _nodes[n].center ? 0 : 0; // in px
-
           // avoid impact between two centered particulses that comes to the center
-          if(_nodes[n].center && _nodes[q].center){
-            if(Math.min(_nodes[n].p.distanceTo(_attracter), _nodes[q].p.distanceTo(_attracter)) > 300){
+          if(na.center && nb.center){
+            if(Math.min(na.p.distanceTo(_attracter), nb.p.distanceTo(_attracter)) > 300){
               if( Math.random()>0.3 ) continue;
             }
           }
 
-          d = _nodes[n].p.distanceTo(_nodes[q].p);
-
-          full_rad = _nodes[n].r + _nodes[q].r + margin;
-
-          // if not colliding skip following
-          if(d > full_rad) continue;
-
-          // apply new forces if colliding
-          newVelX1 = (_nodes[n].p.velocity.x * (_nodes[n].p.mass - _nodes[q].p.mass)
-                      + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelY1 = (_nodes[n].p.velocity.y * (_nodes[n].p.mass - _nodes[q].p.mass)
-                      + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelX2 = (_nodes[q].p.velocity.x * (_nodes[q].p.mass - _nodes[n].p.mass)
-                      + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelY2 = (_nodes[q].p.velocity.y * (_nodes[q].p.mass - _nodes[n].p.mass)
-                      + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
+          w = h = (na.r+nb.r);
+          dx = na.p.position.x - nb.p.position.x;
+          dy = na.p.position.y - nb.p.position.y;
+
+          // if both dx and dy are inferior to w & h so squares are colliding (overlapping)
+          // if( Math.abs(dx) <= w && Math.abs(dy) <= h){ console.log('colliding'); }
+          // else not so skip
+          if( Math.abs(dx) > w || Math.abs(dy) > h) continue;
+
+          if(Math.abs(dx) < Math.abs(dy)){ // vertical collision
+            makeup = (h - Math.abs(dy))/2;
+            if(dy > 0){ // a is upper than b
+              na.p.position.y += makeup;
+              nb.p.position.y -= makeup;
+            }else{ // b is upper than a
+              na.p.position.y -= makeup;
+              nb.p.position.y += makeup;
+            }
+            // bounce
+            // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
+            newVelY1 = (ma-mb)/(ma+mb)*na.p.velocity.y+2*mb/(ma+mb)*nb.p.velocity.y;
+            newVelY2 = (mb-ma)/(mb+ma)*nb.p.velocity.y+2*ma/(mb+ma)*na.p.velocity.y;
+
+            na.p.velocity.y = newVelY1;
+            nb.p.velocity.y = newVelY2;
+
+          }else{ // horizontal collision
+            makeup = (w - Math.abs(dx))/2;
+            if(dx > 0){ // a is at left of b
+              na.p.position.x += makeup;
+              nb.p.position.x -= makeup;
+            }else{ // b is at left of a
+              na.p.position.x -= makeup;
+              nb.p.position.x += makeup;
+            }
+            // bounce
+            // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
+            newVelX1 = (ma-mb)/(ma+mb)*na.p.velocity.x+2*mb/(ma+mb)*nb.p.velocity.x;
+            newVelX2 = (mb-ma)/(mb+ma)*nb.p.velocity.x+2*ma/(mb+ma)*na.p.velocity.x;
 
-          _nodes[n].p.velocity.x = newVelX1;
-          _nodes[n].p.velocity.y = newVelY1;
-          _nodes[q].p.velocity.x = newVelX2;
-          _nodes[q].p.velocity.y = newVelY2;
+            na.p.velocity.x = newVelX1;
+            nb.p.velocity.x = newVelX2;
+          }
 
           // slow down particule on impact
-          _nodes[n].p.velocity.multiplyScalar(_nodes[n].center && _nodes[n].p.velocity.length() < 1 ? 1.1 : 0.90);
-          _nodes[q].p.velocity.multiplyScalar(_nodes[q].center && _nodes[q].p.velocity.length() < 1 ? 1.1 : 0.90);
-
-
-          // move particles if they overlap
-          if (d < full_rad) {
-            makeup = (full_rad/2 - d/2)*1.2;
-            angle = Math.atan2(_nodes[q].p.position.y - _nodes[n].p.position.y, _nodes[q].p.position.x - _nodes[n].p.position.x);
-
-            _nodes[q].p.position.x += makeup * Math.cos(angle);
-            _nodes[q].p.position.y += makeup * Math.sin(angle);
-
-            angle += Math.PI;
-
-            _nodes[n].p.position.x += makeup * Math.cos(angle);
-            _nodes[n].p.position.y += makeup * Math.sin(angle);
-
-          }
+          // na.p.velocity.multiplyScalar(na.center && na.p.velocity.length() < 1 ? 1.1 : 0.90);
+          // nb.p.velocity.multiplyScalar(nb.center && nb.p.velocity.length() < 1 ? 1.1 : 0.90);
+          na.p.velocity.multiplyScalar(0.90);
+          nb.p.velocity.multiplyScalar(0.90);
 
         }
       }

+ 64 - 52
sites/all/modules/figli/edlp_corpus/assets/scripts/corpus.js

@@ -8,6 +8,8 @@
  * @License: GPL-V3
  */
 
+// JS performance improvement http://archive.oreilly.com/pub/a/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
+
 /**
   * depends on :
   *
@@ -520,75 +522,85 @@
     // https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
     function checkParticulesCollisions(){
       // pre create vars to save memory;
-      var d, full_rad, margin,
-          newVelX1, newVelY1, newVelX2, newVelY2,
-          makeup, angle;
+      var na,nb,
+          ma,mb,
+          w,h,dx,dy,
+          makeup,
+          newVelX1, newVelY1, newVelX2, newVelY2;
+          // , angle;
       // colisions between _particules
-      for (var n = 0; n < _nodes.length; n++) {
-
+      for (var n = 0, l = _nodes.length; n < l; n++) {
+        na = _nodes[n];
+        ma = na.p.mass;
         // avoid colliding for centered nodes
         // if(_nodes[n].center) continue;
 
         // avoid colliding for scrambling nodes
-        if(_nodes[n].scrambling) continue;
-
-        for (var q = n+1; q < _nodes.length; q++) {
-          if(q===n) continue;
+        if(na.scrambling) continue;
 
+        for (var q = n+1; q < l; q++) {
+          nb = _nodes[q];
+          mb = nb.p.mass;
           // avoid impact between center and aside particules
-          if((_nodes[n].center && _nodes[q].aside) || (_nodes[n].aside && _nodes[q].center))
+          if((na.center && nb.aside) || (na.aside && nb.center))
             continue;
 
-          margin = _nodes[n].center ? 0 : 0; // in px
-
           // avoid impact between two centered particulses that comes to the center
-          if(_nodes[n].center && _nodes[q].center){
-            if(Math.min(_nodes[n].p.distanceTo(_attracter), _nodes[q].p.distanceTo(_attracter)) > 300){
+          if(na.center && nb.center){
+            if(Math.min(na.p.distanceTo(_attracter), nb.p.distanceTo(_attracter)) > 300){
               if( Math.random()>0.3 ) continue;
             }
           }
 
-          d = _nodes[n].p.distanceTo(_nodes[q].p);
-
-          full_rad = _nodes[n].r + _nodes[q].r + margin;
-
-          // if not colliding skip following
-          if(d > full_rad) continue;
-
-          // apply new forces if colliding
-          newVelX1 = (_nodes[n].p.velocity.x * (_nodes[n].p.mass - _nodes[q].p.mass)
-                      + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelY1 = (_nodes[n].p.velocity.y * (_nodes[n].p.mass - _nodes[q].p.mass)
-                      + (2 * _nodes[q].p.mass * _nodes[q].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelX2 = (_nodes[q].p.velocity.x * (_nodes[q].p.mass - _nodes[n].p.mass)
-                      + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.x)) / (_nodes[n].p.mass + _nodes[q].p.mass);
-          newVelY2 = (_nodes[q].p.velocity.y * (_nodes[q].p.mass - _nodes[n].p.mass)
-                      + (2 * _nodes[n].p.mass * _nodes[n].p.velocity.y)) / (_nodes[n].p.mass + _nodes[q].p.mass);
+          w = h = (na.r+nb.r);
+          dx = na.p.position.x - nb.p.position.x;
+          dy = na.p.position.y - nb.p.position.y;
+
+          // if both dx and dy are inferior to w & h so squares are colliding (overlapping)
+          // if( Math.abs(dx) <= w && Math.abs(dy) <= h){ console.log('colliding'); }
+          // else not so skip
+          if( Math.abs(dx) > w || Math.abs(dy) > h) continue;
+
+          if(Math.abs(dx) < Math.abs(dy)){ // vertical collision
+            makeup = (h - Math.abs(dy))/2;
+            if(dy > 0){ // a is upper than b
+              na.p.position.y += makeup;
+              nb.p.position.y -= makeup;
+            }else{ // b is upper than a
+              na.p.position.y -= makeup;
+              nb.p.position.y += makeup;
+            }
+            // bounce
+            // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
+            newVelY1 = (ma-mb)/(ma+mb)*na.p.velocity.y+2*mb/(ma+mb)*nb.p.velocity.y;
+            newVelY2 = (mb-ma)/(mb+ma)*nb.p.velocity.y+2*ma/(mb+ma)*na.p.velocity.y;
+
+            na.p.velocity.y = newVelY1;
+            nb.p.velocity.y = newVelY2;
+
+          }else{ // horizontal collision
+            makeup = (w - Math.abs(dx))/2;
+            if(dx > 0){ // a is at left of b
+              na.p.position.x += makeup;
+              nb.p.position.x -= makeup;
+            }else{ // b is at left of a
+              na.p.position.x -= makeup;
+              nb.p.position.x += makeup;
+            }
+            // bounce
+            // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
+            newVelX1 = (ma-mb)/(ma+mb)*na.p.velocity.x+2*mb/(ma+mb)*nb.p.velocity.x;
+            newVelX2 = (mb-ma)/(mb+ma)*nb.p.velocity.x+2*ma/(mb+ma)*na.p.velocity.x;
 
-          _nodes[n].p.velocity.x = newVelX1;
-          _nodes[n].p.velocity.y = newVelY1;
-          _nodes[q].p.velocity.x = newVelX2;
-          _nodes[q].p.velocity.y = newVelY2;
+            na.p.velocity.x = newVelX1;
+            nb.p.velocity.x = newVelX2;
+          }
 
           // slow down particule on impact
-          _nodes[n].p.velocity.multiplyScalar(_nodes[n].center && _nodes[n].p.velocity.length() < 1 ? 1.1 : 0.90);
-          _nodes[q].p.velocity.multiplyScalar(_nodes[q].center && _nodes[q].p.velocity.length() < 1 ? 1.1 : 0.90);
-
-
-          // move particles if they overlap
-          if (d < full_rad) {
-            makeup = (full_rad/2 - d/2)*1.2;
-            angle = Math.atan2(_nodes[q].p.position.y - _nodes[n].p.position.y, _nodes[q].p.position.x - _nodes[n].p.position.x);
-
-            _nodes[q].p.position.x += makeup * Math.cos(angle);
-            _nodes[q].p.position.y += makeup * Math.sin(angle);
-
-            angle += Math.PI;
-
-            _nodes[n].p.position.x += makeup * Math.cos(angle);
-            _nodes[n].p.position.y += makeup * Math.sin(angle);
-
-          }
+          // na.p.velocity.multiplyScalar(na.center && na.p.velocity.length() < 1 ? 1.1 : 0.90);
+          // nb.p.velocity.multiplyScalar(nb.center && nb.p.velocity.length() < 1 ? 1.1 : 0.90);
+          na.p.velocity.multiplyScalar(0.90);
+          nb.p.velocity.multiplyScalar(0.90);
 
         }
       }