Dart Documentationsystem_verletSystem_Simulator

System_Simulator class

class System_Simulator extends IntervalEntitySystem {
 //ComponentMapper<Particles> _particlesMapper;
 ComponentMapper0 _particlesMapper;
 ComponentMapper0 _constraintsMapper;
 var _constraintss = new List<Constraints>(0);
 int _constraintssL = 0;

 var steps = 10;
 /// eg : gravity
 final globalAccs = new Vector3(0.0, 0.0, 0.0);
 collisions.Space collSpace;
 final double interval; // = 1000.0/30.0;
 double _timestep = -1.0;

 System_Simulator({this.steps : 3, interval0 : 1000.0/30, collisions.Space space0: null}) :
   super(interval0, Aspect.getAspectForAllOf([Particles])),
   interval = interval0,
   collSpace = (space0 != null)? space0 : new collisions.Space_Noop()
   ;

 void initialize(){
   _particlesMapper = new ComponentMapper0(Particles, world);
   _constraintsMapper = new ComponentMapper0(Constraints, world);
 }

 void processEntities(ReadOnlyBag<Entity> entities) {
   var deplacement = new Vector3.zero();
   var accs = new Vector3.zero();
   collSpace.reset();
   //for (var pass = (delta ~/ interval) + 1; pass > 0; --pass) {
   //apply time corrected verlet [TCV](http://lonesock.net/article/verlet.html)
   var dt = delta.toDouble() / 1000.0;
   var timestepPrevious = (_timestep == -1) ?dt : _timestep;
   _timestep = dt  ;
   var timeScale = (_timestep / timestepPrevious);
   var timestep2 = _timestep * _timestep;
   entities.forEach((e){
     var ps = _particlesMapper.get(e);
     if (ps == null) return;
     for (var i = ps.length -1 ; i > -1; --i){
       var position3d = ps.position3d[i];
       var position3dPrevious = ps.position3dPrevious[i];
       // calculate velocity
       deplacement.setFrom(position3d).sub(position3dPrevious).scale(timeScale * ps.inertia[i]);

//        // ground friction
//        if (particles[i].pos.y >= this.height-1 && velocity.length2() > 0.000001) {
//          var m = velocity.length();
//          velocity.x /= m;
//          velocity.y /= m;
//          velocity.mutableScale(m*this.groundFriction);
//        }

       accs.setFrom(globalAccs);
       accs.add(ps.acc[i]);
       // Position Verlet integration
       accs.scale(timestep2);
       deplacement.add(accs);
       // follow http://lolengine.net/blog/2011/12/14/understanding-motion-in-games
       // Velocity Verlet integration
       // vec3 OldVel = Vel;
       // Vel = Vel + Accel * dt;
       // Pos = Pos + (OldVel + Vel) * 0.5 * dt;
       // Pos = Pos + (2 * OldVel + Accel * dt) * 0.5 * dt;
       //forces.scale(_timestep1);
       //deplacement.scale(2.0).add(forces).scale(0.5 * _timestep1);


       // save last good state
       // TODO optim : store future pos in previous and swap previous (with future) and current values in one swap (swap the list), but this optimisation will break existing code that keep vector of position (eg constraint)
       position3dPrevious.setFrom(position3d);
       position3d.add(deplacement);
     }
     collSpace.addParticles(ps);
   });
   // iterate collisions + constraints
   var stepCoef = 1.0/steps;
   //var bodies = maps(entities, _bodiesMapper);
   _updateConstraintss(entities);

   for(int step = 0; step < steps; ++step ) { //Repeat this a few times to give more exact results
//    // bounds checking
//    //TODO define bounds as constraintes
//    for (c in this.composites) {
//      var particles = this.composites[c].particles;
//      for (i in particles)
//        this.bounds(particles[i]);
//    }

     //relax Constraints (include Edge) correction step
     //TODO optimize the loop
     //TODO check if relax should be done in the same loop as collision
     //TODO check if relax should be done once constraint per step or every constraint per step
     for (int i = 0; i < _constraintssL; i++) {
       var c = _constraintss[i];
       c.l.forEach((j) {
         j.relax(stepCoef);
       });
     };
   }

   for(var i = 0; i < _constraintssL; ++i) {
     var cs = _constraintss[i];
     for(var j = 0; j < cs.l.length; ++j) {
       var c = cs.l[j];
       if(c is Constraint_Distance) {
         collSpace.addSegment(c.segment);
       }
     }
   }
   collSpace.handleCollision();

 }

 _updateConstraintss(entities) {
   _constraintssL = 0;
   if (entities.size > _constraintss.length) {
     _constraintss = new List(entities.size);
   }
   for(var i = 0; i < entities.size; i++) {
     var e = entities[i];
     var c = _constraintsMapper.getSafe(e);
     if (c != null) {
       _constraintss[_constraintssL] = c;
       _constraintssL++;
     }
   }
 }

}

Extends

EntitySystem > IntervalEntitySystem > System_Simulator

Constructors

new System_Simulator({steps: 3, interval0: 1000.0/30, Space space0: null}) #

Creates a new Object instance.

Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.

docs inherited from Object
System_Simulator({this.steps : 3, interval0 : 1000.0/30, collisions.Space space0: null}) :
 super(interval0, Aspect.getAspectForAllOf([Particles])),
 interval = interval0,
 collSpace = (space0 != null)? space0 : new collisions.Space_Noop()
 ;

Properties

Space collSpace #

collisions.Space collSpace

final num delta #

inherited from IntervalEntitySystem

Returns the accumulated delta since the system was last invoked.

num get delta => _delta;

final globalAccs #

eg : gravity

final globalAccs = new Vector3(0.0, 0.0, 0.0)

final double interval #

final double interval

