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

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-21 13:12:43 +01:00
parent 87406875ad
commit 123e3ad7c1
2 changed files with 122 additions and 98 deletions
@@ -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);
w = h = (na.r+nb.r);
dx = na.p.position.x - nb.p.position.x;
dy = na.p.position.y - nb.p.position.y;
full_rad = _nodes[n].r + _nodes[q].r + margin;
// 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 not colliding skip following
if(d > full_rad) 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;
// 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);
na.p.velocity.y = newVelY1;
nb.p.velocity.y = newVelY2;
_nodes[n].p.velocity.x = newVelX1;
_nodes[n].p.velocity.y = newVelY1;
_nodes[q].p.velocity.x = newVelX2;
_nodes[q].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;
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);
}
}
@@ -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);
w = h = (na.r+nb.r);
dx = na.p.position.x - nb.p.position.x;
dy = na.p.position.y - nb.p.position.y;
full_rad = _nodes[n].r + _nodes[q].r + margin;
// 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 not colliding skip following
if(d > full_rad) 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;
// 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);
na.p.velocity.y = newVelY1;
nb.p.velocity.y = newVelY2;
_nodes[n].p.velocity.x = newVelX1;
_nodes[n].p.velocity.y = newVelY1;
_nodes[q].p.velocity.x = newVelX2;
_nodes[q].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;
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);
}
}