Source: skarf.js

/**
 * skarf.js
 * Generic JavaScript augmented reality (AR) framework for handling different JavaScript AR libraries in Three.js
 *
 * Copyright (C) 2013 Skeel Lee (http://cg.skeelogy.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see [http://www.gnu.org/licenses/].
 */

/**
 * @fileOverview Generic JavaScript augmented reality (AR) framework for handling different JavaScript AR libraries in Three.js
 * @author Skeel Lee <skeel@skeelogy.com>
 * @version 1.0.4
 *
 * @example
 * //How to setup Skarf
 *
 * //create a Skarf instance which uses JSARToolKit (as an example)
 * var source = document.getElementById('myVideo');
 * var canvasContainerElem = document.getElementById('canvasContainer');
 * var camFov = 40.0;  //this must be the same value used in the Three.js render cam too
 * var skarf = new SKARF.Skarf({
 *
 *     arLibType: 'jsartoolkit',
 *     trackingElem: source,
 *     markerSize: 1,
 *     verticalFov: camFov,  //you can leave this out because JSARToolKit default projection matrix seems to work better for generic web cams
 *     threshold: 128,
 *     debug: options.displayDebugView,
 *
 *     canvasContainerElem: canvasContainerElem,
 *
 *     renderer: renderer,
 *     scene: scene,
 *     camera: camera,
 *
 *     markersJsonFile: 'models/models_jsartoolkit.json'
 *
 * });
 *
 * //update on every frame
 * skarf.update(dt);
 *
 * @example
 * //How to use GUI markers
 *
 * //in JSON file, define GUI marker
 * "32": {
 *     "name": "Sculpt Amount",
 *     "key": "sculptAmountSlider",
 *     "type": "slider",
 *     "params": {
 *         "speed": 0.01
 *     }
 * }
 *
 * //in your JavaScript, define callback function which will be called when "changed" event happens for the key "sculptAmountSlider" (in the format <em>myKey_myEvent</em>)
 * sculptAmountSlider_changed = function (params) {
 *     //params.delta will give the changed amount that you should add to your variable
 * }
 *
 * //for a full list of events and params available, please refer to the individual classes in this doc
 */

/**
 * @namespace
 */
var SKARF = SKARF || { version: '1.0.4' };
console.log('Using SKARF ' + SKARF.version);

//===================================
// GUI MARKERS
//===================================

/**
 * Factory that creates GuiMarkers
 * @namespace
 */
SKARF.GuiMarkerFactory = {

    __mappings: {},

    /**
     * Function to create a SKARF.GuiMarker instance
     * @param {string} type Type of GuiMarker to create: 'generic', 'button', 'checkbox', 'slider', 'combobox', 'timer'
     * @param {object} options Options
     * @param {string} options.key Unique string ID that identifies this GUI marker. This name is used to search for callback functions related to this GUI marker.
     * @param {string} options.name Name for this GUI marker
     * @param {number} options.markerId ID of the AR marker
     * @param {THREE.Object3D} options.markerTransform A transform to hold this GUI marker
     * @param {number} options.markerSize Scale of the GUI marker
     * @param {object} options.params Additional parameters to customize this GUI marker
     */
    create: function (type, options) {
        if (!type) {
            throw new Error('SKARF.GuiMarker type not specified');
        }
        if (!this.__mappings.hasOwnProperty(type)) {
            throw new Error('SKARF.GuiMarker of this type has not been registered with SKARF.GuiMarkerFactory: ' + type);
        }
        var guiMarker = new this.__mappings[type](options);
        return guiMarker;
    },

    /**
     * Registers a type string to a class
     * @param {string} mappingName Name of the mapping which is used to identify the type when creating instances e.g. 'threejs'
     * @param {SKARF.GuiMarker} mappingClass GuiMarker class that will be created when the associated type is used
     */
    register: function (mappingName, mappingClass) {
        if (this.__mappings.hasOwnProperty(mappingName)) {
            throw new Error('Mapping name already exists: ' + mappingName);
        }
        this.__mappings[mappingName] = mappingClass;
    }
};

/**
 * An augmented reality GUI marker.<br/>
 * @constructor
 * @abstract
 */
SKARF.GuiMarker = function (options) {

    if (typeof options.key === 'undefined') {
        throw new Error('key not specified');
    }
    this.__key = options.key;
    if (typeof options.name === 'undefined') {
        throw new Error('name not specified');
    }
    this.__name = options.name;
    if (typeof options.markerId === 'undefined') {
        throw new Error('markerId not specified');
    }
    this.__markerId = options.markerId;
    if (typeof options.markerTransform === 'undefined') {
        throw new Error('markerTransform not specified');
    }
    this.__markerTransform = options.markerTransform;
    //TODO: determine if markerSize is needed
    if (typeof options.markerSize === 'undefined') {
        throw new Error('markerSize not specified');
    }
    this.__markerSize = options.markerSize;

    this.__firstDetected = true;
    this.__firstHidden = false;

    this.__worldMatrix = null;

    //variables for position
    this.__position = new THREE.Vector3();
    this.__prevPosition = new THREE.Vector3();
    this.__dPosition = new THREE.Vector3();
    this.__moveThresholdLow = 0.02;  //to ignore slight flickerings
    this.__moveThresholdHigh = 0.5;  //in case axes flip and a large change occurs

    //variables for rotation
    this.__worldZAxis = new THREE.Vector3(0, 0, 1);
    this.__worldYAxis = new THREE.Vector3(0, 1, 0);
    this.__currZAxis = new THREE.Vector3();
    this.__rotation = 0;
    this.__prevRotation = 0;
    this.__dRotation = 0;
    this.__rotThresholdLow = 1.0;  //to ignore slight flickerings
    this.__rotThresholdHigh = 10.0;  //in case axes flip and a large change occurs

    //callback objects
    this.__callbackObjs = {};
    this.__callbackObjs['moved'] = {name: this.__key + '_moved', fn: undefined};
    this.__callbackObjs['rotated'] = {name: this.__key + '_rotated', fn: undefined};
    this.__callbackObjs['firstDetected'] = {name: this.__key + '_firstDetected', fn: undefined};
    this.__callbackObjs['firstHidden'] = {name: this.__key + '_firstHidden', fn: undefined};
    this.__callbackObjs['detected'] = {name: this.__key + '_detected', fn: undefined};
    this.__callbackObjs['hidden'] = {name: this.__key + '_hidden', fn: undefined};
};
/**
 * Call this method when the GUI marker is detected
 * @param {number} dt Time elapsed since previous frame
 * @param {THREE.Matrix4} worldMatrix World matrix for the marker
 */
SKARF.GuiMarker.prototype.detected = function (dt, worldMatrix) {

    //store world matrix first
    this.__worldMatrix = worldMatrix;

    //get position and rotation
    this.__processPosition(worldMatrix);
    this.__processRotation(worldMatrix);

    //process callbacks
    this.__processCallbacks();

    //turn off firstDetected
    this.__firstDetected = false;

    //turn on first hidden, for the next hide
    this.__firstHidden = true;
};
SKARF.GuiMarker.prototype.__processPosition = function (worldMatrix) {

    this.__position.getPositionFromMatrix(worldMatrix);

    //check if marker has moved
    this.__dPosition.copy(this.__position.clone().sub(this.__prevPosition));
    var movedDist = this.__dPosition.length();
    if (movedDist >= this.__moveThresholdLow && movedDist <= this.__moveThresholdHigh) {
        //call the moved callback
        this.__invokeCallback('moved', {guiMarker: this, position: this.__position, dPosition: this.__dPosition});
    }

    //store the previous position
    this.__prevPosition.copy(this.__position);
};
SKARF.GuiMarker.prototype.__processRotation = function (worldMatrix) {

    //NOTE: tried to extract the Euler Y rotation and then take the difference but can't seem to get it to work.
    //So I'm finding the angle between local Z and world Z manually

    //get the current X axis
    this.__currZAxis.getColumnFromMatrix(2, worldMatrix).normalize();

    //find the current angle (against world Z)
    this.__rotation = THREE.Math.radToDeg(Math.acos(this.__currZAxis.dot(this.__worldZAxis)));

    //check cross product against world Y
    var orthoAxis = new THREE.Vector3().crossVectors(this.__currZAxis, this.__worldZAxis);
    var orthoAngle = orthoAxis.dot(this.__worldYAxis);
    if (orthoAngle < 0) {  //opposite side
        this.__rotation = 360 - this.__rotation;
    }

    this.__dRotation = this.__rotation - this.__prevRotation;
    var absDRot = Math.abs(this.__dRotation);
    if (!isNaN(this.__dRotation) && absDRot >= this.__rotThresholdLow && absDRot <= this.__rotThresholdHigh) {
        this.__invokeCallback('rotated', {guiMarker: this, rotation: this.__rotation, dRotation: this.__dRotation});
    }

    //store prev rotation
    this.__prevRotation = this.__rotation;
};
SKARF.GuiMarker.prototype.__processCallbacks = function () {

    //call detected callback
    this.__invokeCallback('detected', {guiMarker: this, worldMatrix: this.__worldMatrix, position: this.__position, rotation: this.__rotation});

    //call firstDetected callback
    if (this.__firstDetected) {
        this.__invokeCallback('firstDetected', {guiMarker: this, worldMatrix: this.__worldMatrix, position: this.__position, rotation: this.__rotation});
    }
};
/**
 * Call this method when the marker has been hidden
 */
