#

API Docs for: 0.6.1
Show: Inherited Protected Private Deprecated

# File: src/solver/SplitSolver.js

    module.exports = SplitSolver;

    var Vec3 = require('../math/Vec3');
    var Quaternion = require('../math/Quaternion');
    var Solver = require('./Solver');
    var Body = require('../objects/Body');

    /**
     * Splits the equations into islands and solves them independently. Can improve performance.
     * @class SplitSolver
     * @constructor
     * @extends Solver
     * @param {Solver} subsolver
     */
    function SplitSolver(subsolver){
        Solver.call(this);
        this.iterations = 10;
        this.tolerance = 1e-7;
        this.subsolver = subsolver;
        this.nodes = [];
        this.nodePool = [];

        // Create needed nodes, reuse if possible
        while(this.nodePool.length < 128){
            this.nodePool.push(this.createNode());
        }
    }
    SplitSolver.prototype = new Solver();

    // Returns the number of subsystems
    var SplitSolver_solve_nodes = []; // All allocated node objects
    var SplitSolver_solve_nodePool = []; // All allocated node objects
    var SplitSolver_solve_eqs = [];   // Temp array
    var SplitSolver_solve_bds = [];   // Temp array
    var SplitSolver_solve_dummyWorld = {bodies:[]}; // Temp object

    var STATIC = Body.STATIC;
    function getUnvisitedNode(nodes){
        var Nnodes = nodes.length;
        for(var i=0; i!==Nnodes; i++){
            var node = nodes[i];
            if(!node.visited && !(node.body.type & STATIC)){
                return node;
            }
        }
        return false;
    }

    var queue = [];
    function bfs(root,visitFunc,bds,eqs){
        queue.push(root);
        root.visited = true;
        visitFunc(root,bds,eqs);
        while(queue.length) {
            var node = queue.pop();
            // Loop over unvisited child nodes
            var child;
            while((child = getUnvisitedNode(node.children))) {
                child.visited = true;
                visitFunc(child,bds,eqs);
                queue.push(child);
            }
        }
    }

    function visitFunc(node,bds,eqs){
        bds.push(node.body);
        var Neqs = node.eqs.length;
        for(var i=0; i!==Neqs; i++){
            var eq = node.eqs[i];
            if(eqs.indexOf(eq) === -1){
                eqs.push(eq);
            }
        }
    }

    SplitSolver.prototype.createNode = function(){
        return { body:null, children:[], eqs:[], visited:false };
    };

    /**
     * Solve the subsystems
     * @method solve
     * @param  {Number} dt
     * @param  {World} world
     */
    SplitSolver.prototype.solve = function(dt,world){
        var nodes=SplitSolver_solve_nodes,
            nodePool=this.nodePool,
            bodies=world.bodies,
            equations=this.equations,
            Neq=equations.length,
            Nbodies=bodies.length,
            subsolver=this.subsolver;

        // Create needed nodes, reuse if possible
        while(nodePool.length < Nbodies){
            nodePool.push(this.createNode());
        }
        nodes.length = Nbodies;
        for (var i = 0; i < Nbodies; i++) {
            nodes[i] = nodePool[i];
        }

        // Reset node values
        for(var i=0; i!==Nbodies; i++){
            var node = nodes[i];
            node.body = bodies[i];
            node.children.length = 0;
            node.eqs.length = 0;
            node.visited = false;
        }
        for(var k=0; k!==Neq; k++){
            var eq=equations[k],
                i=bodies.indexOf(eq.bi),
                j=bodies.indexOf(eq.bj),
                ni=nodes[i],
                nj=nodes[j];
            ni.children.push(nj);
            ni.eqs.push(eq);
            nj.children.push(ni);
            nj.eqs.push(eq);
        }

        var child, n=0, eqs=SplitSolver_solve_eqs;

        subsolver.tolerance = this.tolerance;
        subsolver.iterations = this.iterations;

        var dummyWorld = SplitSolver_solve_dummyWorld;
        while((child = getUnvisitedNode(nodes))){
            eqs.length = 0;
            dummyWorld.bodies.length = 0;
            bfs(child, visitFunc, dummyWorld.bodies, eqs);

            var Neqs = eqs.length;

            eqs = eqs.sort(sortById);

            for(var i=0; i!==Neqs; i++){
                subsolver.addEquation(eqs[i]);
            }

            var iter = subsolver.solve(dt,dummyWorld);
            subsolver.removeAllEquations();
            n++;
        }

        return n;
    };

    function sortById(a, b){
        return b.id - a.id;
    }