UNPKG

fieldkit

Version:

Basic building blocks for computational design projects. Written in CoffeeScript for browser and server environments.

314 lines (253 loc) 7.84 kB
// Generated by CoffeeScript 1.6.3 (function() { var Behaviour, Constraint, Emitter, Particle, Physics, Space, Spring, particleModule, util, _ref, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; util = require('../util'); particleModule = require('./particle'); Particle = particleModule.Particle; /* A Particle Physics Simulation */ Physics = (function() { function Physics() { this.particles = []; this.springs = []; this.behaviours = []; this.constraints = []; this.emitter = null; this.space = null; this.constraintIterations = 1; this.springIterations = 1; this.space = new Space(); this.emitter = new Emitter(this); this.clear(); } Physics.prototype.clear = function() { this.particles = []; this.behaviours = []; return this.constraints = []; }; Physics.prototype.add = function() { var arg, state; if (arguments.length === 0) { return; } arg = arguments[0]; if (arg instanceof Particle) { this.addParticle(arg); } else if (arg instanceof Behaviour) { console.log("adding behaviour " + arg); if (arguments.length > 1) { state = arguments[1]; } this.addBehaviour(arg, state); } else if (arg instanceof Spring) { console.log("adding spring " + arg); this.addSpring(arg); } else { "Cannot add " + arg; } return arg; }; Physics.prototype.addParticle = function(particle) { this.particles.push(particle); return particle; }; Physics.prototype.addSpring = function(spring) { this.springs.push(spring); return spring; }; Physics.prototype.addBehaviour = function(effector, state) { var list; if (state == null) { state = particleModule.State.ALIVE; } list = effector instanceof Constraint ? this.constraints : this.behaviours; if (!list[state]) { list[state] = []; } return list[state].push(effector); }; Physics.prototype.update = function() { var dead, i, j, particle, particles, spring, stateDead, _i, _j, _k, _l, _len, _len1, _ref, _ref1, _ref2; this.emitter.update(); this.space.update(this); particles = this.particles; this.applyEffectors(this.behaviours, particles); for (j = _i = 0, _ref = this.constraintIterations; 0 <= _ref ? _i <= _ref : _i >= _ref; j = 0 <= _ref ? ++_i : --_i) { this.applyEffectors(this.constraints, particles); for (i = _j = 0, _ref1 = this.springIterations; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) { _ref2 = this.springs; for (_k = 0, _len = _ref2.length; _k < _len; _k++) { spring = _ref2[_k]; spring.update(); } } } dead = []; stateDead = particleModule.State.DEAD; for (_l = 0, _len1 = particles.length; _l < _len1; _l++) { particle = particles[_l]; particle.update(); if (particle.state === stateDead) { dead.push(particle); } void 0; } i = dead.length; while (i--) { particle = dead[i]; util.removeElement(particle, particles); void 0; } return void 0; }; Physics.prototype.applyEffectors = function(effectors, particles) { var effector, particle, state, stateEffectors, _i, _j, _len, _len1; state = effectors.length; while (state--) { stateEffectors = effectors[state]; for (_i = 0, _len = stateEffectors.length; _i < _len; _i++) { effector = stateEffectors[_i]; effector.prepare(this); for (_j = 0, _len1 = particles.length; _j < _len1; _j++) { particle = particles[_j]; if (particle.state === state && !particle.isLocked) { effector.apply(particle); } void 0; } void 0; } void 0; } return void 0; }; Physics.prototype.size = function() { return this.particles.length; }; return Physics; })(); /* Spatial Search Simple brute force spatial searches. Subclasses may override this to organise particles so they can be found quicker later */ Space = (function() { var physics; physics = null; function Space() {} Space.prototype.update = function(physics_) { return physics = physics_; }; Space.prototype.search = function(center, radius) { var particle, radiusSq, result, _i, _len, _ref; result = []; radiusSq = radius * radius; _ref = physics.particles; for (_i = 0, _len = _ref.length; _i < _len; _i++) { particle = _ref[_i]; if (center.distanceSquared(particle.position) < radiusSq) { result.push(particle); } } return result; }; return Space; })(); /* Particle Emitter */ Emitter = (function() { var id, timer; timer = -1; id = 0; function Emitter(physics) { this.physics = physics; this.rate = 1; this.interval = 1; this.max = 100; this.type = particleModule.Particle3; } Emitter.prototype.update = function() { var i, p; if (timer === -1 || timer >= this.interval) { timer = 0; i = 0; while (i < this.rate && this.physics.size() < this.max) { p = this.create(); this.init(p); i++; } } return timer++; }; Emitter.prototype.create = function() { var p; p = new this.type(id++); this.physics.addParticle(p); return p; }; Emitter.prototype.init = function(particle) {}; return Emitter; })(); /* Base class for all physical forces, behaviours & constraints */ Behaviour = (function() { function Behaviour() {} Behaviour.prototype.prepare = function() {}; Behaviour.prototype.apply = function(particle) {}; return Behaviour; })(); Constraint = (function(_super) { __extends(Constraint, _super); function Constraint() { _ref = Constraint.__super__.constructor.apply(this, arguments); return _ref; } Constraint.prototype.prepare = function() {}; Constraint.prototype.apply = function(particle) {}; return Constraint; })(Behaviour); /* Verlet Spring */ Spring = (function() { function Spring(a, b, strength) { this.a = a; this.b = b; this.strength = strength != null ? strength : 0.5; this.restLength = this.a.position.distance(this.b.position); } Spring.prototype.update = function() { var delta, dist, normDistStrength; delta = this.b.position.sub_(this.a.position); dist = delta.length() + Number.MIN_VALUE; normDistStrength = (dist - this.restLength) / dist * this.strength; if (normDistStrength === 0) { return; } delta.scale(normDistStrength); if (!this.a.isLocked) { this.a.position.add(delta); } if (!this.b.isLocked) { return this.b.position.sub(delta); } }; Spring.prototype.toString = function() { return "Spring(" + a + ", " + b + ")"; }; return Spring; })(); module.exports = { Physics: Physics, Emitter: Emitter, Space: Space, Behaviour: Behaviour, Constraint: Constraint, Spring: Spring }; }).call(this);