SKARF.GuiMarker.prototype.hidden = function () {

    //turn on firstDetected, for the next detection
    this.__firstDetected = true;

    //call firstHidden callback
    if (this.__firstHidden) {
        this.__invokeCallback('firstHidden', {guiMarker: this});
        this.__firstHidden = false;
    }

    //call hidden callback
    this.__invokeCallback('hidden', {guiMarker: this});
};
SKARF.GuiMarker.prototype.__invokeCallback = function (type, options) {

    var callbackObj = this.__callbackObjs[type];

    //if callback function has not been eval'ed, do it first
    if (typeof callbackObj.fn === 'undefined') {
        try {
            callbackObj.fn = eval(callbackObj.name);
        } catch (err) {
            callbackObj.fn = null;
        }
    }

    //call the callback function if it exists
    if (callbackObj.fn) {
        callbackObj.fn.call(this, options);
    }
};

/**
 * Generic SKARF.GuiMarker<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.GenericMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
};
//inherit
SKARF.GenericMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.GenericMarker.prototype.constructor = SKARF.GenericMarker;
//register with factory
SKARF.GuiMarkerFactory.register('generic', SKARF.GenericMarker);

/**
 * SKARF.GuiMarker that activates once until the marker is next shown<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Available events:<br/>
 * <ul>
 *   <li><strong>clicked:</strong> invoked once when marker is shown</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.ButtonMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
    this.__callbackObjs['clicked'] = {name: this.__key + '_clicked', fn: undefined};
};
//inherit
SKARF.ButtonMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.ButtonMarker.prototype.constructor = SKARF.ButtonMarker;
//register with factory
SKARF.GuiMarkerFactory.register('button', SKARF.ButtonMarker);
//override
SKARF.ButtonMarker.prototype.__processCallbacks = function () {
    if (this.__firstDetected) {
        this.__invokeCallback('clicked', {guiMarker: this});
    }
    SKARF.GuiMarker.prototype.__processCallbacks.call(this);
};

/**
 * SKARF.GuiMarker that toggles an on/off state once until the marker is next shown<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Available events:<br/>
 * <ul>
 *   <li><strong>toggled:</strong> invoked once when marker is shown</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.checked: whether the "checkbox" is checked</li>
 *     </ul>
 * </ul>
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.CheckBoxMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
    this.__callbackObjs['toggled'] = {name: this.__key + '_toggled', fn: undefined};
    this.__checked = false;
};
//inherit
SKARF.CheckBoxMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.CheckBoxMarker.prototype.constructor = SKARF.CheckBoxMarker;
//register with factory
SKARF.GuiMarkerFactory.register('checkbox', SKARF.CheckBoxMarker);
//override
SKARF.CheckBoxMarker.prototype.__processCallbacks = function () {
    if (this.__firstDetected) {
        this.__checked = !this.__checked;
        this.__invokeCallback('toggled', {guiMarker: this, checked: this.__checked});
    }
    SKARF.GuiMarker.prototype.__processCallbacks.call(this);
};

/**
 * SKARF.GuiMarker that emulates an attribute-changing slider by rotating<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Available events:<br/>
 * <ul>
 *   <li><strong>changed:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.delta: change in rotation since previous frame, multiplied by the "speed" parameter defined in JSON file</li>
 *     </ul>
 * </ul>
 * </p>
 * <p>
 * Available parameter in JSON file:<br/>
 * <ul>
 *   <li><strong>speed:</strong> multiplier to change in rotation (defaults to 1.0)</li>
 * </ul>
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.SliderMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
    this.__speed = options.params && options.params.speed ? options.params.speed : 1.0;
    this.__callbackObjs['changed'] = {name: this.__key + '_changed', fn: undefined};
};
//inherit
SKARF.SliderMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.SliderMarker.prototype.constructor = SKARF.SliderMarker;
//register with factory
SKARF.GuiMarkerFactory.register('slider', SKARF.SliderMarker);
//override
SKARF.SliderMarker.prototype.__processCallbacks = function () {
    var absDRot = Math.abs(this.__dRotation);
    if (!isNaN(this.__dRotation) && absDRot >= this.__rotThresholdLow && absDRot <= this.__rotThresholdHigh) {
        this.__invokeCallback('changed', {guiMarker: this, delta: this.__dRotation * this.__speed});
    }
    SKARF.GuiMarker.prototype.__processCallbacks.call(this);
};

/**
 * SKARF.GuiMarker that emulates a combo box. Selection is based on orientation of marker.<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Available events:<br/>
 * <ul>
 *   <li><strong>changed</strong></li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.selectedId: 0-based numeric ID of selection</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 * </ul>
 * </p>
 *
 * <p>
 * Available parameter in JSON file:<br/>
 * <ul>
 *   <li><strong>numChoices:</strong> total number of choices for the combo box (compulsory)</li>
 * </ul>
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.ComboBoxMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
    this.__callbackObjs['changed'] = {name: this.__key + '_changed', fn: undefined};
    if (!(options.params && options.params.numChoices)) {
        throw new Error('numChoices not specified as a parameter');
    }
    this.__numChoices = options.params.numChoices;
    this.__currId = 0;
};
//inherit
SKARF.ComboBoxMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.ComboBoxMarker.prototype.constructor = SKARF.ComboBoxMarker;
//register with factory
SKARF.GuiMarkerFactory.register('combobox', SKARF.ComboBoxMarker);
//override
SKARF.ComboBoxMarker.prototype.__processCallbacks = function () {
    var newId = Math.floor(this.__rotation / 360.0 * this.__numChoices);
    if (newId !== this.__currId) {
        this.__invokeCallback('changed', {guiMarker: this, selectedId: newId, rotation: this.__rotation});
        this.__currId = newId;
    }
    SKARF.GuiMarker.prototype.__processCallbacks.call(this);
};

/**
 * SKARF.GuiMarker that activates after a certain amount of time<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.GuiMarkerFactory GuiMarkerFactory} instead.</strong>
 *
 * <p>
 * GUI markers work via event callbacks. Users should define callback functions in their JavaScript which matches this format: <em>myKey_myCallbackType</em>.
 * For example, if you have a GUI marker with key of "sculptAmountSlider" (defined in JSON file) and you want it to react to the "changed" event, create a function named "sculptAmountSlider_changed" i.e.
 * <blockquote><tt>sculptAmountSlider_changed = function (params) { ... }</tt></blockquote>
 * The <tt>params</tt> argument will contain necessary data for that particular event. In the example above, <tt>params.delta</tt> will give the change in rotation since previous frame.
 * </p>
 *
 * <p>
 * Available events:<br/>
 * <ul>
 *   <li><strong>reached:</strong> invoked when timer has reached specified time</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * <p>
 * Available parameter in JSON file:<br/>
 * <ul>
 *   <li><strong>time:</strong> duration of timer (defaults to 2.0) </li>
 * </ul>
 * </p>
 *
 * <p>
 * Inherited events from SKARF.GuiMarker:<br/>
 * <ul>
 *   <li><strong>moved:</strong> invoked when marker is moved</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.position: current world position</li>
 *       <li>params.dPosition: change in position since previous frame</li>
 *     </ul>
 *   <li><strong>rotated:</strong> invoked when marker is rotated</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.rotation: current world rotation</li>
 *       <li>params.dRotation: change in rotation since previous frame</li>
 *     </ul>
 *   <li><strong>detected:</strong> invoked when the <tt>detected()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>firstDetected:</strong> invoked when the <tt>detected()</tt> method is first called since last <tt>hidden()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *       <li>params.worldMatrix: world matrix of the marker solve</li>
 *       <li>params.position: current world position</li>
 *       <li>params.rotation: current world rotation</li>
 *     </ul>
 *   <li><strong>hidden:</strong> invoked when the <tt>hidden()</tt> method is called</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 *   <li><strong>firstHidden:</strong> invoked when the <tt>hidden()</tt> method is first called since last <tt>detected()</tt> call</li>
 *     <ul>
 *       <li>params.guiMarker: this instance</li>
 *     </ul>
 * </ul>
 * </p>
 * @constructor
 * @extends {SKARF.GuiMarker}
 */
