This is constructor of the xBIM Viewer. It gets HTMLCanvasElement or string ID as an argument. Viewer will than be initialized
in the context of specified canvas. Any other argument will throw exception.
@name xViewer
@constructor
@classdesc This is the main and the only class you need to load and render IFC models in wexBIM format. This viewer is part of
xBIM toolkit which can be used to create wexBIM files from IFC, ifcZIP and ifcXML. WexBIM files are highly optimized for
transmition over internet and rendering performance. Viewer uses WebGL technology for hardware accelerated 3D rendering and SVG for
certain kinds of user interaction. This means that it won't work with obsolete and non-standard-compliant browsers like IE10 and less.

@param {string | HTMLCanvasElement} canvas - string ID of the canvas or HTML canvas element.
function xViewer(canvas) {
    if (typeof (canvas) == 'undefined') {
        throw 'Canvas has to be defined';
    }
    this._canvas = null;
    if (typeof(canvas.nodeName) != 'undefined' && canvas.nodeName == 'CANVAS') { 
        this._canvas = canvas;
    }
    if (typeof (canvas) == 'string') {
        this._canvas = document.getElementById(canvas);
    }
    if (this._canvas == null) {
        throw 'You have to specify canvas either as an ID of HTML element or the element itself';
    }

    /**
    * This is a structure that holds settings of perspective camera.
    * @member {PerspectiveCamera} xViewer#perspectiveCamera
    */
    /**
    * This is only a structure. Don't call the constructor.
    * @classdesc This is a structure that holds settings of perspective camera. If you want 
    * to switch viewer to use perspective camera set {@link xViewer#camera camera} to 'perspective'.
    * You can modify this but it is not necessary because sensible values are 
    * defined when geometry model is loaded with {@link xViewer#load load()} method. If you want to 
    * change these values you have to do it after geometry is loaded.
    * @class
    * @name PerspectiveCamera
    */
    this.perspectiveCamera = {
        /** @member {Number} PerspectiveCamera#fov - Field of view*/
        fov: 45,
        /** @member {Number} PerspectiveCamera#near - Near cutting plane*/
        near: 0,
        /** @member {Number} PerspectiveCamera#far - Far cutting plane*/
        far: 0
    };

    /**
    * This is a structure that holds settings of orthogonal camera. You can modify this but it is not necessary because sensible values are 
    * defined when geometry model is loaded with {@link xViewer#load load()} method. If you want to change these values you have to do it after geometry is loaded.
    * @member {OrthogonalCamera} xViewer#orthogonalCamera
    */
    /**
    * This is only a structure. Don't call the constructor.
    * @classdesc This is a structure that holds settings of orthogonal camera. If you want to switch viewer to use orthogonal camera set {@link xViewer#camera camera} to 'orthogonal'.
    * @class
    * @name OrthogonalCamera
    */
    this.orthogonalCamera = {
        /** @member {Number} OrthogonalCamera#left*/
        left: 0,
        /** @member {Number} OrthogonalCamera#right*/
        right: 0,
        /** @member {Number} OrthogonalCamera#top*/
        top: 0,
        /** @member {Number} OrthogonalCamera#bottom*/
        bottom: 0,
        /** @member {Number} OrthogonalCamera#near*/
        near: 0,
        /** @member {Number} OrthogonalCamera#far*/
        far: 0
    };

    /**
    * Type of camera to be used. Available values are <strong>'perspective'</strong> and <strong>'orthogonal'</strong> You can change this value at any time with instant effect.
    * @member {string} xViewer#camera
    */
    this.camera = 'perspective';

    /**
    * Array of four integers between 0 and 255 representing RGBA colour components. This defines background colour of the viewer. You can change this value at any time with instant effect.
    * @member {Number[]} xViewer#background
    */
    this.background = [230, 230, 230, 255];
    /**
    * Array of four integers between 0 and 255 representing RGBA colour components. This defines colour for highlighted elements. You can change this value at any time with instant effect.
    * @member {Number[]} xViewer#highlightingColour
    */
    this.highlightingColour = [255, 173, 33, 255];
    /**
    * Array of four floats. It represents Light A's position <strong>XYZ</strong> and intensity <strong>I</strong> as [X, Y, Z, I]. Intensity should be in range 0.0 - 1.0.
    * @member {Number[]} xViewer#lightA
    */
    this.lightA = [0, 1000000, 200000, 0.8];
    /**
    * Array of four floats. It represents Light B's position <strong>XYZ</strong> and intensity <strong>I</strong> as [X, Y, Z, I]. Intensity should be in range 0.0 - 1.0.
    * @member {Number[]} xViewer#lightB
    */
    this.lightB = [0, -500000, 50000, 0.2];

    /**
    * Switch between different navigation modes for left mouse button. Allowed values: <strong> 'pan', 'zoom', 'orbit' (or 'fixed-orbit') , 'free-orbit' and 'none'</strong>. Default value is <strong>'orbit'</strong>;
    * @member {String} xViewer#navigationMode
    */
    this.navigationMode = 'orbit';

    /**
    * Switch between different rendering modes. Allowed values: <strong> 'normal', 'x-ray'</strong>. Default value is <strong>'normal'</strong>;
    * Only products with state set to state.HIGHLIGHTED or xState.XRAYVISIBLE will be rendered highlighted or in a normal colours. All other products
    * will be rendered semi-transparent and single sided.
    * @member {String} xViewer#renderingMode
    */
    this.renderingMode = 'normal';

    /** 
    * Clipping plane [a, b, c, d] defined as normal equation of the plane ax + by + cz + d = 0. [0,0,0,0] is for no clipping plane.
    * @member {Number[]} xViewer#clippingPlane
    */
    this.clippingPlane = [0, 0, 0, 0];

    this._lastClippingPoint = [0, 0, 0];


    //*************************** Do all the set up of WebGL **************************
    var gl = WebGLUtils.setupWebGL(this._canvas);

    //do not even initialize this object if WebGL is not supported
    if (!gl) {
        return;
    }

    this._gl = gl;

    //detect floating point texture support
    this._fpt = (
	gl.getExtension('OES_texture_float') ||
	gl.getExtension('MOZ_OES_texture_float') ||
	gl.getExtension('WEBKIT_OES_texture_float')
	);


    //set up DEPTH_TEST and BLEND so that transparent objects look right
    //this is not 100% perfect as it would be necessary to sort all objects from back to
    //front when rendering them. We have sacrificed this for the sake of performance.
    //Objects with no transparency in their default style are drawn first and semi-transparent last.
    //This gives 90% right when there is not too much of transparency. It may not look right if you
    //have a look through two windows or if you have a look from inside of the building out.
    //It is granted to be alright when looking from outside of the building inside through one
    //semi-transparent object like curtain wall panel or window which is the case most of the time.
    //This is known limitation but there is no plan to change this behaviour.
    gl.enable(gl.DEPTH_TEST);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.enable(gl.BLEND);

    //cache canvas width and height and change it only when size change
    // it is better to cache this value because it is used frequently and it takes a time to get a value from HTML
    this._width = this._canvas.width = this._canvas.offsetWidth;
    this._height = this._canvas.height = this._canvas.offsetHeight;

    this._geometryLoaded = false;
    //number of active models is used to indicate that state has changed
    this._numberOfActiveModels = 0;
    //this object is used to identify if anything changed before two frames (hence if it is necessary to redraw)
    this._lastStates = {};
    this._visualStateAttributes = ["perspectiveCamera", "orthogonalCamera", "camera", "background", "lightA", "lightB",
        "renderingMode", "clippingPlane", "_mvMatrix", "_pMatrix", "_distance", "_origin", "highlightingColour", "_numberOfActiveModels"];
    this._stylingChanged = true;

    //this is to indicate that user has done some interaction
    this._userAction = true;

    //dictionary of named events which can be registered and unregistered by using '.on('eventname', callback)'
    // and '.off('eventname', callback)'. Registered call-backs are triggered by the viewer when important events occur.
    this._events = {};

    //array of plugins which can implement certain methods which get called at certain points like before draw, after draw and others.
    this._plugins = [];

    //pointers to uniforms in shaders
    this._mvMatrixUniformPointer = null;
    this._pMatrixUniformPointer = null;
    this._lightAUniformPointer = null;
    this._lightBUniformPointer = null;
    this._colorCodingUniformPointer = null;
    this._clippingPlaneUniformPointer = null;
    this._meterUniformPointer = null;
    this._renderingModeUniformPointer = null;
    this._highlightingColourUniformPointer = null;

    //transformation matrices
    this._mvMatrix = mat4.create(); 	//world matrix
    this._pMatrix = mat4.create(); 		//camera matrix (this can be either perspective or orthogonal camera)

    //Navigation settings - coordinates in the WCS of the origin used for orbiting and panning
    this._origin = [0, 0, 0]
    //Default distance for default views (top, bottom, left, right, front, back)
    this._distance = 0;
    //shader program used for rendering
    this._shaderProgram = null;

    //Array of handles which can eventually contain handles to one or more models.
    //Models are loaded using 'load()' function.
    this._handles = [];

    //This array keeps data for overlay styles.
    this._stateStyles = new Uint8Array(15 * 15 * 4);

    //This is a switch which can stop animation.
    this._isRunning = true;

    //********************** Run all the initialize functions *****************************
    //compile shaders for use
    this._initShaders();
    //initialize vertex attribute and uniform pointers
    this._initAttributesAndUniforms();
    //initialize mouse events to capture user interaction
    this._initMouseEvents();
}