final passive #

inherited from EntitySystem
get passive => _passive;

var steps #

var steps = 10

World world #

inherited from EntitySystem
World world

Methods

void added(Entity e) #

inherited from EntitySystem
void added(Entity e) => _check(e);

void begin() #

inherited from EntitySystem

Called before processing of entities begins.

void begin() {}

void changed(Entity e) #

inherited from EntitySystem
void changed(Entity e) => _check(e);

bool checkProcessing() #

inherited from IntervalEntitySystem

Returns true if the system should be processed, false if not.

docs inherited from EntitySystem
bool checkProcessing() {
 _acc += world.delta;
 _delta += world.delta;
 if(_acc >= _interval) {
   _acc -= _interval;
   return true;
 }
 return false;
}

void deleted(Entity e) #

inherited from EntitySystem
void deleted(Entity e) {
 if (_contains(e)) {
   _removeFromSystem(e);
 }
}

void disabled(Entity e) #

inherited from EntitySystem
void disabled(Entity e) {
 if (_contains(e)) {
   _removeFromSystem(e);
 }
}

void enabled(Entity e) #

inherited from EntitySystem
void enabled(Entity e) => _check(e);

void end() #

inherited from IntervalEntitySystem

Resets the accumulated delta to 0.

Call super.end() if you overwrite this function.

void end() {
 _delta = 0;
}

void initialize() #

Override to implement code that gets executed when systems are initialized.

docs inherited from EntitySystem
void initialize(){
 _particlesMapper = new ComponentMapper0(Particles, world);
 _constraintsMapper = new ComponentMapper0(Constraints, world);
}

void inserted(Entity entity) #

inherited from EntitySystem

Called if the system has received an entity it is interested in, e.g. created or a component was added to it.

void inserted(Entity entity) {}

void process() #

inherited from EntitySystem

This is the only method that is supposed to be called from outside the library,

void process() {
 if(checkProcessing()) {
   begin();
   processEntities(_actives.readOnly);
   end();
 }
}

void processEntities(ReadOnlyBag<Entity> entities) #

Any implementing entity system must implement this method and the logic to process the given entities of the system.

docs inherited from EntitySystem
void processEntities(ReadOnlyBag<Entity> entities) {
 var deplacement = new Vector3.zero();
 var accs = new Vector3.zero();
 collSpace.reset();
 //for (var pass = (delta ~/ interval) + 1; pass > 0; --pass) {
 //apply time corrected verlet [TCV](http://lonesock.net/article/verlet.html)
 var dt = delta.toDouble() / 1000.0;
 var timestepPrevious = (_timestep == -1) ?dt : _timestep;
 _timestep = dt  ;
 var timeScale = (_timestep / timestepPrevious);
 var timestep2 = _timestep * _timestep;
 entities.forEach((e){
   var ps = _particlesMapper.get(e);
   if (ps == null) return;
   for (var i = ps.length -1 ; i > -1; --i){
     var position3d = ps.position3d[i];
     var position3dPrevious = ps.position3dPrevious[i];
     // calculate velocity
     deplacement.setFrom(position3d).sub(position3dPrevious).scale(timeScale * ps.inertia[i]);

//        // ground friction
//        if (particles[i].pos.y >= this.height-1 && velocity.length2() > 0.000001) {
//          var m = velocity.length();
//          velocity.x /= m;
//          velocity.y /= m;
//          velocity.mutableScale(m*this.groundFriction);
//        }

     accs.setFrom(globalAccs);
     accs.add(ps.acc[i]);
     // Position Verlet integration
     accs.scale(timestep2);
     deplacement.add(accs);
     // follow http://lolengine.net/blog/2011/12/14/understanding-motion-in-games
     // Velocity Verlet integration
     // vec3 OldVel = Vel;
     // Vel = Vel + Accel * dt;
     // Pos = Pos + (OldVel + Vel) * 0.5 * dt;
     // Pos = Pos + (2 * OldVel + Accel * dt) * 0.5 * dt;
     //forces.scale(_timestep1);
     //deplacement.scale(2.0).add(forces).scale(0.5 * _timestep1);


     // save last good state
     // TODO optim : store future pos in previous and swap previous (with future) and current values in one swap (swap the list), but this optimisation will break existing code that keep vector of position (eg constraint)
     position3dPrevious.setFrom(position3d);
     position3d.add(deplacement);
   }
   collSpace.addParticles(ps);
 });
 // iterate collisions + constraints
 var stepCoef = 1.0/steps;
 //var bodies = maps(entities, _bodiesMapper);
 _updateConstraintss(entities);

 for(int step = 0; step < steps; ++step ) { //Repeat this a few times to give more exact results
//    // bounds checking
//    //TODO define bounds as constraintes
//    for (c in this.composites) {
//      var particles = this.composites[c].particles;
//      for (i in particles)
//        this.bounds(particles[i]);
//    }

   //relax Constraints (include Edge) correction step
   //TODO optimize the loop
   //TODO check if relax should be done in the same loop as collision
   //TODO check if relax should be done once constraint per step or every constraint per step
   for (int i = 0; i < _constraintssL; i++) {
     var c = _constraintss[i];
     c.l.forEach((j) {
       j.relax(stepCoef);
     });
   };
 }

 for(var i = 0; i < _constraintssL; ++i) {
   var cs = _constraintss[i];
   for(var j = 0; j < cs.l.length; ++j) {
     var c = cs.l[j];
     if(c is Constraint_Distance) {
       collSpace.addSegment(c.segment);
     }
   }
 }
 collSpace.handleCollision();

}

void removed(Entity entity) #

inherited from EntitySystem

Called if an entity was removed from this system, e.g. deleted or had one of it's components removed.

void removed(Entity entity) {}