SKARF.TimerMarker = function (options) {
    SKARF.GuiMarker.call(this, options);
    this.__callbackObjs['reached'] = {name: this.__key + '_reached', fn: undefined};
    this.__time = (options.params && options.params.time) || 2.0;
    this.__currTime = 0;
    this.__reached = false;
};
//inherit
SKARF.TimerMarker.prototype = Object.create(SKARF.GuiMarker.prototype);
SKARF.TimerMarker.prototype.constructor = SKARF.TimerMarker;
//register with factory
SKARF.GuiMarkerFactory.register('timer', SKARF.TimerMarker);
//override
/**
 * Call this method when the GUI marker is detected
 * @param {number} dt Time elapsed since previous frame
 * @param {THREE.Matrix4} worldMatrix World matrix for the marker
 */
SKARF.TimerMarker.prototype.detected = function (dt, worldMatrix) {
    SKARF.GuiMarker.prototype.detected.call(this, dt, worldMatrix);
    this.__currTime += dt;
    if (!this.__reached && this.__currTime >= this.__time) {
        this.__reached = true;
        this.__invokeCallback('reached', {guiMarker: this});
    }
};
/**
 * Call this method when the marker has been hidden
 */
SKARF.TimerMarker.prototype.hidden = function () {

    //reset if marker disappears
    this.__currTime = 0;
    this.__reached = false;

    SKARF.GuiMarker.prototype.hidden.call(this);
};
SKARF.TimerMarker.prototype.resetTimer = function () {
    this.__currTime = 0;
};

//===================================
// MODEL LOADERS
//===================================

/**
 * Factory which creates ModelLoaders
 * @namespace
 */
SKARF.ModelLoaderFactory = {

    __mappings: {},

    /**
     * Function to create a SKARF.ModelLoader instance
     * @param {string} type Type of ModelLoader to create: 'empty', 'json', 'json_bin', 'obj'
     */
    create: function (type) {
        if (!type) {
            throw new Error('Model type not specified');
        }
        if (!this.__mappings.hasOwnProperty(type)) {
            throw new Error('SKARF.ModelLoader of this type has not been registered with SKARF.ModelLoaderFactory: ' + type);
        }
        var loader = new this.__mappings[type]();
        return loader;
    },

    /**
     * Registers a type string to a class
     * @param {string} mappingName Name of the mapping which is used to identify the type when creating instances e.g. 'threejs'
     * @param {SKARF.ModelLoader} mappingClass ModelLoader class that will be created when the associated type is used
     */
    register: function (mappingName, mappingClass) {
        if (this.__mappings.hasOwnProperty(mappingName)) {
            throw new Error('Mapping name already exists: ' + mappingName);
        }
        this.__mappings[mappingName] = mappingClass;
    }
};

/**
 * Abstract class for model loaders
 * @constructor
 * @abstract
 */
SKARF.ModelLoader = function () {
    this.__loader = null;
};
/**
 * Loads model for marker
 * @abstract
 * @param  {object}  model Data containing the model info (from JSON file)
 * @param  {number}  markerId ID of marker to laod
 * @param  {THREE.Object3D}  markerTransform Transform to parent to after model has loaded
 * @param  {number}  overallScale Overall scale
 * @param  {boolean} isWireframeVisible Whether to initialize the wireframe mode to true
 * @param  {SKARF.MarkerManager} markerManager Instance of MarkerManager
 */
SKARF.ModelLoader.prototype.loadForMarker = function (model, markerId, markerTransform, overallScale, isWireframeVisible, markerManager) {
    throw new Error('Abstract method not implemented');
};
/**
 * Transforms and parents a model onto a transform
 * @param {object} model Data containing the model info (from JSON file)
 * @param {THREE.Mesh} object Mesh to parent
 * @param {THREE.Object3D} markerTransform Transform to parent to
 * @param {number} overallScale Overall scale
 * @param {SKARF.MarkerManager} markerManager Instance of MarkerManager
 */
SKARF.ModelLoader.prototype.transformAndParent = function (model, obj, markerTransform, overallScale, markerManager) {

    if (obj) {

        obj.traverse(function (object) {
            if (object instanceof THREE.Mesh) {

                //store the model data into the geometry
                object.geometry.__jsonData = model;

                //accumulate transformations into matrix
                var m = new THREE.Matrix4();
                if (model.translate) {
                    m.setPosition(new THREE.Vector3(model.translate[0], model.translate[1], model.translate[2]));
                }
                if (model.rotate) {
                    var rotationMat = new THREE.Matrix4();
                    var rotationVector = new THREE.Vector3(THREE.Math.degToRad(model.rotate[0]), THREE.Math.degToRad(model.rotate[1]), THREE.Math.degToRad(model.rotate[2]));
                    var rotationOrder = model.rotationOrder || 'XYZ';
                    rotationMat.makeRotationFromEuler(rotationVector, model.rotationOrder);
                    m.multiply(rotationMat);
                }
                if (model.scale) {
                    m.scale(new THREE.Vector3(model.scale[0] * overallScale, model.scale[1] * overallScale, model.scale[2] * overallScale));
                }

                //bake transforms into geometry
                object.geometry.applyMatrix(m);
                markerTransform.add(object);

                //store the material in markerManager
                markerManager.__materials.push(object.material);

                //compute bounding box
                object.geometry.computeBoundingBox();

                //also set objects to cast shadows
                object.castShadow = true;
                object.receiveShadow = true;
            }
        });

    }
};

/**
 * Model loader which contains no models<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ModelLoaderFactory ModelLoaderFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ModelLoader}
 */
SKARF.EmptyModelLoader = function () {
    SKARF.ModelLoader.call(this);
    this.__loader = new THREE.JSONLoader();
    console.log('Created a SKARF.EmptyModelLoader');
};
//inherit from SKARF.ModelLoader
SKARF.EmptyModelLoader.prototype = Object.create(SKARF.ModelLoader.prototype);
SKARF.EmptyModelLoader.prototype.constructor = SKARF.EmptyModelLoader;
//register with factory
SKARF.ModelLoaderFactory.register('empty', SKARF.EmptyModelLoader);
//override methods
/**
 * Loads model for marker
 * @param  {object}  model Data containing the model info (from JSON file)
 * @param  {number}  markerId ID of marker to laod
 * @param  {THREE.Object3D}  markerTransform Transform to parent to after model has loaded
 * @param  {number}  overallScale Overall scale
 * @param  {boolean} isWireframeVisible Whether to initialize the wireframe mode to true
 * @param  {SKARF.MarkerManager} markerManager Instance of MarkerManager
 */
SKARF.EmptyModelLoader.prototype.loadForMarker = function (model, markerId, markerTransform, overallScale, isWireframeVisible, markerManager) {
    //TODO: time how long it takes to load

    //bake transformations into vertices
    this.transformAndParent(model, null, markerTransform, overallScale, markerManager);

    console.log('Loaded empty transform for marker id ' + markerId);
};

/**
 * Model loader which contains Three.js JSON model data
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ModelLoaderFactory ModelLoaderFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ModelLoader}
 */
SKARF.JsonModelLoader = function () {
    SKARF.ModelLoader.call(this);
    this.__loader = new THREE.JSONLoader();
    console.log('Created a SKARF.JsonModelLoader');
};
//inherit from SKARF.ModelLoader
SKARF.JsonModelLoader.prototype = Object.create(SKARF.ModelLoader.prototype);
SKARF.JsonModelLoader.prototype.constructor = SKARF.JsonModelLoader;
//register with factory
SKARF.ModelLoaderFactory.register('json', SKARF.JsonModelLoader);
//override methods
/**
 * Loads model for marker
 * @param  {object}  model Data containing the model info (from JSON file)
 * @param  {number}  markerId ID of marker to laod
 * @param  {THREE.Object3D}  markerTransform Transform to parent to after model has loaded
 * @param  {number}  overallScale Overall scale
 * @param  {boolean} isWireframeVisible Whether to initialize the wireframe mode to true
 * @param  {SKARF.MarkerManager} markerManager Instance of MarkerManager
 */
SKARF.JsonModelLoader.prototype.loadForMarker = function (model, markerId, markerTransform, overallScale, isWireframeVisible, markerManager) {
    //TODO: time how long it takes to load

    var that = this;
    this.__loader.load(model.url, function (geometry, materials) {

        //set wireframe visibility
        var i, len;
        for (i = 0, len = materials.length; i < len; i++) {
            materials[i].wireframe = isWireframeVisible;
        }

        //create mesh
        var mesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));

        //bake transformations into vertices
        that.transformAndParent(model, mesh, markerTransform, overallScale, markerManager);

        console.log('Loaded mesh ' + model.url + ' for marker id ' + markerId);
    });
};

