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.
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
final num delta #
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)
var steps #
var steps = 10
Methods
void begin() #
Called before processing of entities begins.
void begin() {}
bool checkProcessing() #
Returns true if the system should be processed, false if not.
bool checkProcessing() { _acc += world.delta; _delta += world.delta; if(_acc >= _interval) { _acc -= _interval; return true; } return false; }
void deleted(Entity e) #
void deleted(Entity e) { if (_contains(e)) { _removeFromSystem(e); } }
void disabled(Entity e) #
void disabled(Entity e) { if (_contains(e)) { _removeFromSystem(e); } }
void end() #
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.
void initialize(){ _particlesMapper = new ComponentMapper0(Particles, world); _constraintsMapper = new ComponentMapper0(Constraints, world); }
void inserted(Entity entity) #
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() #
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.
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) #
Called if an entity was removed from this system, e.g. deleted or had one of it's components removed.
void removed(Entity entity) {}