/**
 * Model loader which contains Three.js JSON binary models
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ModelLoaderFactory ModelLoaderFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ModelLoader}
 */
SKARF.JsonBinaryModelLoader = function () {
    SKARF.ModelLoader.call(this);
    if (typeof THREE.BinaryLoader === 'undefined') {
        throw new Error('THREE.BinaryLoader does not exist. Have you included BinaryLoader.js?');
    }
    this.__loader = new THREE.BinaryLoader();
    console.log('Created a SKARF.JsonBinaryModelLoader');
};
//inherit from SKARF.JsonModelLoader
SKARF.JsonBinaryModelLoader.prototype = Object.create(SKARF.JsonModelLoader.prototype);
SKARF.JsonBinaryModelLoader.prototype.constructor = SKARF.JsonBinaryModelLoader;
//register with factory
SKARF.ModelLoaderFactory.register('json_bin', SKARF.JsonBinaryModelLoader);

/**
 * Model loader which contains OBJ models
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ModelLoaderFactory ModelLoaderFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ModelLoader}
 */
SKARF.ObjModelLoader = function () {

    SKARF.ModelLoader.call(this);

    if (typeof THREE.OBJMTLLoader === 'undefined') {
        throw new Error('THREE.OBJMTLLoader does not exist. Have you included OBJMTLLoader.js and MTLLoader.js?');
    }
    this.__loader = new THREE.OBJMTLLoader();
    console.log('Created a SKARF.ObjModelLoader');

    //register an event listener
    var that = this;
    this.__loader.addEventListener('load', function (event) {

        var object = event.content;  //this ia a THREE.Object3D

        //set wireframe visibility
        var child, grandChild;
        var i, j, leni, lenj;
        for (i = 0, leni = object.children.length; i < leni; i++) {
            child = object.children[i];
            for (j = 0, lenj = child.children.length; j < lenj; j++) {
                grandChild = child.children[j];
                if (grandChild instanceof THREE.Mesh) {
                    grandChild.material.wireframe = that.__isWireframeVisible;
                }
            }
        }

        //transform and parent
        that.transformAndParent(that.__model, object, that.__markerTransform, that.__overallScale, that.__markerManager);

        console.log('Loaded mesh ' + that.__model.url + ' for marker id ' + that.__markerId);
    });
};
//inherit from SKARF.ModelLoader
SKARF.ObjModelLoader.prototype = Object.create(SKARF.ModelLoader.prototype);
SKARF.ObjModelLoader.prototype.constructor = SKARF.ObjModelLoader;
//register with factory
SKARF.ModelLoaderFactory.register('obj', SKARF.ObjModelLoader);
//override methods
/**
 * Loads model for marker
 * @param  {object}  model Data containing the model info (from JSON file)
 * @param  {number}  markerId ID of marker to laod
 * @param  {THREE.Object3D}  markerTransform Transform to parent to after model has loaded
 * @param  {number}  overallScale Overall scale
 * @param  {boolean} isWireframeVisible Whether to initialize the wireframe mode to true
 * @param  {SKARF.MarkerManager} markerManager Instance of MarkerManager
 */
SKARF.ObjModelLoader.prototype.loadForMarker = function (model, markerId, markerTransform, overallScale, isWireframeVisible, markerManager) {

    //store variables in the instance since there seems to be no way to pass to loader.load (TODO: verify this)
    this.__model = model;
    this.__markerId = markerId;
    this.__markerTransform = markerTransform;
    this.__overallScale = overallScale;
    this.__isWireframeVisible = isWireframeVisible;
    this.__markerManager = markerManager;

    //call load()
    var mtlFile = model.url.replace(/\.obj/g, '.mtl');  //assume mtl file has same base name as .obj
    this.__loader.load(model.url, mtlFile);
};

//===================================
// MARKER MANAGER
//===================================

/**
 * Manager to manage markers, both for models and GuiMarkers
 * @constructor
 */
SKARF.MarkerManager = function (markersJsonFile) {
    this.__markersJsonFile = markersJsonFile;

    this.__markerData = null;
    this.__modelLoaders = {};

    this.__materials = [];

    this.__load();
};
SKARF.MarkerManager.prototype.__load = function () {
    console.log('Loading markers json file: ' + this.__markersJsonFile);

    //load the JSON file
    var that = this;
    $.ajax({
        url: this.__markersJsonFile,
        dataType: 'JSON',
        async: false
    }).done(function (data) {
        that.__markerData = data;
        console.log('Loaded ' + that.__markersJsonFile);
        console.log('Main marker id: ' + that.__markerData.mainMarkerId);
    }).error(function (xhr, textStatus, error) {
        throw new Error('error loading ' + this.__markersJsonFile + ': ' + error);
    });
};
/**
 * Loads model for marker
 * @param  {number}  markerId ID of marker to load
 * @param  {THREE.Object3D}  markerTransform Transform to parent to after model has loaded
 * @param  {number}  markerSize Size of marker
 * @param  {boolean} isWireframeVisible Whether to initialize the wireframe mode to true
 */
SKARF.MarkerManager.prototype.loadForMarker = function (markerId, markerTransform, markerSize, isWireframeVisible) {

    markerSize = markerSize || 1.0;

    //two types of markers to load:

    if (this.__markerData.models && this.__markerData.models[markerId]) {
        //1) models
        var model = this.__markerData.models[markerId];
        if (model) {
            var type = model.type;
            if (!this.__modelLoaders.hasOwnProperty(type)) {
                //create a loader using SKARF.ModelLoaderFactory
                this.__modelLoaders[type] = SKARF.ModelLoaderFactory.create(type);
            }
            this.__modelLoaders[type].loadForMarker(model, markerId, markerTransform, markerSize, isWireframeVisible, this);
        }
    } else if (this.__markerData.guiMarkers && this.__markerData.guiMarkers[markerId]) {
        //2) GUI markers
        var guiMarker = this.__markerData.guiMarkers[markerId];
        if (guiMarker) {
            var type = guiMarker.type;
            guiMarker = SKARF.GuiMarkerFactory.create(type, {
                name: guiMarker.name,
                key: guiMarker.key,
                markerId: markerId,
                markerTransform: markerTransform,
                markerSize: markerSize,
                params: guiMarker.params
            });
            markerTransform.guiMarker = guiMarker;
        }
    } else {
        console.warn('Unable to find data for marker id ' + markerId);
    }

};

//===================================
// HELPERS
//===================================

// I'm going to use a glMatrix-style matrix as an intermediary.
// So the first step is to create a function to convert a glMatrix matrix into a Three.js Matrix4.
THREE.Matrix4.prototype.setFromArray = function (m) {
    return this.set(
        m[0], m[4], m[8], m[12],
        m[1], m[5], m[9], m[13],
        m[2], m[6], m[10], m[14],
        m[3], m[7], m[11], m[15]
    );
};

function copyMarkerMatrix(arMat, glMat) {
    glMat[0] = arMat.m00;
    glMat[1] = -arMat.m10;
    glMat[2] = arMat.m20;
    glMat[3] = 0;
    glMat[4] = arMat.m01;
    glMat[5] = -arMat.m11;
    glMat[6] = arMat.m21;
    glMat[7] = 0;
    glMat[8] = -arMat.m02;
    glMat[9] = arMat.m12;
    glMat[10] = -arMat.m22;
    glMat[11] = 0;
    glMat[12] = arMat.m03;
    glMat[13] = -arMat.m13;
    glMat[14] = arMat.m23;
    glMat[15] = 1;
}

//===================================
// AR LIBRARIES
//===================================

/**
 * Factory which creates SKARF.ArLibs<br/>
 * <strong>NOTE: This is meant for internal usage only as the created instance needs some manual variable assignments and initializations before they are usable. These are done internally by a {@linkcode SKARF.Skarf Skarf} instance.</strong>
 * @namespace
 */
SKARF.ArLibFactory = {

    __mappings: {},

    /**
     * Function to create a SKARF.ArLib instance
     * @param {string} type Type of ArLib to create: 'jsartoolkit', 'jsaruco'
     * @param {object} options Options
     * @param {canvas} options.trackingElem Canvas DOM element used for tracking
     * @param {number} options.markerSize Size of marker in mm, determines scale of scene
     * @param {number} options.mainMarkerId ID of main marker
     * @param {number} [options.verticalFov] Vertical field-of-view of web cam (you will have to estimate this). If this is not defined, it will use use some default field-of-view which works in general for web cams.
     * @param {number} [options.threshold=128] Threshold value for turning tracking stream into a binary image. Ranges from 0 to 255. Used only for JSARToolKit.
     * @param {boolean} [options.debug=false] Whether to turn on debug view/mode
     */
    create: function (type, options) {
        if (!type) {
            throw new Error('SKARF.ArLib type not specified');
        }
        if (!this.__mappings.hasOwnProperty(type)) {
            throw new Error('SKARF.ArLib of this type has not been registered with SKARF.ArLibFactory: ' + type);
        }
        var arLib = new this.__mappings[type](options);
        return arLib;
    },

    /**
     * Registers a type string to a class
     * @param {string} mappingName Name of the mapping which is used to identify the type when creating instances e.g. 'jsartoolkit'
     * @param {SKARF.ArLib} mappingClass ArLib class that will be created when the associated type is used
     */
    register: function (mappingName, mappingClass) {
        if (this.__mappings.hasOwnProperty(mappingName)) {
            throw new Error('Mapping name already exists: ' + mappingName);
        }
        this.__mappings[mappingName] = mappingClass;
    }
};

/**
 * Abstract class for ArLibs
 * @constructor
 * @abstract
 */
SKARF.ArLib = function (options) {

    if (typeof options.trackingElem === 'undefined') {
        throw new Error('trackingElem not specified');
    }
    this.__trackingElem = options.trackingElem;

    if (typeof options.markerSize === 'undefined') {
        throw new Error('markerSize not specified');
    }
    this.__markerSize = options.markerSize;

    this.__verticalFov = options.verticalFov;

    if (typeof options.mainMarkerId === 'undefined') {
        throw new Error('mainMarkerId not specified');
    }
    this.__mainMarkerId = options.mainMarkerId;

    this.__debug = (typeof options.debug === 'undefined') ? false : options.debug;

    this.__compensationMatrix = new THREE.Matrix4();

    this.__mainMarkerHasEverBeenDetected = false;

    //temp matrix for calculations later
    this.__tmpMat = new THREE.Matrix4();

    //variables to be assigned by skarf
    this.__canvasElem = null;
    this.__renderer = null;

    this.__markers = {};  //this is just to keep track if a certain marker id has been seen
};
/**
 * Gets debug value
 * @returns {boolean} Debug value
 */
SKARF.ArLib.prototype.getDebug = function () {
    return this.__debug;
};
/**
 * Sets debug value
 * @param {boolean} value Debug value to set to
 */
SKARF.ArLib.prototype.setDebug = function (value) {
    this.__debug = value;
};
/**
 * Initializes the instance
 * @abstract
 */
SKARF.ArLib.prototype.init = function () {
    throw new Error('Abstract method not implemented');
};
/**
 * Updates the instance
 * @abstract
 * @param  {number} dt Time elapsed since previous frame
 */
SKARF.ArLib.prototype.update = function (dt) {
    throw new Error('Abstract method not implemented');
};

/**
 * ArLib class for JSARToolKit.<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ArLibFactory ArLibFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ArLib}
 */
SKARF.JsArToolKitArLib = function (options) {
    SKARF.ArLib.call(this, options);

    this.__threshold = options.threshold || 128;

    this.__compensationMatrix = new THREE.Matrix4().makeScale(1, 1, -1);  //scale in -z to swap from LH-coord to RH-coord
    this.__compensationMatrix.multiply(new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(90)));  //rotate 90deg in X to get Y-up;

    //store some temp variables
    this.__resultMat = new NyARTransMatResult();
    this.__tmp = {};
};
//inherit from SKARF.ArLib
SKARF.JsArToolKitArLib.prototype = Object.create(SKARF.ArLib.prototype);
SKARF.JsArToolKitArLib.prototype.constructor = SKARF.JsArToolKitArLib;
//register with factory
SKARF.ArLibFactory.register('jsartoolkit', SKARF.JsArToolKitArLib);
//override methods
/**
 * Gets threshold value
 * @returns {number} Threshold value
 */
SKARF.JsArToolKitArLib.prototype.getThreshold = function () {
    return this.__threshold;
};
/**
 * Sets threshold value
 * @param {number} value Threshold value to set to
 */
SKARF.JsArToolKitArLib.prototype.setThreshold = function (value) {
    this.__threshold = value;
};
/**
 * Initializes the instance
 */
SKARF.JsArToolKitArLib.prototype.init = function () {
    //required by JSARToolKit to show the debug canvas
    DEBUG = this.__debug;

    // Create a RGB raster object for the 2D canvas.
    // JSARToolKit uses raster objects to read image data.
    // Note that you need to set canvas.changed = true on every frame.
    this.__raster = new NyARRgbRaster_Canvas2D(this.__canvasElem);

    // FLARParam is the thing used by FLARToolKit to set camera parameters.
    this.__flarParam = new FLARParam(this.__canvasElem.width, this.__canvasElem.height, this.__verticalFov);

    // The FLARMultiIdMarkerDetector is the actual detection engine for marker detection.
    // It detects multiple ID markers. ID markers are special markers that encode a number.
    this.__detector = new FLARMultiIdMarkerDetector(this.__flarParam, this.__markerSize);

    // For tracking video set continue mode to true. In continue mode, the detector
    // tracks markers across multiple frames.
    this.__detector.setContinueMode(true);

    //set the camera projection matrix in the renderer
    this.initCameraProjMatrix();
};
/**
 * Initializes the camera projection matrix.
 * This is called automatically during initialization. Call this function only if you need to re-initialize the camera projection matrix again.
 */
SKARF.JsArToolKitArLib.prototype.initCameraProjMatrix = function () {
    var camProjMatrixArray = new Float32Array(16);
    this.__flarParam.copyCameraMatrix(camProjMatrixArray, 0.1, 10000);
    this.__renderer.initCameraProjMatrix(camProjMatrixArray);
};
/**
 * Updates the instance
 * @param  {number} dt Elapsed time since previous frame
 */
SKARF.JsArToolKitArLib.prototype.update = function (dt) {

    DEBUG = this.__debug;

    //set all markers detected to false first
    var keys = Object.keys(this.__markers);
    var i, j;
    for (i = 0; i < keys.length; i++) {
        this.__renderer.__setMarkerDetected(keys[i], false);
    }

    // Do marker detection by using the detector object on the raster object.
    // The threshold parameter determines the threshold value
    // for turning the video frame into a 1-bit black-and-white image.
    //
    //NOTE: THE CANVAS MUST BE THE SAME SIZE AS THE RASTER
    //OTHERWISE WILL GET AN "Uncaught #<Object>" ERROR
    var markerCount = this.__detector.detectMarkerLite(this.__raster, this.__threshold);

    // Go through the detected markers and get their IDs and transformation matrices.
    var id, currId;
    for (i = 0; i < markerCount; i++) {

        // Get the ID marker data for the current marker.
        // ID markers are special kind of markers that encode a number.
        // The bytes for the number are in the ID marker data.
        id = this.__detector.getIdMarkerData(i);

        // Read bytes from the id packet.
        currId = -1;
        // This code handles only 32-bit numbers or shorter.
        if (id.packetLength <= 4) {
            currId = 0;
            for (j = 0; j < id.packetLength; j++) {
                currId = (currId << 8) | id.getPacketData(j);
            }
        }

        // If this is a new id, let's start tracking it.
        if (typeof this.__markers[currId] === 'undefined') {

            //create empty object for the marker
            this.__markers[currId] = {};

            //create a transform for this marker
            var transform = this.__renderer.__createTransformForMarker(currId, this.__markerSize);

            //delay-load the model
            this.__renderer.loadForMarker(currId, transform, this.__markerSize);

            //if this is the main marker id, turn on flag
            if (currId == this.__mainMarkerId) {  //double equals for auto type conversion
                this.__mainMarkerHasEverBeenDetected = true;
            }
        }

        try {
            // Get the transformation matrix for the detected marker.
            this.__detector.getTransformMatrix(i, this.__resultMat);

            // Copy the marker matrix to the tmp matrix.
            copyMarkerMatrix(this.__resultMat, this.__tmp);

            //store the current solved matrix first
            this.__tmpMat.setFromArray(this.__tmp);
            this.__renderer.__setCurrSolvedMatrixValues(currId, this.__tmpMat);

            //register that this marker has been detected
            this.__renderer.__setMarkerDetected(currId, true);
        } catch (err) {
            //just print to console but let the error pass so that the program can continue
            console.log(err.message);
        }
    }

    //update the solved scene
    this.__renderer.__updateSolvedScene(dt, this.__mainMarkerId);
};

/**
 * ArLib class for js-aruco.<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.ArLibFactory ArLibFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.ArLib}
 */
SKARF.JsArucoArLib = function (options) {
    SKARF.ArLib.call(this, options);
};
//inherit from SKARF.ArLib
SKARF.JsArucoArLib.prototype = Object.create(SKARF.ArLib.prototype);
SKARF.JsArucoArLib.prototype.constructor = SKARF.JsArucoArLib;
//register with factory
SKARF.ArLibFactory.register('jsaruco', SKARF.JsArucoArLib);
//override methods
/**
 * Initializes the instance
 */
SKARF.JsArucoArLib.prototype.init = function () {
    this.__detector = new AR.Detector();

    //NOTE: the second parameter is suppose to be canvasWidth (from the js-aruco example).
    //However, it cannot work when I change the aspect ratio of the tracking canvas.
    //It seems as though the tracking canvas must be 4:3, so I'm doing some compensation here to allow any aspect ratio.
    this.__posit = new POS.Posit(this.__markerSize, this.__canvasElem.height * 4.0 / 3.0);

    this.__context = this.__canvasElem.getContext('2d');
};
/**
 * Updates the instance
 * @param  {number} dt Elapsed time since previous frame
 */
SKARF.JsArucoArLib.prototype.update = function (dt) {
    var imageData = this.__context.getImageData(0, 0, this.__canvasElem.width, this.__canvasElem.height);
    var markers = this.__detector.detect(imageData);
    if (this.__debug) {
        this.__drawCorners(markers);
        this.__drawId(markers);
    }

    //update scene
    this.__updateScenes(dt, markers);
};
SKARF.JsArucoArLib.prototype.__updateScenes = function (dt, markers) {
    var corners, corner, pose, markerId;

    //set all markers detected to false first
    var keys = Object.keys(this.__markers);
    var i, j;
    for (i = 0; i < keys.length; i++) {
        this.__renderer.__setMarkerDetected(keys[i], false);
    }

    for (i = 0; i < markers.length; i++) {
        markerId = markers[i].id;
        corners = markers[i].corners;

        // If this is a new id, let's start tracking it.
        if (typeof this.__markers[markerId] === 'undefined') {

            console.log('Creating new marker root for id ' + markerId);

            //create empty object for the marker
            this.__markers[markerId] = {};

            //create a transform for this marker
            var transform = this.__renderer.__createTransformForMarker(markerId, this.__markerSize);

            //delay-load the model
            this.__renderer.loadForMarker(markerId, transform, this.__markerSize);

            //if this is the main marker id, turn on flag
            if (markerId == this.__mainMarkerId) {  //double equals for auto type conversion
                this.__mainMarkerHasEverBeenDetected = true;
            }
        }

        //align corners to center of canvas
        for (j = 0; j < corners.length; j++) {
            corner = corners[j];
            //NOTE: there seems to be some scale away from the center, so I have to scale everything down from the center.
            //The value of 0.97 is by trial-and-error, seems to work pretty well.
            corner.x = 0.97 * (corner.x - (this.__canvasElem.width / 2));
            corner.y = 0.97 * ((this.__canvasElem.height / 2) - corner.y);
        }

        //estimate pose
        try {
            pose = this.__posit.pose(corners);

            //store the current solved matrix first
            this.__updateMatrix4FromRotAndTrans(pose.bestRotation, pose.bestTranslation);
            this.__tmpMat.multiply(new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(90)));
            this.__renderer.__setCurrSolvedMatrixValues(markerId, this.__tmpMat);

            //register that this marker has been detected
            this.__renderer.__setMarkerDetected(markerId, true);

        } catch (err) {
            //just print to console but let the error pass so that the program can continue
            console.log(err.message);
        }
    }

    //update the solved scene
    this.__renderer.__updateSolvedScene(dt, this.__mainMarkerId);
};
SKARF.JsArucoArLib.prototype.__updateMatrix4FromRotAndTrans = function (rotationMat, translationVec) {
    this.__tmpMat.set(
        rotationMat[0][0], rotationMat[0][1], -rotationMat[0][2], translationVec[0],
        rotationMat[1][0], rotationMat[1][1], -rotationMat[1][2], translationVec[1],
        -rotationMat[2][0], -rotationMat[2][1], rotationMat[2][2], -translationVec[2],
        0, 0, 0, 1);
};
SKARF.JsArucoArLib.prototype.__drawCorners = function (markers) {

    var corners, corner, i, j, leni, lenj;
    for (i = 0, leni = markers.length; i < leni; i++) {
        corners = markers[i].corners;

        this.__context.lineWidth = 2;
        this.__context.strokeStyle = "red";
        this.__context.beginPath();

        for (j = 0, lenj = corners.length; j < lenj; j++) {
            corner = corners[j];
            this.__context.moveTo(corner.x, corner.y);
            corner = corners[(j + 1) % corners.length];
            this.__context.lineTo(corner.x, corner.y);
        }

        this.__context.stroke();
        this.__context.closePath();

        this.__context.lineWidth = 3;
        this.__context.strokeStyle = "green";
        this.__context.strokeRect(corners[0].x - 2, corners[0].y - 2, 4, 4);
    }
};
SKARF.JsArucoArLib.prototype.__drawId = function (markers) {

    var corners, corner, x, y, i, len;

    this.__context.font = '12pt Calibri';
    this.__context.fillStyle = "yellow";
    // this.__context.strokeStyle = "black";
    // this.__context.lineWidth = 1.0;

    for (i = 0, len = markers.length; i < len; i++) {
        corners = markers[i].corners;

        x = corners[0].x;
        y = corners[0].y;

        this.__context.fillText(markers[i].id, x, y);
        // this.__context.strokeText(markers[i].id, x, y);
    }
};

//===================================
// RENDERERS
//===================================

/**
 * Factory which creates SKARF.Renderer<br/>
 * <strong>NOTE: This is meant for internal usage only as the created instance needs some manual variable assignments and initializations before they are usable. These are done internally by a {@linkcode SKARF.Skarf Skarf} instance.</strong>
 * @namespace
 */
SKARF.RendererFactory = {

    __mappings: {},

    /**
     * Function to create a SKARF.Renderer instance
     * @param {string} type Type of ArLib to create: 'threejs' (only choice available now)
     * @param {object} options Options
     * @param {THREE.WebGLRenderer} options.renderer Three.js renderer
     * @param {THREE.Scene} options.scene Three.js scene
     * @param {THREE.Camera} options.camera Three.js camera
     * @param {string} options.markersJsonFile Path to a JSON file that specifies markers and models to load
     */
    create: function (type, options) {
        if (!type) {
            throw new Error('SKARF.Renderer type not specified');
        }
        if (!this.__mappings.hasOwnProperty(type)) {
            throw new Error('SKARF.Renderer of this type has not been registered with SKARF.RendererFactory: ' + type);
        }
        var renderer = new this.__mappings[type](options);
        return renderer;
    },

    /**
     * Registers a type string to a class
     * @param {string} mappingName Name of the mapping which is used to identify the type when creating instances e.g. 'threejs'
     * @param {SKARF.Renderer} mappingClass Renderer class that will be created when the associated type is used
     */
    register: function (mappingName, mappingClass) {
        if (this.__mappings.hasOwnProperty(mappingName)) {
            throw new Error('Mapping name already exists: ' + mappingName);
        }
        this.__mappings[mappingName] = mappingClass;
    }
};

/**
 * Abstract class for renderers
 * @constructor
 * @abstract
 */
SKARF.Renderer = function (options) {

    if (typeof options.renderer === 'undefined') {
        throw new Error('renderer not specified');
    }
    this.__renderer = options.renderer;

    if (typeof options.scene === 'undefined') {
        throw new Error('scene not specified');
    }
    this.__scene = options.scene;

    if (typeof options.camera === 'undefined') {
        throw new Error('camera not specified');
    }
    this.__camera = options.camera;

    if (typeof options.markersJsonFile === 'undefined') {
        throw new Error('markersJsonFile not specified');
    }
    this.__markersJsonFile = options.markersJsonFile;

    this.__isWireframeVisible = (typeof options.displayWireframe === 'undefined') ? false : options.displayWireframe;
    this.__isLocalAxisVisible = (typeof options.displayLocalAxis === 'undefined') ? false : options.displayLocalAxis;

    this.__markerManager = new SKARF.MarkerManager(this.__markersJsonFile);
    this.__localAxes = [];

    this.__markerTransforms = {};

    this.__callbacks = {};

    //variables to be assigned by skarf
    this.__arLib = null;
    this.__backgroundCanvasElem = null;
};
/**
 * Initializes the instance
 */
SKARF.Renderer.prototype.init = function () {
    this.__setupBackgroundVideo();
};
/**
 * Adds a callback function that will be called during specific events
 * @param {string} type Type of callback: 'render' (only choice available now)
 * @param {function} callbackFn Callback function to call
 */
SKARF.Renderer.prototype.addCallback = function (type, callbackFn) {
    if (!this.__callbacks.hasOwnProperty(type)) {
        this.__callbacks[type] = [];
    }
    if (callbackFn) {
        if (typeof callbackFn === 'function') {
            this.__callbacks[type].push(callbackFn);
        } else {
            throw new Error('Specified callbackFn is not a function');
        }
    } else {
        throw new Error('Callback function not defined');
    }
};
/**
 * Returns the designated main marker ID
 * @return {number} main marker ID
 */
SKARF.Renderer.prototype.getMainMarkerId = function () {
    return this.__markerManager.__markerData.mainMarkerId;
};
/**
 * Updates the renderer
 * @abstract
 * @param  {number} dt Time elapsed since previous frame
 */
SKARF.Renderer.prototype.update = function (dt) {
    throw new Error('Abstract method not implemented');
};
SKARF.Renderer.prototype.__setupBackgroundVideo = function () {
    throw new Error('Abstract method not implemented');
};
SKARF.Renderer.prototype.__createTransformForMarker = function (markerId, markerSize) {
    throw new Error('Abstract method not implemented');
};
/**
 * Shows all children of marker
 * @param {number} markerId ID of marker
 * @param {boolean} visible Whether to show or hide the children
 */
SKARF.Renderer.prototype.showChildrenOfMarker = function (markerId, visible) {
    this.__showChildren(this.__markerTransforms[markerId], visible);
};
SKARF.Renderer.prototype.__showChildren = function (object3d, visible) {
    throw new Error('Abstract method not implemented');
};
SKARF.Renderer.prototype.loadForMarker = function (markerId, markerTransform, markerSize) {
    this.__markerManager.loadForMarker(markerId, markerTransform, markerSize, this.__isWireframeVisible);
};
SKARF.Renderer.prototype.__setCurrSolvedMatrixValues = function (markerId, matrix) {
    throw new Error('Abstract method not implemented');
};
SKARF.Renderer.prototype.__setMarkerDetected = function (markerId, detected) {
    this.__markerTransforms[markerId].detected = detected;
};
SKARF.Renderer.prototype.__updateSolvedScene = function (dt, mainMarkerId) {
    throw new Error('Abstract method not implemented');
};
/**
 * Sets visibility of wireframe
 * @abstract
 * @param {boolean} isVisible Visibility of wireframe
 */
SKARF.Renderer.prototype.setWireframeVisible = function (isVisible) {
    throw new Error('Abstract method not implemented');
};
/**
 * Sets visibility of local axis
 * @abstract
 * @param {boolean} isVisible Visibility of local axis
 */
SKARF.Renderer.prototype.setLocalAxisVisible = function (isVisible) {
    throw new Error('Abstract method not implemented');
};
/**
 * Hides all models that have been loaded
 * @abstract
 */
SKARF.Renderer.prototype.hideAllModels = function () {
    throw new Error('Abstract method not implemented');
};

/**
 * Renderer class for Three.js<br/>
 * <strong>Please do not instantiate this class on your own. Use the {@linkcode SKARF.RendererFactory RendererFactory} instead.</strong>
 * @constructor
 * @extends {SKARF.Renderer}
 */
SKARF.ThreeJsRenderer = function (options) {
    // this.__markerTransforms = {};
    SKARF.Renderer.call(this, options);

    //temp matrix
    this.__mainMarkerRootSolvedMatrixInv = new THREE.Matrix4();
};
//inherit from SKARF.Renderer
SKARF.ThreeJsRenderer.prototype = Object.create(SKARF.Renderer.prototype);
SKARF.ThreeJsRenderer.prototype.constructor = SKARF.ThreeJsRenderer;
//register with factory
SKARF.RendererFactory.register('threejs', SKARF.ThreeJsRenderer);
//override methods
/**
 * Updates the renderer
 * @param  {number} dt Time elapsed since previous frame
 */
SKARF.ThreeJsRenderer.prototype.update = function (dt) {

    //mark texture for update
    this.__videoTex.needsUpdate = true;

    //clear renderer first
    this.__renderer.autoClear = false;
    this.__renderer.clear();

    //check for the callback of type 'render'
    if (this.__callbacks.hasOwnProperty('render')) {
        var renderCallbacks = this.__callbacks['render'];
        var i, len;
        for (i = 0, len = renderCallbacks.length; i < len; i++) {
            renderCallbacks[i](dt);
        }
    }

    //finally, render actual scene
    this.__renderer.render(this.__videoScene, this.__videoCam);
    this.__renderer.render(this.__scene, this.__camera);
};
SKARF.ThreeJsRenderer.prototype.__showChildren = function (object3d, visible) {
    var children = object3d.children;
    var i, len;
    for (i = 0, len = children.length; i < len; i++) {
        if (!visible) {
            //if hide mode, just hide without caring about the type
            children[i].visible = visible;
        } else {
            //if show mode, just show first
            children[i].visible = visible;
            //if it is an axis, then check also whether it is suppose to be shown
            if (children[i] instanceof THREE.AxisHelper) {
                children[i].visible = children[i].visible && this.__isLocalAxisVisible;
            }
        }
    }
};
SKARF.ThreeJsRenderer.prototype.__setupBackgroundVideo = function () {
    //NOTE: must use <canvas> as the texture, not <video>, otherwise there will be a 1-frame lag
    this.__videoTex = new THREE.Texture(this.__backgroundCanvasElem);
    this.__videoPlane = new THREE.PlaneGeometry(2, 2);
    this.__videoMaterial = new THREE.MeshBasicMaterial({
        map: this.__videoTex,
        depthTest: false,
        depthWrite: false
    });
    var plane = new THREE.Mesh(this.__videoPlane, this.__videoMaterial);
    this.__videoScene = new THREE.Scene();
    this.__videoCam = new THREE.Camera();
    this.__videoScene.add(plane);
    this.__videoScene.add(this.__videoCam);
};
SKARF.ThreeJsRenderer.prototype.__createTransformForMarker = function (markerId, markerSize) {
    //FIXME: no need to create a transform if this markerId is not in the models JSON file

    //create a new Three.js object as marker root
    var markerTransform = new THREE.Object3D();
    markerTransform.matrixAutoUpdate = false;
    markerTransform.currSolvedMatrix = new THREE.Matrix4();
    this.__markerTransforms[markerId] = markerTransform;

    // Add the marker root to your scene.
    this.__scene.add(markerTransform);

    //add a axis helper to see the local axis
    var localAxis = new THREE.AxisHelper(markerSize * 2);
    localAxis.visible = this.__isLocalAxisVisible;
    this.__localAxes.push(localAxis);
    markerTransform.add(localAxis);

    return markerTransform;
};
SKARF.ThreeJsRenderer.prototype.__setCurrSolvedMatrixValues = function (markerId, matrix) {
    this.__markerTransforms[markerId].currSolvedMatrix.copy(matrix);
};
/**
 * Sets visibility of wireframe
 * @param {boolean} isVisible Visibility of wireframe
 */
SKARF.ThreeJsRenderer.prototype.setWireframeVisible = function (isVisible) {

    this.__isWireframeVisible = isVisible;

    var i, j, leni, lenj, m;
    for (i = 0, leni = this.__markerManager.__materials.length; i < leni; i++) {
        m = this.__markerManager.__materials[i];
        if (m instanceof THREE.MeshFaceMaterial) {
            for (j = 0, lenj = m.materials.length; j < lenj; j++) {
                m.materials[j].wireframe = isVisible;
            }
        } else {
            m.wireframe = isVisible;
        }
    }
};
/**
 * Sets visibility of local axis
 * @param {boolean} isVisible Visibility of local axis
 */
SKARF.ThreeJsRenderer.prototype.setLocalAxisVisible = function (isVisible) {
    this.__isLocalAxisVisible = isVisible;
    var i, len;
    for (i = 0, len = this.__localAxes.length; i < len; i++) {
        this.__localAxes[i].visible = isVisible;
    }
};
SKARF.ThreeJsRenderer.prototype.__updateSolvedScene = function (dt, mainMarkerId) {

    var mainMarkerIdDetected = this.__markerTransforms[mainMarkerId] && this.__markerTransforms[mainMarkerId].detected;
    if (mainMarkerIdDetected) {

        //move the camera instead of the marker root
        this.__camera.matrix.copy(this.__arLib.__compensationMatrix);  //compensate coordinate system and up vector differences
        this.__camera.matrix.multiply(this.__mainMarkerRootSolvedMatrixInv.getInverse(this.__markerTransforms[mainMarkerId].currSolvedMatrix));  //multiply inverse of main marker's matrix will force main marker to be at origin and the camera to transform around this world space
        this.__camera.matrixWorldNeedsUpdate = true;
    }

    //for each of the marker root detected, move into the space of the main marker root
    var that = this;
    Object.keys(this.__markerTransforms).forEach(function (key) {
        if (that.__markerTransforms[key].detected) {

            //transform and compensate
            that.__markerTransforms[key].matrix.copy(that.__camera.matrix);  //transform into new camera world space first
            that.__markerTransforms[key].matrix.multiply(that.__markerTransforms[key].currSolvedMatrix);  //since currSolvedMatrix is relative to camera space, multiplying by it next will bring this object into world space
            that.__markerTransforms[key].matrix.multiply(that.__arLib.__compensationMatrix);  //compensate back into the right coordinate system, locally
            that.__markerTransforms[key].matrixWorldNeedsUpdate = true;

            //show the object
            that.__showChildren(that.__markerTransforms[key], true);

            //call detected() on the GUI markers
            if (that.__markerTransforms[key].guiMarker) {
                that.__markerTransforms[key].guiMarker.detected(dt, that.__markerTransforms[key].matrix);
            }
        } else {

            //no need to transform

            //hide the object
            that.__showChildren(that.__markerTransforms[key], false);

            //call hidden() on the GUI markers
            if (that.__markerTransforms[key].guiMarker) {
                that.__markerTransforms[key].guiMarker.hidden();
            }
        }
    });
};
/**
 * Hides all models that have been loaded
 */
SKARF.ThreeJsRenderer.prototype.hideAllModels = function () {
    var id;
    for (id in this.__markerTransforms) {
        if (this.__markerTransforms.hasOwnProperty(id)) {
            this.__showChildren(this.__markerTransforms[id], false);
        }
    }
};
//methods
/**
 * Initializes the camera projection matrix
 * @param  {Three.Matrix4} camProjMatrixArray Camera projection matrix
 */
SKARF.ThreeJsRenderer.prototype.initCameraProjMatrix = function (camProjMatrixArray) {
    this.__camera.projectionMatrix.setFromArray(camProjMatrixArray);
};

//===================================
// SKARF
//===================================

/**
 * Class which handles different augmented reality libraries
 * @constructor
 * @param {object} options Options
 * @param {string} options.arLibType ArLib type: 'jsartoolkit, 'jsaruco'
 * @param {video | img | canvas} options.trackingElem DOM element used for tracking, such as a video, img or canvas
 * @param {number} options.markerSize Size of marker in mm, determines scale of scene
 * @param {number} [options.verticalFov] Vertical field-of-view of web cam (you will have to estimate this). For JSARToolKit,, if this is not defined, it will use a generic vertical field-of-view which seems to work well for general web cams.
 * @param {number} [options.threshold=128] Threshold value for turning tracking stream into a binary image. Ranges from 0 to 255. Used only for JSARToolKit.
 * @param {boolean} [options.debug=false] Whether to turn on debug view/mode
 * @param {canvas} [options.canvasContainerElem] Div DOM element to append a newly-created tracking canvas to. If not specified, the newly-created canvas will just be appended to the body DOM element.
 * @param {string} options.rendererType Renderer type: 'threejs'
 * @param {THREE.WebGLRenderer} options.renderer Three.js renderer
 * @param {THREE.Scene} options.scene Three.js scene
 * @param {THREE.Camera} options.camera Three.js camera
 * @param {string} options.markersJsonFile Path to a JSON file that specifies markers and models to load
 */
SKARF.Skarf = function (options) {

    //AR lib parameters
    if (typeof options.arLibType === 'undefined') {
        throw new Error('arLibType not specified');
    }
    this.__arLibType = options.arLibType;
    if (typeof options.trackingElem === 'undefined') {
        throw new Error('trackingElem not specified');
    }
    this.__trackingElem = options.trackingElem;
    if (typeof options.markerSize === 'undefined') {
        throw new Error('markerSize not specified');
    }
    this.__markerSize = options.markerSize;
    this.__verticalFov = options.verticalFov;
    this.__threshold = options.threshold || 128;
    this.__debug = typeof options.debug === 'undefined' ? false : options.debug;

    //canvas
    this.__canvasContainerElem = options.canvasContainerElem;

    //renderer parameters
    this.__rendererType = 'threejs';  //only create Three.js instances
    if (typeof options.renderer === 'undefined') {
        throw new Error('renderer not specified');
    }
    this.__threejsRenderer = options.renderer;
    if (typeof options.scene === 'undefined') {
        throw new Error('scene not specified');
    }
    this.__scene = options.scene;
    if (typeof options.camera === 'undefined') {
        throw new Error('camera not specified');
    }
    this.__camera = options.camera;
    if (typeof options.markersJsonFile === 'undefined') {
        throw new Error('markersJsonFile not specified');
    }
    this.__markersJsonFile = options.markersJsonFile;

    //init
    this.__init();
};
SKARF.Skarf.prototype.__create2dCanvas = function () {

    //create canvas
    this.__canvasElem = document.createElement('canvas');

    //canvas should be same width/height as the tracking element
    this.__canvasElem.width = this.__trackingElem.width;
    this.__canvasElem.height = this.__trackingElem.height;

    //attach to container if specified, otherwise attach to body
    if (this.__canvasContainerElem) {
        this.__canvasContainerElem.append(this.__canvasElem);
    } else {
        $('body').append(this.__canvasElem);
    }

    //store the 2d context
    this.__context = this.__canvasElem.getContext('2d');
};
SKARF.Skarf.prototype.__init = function () {

    //create a 2d canvas for copying data from tracking element
    this.__create2dCanvas();

    //create renderer instance
    this.__renderer = SKARF.RendererFactory.create(this.__rendererType, {
        renderer: this.__threejsRenderer,
        scene: this.__scene,
        camera: this.__camera,
        markersJsonFile: this.__markersJsonFile
    });

    //create AR lib instance
    this.__arLib = SKARF.ArLibFactory.create(this.__arLibType, {
        trackingElem: this.__trackingElem,
        markerSize: this.__markerSize,
        verticalFov: this.__verticalFov,
        mainMarkerId: this.__renderer.getMainMarkerId(),
        threshold: this.__threshold,
        debug: this.__debug
    });

    //assign necessary pointers of itself to each other
    this.__arLib.__renderer = this.__renderer;
    this.__renderer.__arLib = this.__arLib;

    //assign the canvas to arLib and renderer
    this.__arLib.__canvasElem = this.__canvasElem;
    this.__renderer.__backgroundCanvasElem = this.__canvasElem;

    //finally call init of both
    this.__renderer.init();
    this.__arLib.init();
};
/**
 * Returns the renderer associated with this instance
 * @returns {SKARF.Renderer} Renderer
 */
SKARF.Skarf.prototype.getRenderer = function () {
    return this.__renderer;
};
/**
 * Returns the AR lib associated with this instance
 * @returns {SKARF.ArLib} AR lib
 */
SKARF.Skarf.prototype.getArLib = function () {
    return this.__arLib;
};
/**
 * Draws tracking data to canvas, and then updates both the AR lib and renderer
 * @param {number} dt Elapsed time since previous frame
 */
SKARF.Skarf.prototype.update = function (dt) {

    //draw image from tracking element (video, img, canvas) to the actual canvas meant for tracking
    try {
        this.__context.drawImage(this.__trackingElem, 0, 0, this.__canvasElem.width, this.__canvasElem.height);
        this.__canvasElem.changed = true;
    } catch (err) {
        if (err.name !== 'NS_ERROR_NOT_AVAILABLE') {
            throw err;
        }
    }

    //call updates
    this.__arLib.update(dt);
    this.__renderer.update(dt);
};
/**
 * Adds a callback function that will be called during specific events
 * @param {string} type Type of callback: 'render' (only choice available now)
 * @param {function} callbackFn Callback function to call
 */
SKARF.Skarf.prototype.addCallback = function (type, callbackFn) {
    //pass all callbacks to renderer for now
    //TODO: manage callbacks better
    this.__renderer.addCallback(type, callbackFn);
};
/**
 * Returns true if the designated main marker has been detected
 * @return {bool} True if the designated main marker has been detected
 */
SKARF.Skarf.prototype.mainMarkerDetected = function () {
    return this.__arLib.__mainMarkerHasEverBeenDetected;
};
/**
 * Inits camera projection matrix, used only for JSARToolKit.
 * This is called automatically during initialization. Call this function only if you need to re-initialize the camera projection matrix again.
 */
SKARF.Skarf.prototype.initCameraProjMatrix = function () {
    if (this.__arLib instanceof SKARF.JsArToolKitArLib) {
        this.__arLib.initCameraProjMatrix();
    }
};