SHARE
TWEET

Untitled

a guest Mar 18th, 2016 437 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (function($) {
  2.  if (!$.fn.on) {
  3.   $.fn.on = function(events, selector, data, handler) {
  4.    var self = this;
  5.    var args = arguments.length;
  6.    if (args > 3) {
  7.     return self.delegate(selector, events, data, handler)
  8.    } else if (args > 2) {
  9.     if (typeof selector === "string") {
  10.      return self.delegate(selector, events, data)
  11.     } else {
  12.      return self.bind(events, selector, data)
  13.     }
  14.    } else {
  15.     return self.bind(events, selector)
  16.    }
  17.   }
  18.  }
  19.  if (!$.fn.off) {
  20.   $.fn.off = function(events, selector, handler) {
  21.    var self = this;
  22.    var args = arguments.length;
  23.    if (typeof selector === "string") {
  24.     if (args > 2) {
  25.      return self.undelegate(selector, events, handler)
  26.     } else if (args > 1) {
  27.      return self.undelegate(selector, events)
  28.     } else {
  29.      return self.undelegate()
  30.     }
  31.    } else {
  32.     if (args > 1) {
  33.      handler = selector;
  34.      return self.unbind(events, handler)
  35.     } else if (args > 0) {
  36.      return self.unbind(events)
  37.     } else {
  38.      return self.unbind()
  39.     }
  40.    }
  41.   }
  42.  }
  43. })(this.jQuery);
  44. (function(_global) {
  45.  "use strict";
  46.  var shim = {};
  47.  if (typeof exports === "undefined") {
  48.   if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
  49.    shim.exports = {};
  50.    define(function() {
  51.     return shim.exports
  52.    })
  53.   } else {
  54.    shim.exports = typeof window !== "undefined" ? window : _global
  55.   }
  56.  } else {
  57.   shim.exports = exports
  58.  }(function(exports) {
  59.   if (!GLMAT_EPSILON) {
  60.    var GLMAT_EPSILON = 1e-6
  61.   }
  62.   if (!GLMAT_ARRAY_TYPE) {
  63.    var GLMAT_ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array
  64.   }
  65.   if (!GLMAT_RANDOM) {
  66.    var GLMAT_RANDOM = Math.random
  67.   }
  68.   var glMatrix = {};
  69.   glMatrix.setMatrixArrayType = function(type) {
  70.    GLMAT_ARRAY_TYPE = type
  71.   };
  72.   if (typeof exports !== "undefined") {
  73.    exports.glMatrix = glMatrix
  74.   }
  75.   var degree = Math.PI / 180;
  76.   glMatrix.toRadian = function(a) {
  77.    return a * degree
  78.   };
  79.   var vec2 = {};
  80.   vec2.create = function() {
  81.    var out = new GLMAT_ARRAY_TYPE(2);
  82.    out[0] = 0;
  83.    out[1] = 0;
  84.    return out
  85.   };
  86.   vec2.clone = function(a) {
  87.    var out = new GLMAT_ARRAY_TYPE(2);
  88.    out[0] = a[0];
  89.    out[1] = a[1];
  90.    return out
  91.   };
  92.   vec2.fromValues = function(x, y) {
  93.    var out = new GLMAT_ARRAY_TYPE(2);
  94.    out[0] = x;
  95.    out[1] = y;
  96.    return out
  97.   };
  98.   vec2.copy = function(out, a) {
  99.    out[0] = a[0];
  100.    out[1] = a[1];
  101.    return out
  102.   };
  103.   vec2.set = function(out, x, y) {
  104.    out[0] = x;
  105.    out[1] = y;
  106.    return out
  107.   };
  108.   vec2.add = function(out, a, b) {
  109.    out[0] = a[0] + b[0];
  110.    out[1] = a[1] + b[1];
  111.    return out
  112.   };
  113.   vec2.subtract = function(out, a, b) {
  114.    out[0] = a[0] - b[0];
  115.    out[1] = a[1] - b[1];
  116.    return out
  117.   };
  118.   vec2.sub = vec2.subtract;
  119.   vec2.multiply = function(out, a, b) {
  120.    out[0] = a[0] * b[0];
  121.    out[1] = a[1] * b[1];
  122.    return out
  123.   };
  124.   vec2.mul = vec2.multiply;
  125.   vec2.divide = function(out, a, b) {
  126.    out[0] = a[0] / b[0];
  127.    out[1] = a[1] / b[1];
  128.    return out
  129.   };
  130.   vec2.div = vec2.divide;
  131.   vec2.min = function(out, a, b) {
  132.    out[0] = Math.min(a[0], b[0]);
  133.    out[1] = Math.min(a[1], b[1]);
  134.    return out
  135.   };
  136.   vec2.max = function(out, a, b) {
  137.    out[0] = Math.max(a[0], b[0]);
  138.    out[1] = Math.max(a[1], b[1]);
  139.    return out
  140.   };
  141.   vec2.scale = function(out, a, b) {
  142.    out[0] = a[0] * b;
  143.    out[1] = a[1] * b;
  144.    return out
  145.   };
  146.   vec2.scaleAndAdd = function(out, a, b, scale) {
  147.    out[0] = a[0] + b[0] * scale;
  148.    out[1] = a[1] + b[1] * scale;
  149.    return out
  150.   };
  151.   vec2.distance = function(a, b) {
  152.    var x = b[0] - a[0],
  153.     y = b[1] - a[1];
  154.    return Math.sqrt(x * x + y * y)
  155.   };
  156.   vec2.dist = vec2.distance;
  157.   vec2.squaredDistance = function(a, b) {
  158.    var x = b[0] - a[0],
  159.     y = b[1] - a[1];
  160.    return x * x + y * y
  161.   };
  162.   vec2.sqrDist = vec2.squaredDistance;
  163.   vec2.length = function(a) {
  164.    var x = a[0],
  165.     y = a[1];
  166.    return Math.sqrt(x * x + y * y)
  167.   };
  168.   vec2.len = vec2.length;
  169.   vec2.squaredLength = function(a) {
  170.    var x = a[0],
  171.     y = a[1];
  172.    return x * x + y * y
  173.   };
  174.   vec2.sqrLen = vec2.squaredLength;
  175.   vec2.negate = function(out, a) {
  176.    out[0] = -a[0];
  177.    out[1] = -a[1];
  178.    return out
  179.   };
  180.   vec2.normalize = function(out, a) {
  181.    var x = a[0],
  182.     y = a[1];
  183.    var len = x * x + y * y;
  184.    if (len > 0) {
  185.     len = 1 / Math.sqrt(len);
  186.     out[0] = a[0] * len;
  187.     out[1] = a[1] * len
  188.    }
  189.    return out
  190.   };
  191.   vec2.dot = function(a, b) {
  192.    return a[0] * b[0] + a[1] * b[1]
  193.   };
  194.   vec2.cross = function(out, a, b) {
  195.    var z = a[0] * b[1] - a[1] * b[0];
  196.    out[0] = out[1] = 0;
  197.    out[2] = z;
  198.    return out
  199.   };
  200.   vec2.lerp = function(out, a, b, t) {
  201.    var ax = a[0],
  202.     ay = a[1];
  203.    out[0] = ax + t * (b[0] - ax);
  204.    out[1] = ay + t * (b[1] - ay);
  205.    return out
  206.   };
  207.   vec2.random = function(out, scale) {
  208.    scale = scale || 1;
  209.    var r = GLMAT_RANDOM() * 2 * Math.PI;
  210.    out[0] = Math.cos(r) * scale;
  211.    out[1] = Math.sin(r) * scale;
  212.    return out
  213.   };
  214.   vec2.transformMat2 = function(out, a, m) {
  215.    var x = a[0],
  216.     y = a[1];
  217.    out[0] = m[0] * x + m[2] * y;
  218.    out[1] = m[1] * x + m[3] * y;
  219.    return out
  220.   };
  221.   vec2.transformMat2d = function(out, a, m) {
  222.    var x = a[0],
  223.     y = a[1];
  224.    out[0] = m[0] * x + m[2] * y + m[4];
  225.    out[1] = m[1] * x + m[3] * y + m[5];
  226.    return out
  227.   };
  228.   vec2.transformMat3 = function(out, a, m) {
  229.    var x = a[0],
  230.     y = a[1];
  231.    out[0] = m[0] * x + m[3] * y + m[6];
  232.    out[1] = m[1] * x + m[4] * y + m[7];
  233.    return out
  234.   };
  235.   vec2.transformMat4 = function(out, a, m) {
  236.    var x = a[0],
  237.     y = a[1];
  238.    out[0] = m[0] * x + m[4] * y + m[12];
  239.    out[1] = m[1] * x + m[5] * y + m[13];
  240.    return out
  241.   };
  242.   vec2.forEach = function() {
  243.    var vec = vec2.create();
  244.    return function(a, stride, offset, count, fn, arg) {
  245.     var i, l;
  246.     if (!stride) {
  247.      stride = 2
  248.     }
  249.     if (!offset) {
  250.      offset = 0
  251.     }
  252.     if (count) {
  253.      l = Math.min(count * stride + offset, a.length)
  254.     } else {
  255.      l = a.length
  256.     }
  257.     for (i = offset; i < l; i += stride) {
  258.      vec[0] = a[i];
  259.      vec[1] = a[i + 1];
  260.      fn(vec, vec, arg);
  261.      a[i] = vec[0];
  262.      a[i + 1] = vec[1]
  263.     }
  264.     return a
  265.    }
  266.   }();
  267.   vec2.str = function(a) {
  268.    return "vec2(" + a[0] + ", " + a[1] + ")"
  269.   };
  270.   if (typeof exports !== "undefined") {
  271.    exports.vec2 = vec2
  272.   }
  273.   var vec3 = {};
  274.   vec3.create = function() {
  275.    var out = new GLMAT_ARRAY_TYPE(3);
  276.    out[0] = 0;
  277.    out[1] = 0;
  278.    out[2] = 0;
  279.    return out
  280.   };
  281.   vec3.clone = function(a) {
  282.    var out = new GLMAT_ARRAY_TYPE(3);
  283.    out[0] = a[0];
  284.    out[1] = a[1];
  285.    out[2] = a[2];
  286.    return out
  287.   };
  288.   vec3.fromValues = function(x, y, z) {
  289.    var out = new GLMAT_ARRAY_TYPE(3);
  290.    out[0] = x;
  291.    out[1] = y;
  292.    out[2] = z;
  293.    return out
  294.   };
  295.   vec3.copy = function(out, a) {
  296.    out[0] = a[0];
  297.    out[1] = a[1];
  298.    out[2] = a[2];
  299.    return out
  300.   };
  301.   vec3.set = function(out, x, y, z) {
  302.    out[0] = x;
  303.    out[1] = y;
  304.    out[2] = z;
  305.    return out
  306.   };
  307.   vec3.add = function(out, a, b) {
  308.    out[0] = a[0] + b[0];
  309.    out[1] = a[1] + b[1];
  310.    out[2] = a[2] + b[2];
  311.    return out
  312.   };
  313.   vec3.subtract = function(out, a, b) {
  314.    out[0] = a[0] - b[0];
  315.    out[1] = a[1] - b[1];
  316.    out[2] = a[2] - b[2];
  317.    return out
  318.   };
  319.   vec3.sub = vec3.subtract;
  320.   vec3.multiply = function(out, a, b) {
  321.    out[0] = a[0] * b[0];
  322.    out[1] = a[1] * b[1];
  323.    out[2] = a[2] * b[2];
  324.    return out
  325.   };
  326.   vec3.mul = vec3.multiply;
  327.   vec3.divide = function(out, a, b) {
  328.    out[0] = a[0] / b[0];
  329.    out[1] = a[1] / b[1];
  330.    out[2] = a[2] / b[2];
  331.    return out
  332.   };
  333.   vec3.div = vec3.divide;
  334.   vec3.min = function(out, a, b) {
  335.    out[0] = Math.min(a[0], b[0]);
  336.    out[1] = Math.min(a[1], b[1]);
  337.    out[2] = Math.min(a[2], b[2]);
  338.    return out
  339.   };
  340.   vec3.max = function(out, a, b) {
  341.    out[0] = Math.max(a[0], b[0]);
  342.    out[1] = Math.max(a[1], b[1]);
  343.    out[2] = Math.max(a[2], b[2]);
  344.    return out
  345.   };
  346.   vec3.scale = function(out, a, b) {
  347.    out[0] = a[0] * b;
  348.    out[1] = a[1] * b;
  349.    out[2] = a[2] * b;
  350.    return out
  351.   };
  352.   vec3.scaleAndAdd = function(out, a, b, scale) {
  353.    out[0] = a[0] + b[0] * scale;
  354.    out[1] = a[1] + b[1] * scale;
  355.    out[2] = a[2] + b[2] * scale;
  356.    return out
  357.   };
  358.   vec3.distance = function(a, b) {
  359.    var x = b[0] - a[0],
  360.     y = b[1] - a[1],
  361.     z = b[2] - a[2];
  362.    return Math.sqrt(x * x + y * y + z * z)
  363.   };
  364.   vec3.dist = vec3.distance;
  365.   vec3.squaredDistance = function(a, b) {
  366.    var x = b[0] - a[0],
  367.     y = b[1] - a[1],
  368.     z = b[2] - a[2];
  369.    return x * x + y * y + z * z
  370.   };
  371.   vec3.sqrDist = vec3.squaredDistance;
  372.   vec3.length = function(a) {
  373.    var x = a[0],
  374.     y = a[1],
  375.     z = a[2];
  376.    return Math.sqrt(x * x + y * y + z * z)
  377.   };
  378.   vec3.len = vec3.length;
  379.   vec3.squaredLength = function(a) {
  380.    var x = a[0],
  381.     y = a[1],
  382.     z = a[2];
  383.    return x * x + y * y + z * z
  384.   };
  385.   vec3.sqrLen = vec3.squaredLength;
  386.   vec3.negate = function(out, a) {
  387.    out[0] = -a[0];
  388.    out[1] = -a[1];
  389.    out[2] = -a[2];
  390.    return out
  391.   };
  392.   vec3.normalize = function(out, a) {
  393.    var x = a[0],
  394.     y = a[1],
  395.     z = a[2];
  396.    var len = x * x + y * y + z * z;
  397.    if (len > 0) {
  398.     len = 1 / Math.sqrt(len);
  399.     out[0] = a[0] * len;
  400.     out[1] = a[1] * len;
  401.     out[2] = a[2] * len
  402.    }
  403.    return out
  404.   };
  405.   vec3.dot = function(a, b) {
  406.    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
  407.   };
  408.   vec3.cross = function(out, a, b) {
  409.    var ax = a[0],
  410.     ay = a[1],
  411.     az = a[2],
  412.     bx = b[0],
  413.     by = b[1],
  414.     bz = b[2];
  415.    out[0] = ay * bz - az * by;
  416.    out[1] = az * bx - ax * bz;
  417.    out[2] = ax * by - ay * bx;
  418.    return out
  419.   };
  420.   vec3.lerp = function(out, a, b, t) {
  421.    var ax = a[0],
  422.     ay = a[1],
  423.     az = a[2];
  424.    out[0] = ax + t * (b[0] - ax);
  425.    out[1] = ay + t * (b[1] - ay);
  426.    out[2] = az + t * (b[2] - az);
  427.    return out
  428.   };
  429.   vec3.random = function(out, scale) {
  430.    scale = scale || 1;
  431.    var r = GLMAT_RANDOM() * 2 * Math.PI;
  432.    var z = GLMAT_RANDOM() * 2 - 1;
  433.    var zScale = Math.sqrt(1 - z * z) * scale;
  434.    out[0] = Math.cos(r) * zScale;
  435.    out[1] = Math.sin(r) * zScale;
  436.    out[2] = z * scale;
  437.    return out
  438.   };
  439.   vec3.transformMat4 = function(out, a, m) {
  440.    var x = a[0],
  441.     y = a[1],
  442.     z = a[2];
  443.    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
  444.    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
  445.    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
  446.    return out
  447.   };
  448.   vec3.transformMat3 = function(out, a, m) {
  449.    var x = a[0],
  450.     y = a[1],
  451.     z = a[2];
  452.    out[0] = x * m[0] + y * m[3] + z * m[6];
  453.    out[1] = x * m[1] + y * m[4] + z * m[7];
  454.    out[2] = x * m[2] + y * m[5] + z * m[8];
  455.    return out
  456.   };
  457.   vec3.transformQuat = function(out, a, q) {
  458.    var x = a[0],
  459.     y = a[1],
  460.     z = a[2],
  461.     qx = q[0],
  462.     qy = q[1],
  463.     qz = q[2],
  464.     qw = q[3],
  465.     ix = qw * x + qy * z - qz * y,
  466.     iy = qw * y + qz * x - qx * z,
  467.     iz = qw * z + qx * y - qy * x,
  468.     iw = -qx * x - qy * y - qz * z;
  469.    out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
  470.    out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
  471.    out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  472.    return out
  473.   };
  474.   vec3.rotateX = function(out, a, b, c) {
  475.    var p = [],
  476.     r = [];
  477.    p[0] = a[0] - b[0];
  478.    p[1] = a[1] - b[1];
  479.    p[2] = a[2] - b[2];
  480.    r[0] = p[0];
  481.    r[1] = p[1] * Math.cos(c) - p[2] * Math.sin(c);
  482.    r[2] = p[1] * Math.sin(c) + p[2] * Math.cos(c);
  483.    out[0] = r[0] + b[0];
  484.    out[1] = r[1] + b[1];
  485.    out[2] = r[2] + b[2];
  486.    return out
  487.   };
  488.   vec3.rotateY = function(out, a, b, c) {
  489.    var p = [],
  490.     r = [];
  491.    p[0] = a[0] - b[0];
  492.    p[1] = a[1] - b[1];
  493.    p[2] = a[2] - b[2];
  494.    r[0] = p[2] * Math.sin(c) + p[0] * Math.cos(c);
  495.    r[1] = p[1];
  496.    r[2] = p[2] * Math.cos(c) - p[0] * Math.sin(c);
  497.    out[0] = r[0] + b[0];
  498.    out[1] = r[1] + b[1];
  499.    out[2] = r[2] + b[2];
  500.    return out
  501.   };
  502.   vec3.rotateZ = function(out, a, b, c) {
  503.    var p = [],
  504.     r = [];
  505.    p[0] = a[0] - b[0];
  506.    p[1] = a[1] - b[1];
  507.    p[2] = a[2] - b[2];
  508.    r[0] = p[0] * Math.cos(c) - p[1] * Math.sin(c);
  509.    r[1] = p[0] * Math.sin(c) + p[1] * Math.cos(c);
  510.    r[2] = p[2];
  511.    out[0] = r[0] + b[0];
  512.    out[1] = r[1] + b[1];
  513.    out[2] = r[2] + b[2];
  514.    return out
  515.   };
  516.   vec3.forEach = function() {
  517.    var vec = vec3.create();
  518.    return function(a, stride, offset, count, fn, arg) {
  519.     var i, l;
  520.     if (!stride) {
  521.      stride = 3
  522.     }
  523.     if (!offset) {
  524.      offset = 0
  525.     }
  526.     if (count) {
  527.      l = Math.min(count * stride + offset, a.length)
  528.     } else {
  529.      l = a.length
  530.     }
  531.     for (i = offset; i < l; i += stride) {
  532.      vec[0] = a[i];
  533.      vec[1] = a[i + 1];
  534.      vec[2] = a[i + 2];
  535.      fn(vec, vec, arg);
  536.      a[i] = vec[0];
  537.      a[i + 1] = vec[1];
  538.      a[i + 2] = vec[2]
  539.     }
  540.     return a
  541.    }
  542.   }();
  543.   vec3.str = function(a) {
  544.    return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")"
  545.   };
  546.   if (typeof exports !== "undefined") {
  547.    exports.vec3 = vec3
  548.   }
  549.   var vec4 = {};
  550.   vec4.create = function() {
  551.    var out = new GLMAT_ARRAY_TYPE(4);
  552.    out[0] = 0;
  553.    out[1] = 0;
  554.    out[2] = 0;
  555.    out[3] = 0;
  556.    return out
  557.   };
  558.   vec4.clone = function(a) {
  559.    var out = new GLMAT_ARRAY_TYPE(4);
  560.    out[0] = a[0];
  561.    out[1] = a[1];
  562.    out[2] = a[2];
  563.    out[3] = a[3];
  564.    return out
  565.   };
  566.   vec4.fromValues = function(x, y, z, w) {
  567.    var out = new GLMAT_ARRAY_TYPE(4);
  568.    out[0] = x;
  569.    out[1] = y;
  570.    out[2] = z;
  571.    out[3] = w;
  572.    return out
  573.   };
  574.   vec4.copy = function(out, a) {
  575.    out[0] = a[0];
  576.    out[1] = a[1];
  577.    out[2] = a[2];
  578.    out[3] = a[3];
  579.    return out
  580.   };
  581.   vec4.set = function(out, x, y, z, w) {
  582.    out[0] = x;
  583.    out[1] = y;
  584.    out[2] = z;
  585.    out[3] = w;
  586.    return out
  587.   };
  588.   vec4.add = function(out, a, b) {
  589.    out[0] = a[0] + b[0];
  590.    out[1] = a[1] + b[1];
  591.    out[2] = a[2] + b[2];
  592.    out[3] = a[3] + b[3];
  593.    return out
  594.   };
  595.   vec4.subtract = function(out, a, b) {
  596.    out[0] = a[0] - b[0];
  597.    out[1] = a[1] - b[1];
  598.    out[2] = a[2] - b[2];
  599.    out[3] = a[3] - b[3];
  600.    return out
  601.   };
  602.   vec4.sub = vec4.subtract;
  603.   vec4.multiply = function(out, a, b) {
  604.    out[0] = a[0] * b[0];
  605.    out[1] = a[1] * b[1];
  606.    out[2] = a[2] * b[2];
  607.    out[3] = a[3] * b[3];
  608.    return out
  609.   };
  610.   vec4.mul = vec4.multiply;
  611.   vec4.divide = function(out, a, b) {
  612.    out[0] = a[0] / b[0];
  613.    out[1] = a[1] / b[1];
  614.    out[2] = a[2] / b[2];
  615.    out[3] = a[3] / b[3];
  616.    return out
  617.   };
  618.   vec4.div = vec4.divide;
  619.   vec4.min = function(out, a, b) {
  620.    out[0] = Math.min(a[0], b[0]);
  621.    out[1] = Math.min(a[1], b[1]);
  622.    out[2] = Math.min(a[2], b[2]);
  623.    out[3] = Math.min(a[3], b[3]);
  624.    return out
  625.   };
  626.   vec4.max = function(out, a, b) {
  627.    out[0] = Math.max(a[0], b[0]);
  628.    out[1] = Math.max(a[1], b[1]);
  629.    out[2] = Math.max(a[2], b[2]);
  630.    out[3] = Math.max(a[3], b[3]);
  631.    return out
  632.   };
  633.   vec4.scale = function(out, a, b) {
  634.    out[0] = a[0] * b;
  635.    out[1] = a[1] * b;
  636.    out[2] = a[2] * b;
  637.    out[3] = a[3] * b;
  638.    return out
  639.   };
  640.   vec4.scaleAndAdd = function(out, a, b, scale) {
  641.    out[0] = a[0] + b[0] * scale;
  642.    out[1] = a[1] + b[1] * scale;
  643.    out[2] = a[2] + b[2] * scale;
  644.    out[3] = a[3] + b[3] * scale;
  645.    return out
  646.   };
  647.   vec4.distance = function(a, b) {
  648.    var x = b[0] - a[0],
  649.     y = b[1] - a[1],
  650.     z = b[2] - a[2],
  651.     w = b[3] - a[3];
  652.    return Math.sqrt(x * x + y * y + z * z + w * w)
  653.   };
  654.   vec4.dist = vec4.distance;
  655.   vec4.squaredDistance = function(a, b) {
  656.    var x = b[0] - a[0],
  657.     y = b[1] - a[1],
  658.     z = b[2] - a[2],
  659.     w = b[3] - a[3];
  660.    return x * x + y * y + z * z + w * w
  661.   };
  662.   vec4.sqrDist = vec4.squaredDistance;
  663.   vec4.length = function(a) {
  664.    var x = a[0],
  665.     y = a[1],
  666.     z = a[2],
  667.     w = a[3];
  668.    return Math.sqrt(x * x + y * y + z * z + w * w)
  669.   };
  670.   vec4.len = vec4.length;
  671.   vec4.squaredLength = function(a) {
  672.    var x = a[0],
  673.     y = a[1],
  674.     z = a[2],
  675.     w = a[3];
  676.    return x * x + y * y + z * z + w * w
  677.   };
  678.   vec4.sqrLen = vec4.squaredLength;
  679.   vec4.negate = function(out, a) {
  680.    out[0] = -a[0];
  681.    out[1] = -a[1];
  682.    out[2] = -a[2];
  683.    out[3] = -a[3];
  684.    return out
  685.   };
  686.   vec4.normalize = function(out, a) {
  687.    var x = a[0],
  688.     y = a[1],
  689.     z = a[2],
  690.     w = a[3];
  691.    var len = x * x + y * y + z * z + w * w;
  692.    if (len > 0) {
  693.     len = 1 / Math.sqrt(len);
  694.     out[0] = a[0] * len;
  695.     out[1] = a[1] * len;
  696.     out[2] = a[2] * len;
  697.     out[3] = a[3] * len
  698.    }
  699.    return out
  700.   };
  701.   vec4.dot = function(a, b) {
  702.    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
  703.   };
  704.   vec4.lerp = function(out, a, b, t) {
  705.    var ax = a[0],
  706.     ay = a[1],
  707.     az = a[2],
  708.     aw = a[3];
  709.    out[0] = ax + t * (b[0] - ax);
  710.    out[1] = ay + t * (b[1] - ay);
  711.    out[2] = az + t * (b[2] - az);
  712.    out[3] = aw + t * (b[3] - aw);
  713.    return out
  714.   };
  715.   vec4.random = function(out, scale) {
  716.    scale = scale || 1;
  717.    out[0] = GLMAT_RANDOM();
  718.    out[1] = GLMAT_RANDOM();
  719.    out[2] = GLMAT_RANDOM();
  720.    out[3] = GLMAT_RANDOM();
  721.    vec4.normalize(out, out);
  722.    vec4.scale(out, out, scale);
  723.    return out
  724.   };
  725.   vec4.transformMat4 = function(out, a, m) {
  726.    var x = a[0],
  727.     y = a[1],
  728.     z = a[2],
  729.     w = a[3];
  730.    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
  731.    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
  732.    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
  733.    out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
  734.    return out
  735.   };
  736.   vec4.transformQuat = function(out, a, q) {
  737.    var x = a[0],
  738.     y = a[1],
  739.     z = a[2],
  740.     qx = q[0],
  741.     qy = q[1],
  742.     qz = q[2],
  743.     qw = q[3],
  744.     ix = qw * x + qy * z - qz * y,
  745.     iy = qw * y + qz * x - qx * z,
  746.     iz = qw * z + qx * y - qy * x,
  747.     iw = -qx * x - qy * y - qz * z;
  748.    out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
  749.    out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
  750.    out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  751.    return out
  752.   };
  753.   vec4.forEach = function() {
  754.    var vec = vec4.create();
  755.    return function(a, stride, offset, count, fn, arg) {
  756.     var i, l;
  757.     if (!stride) {
  758.      stride = 4
  759.     }
  760.     if (!offset) {
  761.      offset = 0
  762.     }
  763.     if (count) {
  764.      l = Math.min(count * stride + offset, a.length)
  765.     } else {
  766.      l = a.length
  767.     }
  768.     for (i = offset; i < l; i += stride) {
  769.      vec[0] = a[i];
  770.      vec[1] = a[i + 1];
  771.      vec[2] = a[i + 2];
  772.      vec[3] = a[i + 3];
  773.      fn(vec, vec, arg);
  774.      a[i] = vec[0];
  775.      a[i + 1] = vec[1];
  776.      a[i + 2] = vec[2];
  777.      a[i + 3] = vec[3]
  778.     }
  779.     return a
  780.    }
  781.   }();
  782.   vec4.str = function(a) {
  783.    return "vec4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")"
  784.   };
  785.   if (typeof exports !== "undefined") {
  786.    exports.vec4 = vec4
  787.   }
  788.   var mat2 = {};
  789.   mat2.create = function() {
  790.    var out = new GLMAT_ARRAY_TYPE(4);
  791.    out[0] = 1;
  792.    out[1] = 0;
  793.    out[2] = 0;
  794.    out[3] = 1;
  795.    return out
  796.   };
  797.   mat2.clone = function(a) {
  798.    var out = new GLMAT_ARRAY_TYPE(4);
  799.    out[0] = a[0];
  800.    out[1] = a[1];
  801.    out[2] = a[2];
  802.    out[3] = a[3];
  803.    return out
  804.   };
  805.   mat2.copy = function(out, a) {
  806.    out[0] = a[0];
  807.    out[1] = a[1];
  808.    out[2] = a[2];
  809.    out[3] = a[3];
  810.    return out
  811.   };
  812.   mat2.identity = function(out) {
  813.    out[0] = 1;
  814.    out[1] = 0;
  815.    out[2] = 0;
  816.    out[3] = 1;
  817.    return out
  818.   };
  819.   mat2.transpose = function(out, a) {
  820.    if (out === a) {
  821.     var a1 = a[1];
  822.     out[1] = a[2];
  823.     out[2] = a1
  824.    } else {
  825.     out[0] = a[0];
  826.     out[1] = a[2];
  827.     out[2] = a[1];
  828.     out[3] = a[3]
  829.    }
  830.    return out
  831.   };
  832.   mat2.invert = function(out, a) {
  833.    var a0 = a[0],
  834.     a1 = a[1],
  835.     a2 = a[2],
  836.     a3 = a[3],
  837.     det = a0 * a3 - a2 * a1;
  838.    if (!det) {
  839.     return null
  840.    }
  841.    det = 1 / det;
  842.    out[0] = a3 * det;
  843.    out[1] = -a1 * det;
  844.    out[2] = -a2 * det;
  845.    out[3] = a0 * det;
  846.    return out
  847.   };
  848.   mat2.adjoint = function(out, a) {
  849.    var a0 = a[0];
  850.    out[0] = a[3];
  851.    out[1] = -a[1];
  852.    out[2] = -a[2];
  853.    out[3] = a0;
  854.    return out
  855.   };
  856.   mat2.determinant = function(a) {
  857.    return a[0] * a[3] - a[2] * a[1]
  858.   };
  859.   mat2.multiply = function(out, a, b) {
  860.    var a0 = a[0],
  861.     a1 = a[1],
  862.     a2 = a[2],
  863.     a3 = a[3];
  864.    var b0 = b[0],
  865.     b1 = b[1],
  866.     b2 = b[2],
  867.     b3 = b[3];
  868.    out[0] = a0 * b0 + a2 * b1;
  869.    out[1] = a1 * b0 + a3 * b1;
  870.    out[2] = a0 * b2 + a2 * b3;
  871.    out[3] = a1 * b2 + a3 * b3;
  872.    return out
  873.   };
  874.   mat2.mul = mat2.multiply;
  875.   mat2.rotate = function(out, a, rad) {
  876.    var a0 = a[0],
  877.     a1 = a[1],
  878.     a2 = a[2],
  879.     a3 = a[3],
  880.     s = Math.sin(rad),
  881.     c = Math.cos(rad);
  882.    out[0] = a0 * c + a2 * s;
  883.    out[1] = a1 * c + a3 * s;
  884.    out[2] = a0 * -s + a2 * c;
  885.    out[3] = a1 * -s + a3 * c;
  886.    return out
  887.   };
  888.   mat2.scale = function(out, a, v) {
  889.    var a0 = a[0],
  890.     a1 = a[1],
  891.     a2 = a[2],
  892.     a3 = a[3],
  893.     v0 = v[0],
  894.     v1 = v[1];
  895.    out[0] = a0 * v0;
  896.    out[1] = a1 * v0;
  897.    out[2] = a2 * v1;
  898.    out[3] = a3 * v1;
  899.    return out
  900.   };
  901.   mat2.str = function(a) {
  902.    return "mat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")"
  903.   };
  904.   mat2.frob = function(a) {
  905.    return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2))
  906.   };
  907.   mat2.LDU = function(L, D, U, a) {
  908.    L[2] = a[2] / a[0];
  909.    U[0] = a[0];
  910.    U[1] = a[1];
  911.    U[3] = a[3] - L[2] * U[1];
  912.    return [L, D, U]
  913.   };
  914.   if (typeof exports !== "undefined") {
  915.    exports.mat2 = mat2
  916.   }
  917.   var mat2d = {};
  918.   mat2d.create = function() {
  919.    var out = new GLMAT_ARRAY_TYPE(6);
  920.    out[0] = 1;
  921.    out[1] = 0;
  922.    out[2] = 0;
  923.    out[3] = 1;
  924.    out[4] = 0;
  925.    out[5] = 0;
  926.    return out
  927.   };
  928.   mat2d.clone = function(a) {
  929.    var out = new GLMAT_ARRAY_TYPE(6);
  930.    out[0] = a[0];
  931.    out[1] = a[1];
  932.    out[2] = a[2];
  933.    out[3] = a[3];
  934.    out[4] = a[4];
  935.    out[5] = a[5];
  936.    return out
  937.   };
  938.   mat2d.copy = function(out, a) {
  939.    out[0] = a[0];
  940.    out[1] = a[1];
  941.    out[2] = a[2];
  942.    out[3] = a[3];
  943.    out[4] = a[4];
  944.    out[5] = a[5];
  945.    return out
  946.   };
  947.   mat2d.identity = function(out) {
  948.    out[0] = 1;
  949.    out[1] = 0;
  950.    out[2] = 0;
  951.    out[3] = 1;
  952.    out[4] = 0;
  953.    out[5] = 0;
  954.    return out
  955.   };
  956.   mat2d.invert = function(out, a) {
  957.    var aa = a[0],
  958.     ab = a[1],
  959.     ac = a[2],
  960.     ad = a[3],
  961.     atx = a[4],
  962.     aty = a[5];
  963.    var det = aa * ad - ab * ac;
  964.    if (!det) {
  965.     return null
  966.    }
  967.    det = 1 / det;
  968.    out[0] = ad * det;
  969.    out[1] = -ab * det;
  970.    out[2] = -ac * det;
  971.    out[3] = aa * det;
  972.    out[4] = (ac * aty - ad * atx) * det;
  973.    out[5] = (ab * atx - aa * aty) * det;
  974.    return out
  975.   };
  976.   mat2d.determinant = function(a) {
  977.    return a[0] * a[3] - a[1] * a[2]
  978.   };
  979.   mat2d.multiply = function(out, a, b) {
  980.    var a0 = a[0],
  981.     a1 = a[1],
  982.     a2 = a[2],
  983.     a3 = a[3],
  984.     a4 = a[4],
  985.     a5 = a[5],
  986.     b0 = b[0],
  987.     b1 = b[1],
  988.     b2 = b[2],
  989.     b3 = b[3],
  990.     b4 = b[4],
  991.     b5 = b[5];
  992.    out[0] = a0 * b0 + a2 * b1;
  993.    out[1] = a1 * b0 + a3 * b1;
  994.    out[2] = a0 * b2 + a2 * b3;
  995.    out[3] = a1 * b2 + a3 * b3;
  996.    out[4] = a0 * b4 + a2 * b5 + a4;
  997.    out[5] = a1 * b4 + a3 * b5 + a5;
  998.    return out
  999.   };
  1000.   mat2d.mul = mat2d.multiply;
  1001.   mat2d.rotate = function(out, a, rad) {
  1002.    var a0 = a[0],
  1003.     a1 = a[1],
  1004.     a2 = a[2],
  1005.     a3 = a[3],
  1006.     a4 = a[4],
  1007.     a5 = a[5],
  1008.     s = Math.sin(rad),
  1009.     c = Math.cos(rad);
  1010.    out[0] = a0 * c + a2 * s;
  1011.    out[1] = a1 * c + a3 * s;
  1012.    out[2] = a0 * -s + a2 * c;
  1013.    out[3] = a1 * -s + a3 * c;
  1014.    out[4] = a4;
  1015.    out[5] = a5;
  1016.    return out
  1017.   };
  1018.   mat2d.scale = function(out, a, v) {
  1019.    var a0 = a[0],
  1020.     a1 = a[1],
  1021.     a2 = a[2],
  1022.     a3 = a[3],
  1023.     a4 = a[4],
  1024.     a5 = a[5],
  1025.     v0 = v[0],
  1026.     v1 = v[1];
  1027.    out[0] = a0 * v0;
  1028.    out[1] = a1 * v0;
  1029.    out[2] = a2 * v1;
  1030.    out[3] = a3 * v1;
  1031.    out[4] = a4;
  1032.    out[5] = a5;
  1033.    return out
  1034.   };
  1035.   mat2d.translate = function(out, a, v) {
  1036.    var a0 = a[0],
  1037.     a1 = a[1],
  1038.     a2 = a[2],
  1039.     a3 = a[3],
  1040.     a4 = a[4],
  1041.     a5 = a[5],
  1042.     v0 = v[0],
  1043.     v1 = v[1];
  1044.    out[0] = a0;
  1045.    out[1] = a1;
  1046.    out[2] = a2;
  1047.    out[3] = a3;
  1048.    out[4] = a0 * v0 + a2 * v1 + a4;
  1049.    out[5] = a1 * v0 + a3 * v1 + a5;
  1050.    return out
  1051.   };
  1052.   mat2d.str = function(a) {
  1053.    return "mat2d(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ")"
  1054.   };
  1055.   mat2d.frob = function(a) {
  1056.    return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1)
  1057.   };
  1058.   if (typeof exports !== "undefined") {
  1059.    exports.mat2d = mat2d
  1060.   }
  1061.   var mat3 = {};
  1062.   mat3.create = function() {
  1063.    var out = new GLMAT_ARRAY_TYPE(9);
  1064.    out[0] = 1;
  1065.    out[1] = 0;
  1066.    out[2] = 0;
  1067.    out[3] = 0;
  1068.    out[4] = 1;
  1069.    out[5] = 0;
  1070.    out[6] = 0;
  1071.    out[7] = 0;
  1072.    out[8] = 1;
  1073.    return out
  1074.   };
  1075.   mat3.fromMat4 = function(out, a) {
  1076.    out[0] = a[0];
  1077.    out[1] = a[1];
  1078.    out[2] = a[2];
  1079.    out[3] = a[4];
  1080.    out[4] = a[5];
  1081.    out[5] = a[6];
  1082.    out[6] = a[8];
  1083.    out[7] = a[9];
  1084.    out[8] = a[10];
  1085.    return out
  1086.   };
  1087.   mat3.clone = function(a) {
  1088.    var out = new GLMAT_ARRAY_TYPE(9);
  1089.    out[0] = a[0];
  1090.    out[1] = a[1];
  1091.    out[2] = a[2];
  1092.    out[3] = a[3];
  1093.    out[4] = a[4];
  1094.    out[5] = a[5];
  1095.    out[6] = a[6];
  1096.    out[7] = a[7];
  1097.    out[8] = a[8];
  1098.    return out
  1099.   };
  1100.   mat3.copy = function(out, a) {
  1101.    out[0] = a[0];
  1102.    out[1] = a[1];
  1103.    out[2] = a[2];
  1104.    out[3] = a[3];
  1105.    out[4] = a[4];
  1106.    out[5] = a[5];
  1107.    out[6] = a[6];
  1108.    out[7] = a[7];
  1109.    out[8] = a[8];
  1110.    return out
  1111.   };
  1112.   mat3.identity = function(out) {
  1113.    out[0] = 1;
  1114.    out[1] = 0;
  1115.    out[2] = 0;
  1116.    out[3] = 0;
  1117.    out[4] = 1;
  1118.    out[5] = 0;
  1119.    out[6] = 0;
  1120.    out[7] = 0;
  1121.    out[8] = 1;
  1122.    return out
  1123.   };
  1124.   mat3.transpose = function(out, a) {
  1125.    if (out === a) {
  1126.     var a01 = a[1],
  1127.      a02 = a[2],
  1128.      a12 = a[5];
  1129.     out[1] = a[3];
  1130.     out[2] = a[6];
  1131.     out[3] = a01;
  1132.     out[5] = a[7];
  1133.     out[6] = a02;
  1134.     out[7] = a12
  1135.    } else {
  1136.     out[0] = a[0];
  1137.     out[1] = a[3];
  1138.     out[2] = a[6];
  1139.     out[3] = a[1];
  1140.     out[4] = a[4];
  1141.     out[5] = a[7];
  1142.     out[6] = a[2];
  1143.     out[7] = a[5];
  1144.     out[8] = a[8]
  1145.    }
  1146.    return out
  1147.   };
  1148.   mat3.invert = function(out, a) {
  1149.    var a00 = a[0],
  1150.     a01 = a[1],
  1151.     a02 = a[2],
  1152.     a10 = a[3],
  1153.     a11 = a[4],
  1154.     a12 = a[5],
  1155.     a20 = a[6],
  1156.     a21 = a[7],
  1157.     a22 = a[8],
  1158.     b01 = a22 * a11 - a12 * a21,
  1159.     b11 = -a22 * a10 + a12 * a20,
  1160.     b21 = a21 * a10 - a11 * a20,
  1161.     det = a00 * b01 + a01 * b11 + a02 * b21;
  1162.    if (!det) {
  1163.     return null
  1164.    }
  1165.    det = 1 / det;
  1166.    out[0] = b01 * det;
  1167.    out[1] = (-a22 * a01 + a02 * a21) * det;
  1168.    out[2] = (a12 * a01 - a02 * a11) * det;
  1169.    out[3] = b11 * det;
  1170.    out[4] = (a22 * a00 - a02 * a20) * det;
  1171.    out[5] = (-a12 * a00 + a02 * a10) * det;
  1172.    out[6] = b21 * det;
  1173.    out[7] = (-a21 * a00 + a01 * a20) * det;
  1174.    out[8] = (a11 * a00 - a01 * a10) * det;
  1175.    return out
  1176.   };
  1177.   mat3.adjoint = function(out, a) {
  1178.    var a00 = a[0],
  1179.     a01 = a[1],
  1180.     a02 = a[2],
  1181.     a10 = a[3],
  1182.     a11 = a[4],
  1183.     a12 = a[5],
  1184.     a20 = a[6],
  1185.     a21 = a[7],
  1186.     a22 = a[8];
  1187.    out[0] = a11 * a22 - a12 * a21;
  1188.    out[1] = a02 * a21 - a01 * a22;
  1189.    out[2] = a01 * a12 - a02 * a11;
  1190.    out[3] = a12 * a20 - a10 * a22;
  1191.    out[4] = a00 * a22 - a02 * a20;
  1192.    out[5] = a02 * a10 - a00 * a12;
  1193.    out[6] = a10 * a21 - a11 * a20;
  1194.    out[7] = a01 * a20 - a00 * a21;
  1195.    out[8] = a00 * a11 - a01 * a10;
  1196.    return out
  1197.   };
  1198.   mat3.determinant = function(a) {
  1199.    var a00 = a[0],
  1200.     a01 = a[1],
  1201.     a02 = a[2],
  1202.     a10 = a[3],
  1203.     a11 = a[4],
  1204.     a12 = a[5],
  1205.     a20 = a[6],
  1206.     a21 = a[7],
  1207.     a22 = a[8];
  1208.    return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20)
  1209.   };
  1210.   mat3.multiply = function(out, a, b) {
  1211.    var a00 = a[0],
  1212.     a01 = a[1],
  1213.     a02 = a[2],
  1214.     a10 = a[3],
  1215.     a11 = a[4],
  1216.     a12 = a[5],
  1217.     a20 = a[6],
  1218.     a21 = a[7],
  1219.     a22 = a[8],
  1220.     b00 = b[0],
  1221.     b01 = b[1],
  1222.     b02 = b[2],
  1223.     b10 = b[3],
  1224.     b11 = b[4],
  1225.     b12 = b[5],
  1226.     b20 = b[6],
  1227.     b21 = b[7],
  1228.     b22 = b[8];
  1229.    out[0] = b00 * a00 + b01 * a10 + b02 * a20;
  1230.    out[1] = b00 * a01 + b01 * a11 + b02 * a21;
  1231.    out[2] = b00 * a02 + b01 * a12 + b02 * a22;
  1232.    out[3] = b10 * a00 + b11 * a10 + b12 * a20;
  1233.    out[4] = b10 * a01 + b11 * a11 + b12 * a21;
  1234.    out[5] = b10 * a02 + b11 * a12 + b12 * a22;
  1235.    out[6] = b20 * a00 + b21 * a10 + b22 * a20;
  1236.    out[7] = b20 * a01 + b21 * a11 + b22 * a21;
  1237.    out[8] = b20 * a02 + b21 * a12 + b22 * a22;
  1238.    return out
  1239.   };
  1240.   mat3.mul = mat3.multiply;
  1241.   mat3.translate = function(out, a, v) {
  1242.    var a00 = a[0],
  1243.     a01 = a[1],
  1244.     a02 = a[2],
  1245.     a10 = a[3],
  1246.     a11 = a[4],
  1247.     a12 = a[5],
  1248.     a20 = a[6],
  1249.     a21 = a[7],
  1250.     a22 = a[8],
  1251.     x = v[0],
  1252.     y = v[1];
  1253.    out[0] = a00;
  1254.    out[1] = a01;
  1255.    out[2] = a02;
  1256.    out[3] = a10;
  1257.    out[4] = a11;
  1258.    out[5] = a12;
  1259.    out[6] = x * a00 + y * a10 + a20;
  1260.    out[7] = x * a01 + y * a11 + a21;
  1261.    out[8] = x * a02 + y * a12 + a22;
  1262.    return out
  1263.   };
  1264.   mat3.rotate = function(out, a, rad) {
  1265.    var a00 = a[0],
  1266.     a01 = a[1],
  1267.     a02 = a[2],
  1268.     a10 = a[3],
  1269.     a11 = a[4],
  1270.     a12 = a[5],
  1271.     a20 = a[6],
  1272.     a21 = a[7],
  1273.     a22 = a[8],
  1274.     s = Math.sin(rad),
  1275.     c = Math.cos(rad);
  1276.    out[0] = c * a00 + s * a10;
  1277.    out[1] = c * a01 + s * a11;
  1278.    out[2] = c * a02 + s * a12;
  1279.    out[3] = c * a10 - s * a00;
  1280.    out[4] = c * a11 - s * a01;
  1281.    out[5] = c * a12 - s * a02;
  1282.    out[6] = a20;
  1283.    out[7] = a21;
  1284.    out[8] = a22;
  1285.    return out
  1286.   };
  1287.   mat3.scale = function(out, a, v) {
  1288.    var x = v[0],
  1289.     y = v[1];
  1290.    out[0] = x * a[0];
  1291.    out[1] = x * a[1];
  1292.    out[2] = x * a[2];
  1293.    out[3] = y * a[3];
  1294.    out[4] = y * a[4];
  1295.    out[5] = y * a[5];
  1296.    out[6] = a[6];
  1297.    out[7] = a[7];
  1298.    out[8] = a[8];
  1299.    return out
  1300.   };
  1301.   mat3.fromMat2d = function(out, a) {
  1302.    out[0] = a[0];
  1303.    out[1] = a[1];
  1304.    out[2] = 0;
  1305.    out[3] = a[2];
  1306.    out[4] = a[3];
  1307.    out[5] = 0;
  1308.    out[6] = a[4];
  1309.    out[7] = a[5];
  1310.    out[8] = 1;
  1311.    return out
  1312.   };
  1313.   mat3.fromQuat = function(out, q) {
  1314.    var x = q[0],
  1315.     y = q[1],
  1316.     z = q[2],
  1317.     w = q[3],
  1318.     x2 = x + x,
  1319.     y2 = y + y,
  1320.     z2 = z + z,
  1321.     xx = x * x2,
  1322.     yx = y * x2,
  1323.     yy = y * y2,
  1324.     zx = z * x2,
  1325.     zy = z * y2,
  1326.     zz = z * z2,
  1327.     wx = w * x2,
  1328.     wy = w * y2,
  1329.     wz = w * z2;
  1330.    out[0] = 1 - yy - zz;
  1331.    out[3] = yx - wz;
  1332.    out[6] = zx + wy;
  1333.    out[1] = yx + wz;
  1334.    out[4] = 1 - xx - zz;
  1335.    out[7] = zy - wx;
  1336.    out[2] = zx - wy;
  1337.    out[5] = zy + wx;
  1338.    out[8] = 1 - xx - yy;
  1339.    return out
  1340.   };
  1341.   mat3.normalFromMat4 = function(out, a) {
  1342.    var a00 = a[0],
  1343.     a01 = a[1],
  1344.     a02 = a[2],
  1345.     a03 = a[3],
  1346.     a10 = a[4],
  1347.     a11 = a[5],
  1348.     a12 = a[6],
  1349.     a13 = a[7],
  1350.     a20 = a[8],
  1351.     a21 = a[9],
  1352.     a22 = a[10],
  1353.     a23 = a[11],
  1354.     a30 = a[12],
  1355.     a31 = a[13],
  1356.     a32 = a[14],
  1357.     a33 = a[15],
  1358.     b00 = a00 * a11 - a01 * a10,
  1359.     b01 = a00 * a12 - a02 * a10,
  1360.     b02 = a00 * a13 - a03 * a10,
  1361.     b03 = a01 * a12 - a02 * a11,
  1362.     b04 = a01 * a13 - a03 * a11,
  1363.     b05 = a02 * a13 - a03 * a12,
  1364.     b06 = a20 * a31 - a21 * a30,
  1365.     b07 = a20 * a32 - a22 * a30,
  1366.     b08 = a20 * a33 - a23 * a30,
  1367.     b09 = a21 * a32 - a22 * a31,
  1368.     b10 = a21 * a33 - a23 * a31,
  1369.     b11 = a22 * a33 - a23 * a32,
  1370.     det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  1371.    if (!det) {
  1372.     return null
  1373.    }
  1374.    det = 1 / det;
  1375.    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  1376.    out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  1377.    out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  1378.    out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  1379.    out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  1380.    out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  1381.    out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  1382.    out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  1383.    out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  1384.    return out
  1385.   };
  1386.   mat3.str = function(a) {
  1387.    return "mat3(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ")"
  1388.   };
  1389.   mat3.frob = function(a) {
  1390.    return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2))
  1391.   };
  1392.   if (typeof exports !== "undefined") {
  1393.    exports.mat3 = mat3
  1394.   }
  1395.   var mat4 = {};
  1396.   mat4.create = function() {
  1397.    var out = new GLMAT_ARRAY_TYPE(16);
  1398.    out[0] = 1;
  1399.    out[1] = 0;
  1400.    out[2] = 0;
  1401.    out[3] = 0;
  1402.    out[4] = 0;
  1403.    out[5] = 1;
  1404.    out[6] = 0;
  1405.    out[7] = 0;
  1406.    out[8] = 0;
  1407.    out[9] = 0;
  1408.    out[10] = 1;
  1409.    out[11] = 0;
  1410.    out[12] = 0;
  1411.    out[13] = 0;
  1412.    out[14] = 0;
  1413.    out[15] = 1;
  1414.    return out
  1415.   };
  1416.   mat4.clone = function(a) {
  1417.    var out = new GLMAT_ARRAY_TYPE(16);
  1418.    out[0] = a[0];
  1419.    out[1] = a[1];
  1420.    out[2] = a[2];
  1421.    out[3] = a[3];
  1422.    out[4] = a[4];
  1423.    out[5] = a[5];
  1424.    out[6] = a[6];
  1425.    out[7] = a[7];
  1426.    out[8] = a[8];
  1427.    out[9] = a[9];
  1428.    out[10] = a[10];
  1429.    out[11] = a[11];
  1430.    out[12] = a[12];
  1431.    out[13] = a[13];
  1432.    out[14] = a[14];
  1433.    out[15] = a[15];
  1434.    return out
  1435.   };
  1436.   mat4.copy = function(out, a) {
  1437.    out[0] = a[0];
  1438.    out[1] = a[1];
  1439.    out[2] = a[2];
  1440.    out[3] = a[3];
  1441.    out[4] = a[4];
  1442.    out[5] = a[5];
  1443.    out[6] = a[6];
  1444.    out[7] = a[7];
  1445.    out[8] = a[8];
  1446.    out[9] = a[9];
  1447.    out[10] = a[10];
  1448.    out[11] = a[11];
  1449.    out[12] = a[12];
  1450.    out[13] = a[13];
  1451.    out[14] = a[14];
  1452.    out[15] = a[15];
  1453.    return out
  1454.   };
  1455.   mat4.identity = function(out) {
  1456.    out[0] = 1;
  1457.    out[1] = 0;
  1458.    out[2] = 0;
  1459.    out[3] = 0;
  1460.    out[4] = 0;
  1461.    out[5] = 1;
  1462.    out[6] = 0;
  1463.    out[7] = 0;
  1464.    out[8] = 0;
  1465.    out[9] = 0;
  1466.    out[10] = 1;
  1467.    out[11] = 0;
  1468.    out[12] = 0;
  1469.    out[13] = 0;
  1470.    out[14] = 0;
  1471.    out[15] = 1;
  1472.    return out
  1473.   };
  1474.   mat4.transpose = function(out, a) {
  1475.    if (out === a) {
  1476.     var a01 = a[1],
  1477.      a02 = a[2],
  1478.      a03 = a[3],
  1479.      a12 = a[6],
  1480.      a13 = a[7],
  1481.      a23 = a[11];
  1482.     out[1] = a[4];
  1483.     out[2] = a[8];
  1484.     out[3] = a[12];
  1485.     out[4] = a01;
  1486.     out[6] = a[9];
  1487.     out[7] = a[13];
  1488.     out[8] = a02;
  1489.     out[9] = a12;
  1490.     out[11] = a[14];
  1491.     out[12] = a03;
  1492.     out[13] = a13;
  1493.     out[14] = a23
  1494.    } else {
  1495.     out[0] = a[0];
  1496.     out[1] = a[4];
  1497.     out[2] = a[8];
  1498.     out[3] = a[12];
  1499.     out[4] = a[1];
  1500.     out[5] = a[5];
  1501.     out[6] = a[9];
  1502.     out[7] = a[13];
  1503.     out[8] = a[2];
  1504.     out[9] = a[6];
  1505.     out[10] = a[10];
  1506.     out[11] = a[14];
  1507.     out[12] = a[3];
  1508.     out[13] = a[7];
  1509.     out[14] = a[11];
  1510.     out[15] = a[15]
  1511.    }
  1512.    return out
  1513.   };
  1514.   mat4.invert = function(out, a) {
  1515.    var a00 = a[0],
  1516.     a01 = a[1],
  1517.     a02 = a[2],
  1518.     a03 = a[3],
  1519.     a10 = a[4],
  1520.     a11 = a[5],
  1521.     a12 = a[6],
  1522.     a13 = a[7],
  1523.     a20 = a[8],
  1524.     a21 = a[9],
  1525.     a22 = a[10],
  1526.     a23 = a[11],
  1527.     a30 = a[12],
  1528.     a31 = a[13],
  1529.     a32 = a[14],
  1530.     a33 = a[15],
  1531.     b00 = a00 * a11 - a01 * a10,
  1532.     b01 = a00 * a12 - a02 * a10,
  1533.     b02 = a00 * a13 - a03 * a10,
  1534.     b03 = a01 * a12 - a02 * a11,
  1535.     b04 = a01 * a13 - a03 * a11,
  1536.     b05 = a02 * a13 - a03 * a12,
  1537.     b06 = a20 * a31 - a21 * a30,
  1538.     b07 = a20 * a32 - a22 * a30,
  1539.     b08 = a20 * a33 - a23 * a30,
  1540.     b09 = a21 * a32 - a22 * a31,
  1541.     b10 = a21 * a33 - a23 * a31,
  1542.     b11 = a22 * a33 - a23 * a32,
  1543.     det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  1544.    if (!det) {
  1545.     return null
  1546.    }
  1547.    det = 1 / det;
  1548.    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  1549.    out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  1550.    out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  1551.    out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  1552.    out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  1553.    out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  1554.    out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  1555.    out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  1556.    out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  1557.    out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  1558.    out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  1559.    out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  1560.    out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  1561.    out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  1562.    out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  1563.    out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  1564.    return out
  1565.   };
  1566.   mat4.adjoint = function(out, a) {
  1567.    var a00 = a[0],
  1568.     a01 = a[1],
  1569.     a02 = a[2],
  1570.     a03 = a[3],
  1571.     a10 = a[4],
  1572.     a11 = a[5],
  1573.     a12 = a[6],
  1574.     a13 = a[7],
  1575.     a20 = a[8],
  1576.     a21 = a[9],
  1577.     a22 = a[10],
  1578.     a23 = a[11],
  1579.     a30 = a[12],
  1580.     a31 = a[13],
  1581.     a32 = a[14],
  1582.     a33 = a[15];
  1583.    out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);
  1584.    out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
  1585.    out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);
  1586.    out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
  1587.    out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
  1588.    out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);
  1589.    out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
  1590.    out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);
  1591.    out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);
  1592.    out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
  1593.    out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);
  1594.    out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
  1595.    out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
  1596.    out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);
  1597.    out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
  1598.    out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);
  1599.    return out
  1600.   };
  1601.   mat4.determinant = function(a) {
  1602.    var a00 = a[0],
  1603.     a01 = a[1],
  1604.     a02 = a[2],
  1605.     a03 = a[3],
  1606.     a10 = a[4],
  1607.     a11 = a[5],
  1608.     a12 = a[6],
  1609.     a13 = a[7],
  1610.     a20 = a[8],
  1611.     a21 = a[9],
  1612.     a22 = a[10],
  1613.     a23 = a[11],
  1614.     a30 = a[12],
  1615.     a31 = a[13],
  1616.     a32 = a[14],
  1617.     a33 = a[15],
  1618.     b00 = a00 * a11 - a01 * a10,
  1619.     b01 = a00 * a12 - a02 * a10,
  1620.     b02 = a00 * a13 - a03 * a10,
  1621.     b03 = a01 * a12 - a02 * a11,
  1622.     b04 = a01 * a13 - a03 * a11,
  1623.     b05 = a02 * a13 - a03 * a12,
  1624.     b06 = a20 * a31 - a21 * a30,
  1625.     b07 = a20 * a32 - a22 * a30,
  1626.     b08 = a20 * a33 - a23 * a30,
  1627.     b09 = a21 * a32 - a22 * a31,
  1628.     b10 = a21 * a33 - a23 * a31,
  1629.     b11 = a22 * a33 - a23 * a32;
  1630.    return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06
  1631.   };
  1632.   mat4.multiply = function(out, a, b) {
  1633.    var a00 = a[0],
  1634.     a01 = a[1],
  1635.     a02 = a[2],
  1636.     a03 = a[3],
  1637.     a10 = a[4],
  1638.     a11 = a[5],
  1639.     a12 = a[6],
  1640.     a13 = a[7],
  1641.     a20 = a[8],
  1642.     a21 = a[9],
  1643.     a22 = a[10],
  1644.     a23 = a[11],
  1645.     a30 = a[12],
  1646.     a31 = a[13],
  1647.     a32 = a[14],
  1648.     a33 = a[15];
  1649.    var b0 = b[0],
  1650.     b1 = b[1],
  1651.     b2 = b[2],
  1652.     b3 = b[3];
  1653.    out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  1654.    out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  1655.    out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  1656.    out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  1657.    b0 = b[4];
  1658.    b1 = b[5];
  1659.    b2 = b[6];
  1660.    b3 = b[7];
  1661.    out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  1662.    out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  1663.    out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  1664.    out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  1665.    b0 = b[8];
  1666.    b1 = b[9];
  1667.    b2 = b[10];
  1668.    b3 = b[11];
  1669.    out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  1670.    out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  1671.    out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  1672.    out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  1673.    b0 = b[12];
  1674.    b1 = b[13];
  1675.    b2 = b[14];
  1676.    b3 = b[15];
  1677.    out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  1678.    out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  1679.    out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  1680.    out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  1681.    return out
  1682.   };
  1683.   mat4.mul = mat4.multiply;
  1684.   mat4.translate = function(out, a, v) {
  1685.    var x = v[0],
  1686.     y = v[1],
  1687.     z = v[2],
  1688.     a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23;
  1689.    if (a === out) {
  1690.     out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
  1691.     out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
  1692.     out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
  1693.     out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]
  1694.    } else {
  1695.     a00 = a[0];
  1696.     a01 = a[1];
  1697.     a02 = a[2];
  1698.     a03 = a[3];
  1699.     a10 = a[4];
  1700.     a11 = a[5];
  1701.     a12 = a[6];
  1702.     a13 = a[7];
  1703.     a20 = a[8];
  1704.     a21 = a[9];
  1705.     a22 = a[10];
  1706.     a23 = a[11];
  1707.     out[0] = a00;
  1708.     out[1] = a01;
  1709.     out[2] = a02;
  1710.     out[3] = a03;
  1711.     out[4] = a10;
  1712.     out[5] = a11;
  1713.     out[6] = a12;
  1714.     out[7] = a13;
  1715.     out[8] = a20;
  1716.     out[9] = a21;
  1717.     out[10] = a22;
  1718.     out[11] = a23;
  1719.     out[12] = a00 * x + a10 * y + a20 * z + a[12];
  1720.     out[13] = a01 * x + a11 * y + a21 * z + a[13];
  1721.     out[14] = a02 * x + a12 * y + a22 * z + a[14];
  1722.     out[15] = a03 * x + a13 * y + a23 * z + a[15]
  1723.    }
  1724.    return out
  1725.   };
  1726.   mat4.scale = function(out, a, v) {
  1727.    var x = v[0],
  1728.     y = v[1],
  1729.     z = v[2];
  1730.    out[0] = a[0] * x;
  1731.    out[1] = a[1] * x;
  1732.    out[2] = a[2] * x;
  1733.    out[3] = a[3] * x;
  1734.    out[4] = a[4] * y;
  1735.    out[5] = a[5] * y;
  1736.    out[6] = a[6] * y;
  1737.    out[7] = a[7] * y;
  1738.    out[8] = a[8] * z;
  1739.    out[9] = a[9] * z;
  1740.    out[10] = a[10] * z;
  1741.    out[11] = a[11] * z;
  1742.    out[12] = a[12];
  1743.    out[13] = a[13];
  1744.    out[14] = a[14];
  1745.    out[15] = a[15];
  1746.    return out
  1747.   };
  1748.   mat4.rotate = function(out, a, rad, axis) {
  1749.    var x = axis[0],
  1750.     y = axis[1],
  1751.     z = axis[2],
  1752.     len = Math.sqrt(x * x + y * y + z * z),
  1753.     s, c, t, a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20, b21, b22;
  1754.    if (Math.abs(len) < GLMAT_EPSILON) {
  1755.     return null
  1756.    }
  1757.    len = 1 / len;
  1758.    x *= len;
  1759.    y *= len;
  1760.    z *= len;
  1761.    s = Math.sin(rad);
  1762.    c = Math.cos(rad);
  1763.    t = 1 - c;
  1764.    a00 = a[0];
  1765.    a01 = a[1];
  1766.    a02 = a[2];
  1767.    a03 = a[3];
  1768.    a10 = a[4];
  1769.    a11 = a[5];
  1770.    a12 = a[6];
  1771.    a13 = a[7];
  1772.    a20 = a[8];
  1773.    a21 = a[9];
  1774.    a22 = a[10];
  1775.    a23 = a[11];
  1776.    b00 = x * x * t + c;
  1777.    b01 = y * x * t + z * s;
  1778.    b02 = z * x * t - y * s;
  1779.    b10 = x * y * t - z * s;
  1780.    b11 = y * y * t + c;
  1781.    b12 = z * y * t + x * s;
  1782.    b20 = x * z * t + y * s;
  1783.    b21 = y * z * t - x * s;
  1784.    b22 = z * z * t + c;
  1785.    out[0] = a00 * b00 + a10 * b01 + a20 * b02;
  1786.    out[1] = a01 * b00 + a11 * b01 + a21 * b02;
  1787.    out[2] = a02 * b00 + a12 * b01 + a22 * b02;
  1788.    out[3] = a03 * b00 + a13 * b01 + a23 * b02;
  1789.    out[4] = a00 * b10 + a10 * b11 + a20 * b12;
  1790.    out[5] = a01 * b10 + a11 * b11 + a21 * b12;
  1791.    out[6] = a02 * b10 + a12 * b11 + a22 * b12;
  1792.    out[7] = a03 * b10 + a13 * b11 + a23 * b12;
  1793.    out[8] = a00 * b20 + a10 * b21 + a20 * b22;
  1794.    out[9] = a01 * b20 + a11 * b21 + a21 * b22;
  1795.    out[10] = a02 * b20 + a12 * b21 + a22 * b22;
  1796.    out[11] = a03 * b20 + a13 * b21 + a23 * b22;
  1797.    if (a !== out) {
  1798.     out[12] = a[12];
  1799.     out[13] = a[13];
  1800.     out[14] = a[14];
  1801.     out[15] = a[15]
  1802.    }
  1803.    return out
  1804.   };
  1805.   mat4.rotateX = function(out, a, rad) {
  1806.    var s = Math.sin(rad),
  1807.     c = Math.cos(rad),
  1808.     a10 = a[4],
  1809.     a11 = a[5],
  1810.     a12 = a[6],
  1811.     a13 = a[7],
  1812.     a20 = a[8],
  1813.     a21 = a[9],
  1814.     a22 = a[10],
  1815.     a23 = a[11];
  1816.    if (a !== out) {
  1817.     out[0] = a[0];
  1818.     out[1] = a[1];
  1819.     out[2] = a[2];
  1820.     out[3] = a[3];
  1821.     out[12] = a[12];
  1822.     out[13] = a[13];
  1823.     out[14] = a[14];
  1824.     out[15] = a[15]
  1825.    }
  1826.    out[4] = a10 * c + a20 * s;
  1827.    out[5] = a11 * c + a21 * s;
  1828.    out[6] = a12 * c + a22 * s;
  1829.    out[7] = a13 * c + a23 * s;
  1830.    out[8] = a20 * c - a10 * s;
  1831.    out[9] = a21 * c - a11 * s;
  1832.    out[10] = a22 * c - a12 * s;
  1833.    out[11] = a23 * c - a13 * s;
  1834.    return out
  1835.   };
  1836.   mat4.rotateY = function(out, a, rad) {
  1837.    var s = Math.sin(rad),
  1838.     c = Math.cos(rad),
  1839.     a00 = a[0],
  1840.     a01 = a[1],
  1841.     a02 = a[2],
  1842.     a03 = a[3],
  1843.     a20 = a[8],
  1844.     a21 = a[9],
  1845.     a22 = a[10],
  1846.     a23 = a[11];
  1847.    if (a !== out) {
  1848.     out[4] = a[4];
  1849.     out[5] = a[5];
  1850.     out[6] = a[6];
  1851.     out[7] = a[7];
  1852.     out[12] = a[12];
  1853.     out[13] = a[13];
  1854.     out[14] = a[14];
  1855.     out[15] = a[15]
  1856.    }
  1857.    out[0] = a00 * c - a20 * s;
  1858.    out[1] = a01 * c - a21 * s;
  1859.    out[2] = a02 * c - a22 * s;
  1860.    out[3] = a03 * c - a23 * s;
  1861.    out[8] = a00 * s + a20 * c;
  1862.    out[9] = a01 * s + a21 * c;
  1863.    out[10] = a02 * s + a22 * c;
  1864.    out[11] = a03 * s + a23 * c;
  1865.    return out
  1866.   };
  1867.   mat4.rotateZ = function(out, a, rad) {
  1868.    var s = Math.sin(rad),
  1869.     c = Math.cos(rad),
  1870.     a00 = a[0],
  1871.     a01 = a[1],
  1872.     a02 = a[2],
  1873.     a03 = a[3],
  1874.     a10 = a[4],
  1875.     a11 = a[5],
  1876.     a12 = a[6],
  1877.     a13 = a[7];
  1878.    if (a !== out) {
  1879.     out[8] = a[8];
  1880.     out[9] = a[9];
  1881.     out[10] = a[10];
  1882.     out[11] = a[11];
  1883.     out[12] = a[12];
  1884.     out[13] = a[13];
  1885.     out[14] = a[14];
  1886.     out[15] = a[15]
  1887.    }
  1888.    out[0] = a00 * c + a10 * s;
  1889.    out[1] = a01 * c + a11 * s;
  1890.    out[2] = a02 * c + a12 * s;
  1891.    out[3] = a03 * c + a13 * s;
  1892.    out[4] = a10 * c - a00 * s;
  1893.    out[5] = a11 * c - a01 * s;
  1894.    out[6] = a12 * c - a02 * s;
  1895.    out[7] = a13 * c - a03 * s;
  1896.    return out
  1897.   };
  1898.   mat4.fromRotationTranslation = function(out, q, v) {
  1899.    var x = q[0],
  1900.     y = q[1],
  1901.     z = q[2],
  1902.     w = q[3],
  1903.     x2 = x + x,
  1904.     y2 = y + y,
  1905.     z2 = z + z,
  1906.     xx = x * x2,
  1907.     xy = x * y2,
  1908.     xz = x * z2,
  1909.     yy = y * y2,
  1910.     yz = y * z2,
  1911.     zz = z * z2,
  1912.     wx = w * x2,
  1913.     wy = w * y2,
  1914.     wz = w * z2;
  1915.    out[0] = 1 - (yy + zz);
  1916.    out[1] = xy + wz;
  1917.    out[2] = xz - wy;
  1918.    out[3] = 0;
  1919.    out[4] = xy - wz;
  1920.    out[5] = 1 - (xx + zz);
  1921.    out[6] = yz + wx;
  1922.    out[7] = 0;
  1923.    out[8] = xz + wy;
  1924.    out[9] = yz - wx;
  1925.    out[10] = 1 - (xx + yy);
  1926.    out[11] = 0;
  1927.    out[12] = v[0];
  1928.    out[13] = v[1];
  1929.    out[14] = v[2];
  1930.    out[15] = 1;
  1931.    return out
  1932.   };
  1933.   mat4.fromQuat = function(out, q) {
  1934.    var x = q[0],
  1935.     y = q[1],
  1936.     z = q[2],
  1937.     w = q[3],
  1938.     x2 = x + x,
  1939.     y2 = y + y,
  1940.     z2 = z + z,
  1941.     xx = x * x2,
  1942.     yx = y * x2,
  1943.     yy = y * y2,
  1944.     zx = z * x2,
  1945.     zy = z * y2,
  1946.     zz = z * z2,
  1947.     wx = w * x2,
  1948.     wy = w * y2,
  1949.     wz = w * z2;
  1950.    out[0] = 1 - yy - zz;
  1951.    out[1] = yx + wz;
  1952.    out[2] = zx - wy;
  1953.    out[3] = 0;
  1954.    out[4] = yx - wz;
  1955.    out[5] = 1 - xx - zz;
  1956.    out[6] = zy + wx;
  1957.    out[7] = 0;
  1958.    out[8] = zx + wy;
  1959.    out[9] = zy - wx;
  1960.    out[10] = 1 - xx - yy;
  1961.    out[11] = 0;
  1962.    out[12] = 0;
  1963.    out[13] = 0;
  1964.    out[14] = 0;
  1965.    out[15] = 1;
  1966.    return out
  1967.   };
  1968.   mat4.frustum = function(out, left, right, bottom, top, near, far) {
  1969.    var rl = 1 / (right - left),
  1970.     tb = 1 / (top - bottom),
  1971.     nf = 1 / (near - far);
  1972.    out[0] = near * 2 * rl;
  1973.    out[1] = 0;
  1974.    out[2] = 0;
  1975.    out[3] = 0;
  1976.    out[4] = 0;
  1977.    out[5] = near * 2 * tb;
  1978.    out[6] = 0;
  1979.    out[7] = 0;
  1980.    out[8] = (right + left) * rl;
  1981.    out[9] = (top + bottom) * tb;
  1982.    out[10] = (far + near) * nf;
  1983.    out[11] = -1;
  1984.    out[12] = 0;
  1985.    out[13] = 0;
  1986.    out[14] = far * near * 2 * nf;
  1987.    out[15] = 0;
  1988.    return out
  1989.   };
  1990.   mat4.perspective = function(out, fovy, aspect, near, far) {
  1991.    var f = 1 / Math.tan(fovy / 2),
  1992.     nf = 1 / (near - far);
  1993.    out[0] = f / aspect;
  1994.    out[1] = 0;
  1995.    out[2] = 0;
  1996.    out[3] = 0;
  1997.    out[4] = 0;
  1998.    out[5] = f;
  1999.    out[6] = 0;
  2000.    out[7] = 0;
  2001.    out[8] = 0;
  2002.    out[9] = 0;
  2003.    out[10] = (far + near) * nf;
  2004.    out[11] = -1;
  2005.    out[12] = 0;
  2006.    out[13] = 0;
  2007.    out[14] = 2 * far * near * nf;
  2008.    out[15] = 0;
  2009.    return out
  2010.   };
  2011.   mat4.ortho = function(out, left, right, bottom, top, near, far) {
  2012.    var lr = 1 / (left - right),
  2013.     bt = 1 / (bottom - top),
  2014.     nf = 1 / (near - far);
  2015.    out[0] = -2 * lr;
  2016.    out[1] = 0;
  2017.    out[2] = 0;
  2018.    out[3] = 0;
  2019.    out[4] = 0;
  2020.    out[5] = -2 * bt;
  2021.    out[6] = 0;
  2022.    out[7] = 0;
  2023.    out[8] = 0;
  2024.    out[9] = 0;
  2025.    out[10] = 2 * nf;
  2026.    out[11] = 0;
  2027.    out[12] = (left + right) * lr;
  2028.    out[13] = (top + bottom) * bt;
  2029.    out[14] = (far + near) * nf;
  2030.    out[15] = 1;
  2031.    return out
  2032.   };
  2033.   mat4.lookAt = function(out, eye, center, up) {
  2034.    var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, eyex = eye[0],
  2035.     eyey = eye[1],
  2036.     eyez = eye[2],
  2037.     upx = up[0],
  2038.     upy = up[1],
  2039.     upz = up[2],
  2040.     centerx = center[0],
  2041.     centery = center[1],
  2042.     centerz = center[2];
  2043.    if (Math.abs(eyex - centerx) < GLMAT_EPSILON && Math.abs(eyey - centery) < GLMAT_EPSILON && Math.abs(eyez - centerz) < GLMAT_EPSILON) {
  2044.     return mat4.identity(out)
  2045.    }
  2046.    z0 = eyex - centerx;
  2047.    z1 = eyey - centery;
  2048.    z2 = eyez - centerz;
  2049.    len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
  2050.    z0 *= len;
  2051.    z1 *= len;
  2052.    z2 *= len;
  2053.    x0 = upy * z2 - upz * z1;
  2054.    x1 = upz * z0 - upx * z2;
  2055.    x2 = upx * z1 - upy * z0;
  2056.    len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
  2057.    if (!len) {
  2058.     x0 = 0;
  2059.     x1 = 0;
  2060.     x2 = 0
  2061.    } else {
  2062.     len = 1 / len;
  2063.     x0 *= len;
  2064.     x1 *= len;
  2065.     x2 *= len
  2066.    }
  2067.    y0 = z1 * x2 - z2 * x1;
  2068.    y1 = z2 * x0 - z0 * x2;
  2069.    y2 = z0 * x1 - z1 * x0;
  2070.    len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
  2071.    if (!len) {
  2072.     y0 = 0;
  2073.     y1 = 0;
  2074.     y2 = 0
  2075.    } else {
  2076.     len = 1 / len;
  2077.     y0 *= len;
  2078.     y1 *= len;
  2079.     y2 *= len
  2080.    }
  2081.    out[0] = x0;
  2082.    out[1] = y0;
  2083.    out[2] = z0;
  2084.    out[3] = 0;
  2085.    out[4] = x1;
  2086.    out[5] = y1;
  2087.    out[6] = z1;
  2088.    out[7] = 0;
  2089.    out[8] = x2;
  2090.    out[9] = y2;
  2091.    out[10] = z2;
  2092.    out[11] = 0;
  2093.    out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
  2094.    out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
  2095.    out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
  2096.    out[15] = 1;
  2097.    return out
  2098.   };
  2099.   mat4.str = function(a) {
  2100.    return "mat4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ", " + a[9] + ", " + a[10] + ", " + a[11] + ", " + a[12] + ", " + a[13] + ", " + a[14] + ", " + a[15] + ")"
  2101.   };
  2102.   mat4.frob = function(a) {
  2103.    return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2))
  2104.   };
  2105.   if (typeof exports !== "undefined") {
  2106.    exports.mat4 = mat4
  2107.   }
  2108.   var quat = {};
  2109.   quat.create = function() {
  2110.    var out = new GLMAT_ARRAY_TYPE(4);
  2111.    out[0] = 0;
  2112.    out[1] = 0;
  2113.    out[2] = 0;
  2114.    out[3] = 1;
  2115.    return out
  2116.   };
  2117.   quat.rotationTo = function() {
  2118.    var tmpvec3 = vec3.create();
  2119.    var xUnitVec3 = vec3.fromValues(1, 0, 0);
  2120.    var yUnitVec3 = vec3.fromValues(0, 1, 0);
  2121.    return function(out, a, b) {
  2122.     var dot = vec3.dot(a, b);
  2123.     if (dot < -.999999) {
  2124.      vec3.cross(tmpvec3, xUnitVec3, a);
  2125.      if (vec3.length(tmpvec3) < 1e-6) vec3.cross(tmpvec3, yUnitVec3, a);
  2126.      vec3.normalize(tmpvec3, tmpvec3);
  2127.      quat.setAxisAngle(out, tmpvec3, Math.PI);
  2128.      return out
  2129.     } else if (dot > .999999) {
  2130.      out[0] = 0;
  2131.      out[1] = 0;
  2132.      out[2] = 0;
  2133.      out[3] = 1;
  2134.      return out
  2135.     } else {
  2136.      vec3.cross(tmpvec3, a, b);
  2137.      out[0] = tmpvec3[0];
  2138.      out[1] = tmpvec3[1];
  2139.      out[2] = tmpvec3[2];
  2140.      out[3] = 1 + dot;
  2141.      return quat.normalize(out, out)
  2142.     }
  2143.    }
  2144.   }();
  2145.   quat.setAxes = function() {
  2146.    var matr = mat3.create();
  2147.    return function(out, view, right, up) {
  2148.     matr[0] = right[0];
  2149.     matr[3] = right[1];
  2150.     matr[6] = right[2];
  2151.     matr[1] = up[0];
  2152.     matr[4] = up[1];
  2153.     matr[7] = up[2];
  2154.     matr[2] = -view[0];
  2155.     matr[5] = -view[1];
  2156.     matr[8] = -view[2];
  2157.     return quat.normalize(out, quat.fromMat3(out, matr))
  2158.    }
  2159.   }();
  2160.   quat.clone = vec4.clone;
  2161.   quat.fromValues = vec4.fromValues;
  2162.   quat.copy = vec4.copy;
  2163.   quat.set = vec4.set;
  2164.   quat.identity = function(out) {
  2165.    out[0] = 0;
  2166.    out[1] = 0;
  2167.    out[2] = 0;
  2168.    out[3] = 1;
  2169.    return out
  2170.   };
  2171.   quat.setAxisAngle = function(out, axis, rad) {
  2172.    rad = rad * .5;
  2173.    var s = Math.sin(rad);
  2174.    out[0] = s * axis[0];
  2175.    out[1] = s * axis[1];
  2176.    out[2] = s * axis[2];
  2177.    out[3] = Math.cos(rad);
  2178.    return out
  2179.   };
  2180.   quat.add = vec4.add;
  2181.   quat.multiply = function(out, a, b) {
  2182.    var ax = a[0],
  2183.     ay = a[1],
  2184.     az = a[2],
  2185.     aw = a[3],
  2186.     bx = b[0],
  2187.     by = b[1],
  2188.     bz = b[2],
  2189.     bw = b[3];
  2190.    out[0] = ax * bw + aw * bx + ay * bz - az * by;
  2191.    out[1] = ay * bw + aw * by + az * bx - ax * bz;
  2192.    out[2] = az * bw + aw * bz + ax * by - ay * bx;
  2193.    out[3] = aw * bw - ax * bx - ay * by - az * bz;
  2194.    return out
  2195.   };
  2196.   quat.mul = quat.multiply;
  2197.   quat.scale = vec4.scale;
  2198.   quat.rotateX = function(out, a, rad) {
  2199.    rad *= .5;
  2200.    var ax = a[0],
  2201.     ay = a[1],
  2202.     az = a[2],
  2203.     aw = a[3],
  2204.     bx = Math.sin(rad),
  2205.     bw = Math.cos(rad);
  2206.    out[0] = ax * bw + aw * bx;
  2207.    out[1] = ay * bw + az * bx;
  2208.    out[2] = az * bw - ay * bx;
  2209.    out[3] = aw * bw - ax * bx;
  2210.    return out
  2211.   };
  2212.   quat.rotateY = function(out, a, rad) {
  2213.    rad *= .5;
  2214.    var ax = a[0],
  2215.     ay = a[1],
  2216.     az = a[2],
  2217.     aw = a[3],
  2218.     by = Math.sin(rad),
  2219.     bw = Math.cos(rad);
  2220.    out[0] = ax * bw - az * by;
  2221.    out[1] = ay * bw + aw * by;
  2222.    out[2] = az * bw + ax * by;
  2223.    out[3] = aw * bw - ay * by;
  2224.    return out
  2225.   };
  2226.   quat.rotateZ = function(out, a, rad) {
  2227.    rad *= .5;
  2228.    var ax = a[0],
  2229.     ay = a[1],
  2230.     az = a[2],
  2231.     aw = a[3],
  2232.     bz = Math.sin(rad),
  2233.     bw = Math.cos(rad);
  2234.    out[0] = ax * bw + ay * bz;
  2235.    out[1] = ay * bw - ax * bz;
  2236.    out[2] = az * bw + aw * bz;
  2237.    out[3] = aw * bw - az * bz;
  2238.    return out
  2239.   };
  2240.   quat.calculateW = function(out, a) {
  2241.    var x = a[0],
  2242.     y = a[1],
  2243.     z = a[2];
  2244.    out[0] = x;
  2245.    out[1] = y;
  2246.    out[2] = z;
  2247.    out[3] = -Math.sqrt(Math.abs(1 - x * x - y * y - z * z));
  2248.    return out
  2249.   };
  2250.   quat.dot = vec4.dot;
  2251.   quat.lerp = vec4.lerp;
  2252.   quat.slerp = function(out, a, b, t) {
  2253.    var ax = a[0],
  2254.     ay = a[1],
  2255.     az = a[2],
  2256.     aw = a[3],
  2257.     bx = b[0],
  2258.     by = b[1],
  2259.     bz = b[2],
  2260.     bw = b[3];
  2261.    var omega, cosom, sinom, scale0, scale1;
  2262.    cosom = ax * bx + ay * by + az * bz + aw * bw;
  2263.    if (cosom < 0) {
  2264.     cosom = -cosom;
  2265.     bx = -bx;
  2266.     by = -by;
  2267.     bz = -bz;
  2268.     bw = -bw
  2269.    }
  2270.    if (1 - cosom > 1e-6) {
  2271.     omega = Math.acos(cosom);
  2272.     sinom = Math.sin(omega);
  2273.     scale0 = Math.sin((1 - t) * omega) / sinom;
  2274.     scale1 = Math.sin(t * omega) / sinom
  2275.    } else {
  2276.     scale0 = 1 - t;
  2277.     scale1 = t
  2278.    }
  2279.    out[0] = scale0 * ax + scale1 * bx;
  2280.    out[1] = scale0 * ay + scale1 * by;
  2281.    out[2] = scale0 * az + scale1 * bz;
  2282.    out[3] = scale0 * aw + scale1 * bw;
  2283.    return out
  2284.   };
  2285.   quat.invert = function(out, a) {
  2286.    var a0 = a[0],
  2287.     a1 = a[1],
  2288.     a2 = a[2],
  2289.     a3 = a[3],
  2290.     dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3,
  2291.     invDot = dot ? 1 / dot : 0;
  2292.    out[0] = -a0 * invDot;
  2293.    out[1] = -a1 * invDot;
  2294.    out[2] = -a2 * invDot;
  2295.    out[3] = a3 * invDot;
  2296.    return out
  2297.   };
  2298.   quat.conjugate = function(out, a) {
  2299.    out[0] = -a[0];
  2300.    out[1] = -a[1];
  2301.    out[2] = -a[2];
  2302.    out[3] = a[3];
  2303.    return out
  2304.   };
  2305.   quat.length = vec4.length;
  2306.   quat.len = quat.length;
  2307.   quat.squaredLength = vec4.squaredLength;
  2308.   quat.sqrLen = quat.squaredLength;
  2309.   quat.normalize = vec4.normalize;
  2310.   quat.fromMat3 = function(out, m) {
  2311.    var fTrace = m[0] + m[4] + m[8];
  2312.    var fRoot;
  2313.    if (fTrace > 0) {
  2314.     fRoot = Math.sqrt(fTrace + 1);
  2315.     out[3] = .5 * fRoot;
  2316.     fRoot = .5 / fRoot;
  2317.     out[0] = (m[7] - m[5]) * fRoot;
  2318.     out[1] = (m[2] - m[6]) * fRoot;
  2319.     out[2] = (m[3] - m[1]) * fRoot
  2320.    } else {
  2321.     var i = 0;
  2322.     if (m[4] > m[0]) i = 1;
  2323.     if (m[8] > m[i * 3 + i]) i = 2;
  2324.     var j = (i + 1) % 3;
  2325.     var k = (i + 2) % 3;
  2326.     fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1);
  2327.     out[i] = .5 * fRoot;
  2328.     fRoot = .5 / fRoot;
  2329.     out[3] = (m[k * 3 + j] - m[j * 3 + k]) * fRoot;
  2330.     out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
  2331.     out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot
  2332.    }
  2333.    return out
  2334.   };
  2335.   quat.str = function(a) {
  2336.    return "quat(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")"
  2337.   };
  2338.   if (typeof exports !== "undefined") {
  2339.    exports.quat = quat
  2340.   }
  2341.  })(shim.exports)
  2342. })(this);
  2343. ! function(e) {
  2344.  if ("object" == typeof exports && "undefined" != typeof module) module.exports = e();
  2345.  else if ("function" == typeof define && define.amd) define([], e);
  2346.  else {
  2347.   var f;
  2348.   "undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self), f.pako = e()
  2349.  }
  2350. }(function() {
  2351.  var define, module, exports;
  2352.  return function e(t, n, r) {
  2353.   function s(o, u) {
  2354.    if (!n[o]) {
  2355.     if (!t[o]) {
  2356.      var a = typeof require == "function" && require;
  2357.      if (!u && a) return a(o, !0);
  2358.      if (i) return i(o, !0);
  2359.      throw new Error("Cannot find module '" + o + "'")
  2360.     }
  2361.     var f = n[o] = {
  2362.      exports: {}
  2363.     };
  2364.     t[o][0].call(f.exports, function(e) {
  2365.      var n = t[o][1][e];
  2366.      return s(n ? n : e)
  2367.     }, f, f.exports, e, t, n, r)
  2368.    }
  2369.    return n[o].exports
  2370.   }
  2371.   var i = typeof require == "function" && require;
  2372.   for (var o = 0; o < r.length; o++) s(r[o]);
  2373.   return s
  2374.  }({
  2375.   1: [function(_dereq_, module, exports) {
  2376.    "use strict";
  2377.    var zlib_inflate = _dereq_("./zlib/inflate.js");
  2378.    var utils = _dereq_("./utils/common");
  2379.    var strings = _dereq_("./utils/strings");
  2380.    var c = _dereq_("./zlib/constants");
  2381.    var msg = _dereq_("./zlib/messages");
  2382.    var zstream = _dereq_("./zlib/zstream");
  2383.    var gzheader = _dereq_("./zlib/gzheader");
  2384.    var Inflate = function(options) {
  2385.     this.options = utils.assign({
  2386.      chunkSize: 16384,
  2387.      windowBits: 0,
  2388.      to: ""
  2389.     }, options || {});
  2390.     var opt = this.options;
  2391.     if (opt.raw && opt.windowBits >= 0 && opt.windowBits < 16) {
  2392.      opt.windowBits = -opt.windowBits;
  2393.      if (opt.windowBits === 0) {
  2394.       opt.windowBits = -15
  2395.      }
  2396.     }
  2397.     if (opt.windowBits >= 0 && opt.windowBits < 16 && !(options && options.windowBits)) {
  2398.      opt.windowBits += 32
  2399.     }
  2400.     if (opt.windowBits > 15 && opt.windowBits < 48) {
  2401.      if ((opt.windowBits & 15) === 0) {
  2402.       opt.windowBits |= 15
  2403.      }
  2404.     }
  2405.     this.err = 0;
  2406.     this.msg = "";
  2407.     this.ended = false;
  2408.     this.chunks = [];
  2409.     this.strm = new zstream;
  2410.     this.strm.avail_out = 0;
  2411.     var status = zlib_inflate.inflateInit2(this.strm, opt.windowBits);
  2412.     if (status !== c.Z_OK) {
  2413.      throw new Error(msg[status])
  2414.     }
  2415.     this.header = new gzheader;
  2416.     zlib_inflate.inflateGetHeader(this.strm, this.header)
  2417.    };
  2418.    Inflate.prototype.push = function(data, mode) {
  2419.     var strm = this.strm;
  2420.     var chunkSize = this.options.chunkSize;
  2421.     var status, _mode;
  2422.     var next_out_utf8, tail, utf8str;
  2423.     if (this.ended) {
  2424.      return false
  2425.     }
  2426.     _mode = mode === ~~mode ? mode : mode === true ? c.Z_FINISH : c.Z_NO_FLUSH;
  2427.     if (typeof data === "string") {
  2428.      strm.input = strings.binstring2buf(data)
  2429.     } else {
  2430.      strm.input = data
  2431.     }
  2432.     strm.next_in = 0;
  2433.     strm.avail_in = strm.input.length;
  2434.     do {
  2435.      if (strm.avail_out === 0) {
  2436.       strm.output = new utils.Buf8(chunkSize);
  2437.       strm.next_out = 0;
  2438.       strm.avail_out = chunkSize
  2439.      }
  2440.      status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH);
  2441.      if (status !== c.Z_STREAM_END && status !== c.Z_OK) {
  2442.       this.onEnd(status);
  2443.       this.ended = true;
  2444.       return false
  2445.      }
  2446.      if (strm.next_out) {
  2447.       if (strm.avail_out === 0 || status === c.Z_STREAM_END || strm.avail_in === 0 && _mode === c.Z_FINISH) {
  2448.        if (this.options.to === "string") {
  2449.         next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
  2450.         tail = strm.next_out - next_out_utf8;
  2451.         utf8str = strings.buf2string(strm.output, next_out_utf8);
  2452.         strm.next_out = tail;
  2453.         strm.avail_out = chunkSize - tail;
  2454.         if (tail) {
  2455.          utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0)
  2456.         }
  2457.         this.onData(utf8str)
  2458.        } else {
  2459.         this.onData(utils.shrinkBuf(strm.output, strm.next_out))
  2460.        }
  2461.       }
  2462.      }
  2463.     } while (strm.avail_in > 0 && status !== c.Z_STREAM_END);
  2464.     if (status === c.Z_STREAM_END) {
  2465.      _mode = c.Z_FINISH
  2466.     }
  2467.     if (_mode === c.Z_FINISH) {
  2468.      status = zlib_inflate.inflateEnd(this.strm);
  2469.      this.onEnd(status);
  2470.      this.ended = true;
  2471.      return status === c.Z_OK
  2472.     }
  2473.     return true
  2474.    };
  2475.    Inflate.prototype.onData = function(chunk) {
  2476.     this.chunks.push(chunk)
  2477.    };
  2478.    Inflate.prototype.onEnd = function(status) {
  2479.     if (status === c.Z_OK) {
  2480.      if (this.options.to === "string") {
  2481.       this.result = this.chunks.join("")
  2482.      } else {
  2483.       this.result = utils.flattenChunks(this.chunks)
  2484.      }
  2485.     }
  2486.     this.chunks = [];
  2487.     this.err = status;
  2488.     this.msg = this.strm.msg
  2489.    };
  2490.  
  2491.    function inflate(input, options) {
  2492.     var inflator = new Inflate(options);
  2493.     inflator.push(input, true);
  2494.     if (inflator.err) {
  2495.      throw inflator.msg
  2496.     }
  2497.     return inflator.result
  2498.    }
  2499.  
  2500.    function inflateRaw(input, options) {
  2501.     options = options || {};
  2502.     options.raw = true;
  2503.     return inflate(input, options)
  2504.    }
  2505.    exports.Inflate = Inflate;
  2506.    exports.inflate = inflate;
  2507.    exports.inflateRaw = inflateRaw;
  2508.    exports.ungzip = inflate
  2509.   }, {
  2510.    "./utils/common": 2,
  2511.    "./utils/strings": 3,
  2512.    "./zlib/constants": 5,
  2513.    "./zlib/gzheader": 7,
  2514.    "./zlib/inflate.js": 9,
  2515.    "./zlib/messages": 11,
  2516.    "./zlib/zstream": 12
  2517.   }],
  2518.   2: [function(_dereq_, module, exports) {
  2519.    "use strict";
  2520.    var TYPED_OK = typeof Uint8Array !== "undefined" && typeof Uint16Array !== "undefined" && typeof Int32Array !== "undefined";
  2521.    exports.assign = function(obj) {
  2522.     var sources = Array.prototype.slice.call(arguments, 1);
  2523.     while (sources.length) {
  2524.      var source = sources.shift();
  2525.      if (!source) {
  2526.       continue
  2527.      }
  2528.      if (typeof source !== "object") {
  2529.       throw new TypeError(source + "must be non-object")
  2530.      }
  2531.      for (var p in source) {
  2532.       if (source.hasOwnProperty(p)) {
  2533.        obj[p] = source[p]
  2534.       }
  2535.      }
  2536.     }
  2537.     return obj
  2538.    };
  2539.    exports.shrinkBuf = function(buf, size) {
  2540.     if (buf.length === size) {
  2541.      return buf
  2542.     }
  2543.     if (buf.subarray) {
  2544.      return buf.subarray(0, size)
  2545.     }
  2546.     buf.length = size;
  2547.     return buf
  2548.    };
  2549.    var fnTyped = {
  2550.     arraySet: function(dest, src, src_offs, len, dest_offs) {
  2551.      if (src.subarray && dest.subarray) {
  2552.       dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
  2553.       return
  2554.      }
  2555.      for (var i = 0; i < len; i++) {
  2556.       dest[dest_offs + i] = src[src_offs + i]
  2557.      }
  2558.     },
  2559.     flattenChunks: function(chunks) {
  2560.      var i, l, len, pos, chunk, result;
  2561.      len = 0;
  2562.      for (i = 0, l = chunks.length; i < l; i++) {
  2563.       len += chunks[i].length
  2564.      }
  2565.      result = new Uint8Array(len);
  2566.      pos = 0;
  2567.      for (i = 0, l = chunks.length; i < l; i++) {
  2568.       chunk = chunks[i];
  2569.       result.set(chunk, pos);
  2570.       pos += chunk.length
  2571.      }
  2572.      return result
  2573.     }
  2574.    };
  2575.    var fnUntyped = {
  2576.     arraySet: function(dest, src, src_offs, len, dest_offs) {
  2577.      for (var i = 0; i < len; i++) {
  2578.       dest[dest_offs + i] = src[src_offs + i]
  2579.      }
  2580.     },
  2581.     flattenChunks: function(chunks) {
  2582.      return [].concat.apply([], chunks)
  2583.     }
  2584.    };
  2585.    exports.setTyped = function(on) {
  2586.     if (on) {
  2587.      exports.Buf8 = Uint8Array;
  2588.      exports.Buf16 = Uint16Array;
  2589.      exports.Buf32 = Int32Array;
  2590.      exports.assign(exports, fnTyped)
  2591.     } else {
  2592.      exports.Buf8 = Array;
  2593.      exports.Buf16 = Array;
  2594.      exports.Buf32 = Array;
  2595.      exports.assign(exports, fnUntyped)
  2596.     }
  2597.    };
  2598.    exports.setTyped(TYPED_OK)
  2599.   }, {}],
  2600.   3: [function(_dereq_, module, exports) {
  2601.    "use strict";
  2602.    var utils = _dereq_("./common");
  2603.    var STR_APPLY_OK = true;
  2604.    var STR_APPLY_UIA_OK = true;
  2605.    try {
  2606.     String.fromCharCode.apply(null, [0])
  2607.    } catch (__) {
  2608.     STR_APPLY_OK = false
  2609.    }
  2610.    try {
  2611.     String.fromCharCode.apply(null, new Uint8Array(1))
  2612.    } catch (__) {
  2613.     STR_APPLY_UIA_OK = false
  2614.    }
  2615.    var _utf8len = new utils.Buf8(256);
  2616.    for (var i = 0; i < 256; i++) {
  2617.     _utf8len[i] = i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1
  2618.    }
  2619.    _utf8len[254] = _utf8len[254] = 1;
  2620.    exports.string2buf = function(str) {
  2621.     var buf, c, c2, m_pos, i, str_len = str.length,
  2622.      buf_len = 0;
  2623.     for (m_pos = 0; m_pos < str_len; m_pos++) {
  2624.      c = str.charCodeAt(m_pos);
  2625.      if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
  2626.       c2 = str.charCodeAt(m_pos + 1);
  2627.       if ((c2 & 64512) === 56320) {
  2628.        c = 65536 + (c - 55296 << 10) + (c2 - 56320);
  2629.        m_pos++
  2630.       }
  2631.      }
  2632.      buf_len += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4
  2633.     }
  2634.     buf = new utils.Buf8(buf_len);
  2635.     for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
  2636.      c = str.charCodeAt(m_pos);
  2637.      if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
  2638.       c2 = str.charCodeAt(m_pos + 1);
  2639.       if ((c2 & 64512) === 56320) {
  2640.        c = 65536 + (c - 55296 << 10) + (c2 - 56320);
  2641.        m_pos++
  2642.       }
  2643.      }
  2644.      if (c < 128) {
  2645.       buf[i++] = c
  2646.      } else if (c < 2048) {
  2647.       buf[i++] = 192 | c >>> 6;
  2648.       buf[i++] = 128 | c & 63
  2649.      } else if (c < 65536) {
  2650.       buf[i++] = 224 | c >>> 12;
  2651.       buf[i++] = 128 | c >>> 6 & 63;
  2652.       buf[i++] = 128 | c & 63
  2653.      } else {
  2654.       buf[i++] = 240 | c >>> 18;
  2655.       buf[i++] = 128 | c >>> 12 & 63;
  2656.       buf[i++] = 128 | c >>> 6 & 63;
  2657.       buf[i++] = 128 | c & 63
  2658.      }
  2659.     }
  2660.     return buf
  2661.    };
  2662.  
  2663.    function buf2binstring(buf, len) {
  2664.     if (len < 65537) {
  2665.      if (buf.subarray && STR_APPLY_UIA_OK || !buf.subarray && STR_APPLY_OK) {
  2666.       return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len))
  2667.      }
  2668.     }
  2669.     var result = "";
  2670.     for (var i = 0; i < len; i++) {
  2671.      result += String.fromCharCode(buf[i])
  2672.     }
  2673.     return result
  2674.    }
  2675.    exports.buf2binstring = function(buf) {
  2676.     return buf2binstring(buf, buf.length)
  2677.    };
  2678.    exports.binstring2buf = function(str) {
  2679.     var buf = new utils.Buf8(str.length);
  2680.     for (var i = 0, len = buf.length; i < len; i++) {
  2681.      buf[i] = str.charCodeAt(i)
  2682.     }
  2683.     return buf
  2684.    };
  2685.    exports.buf2string = function(buf, max) {
  2686.     var i, out, c, c_len;
  2687.     var len = max || buf.length;
  2688.     var utf16buf = new Array(len * 2);
  2689.     for (out = 0, i = 0; i < len;) {
  2690.      c = buf[i++];
  2691.      if (c < 128) {
  2692.       utf16buf[out++] = c;
  2693.       continue
  2694.      }
  2695.      c_len = _utf8len[c];
  2696.      if (c_len > 4) {
  2697.       utf16buf[out++] = 65533;
  2698.       i += c_len - 1;
  2699.       continue
  2700.      }
  2701.      c &= c_len === 2 ? 31 : c_len === 3 ? 15 : 7;
  2702.      while (c_len > 1 && i < len) {
  2703.       c = c << 6 | buf[i++] & 63;
  2704.       c_len--
  2705.      }
  2706.      if (c_len > 1) {
  2707.       utf16buf[out++] = 65533;
  2708.       continue
  2709.      }
  2710.      if (c < 65536) {
  2711.       utf16buf[out++] = c
  2712.      } else {
  2713.       c -= 65536;
  2714.       utf16buf[out++] = 55296 | c >> 10 & 1023;
  2715.       utf16buf[out++] = 56320 | c & 1023
  2716.      }
  2717.     }
  2718.     return buf2binstring(utf16buf, out)
  2719.    };
  2720.    exports.utf8border = function(buf, max) {
  2721.     var pos;
  2722.     max = max || buf.length;
  2723.     if (max > buf.length) {
  2724.      max = buf.length
  2725.     }
  2726.     pos = max - 1;
  2727.     while (pos >= 0 && (buf[pos] & 192) === 128) {
  2728.      pos--
  2729.     }
  2730.     if (pos < 0) {
  2731.      return max
  2732.     }
  2733.     if (pos === 0) {
  2734.      return max
  2735.     }
  2736.     return pos + _utf8len[buf[pos]] > max ? pos : max
  2737.    }
  2738.   }, {
  2739.    "./common": 2
  2740.   }],
  2741.   4: [function(_dereq_, module, exports) {
  2742.    "use strict";
  2743.  
  2744.    function adler32(adler, buf, len, pos) {
  2745.     var s1 = adler & 65535 | 0,
  2746.      s2 = adler >>> 16 & 65535 | 0,
  2747.      n = 0;
  2748.     while (len !== 0) {
  2749.      n = len > 2e3 ? 2e3 : len;
  2750.      len -= n;
  2751.      do {
  2752.       s1 = s1 + buf[pos++] | 0;
  2753.       s2 = s2 + s1 | 0
  2754.      } while (--n);
  2755.      s1 %= 65521;
  2756.      s2 %= 65521
  2757.     }
  2758.     return s1 | s2 << 16 | 0
  2759.    }
  2760.    module.exports = adler32
  2761.   }, {}],
  2762.   5: [function(_dereq_, module, exports) {
  2763.    module.exports = {
  2764.     Z_NO_FLUSH: 0,
  2765.     Z_PARTIAL_FLUSH: 1,
  2766.     Z_SYNC_FLUSH: 2,
  2767.     Z_FULL_FLUSH: 3,
  2768.     Z_FINISH: 4,
  2769.     Z_BLOCK: 5,
  2770.     Z_TREES: 6,
  2771.     Z_OK: 0,
  2772.     Z_STREAM_END: 1,
  2773.     Z_NEED_DICT: 2,
  2774.     Z_ERRNO: -1,
  2775.     Z_STREAM_ERROR: -2,
  2776.     Z_DATA_ERROR: -3,
  2777.     Z_BUF_ERROR: -5,
  2778.     Z_NO_COMPRESSION: 0,
  2779.     Z_BEST_SPEED: 1,
  2780.     Z_BEST_COMPRESSION: 9,
  2781.     Z_DEFAULT_COMPRESSION: -1,
  2782.     Z_FILTERED: 1,
  2783.     Z_HUFFMAN_ONLY: 2,
  2784.     Z_RLE: 3,
  2785.     Z_FIXED: 4,
  2786.     Z_DEFAULT_STRATEGY: 0,
  2787.     Z_BINARY: 0,
  2788.     Z_TEXT: 1,
  2789.     Z_UNKNOWN: 2,
  2790.     Z_DEFLATED: 8
  2791.    }
  2792.   }, {}],
  2793.   6: [function(_dereq_, module, exports) {
  2794.    "use strict";
  2795.  
  2796.    function makeTable() {
  2797.     var c, table = [];
  2798.     for (var n = 0; n < 256; n++) {
  2799.      c = n;
  2800.      for (var k = 0; k < 8; k++) {
  2801.       c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1
  2802.      }
  2803.      table[n] = c
  2804.     }
  2805.     return table
  2806.    }
  2807.    var crcTable = makeTable();
  2808.  
  2809.    function crc32(crc, buf, len, pos) {
  2810.     var t = crcTable,
  2811.      end = pos + len;
  2812.     crc = crc ^ -1;
  2813.     for (var i = pos; i < end; i++) {
  2814.      crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 255]
  2815.     }
  2816.     return crc ^ -1
  2817.    }
  2818.    module.exports = crc32
  2819.   }, {}],
  2820.   7: [function(_dereq_, module, exports) {
  2821.    "use strict";
  2822.  
  2823.    function GZheader() {
  2824.     this.text = 0;
  2825.     this.time = 0;
  2826.     this.xflags = 0;
  2827.     this.os = 0;
  2828.     this.extra = null;
  2829.     this.extra_len = 0;
  2830.     this.name = "";
  2831.     this.comment = "";
  2832.     this.hcrc = 0;
  2833.     this.done = false
  2834.    }
  2835.    module.exports = GZheader
  2836.   }, {}],
  2837.   8: [function(_dereq_, module, exports) {
  2838.    "use strict";
  2839.    var BAD = 30;
  2840.    var TYPE = 12;
  2841.    module.exports = function inflate_fast(strm, start) {
  2842.     var state;
  2843.     var _in;
  2844.     var last;
  2845.     var _out;
  2846.     var beg;
  2847.     var end;
  2848.     var dmax;
  2849.     var wsize;
  2850.     var whave;
  2851.     var wnext;
  2852.     var window;
  2853.     var hold;
  2854.     var bits;
  2855.     var lcode;
  2856.     var dcode;
  2857.     var lmask;
  2858.     var dmask;
  2859.     var here;
  2860.     var op;
  2861.     var len;
  2862.     var dist;
  2863.     var from;
  2864.     var from_source;
  2865.     var input, output;
  2866.     state = strm.state;
  2867.     _in = strm.next_in;
  2868.     input = strm.input;
  2869.     last = _in + (strm.avail_in - 5);
  2870.     _out = strm.next_out;
  2871.     output = strm.output;
  2872.     beg = _out - (start - strm.avail_out);
  2873.     end = _out + (strm.avail_out - 257);
  2874.     dmax = state.dmax;
  2875.     wsize = state.wsize;
  2876.     whave = state.whave;
  2877.     wnext = state.wnext;
  2878.     window = state.window;
  2879.     hold = state.hold;
  2880.     bits = state.bits;
  2881.     lcode = state.lencode;
  2882.     dcode = state.distcode;
  2883.     lmask = (1 << state.lenbits) - 1;
  2884.     dmask = (1 << state.distbits) - 1;
  2885.     top: do {
  2886.      if (bits < 15) {
  2887.       hold += input[_in++] << bits;
  2888.       bits += 8;
  2889.       hold += input[_in++] << bits;
  2890.       bits += 8
  2891.      }
  2892.      here = lcode[hold & lmask];
  2893.      dolen: for (;;) {
  2894.       op = here >>> 24;
  2895.       hold >>>= op;
  2896.       bits -= op;
  2897.       op = here >>> 16 & 255;
  2898.       if (op === 0) {
  2899.        output[_out++] = here & 65535
  2900.       } else if (op & 16) {
  2901.        len = here & 65535;
  2902.        op &= 15;
  2903.        if (op) {
  2904.         if (bits < op) {
  2905.          hold += input[_in++] << bits;
  2906.          bits += 8
  2907.         }
  2908.         len += hold & (1 << op) - 1;
  2909.         hold >>>= op;
  2910.         bits -= op
  2911.        }
  2912.        if (bits < 15) {
  2913.         hold += input[_in++] << bits;
  2914.         bits += 8;
  2915.         hold += input[_in++] << bits;
  2916.         bits += 8
  2917.        }
  2918.        here = dcode[hold & dmask];
  2919.        dodist: for (;;) {
  2920.         op = here >>> 24;
  2921.         hold >>>= op;
  2922.         bits -= op;
  2923.         op = here >>> 16 & 255;
  2924.         if (op & 16) {
  2925.          dist = here & 65535;
  2926.          op &= 15;
  2927.          if (bits < op) {
  2928.           hold += input[_in++] << bits;
  2929.           bits += 8;
  2930.           if (bits < op) {
  2931.            hold += input[_in++] << bits;
  2932.            bits += 8
  2933.           }
  2934.          }
  2935.          dist += hold & (1 << op) - 1;
  2936.          if (dist > dmax) {
  2937.           strm.msg = "invalid distance too far back";
  2938.           state.mode = BAD;
  2939.           break top
  2940.          }
  2941.          hold >>>= op;
  2942.          bits -= op;
  2943.          op = _out - beg;
  2944.          if (dist > op) {
  2945.           op = dist - op;
  2946.           if (op > whave) {
  2947.            if (state.sane) {
  2948.             strm.msg = "invalid distance too far back";
  2949.             state.mode = BAD;
  2950.             break top
  2951.            }
  2952.           }
  2953.           from = 0;
  2954.           from_source = window;
  2955.           if (wnext === 0) {
  2956.            from += wsize - op;
  2957.            if (op < len) {
  2958.             len -= op;
  2959.             do {
  2960.              output[_out++] = window[from++]
  2961.             } while (--op);
  2962.             from = _out - dist;
  2963.             from_source = output
  2964.            }
  2965.           } else if (wnext < op) {
  2966.            from += wsize + wnext - op;
  2967.            op -= wnext;
  2968.            if (op < len) {
  2969.             len -= op;
  2970.             do {
  2971.              output[_out++] = window[from++]
  2972.             } while (--op);
  2973.             from = 0;
  2974.             if (wnext < len) {
  2975.              op = wnext;
  2976.              len -= op;
  2977.              do {
  2978.               output[_out++] = window[from++]
  2979.              } while (--op);
  2980.              from = _out - dist;
  2981.              from_source = output
  2982.             }
  2983.            }
  2984.           } else {
  2985.            from += wnext - op;
  2986.            if (op < len) {
  2987.             len -= op;
  2988.             do {
  2989.              output[_out++] = window[from++]
  2990.             } while (--op);
  2991.             from = _out - dist;
  2992.             from_source = output
  2993.            }
  2994.           }
  2995.           while (len > 2) {
  2996.            output[_out++] = from_source[from++];
  2997.            output[_out++] = from_source[from++];
  2998.            output[_out++] = from_source[from++];
  2999.            len -= 3
  3000.           }
  3001.           if (len) {
  3002.            output[_out++] = from_source[from++];
  3003.            if (len > 1) {
  3004.             output[_out++] = from_source[from++]
  3005.            }
  3006.           }
  3007.          } else {
  3008.           from = _out - dist;
  3009.           do {
  3010.            output[_out++] = output[from++];
  3011.            output[_out++] = output[from++];
  3012.            output[_out++] = output[from++];
  3013.            len -= 3
  3014.           } while (len > 2);
  3015.           if (len) {
  3016.            output[_out++] = output[from++];
  3017.            if (len > 1) {
  3018.             output[_out++] = output[from++]
  3019.            }
  3020.           }
  3021.          }
  3022.         } else if ((op & 64) === 0) {
  3023.          here = dcode[(here & 65535) + (hold & (1 << op) - 1)];
  3024.          continue dodist
  3025.         } else {
  3026.          strm.msg = "invalid distance code";
  3027.          state.mode = BAD;
  3028.          break top
  3029.         }
  3030.         break
  3031.        }
  3032.       } else if ((op & 64) === 0) {
  3033.        here = lcode[(here & 65535) + (hold & (1 << op) - 1)];
  3034.        continue dolen
  3035.       } else if (op & 32) {
  3036.        state.mode = TYPE;
  3037.        break top
  3038.       } else {
  3039.        strm.msg = "invalid literal/length code";
  3040.        state.mode = BAD;
  3041.        break top
  3042.       }
  3043.       break
  3044.      }
  3045.     } while (_in < last && _out < end);
  3046.     len = bits >> 3;
  3047.     _in -= len;
  3048.     bits -= len << 3;
  3049.     hold &= (1 << bits) - 1;
  3050.     strm.next_in = _in;
  3051.     strm.next_out = _out;
  3052.     strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last);
  3053.     strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end);
  3054.     state.hold = hold;
  3055.     state.bits = bits;
  3056.     return
  3057.    }
  3058.   }, {}],
  3059.   9: [function(_dereq_, module, exports) {
  3060.    "use strict";
  3061.    var utils = _dereq_("../utils/common");
  3062.    var adler32 = _dereq_("./adler32");
  3063.    var crc32 = _dereq_("./crc32");
  3064.    var inflate_fast = _dereq_("./inffast");
  3065.    var inflate_table = _dereq_("./inftrees");
  3066.    var CODES = 0;
  3067.    var LENS = 1;
  3068.    var DISTS = 2;
  3069.    var Z_FINISH = 4;
  3070.    var Z_BLOCK = 5;
  3071.    var Z_TREES = 6;
  3072.    var Z_OK = 0;
  3073.    var Z_STREAM_END = 1;
  3074.    var Z_NEED_DICT = 2;
  3075.    var Z_STREAM_ERROR = -2;
  3076.    var Z_DATA_ERROR = -3;
  3077.    var Z_MEM_ERROR = -4;
  3078.    var Z_BUF_ERROR = -5;
  3079.    var Z_DEFLATED = 8;
  3080.    var HEAD = 1;
  3081.    var FLAGS = 2;
  3082.    var TIME = 3;
  3083.    var OS = 4;
  3084.    var EXLEN = 5;
  3085.    var EXTRA = 6;
  3086.    var NAME = 7;
  3087.    var COMMENT = 8;
  3088.    var HCRC = 9;
  3089.    var DICTID = 10;
  3090.    var DICT = 11;
  3091.    var TYPE = 12;
  3092.    var TYPEDO = 13;
  3093.    var STORED = 14;
  3094.    var COPY_ = 15;
  3095.    var COPY = 16;
  3096.    var TABLE = 17;
  3097.    var LENLENS = 18;
  3098.    var CODELENS = 19;
  3099.    var LEN_ = 20;
  3100.    var LEN = 21;
  3101.    var LENEXT = 22;
  3102.    var DIST = 23;
  3103.    var DISTEXT = 24;
  3104.    var MATCH = 25;
  3105.    var LIT = 26;
  3106.    var CHECK = 27;
  3107.    var LENGTH = 28;
  3108.    var DONE = 29;
  3109.    var BAD = 30;
  3110.    var MEM = 31;
  3111.    var SYNC = 32;
  3112.    var ENOUGH_LENS = 852;
  3113.    var ENOUGH_DISTS = 592;
  3114.    var MAX_WBITS = 15;
  3115.    var DEF_WBITS = MAX_WBITS;
  3116.  
  3117.    function ZSWAP32(q) {
  3118.     return (q >>> 24 & 255) + (q >>> 8 & 65280) + ((q & 65280) << 8) + ((q & 255) << 24)
  3119.    }
  3120.  
  3121.    function InflateState() {
  3122.     this.mode = 0;
  3123.     this.last = false;
  3124.     this.wrap = 0;
  3125.     this.havedict = false;
  3126.     this.flags = 0;
  3127.     this.dmax = 0;
  3128.     this.check = 0;
  3129.     this.total = 0;
  3130.     this.head = null;
  3131.     this.wbits = 0;
  3132.     this.wsize = 0;
  3133.     this.whave = 0;
  3134.     this.wnext = 0;
  3135.     this.window = null;
  3136.     this.hold = 0;
  3137.     this.bits = 0;
  3138.     this.length = 0;
  3139.     this.offset = 0;
  3140.     this.extra = 0;
  3141.     this.lencode = null;
  3142.     this.distcode = null;
  3143.     this.lenbits = 0;
  3144.     this.distbits = 0;
  3145.     this.ncode = 0;
  3146.     this.nlen = 0;
  3147.     this.ndist = 0;
  3148.     this.have = 0;
  3149.     this.next = null;
  3150.     this.lens = new utils.Buf16(320);
  3151.     this.work = new utils.Buf16(288);
  3152.     this.lendyn = null;
  3153.     this.distdyn = null;
  3154.     this.sane = 0;
  3155.     this.back = 0;
  3156.     this.was = 0
  3157.    }
  3158.  
  3159.    function inflateResetKeep(strm) {
  3160.     var state;
  3161.     if (!strm || !strm.state) {
  3162.      return Z_STREAM_ERROR
  3163.     }
  3164.     state = strm.state;
  3165.     strm.total_in = strm.total_out = state.total = 0;
  3166.     strm.msg = "";
  3167.     if (state.wrap) {
  3168.      strm.adler = state.wrap & 1
  3169.     }
  3170.     state.mode = HEAD;
  3171.     state.last = 0;
  3172.     state.havedict = 0;
  3173.     state.dmax = 32768;
  3174.     state.head = null;
  3175.     state.hold = 0;
  3176.     state.bits = 0;
  3177.     state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS);
  3178.     state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS);
  3179.     state.sane = 1;
  3180.     state.back = -1;
  3181.     return Z_OK
  3182.    }
  3183.  
  3184.    function inflateReset(strm) {
  3185.     var state;
  3186.     if (!strm || !strm.state) {
  3187.      return Z_STREAM_ERROR
  3188.     }
  3189.     state = strm.state;
  3190.     state.wsize = 0;
  3191.     state.whave = 0;
  3192.     state.wnext = 0;
  3193.     return inflateResetKeep(strm)
  3194.    }
  3195.  
  3196.    function inflateReset2(strm, windowBits) {
  3197.     var wrap;
  3198.     var state;
  3199.     if (!strm || !strm.state) {
  3200.      return Z_STREAM_ERROR
  3201.     }
  3202.     state = strm.state;
  3203.     if (windowBits < 0) {
  3204.      wrap = 0;
  3205.      windowBits = -windowBits
  3206.     } else {
  3207.      wrap = (windowBits >> 4) + 1;
  3208.      if (windowBits < 48) {
  3209.       windowBits &= 15
  3210.      }
  3211.     }
  3212.     if (windowBits && (windowBits < 8 || windowBits > 15)) {
  3213.      return Z_STREAM_ERROR
  3214.     }
  3215.     if (state.window !== null && state.wbits !== windowBits) {
  3216.      state.window = null
  3217.     }
  3218.     state.wrap = wrap;
  3219.     state.wbits = windowBits;
  3220.     return inflateReset(strm)
  3221.    }
  3222.  
  3223.    function inflateInit2(strm, windowBits) {
  3224.     var ret;
  3225.     var state;
  3226.     if (!strm) {
  3227.      return Z_STREAM_ERROR
  3228.     }
  3229.     state = new InflateState;
  3230.     strm.state = state;
  3231.     state.window = null;
  3232.     ret = inflateReset2(strm, windowBits);
  3233.     if (ret !== Z_OK) {
  3234.      strm.state = null
  3235.     }
  3236.     return ret
  3237.    }
  3238.  
  3239.    function inflateInit(strm) {
  3240.     return inflateInit2(strm, DEF_WBITS)
  3241.    }
  3242.    var virgin = true;
  3243.    var lenfix, distfix;
  3244.  
  3245.    function fixedtables(state) {
  3246.     if (virgin) {
  3247.      var sym;
  3248.      lenfix = new utils.Buf32(512);
  3249.      distfix = new utils.Buf32(32);
  3250.      sym = 0;
  3251.      while (sym < 144) {
  3252.       state.lens[sym++] = 8
  3253.      }
  3254.      while (sym < 256) {
  3255.       state.lens[sym++] = 9
  3256.      }
  3257.      while (sym < 280) {
  3258.       state.lens[sym++] = 7
  3259.      }
  3260.      while (sym < 288) {
  3261.       state.lens[sym++] = 8
  3262.      }
  3263.      inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {
  3264.       bits: 9
  3265.      });
  3266.      sym = 0;
  3267.      while (sym < 32) {
  3268.       state.lens[sym++] = 5
  3269.      }
  3270.      inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {
  3271.       bits: 5
  3272.      });
  3273.      virgin = false
  3274.     }
  3275.     state.lencode = lenfix;
  3276.     state.lenbits = 9;
  3277.     state.distcode = distfix;
  3278.     state.distbits = 5
  3279.    }
  3280.  
  3281.    function updatewindow(strm, src, end, copy) {
  3282.     var dist;
  3283.     var state = strm.state;
  3284.     if (state.window === null) {
  3285.      state.wsize = 1 << state.wbits;
  3286.      state.wnext = 0;
  3287.      state.whave = 0;
  3288.      state.window = new utils.Buf8(state.wsize)
  3289.     }
  3290.     if (copy >= state.wsize) {
  3291.      utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
  3292.      state.wnext = 0;
  3293.      state.whave = state.wsize
  3294.     } else {
  3295.      dist = state.wsize - state.wnext;
  3296.      if (dist > copy) {
  3297.       dist = copy
  3298.      }
  3299.      utils.arraySet(state.window, src, end - copy, dist, state.wnext);
  3300.      copy -= dist;
  3301.      if (copy) {
  3302.       utils.arraySet(state.window, src, end - copy, copy, 0);
  3303.       state.wnext = copy;
  3304.       state.whave = state.wsize
  3305.      } else {
  3306.       state.wnext += dist;
  3307.       if (state.wnext === state.wsize) {
  3308.        state.wnext = 0
  3309.       }
  3310.       if (state.whave < state.wsize) {
  3311.        state.whave += dist
  3312.       }
  3313.      }
  3314.     }
  3315.     return 0
  3316.    }
  3317.  
  3318.    function inflate(strm, flush) {
  3319.     var state;
  3320.     var input, output;
  3321.     var next;
  3322.     var put;
  3323.     var have, left;
  3324.     var hold;
  3325.     var bits;
  3326.     var _in, _out;
  3327.     var copy;
  3328.     var from;
  3329.     var from_source;
  3330.     var here = 0;
  3331.     var here_bits, here_op, here_val;
  3332.     var last_bits, last_op, last_val;
  3333.     var len;
  3334.     var ret;
  3335.     var hbuf = new utils.Buf8(4);
  3336.     var opts;
  3337.     var n;
  3338.     var order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
  3339.     if (!strm || !strm.state || !strm.output || !strm.input && strm.avail_in !== 0) {
  3340.      return Z_STREAM_ERROR
  3341.     }
  3342.     state = strm.state;
  3343.     if (state.mode === TYPE) {
  3344.      state.mode = TYPEDO
  3345.     }
  3346.     put = strm.next_out;
  3347.     output = strm.output;
  3348.     left = strm.avail_out;
  3349.     next = strm.next_in;
  3350.     input = strm.input;
  3351.     have = strm.avail_in;
  3352.     hold = state.hold;
  3353.     bits = state.bits;
  3354.     _in = have;
  3355.     _out = left;
  3356.     ret = Z_OK;
  3357.     inf_leave: for (;;) {
  3358.      switch (state.mode) {
  3359.       case HEAD:
  3360.        if (state.wrap === 0) {
  3361.         state.mode = TYPEDO;
  3362.         break
  3363.        }
  3364.        while (bits < 16) {
  3365.         if (have === 0) {
  3366.          break inf_leave
  3367.         }
  3368.         have--;
  3369.         hold += input[next++] << bits;
  3370.         bits += 8
  3371.        }
  3372.        if (state.wrap & 2 && hold === 35615) {
  3373.         state.check = 0;
  3374.         hbuf[0] = hold & 255;
  3375.         hbuf[1] = hold >>> 8 & 255;
  3376.         state.check = crc32(state.check, hbuf, 2, 0);
  3377.         hold = 0;
  3378.         bits = 0;
  3379.         state.mode = FLAGS;
  3380.         break
  3381.        }
  3382.        state.flags = 0;
  3383.        if (state.head) {
  3384.         state.head.done = false
  3385.        }
  3386.        if (!(state.wrap & 1) || (((hold & 255) << 8) + (hold >> 8)) % 31) {
  3387.         strm.msg = "incorrect header check";
  3388.         state.mode = BAD;
  3389.         break
  3390.        }
  3391.        if ((hold & 15) !== Z_DEFLATED) {
  3392.         strm.msg = "unknown compression method";
  3393.         state.mode = BAD;
  3394.         break
  3395.        }
  3396.        hold >>>= 4;
  3397.        bits -= 4;
  3398.        len = (hold & 15) + 8;
  3399.        if (state.wbits === 0) {
  3400.         state.wbits = len
  3401.        } else if (len > state.wbits) {
  3402.         strm.msg = "invalid window size";
  3403.         state.mode = BAD;
  3404.         break
  3405.        }
  3406.        state.dmax = 1 << len;
  3407.        strm.adler = state.check = 1;
  3408.        state.mode = hold & 512 ? DICTID : TYPE;
  3409.        hold = 0;
  3410.        bits = 0;
  3411.        break;
  3412.       case FLAGS:
  3413.        while (bits < 16) {
  3414.         if (have === 0) {
  3415.          break inf_leave
  3416.         }
  3417.         have--;
  3418.         hold += input[next++] << bits;
  3419.         bits += 8
  3420.        }
  3421.        state.flags = hold;
  3422.        if ((state.flags & 255) !== Z_DEFLATED) {
  3423.         strm.msg = "unknown compression method";
  3424.         state.mode = BAD;
  3425.         break
  3426.        }
  3427.        if (state.flags & 57344) {
  3428.         strm.msg = "unknown header flags set";
  3429.         state.mode = BAD;
  3430.         break
  3431.        }
  3432.        if (state.head) {
  3433.         state.head.text = hold >> 8 & 1
  3434.        }
  3435.        if (state.flags & 512) {
  3436.         hbuf[0] = hold & 255;
  3437.         hbuf[1] = hold >>> 8 & 255;
  3438.         state.check = crc32(state.check, hbuf, 2, 0)
  3439.        }
  3440.        hold = 0;
  3441.        bits = 0;
  3442.        state.mode = TIME;
  3443.       case TIME:
  3444.        while (bits < 32) {
  3445.         if (have === 0) {
  3446.          break inf_leave
  3447.         }
  3448.         have--;
  3449.         hold += input[next++] << bits;
  3450.         bits += 8
  3451.        }
  3452.        if (state.head) {
  3453.         state.head.time = hold
  3454.        }
  3455.        if (state.flags & 512) {
  3456.         hbuf[0] = hold & 255;
  3457.         hbuf[1] = hold >>> 8 & 255;
  3458.         hbuf[2] = hold >>> 16 & 255;
  3459.         hbuf[3] = hold >>> 24 & 255;
  3460.         state.check = crc32(state.check, hbuf, 4, 0)
  3461.        }
  3462.        hold = 0;
  3463.        bits = 0;
  3464.        state.mode = OS;
  3465.       case OS:
  3466.        while (bits < 16) {
  3467.         if (have === 0) {
  3468.          break inf_leave
  3469.         }
  3470.         have--;
  3471.         hold += input[next++] << bits;
  3472.         bits += 8
  3473.        }
  3474.        if (state.head) {
  3475.         state.head.xflags = hold & 255;
  3476.         state.head.os = hold >> 8
  3477.        }
  3478.        if (state.flags & 512) {
  3479.         hbuf[0] = hold & 255;
  3480.         hbuf[1] = hold >>> 8 & 255;
  3481.         state.check = crc32(state.check, hbuf, 2, 0)
  3482.        }
  3483.        hold = 0;
  3484.        bits = 0;
  3485.        state.mode = EXLEN;
  3486.       case EXLEN:
  3487.        if (state.flags & 1024) {
  3488.         while (bits < 16) {
  3489.          if (have === 0) {
  3490.           break inf_leave
  3491.          }
  3492.          have--;
  3493.          hold += input[next++] << bits;
  3494.          bits += 8
  3495.         }
  3496.         state.length = hold;
  3497.         if (state.head) {
  3498.          state.head.extra_len = hold
  3499.         }
  3500.         if (state.flags & 512) {
  3501.          hbuf[0] = hold & 255;
  3502.          hbuf[1] = hold >>> 8 & 255;
  3503.          state.check = crc32(state.check, hbuf, 2, 0)
  3504.         }
  3505.         hold = 0;
  3506.         bits = 0
  3507.        } else if (state.head) {
  3508.         state.head.extra = null
  3509.        }
  3510.        state.mode = EXTRA;
  3511.       case EXTRA:
  3512.        if (state.flags & 1024) {
  3513.         copy = state.length;
  3514.         if (copy > have) {
  3515.          copy = have
  3516.         }
  3517.         if (copy) {
  3518.          if (state.head) {
  3519.           len = state.head.extra_len - state.length;
  3520.           if (!state.head.extra) {
  3521.            state.head.extra = new Array(state.head.extra_len)
  3522.           }
  3523.           utils.arraySet(state.head.extra, input, next, copy, len)
  3524.          }
  3525.          if (state.flags & 512) {
  3526.           state.check = crc32(state.check, input, copy, next)
  3527.          }
  3528.          have -= copy;
  3529.          next += copy;
  3530.          state.length -= copy
  3531.         }
  3532.         if (state.length) {
  3533.          break inf_leave
  3534.         }
  3535.        }
  3536.        state.length = 0;
  3537.        state.mode = NAME;
  3538.       case NAME:
  3539.        if (state.flags & 2048) {
  3540.         if (have === 0) {
  3541.          break inf_leave
  3542.         }
  3543.         copy = 0;
  3544.         do {
  3545.          len = input[next + copy++];
  3546.          if (state.head && len && state.length < 65536) {
  3547.           state.head.name += String.fromCharCode(len)
  3548.          }
  3549.         } while (len && copy < have);
  3550.         if (state.flags & 512) {
  3551.          state.check = crc32(state.check, input, copy, next)
  3552.         }
  3553.         have -= copy;
  3554.         next += copy;
  3555.         if (len) {
  3556.          break inf_leave
  3557.         }
  3558.        } else if (state.head) {
  3559.         state.head.name = null
  3560.        }
  3561.        state.length = 0;
  3562.        state.mode = COMMENT;
  3563.       case COMMENT:
  3564.        if (state.flags & 4096) {
  3565.         if (have === 0) {
  3566.          break inf_leave
  3567.         }
  3568.         copy = 0;
  3569.         do {
  3570.          len = input[next + copy++];
  3571.          if (state.head && len && state.length < 65536) {
  3572.           state.head.comment += String.fromCharCode(len)
  3573.          }
  3574.         } while (len && copy < have);
  3575.         if (state.flags & 512) {
  3576.          state.check = crc32(state.check, input, copy, next)
  3577.         }
  3578.         have -= copy;
  3579.         next += copy;
  3580.         if (len) {
  3581.          break inf_leave
  3582.         }
  3583.        } else if (state.head) {
  3584.         state.head.comment = null
  3585.        }
  3586.        state.mode = HCRC;
  3587.       case HCRC:
  3588.        if (state.flags & 512) {
  3589.         while (bits < 16) {
  3590.          if (have === 0) {
  3591.           break inf_leave
  3592.          }
  3593.          have--;
  3594.          hold += input[next++] << bits;
  3595.          bits += 8
  3596.         }
  3597.         if (hold !== (state.check & 65535)) {
  3598.          strm.msg = "header crc mismatch";
  3599.          state.mode = BAD;
  3600.          break
  3601.         }
  3602.         hold = 0;
  3603.         bits = 0
  3604.        }
  3605.        if (state.head) {
  3606.         state.head.hcrc = state.flags >> 9 & 1;
  3607.         state.head.done = true
  3608.        }
  3609.        strm.adler = state.check = 0;
  3610.        state.mode = TYPE;
  3611.        break;
  3612.       case DICTID:
  3613.        while (bits < 32) {
  3614.         if (have === 0) {
  3615.          break inf_leave
  3616.         }
  3617.         have--;
  3618.         hold += input[next++] << bits;
  3619.         bits += 8
  3620.        }
  3621.        strm.adler = state.check = ZSWAP32(hold);
  3622.        hold = 0;
  3623.        bits = 0;
  3624.        state.mode = DICT;
  3625.       case DICT:
  3626.        if (state.havedict === 0) {
  3627.         strm.next_out = put;
  3628.         strm.avail_out = left;
  3629.         strm.next_in = next;
  3630.         strm.avail_in = have;
  3631.         state.hold = hold;
  3632.         state.bits = bits;
  3633.         return Z_NEED_DICT
  3634.        }
  3635.        strm.adler = state.check = 1;
  3636.        state.mode = TYPE;
  3637.       case TYPE:
  3638.        if (flush === Z_BLOCK || flush === Z_TREES) {
  3639.         break inf_leave
  3640.        }
  3641.       case TYPEDO:
  3642.        if (state.last) {
  3643.         hold >>>= bits & 7;
  3644.         bits -= bits & 7;
  3645.         state.mode = CHECK;
  3646.         break
  3647.        }
  3648.        while (bits < 3) {
  3649.         if (have === 0) {
  3650.          break inf_leave
  3651.         }
  3652.         have--;
  3653.         hold += input[next++] << bits;
  3654.         bits += 8
  3655.        }
  3656.        state.last = hold & 1;
  3657.        hold >>>= 1;
  3658.        bits -= 1;
  3659.        switch (hold & 3) {
  3660.         case 0:
  3661.          state.mode = STORED;
  3662.          break;
  3663.         case 1:
  3664.          fixedtables(state);
  3665.          state.mode = LEN_;
  3666.          if (flush === Z_TREES) {
  3667.           hold >>>= 2;
  3668.           bits -= 2;
  3669.           break inf_leave
  3670.          }
  3671.          break;
  3672.         case 2:
  3673.          state.mode = TABLE;
  3674.          break;
  3675.         case 3:
  3676.          strm.msg = "invalid block type";
  3677.          state.mode = BAD
  3678.        }
  3679.        hold >>>= 2;
  3680.        bits -= 2;
  3681.        break;
  3682.       case STORED:
  3683.        hold >>>= bits & 7;
  3684.        bits -= bits & 7;
  3685.        while (bits < 32) {
  3686.         if (have === 0) {
  3687.          break inf_leave
  3688.         }
  3689.         have--;
  3690.         hold += input[next++] << bits;
  3691.         bits += 8
  3692.        }
  3693.        if ((hold & 65535) !== (hold >>> 16 ^ 65535)) {
  3694.         strm.msg = "invalid stored block lengths";
  3695.         state.mode = BAD;
  3696.         break
  3697.        }
  3698.        state.length = hold & 65535;
  3699.        hold = 0;
  3700.        bits = 0;
  3701.        state.mode = COPY_;
  3702.        if (flush === Z_TREES) {
  3703.         break inf_leave
  3704.        }
  3705.       case COPY_:
  3706.        state.mode = COPY;
  3707.       case COPY:
  3708.        copy = state.length;
  3709.        if (copy) {
  3710.         if (copy > have) {
  3711.          copy = have
  3712.         }
  3713.         if (copy > left) {
  3714.          copy = left
  3715.         }
  3716.         if (copy === 0) {
  3717.          break inf_leave
  3718.         }
  3719.         utils.arraySet(output, input, next, copy, put);
  3720.         have -= copy;
  3721.         next += copy;
  3722.         left -= copy;
  3723.         put += copy;
  3724.         state.length -= copy;
  3725.         break
  3726.        }
  3727.        state.mode = TYPE;
  3728.        break;
  3729.       case TABLE:
  3730.        while (bits < 14) {
  3731.         if (have === 0) {
  3732.          break inf_leave
  3733.         }
  3734.         have--;
  3735.         hold += input[next++] << bits;
  3736.         bits += 8
  3737.        }
  3738.        state.nlen = (hold & 31) + 257;
  3739.        hold >>>= 5;
  3740.        bits -= 5;
  3741.        state.ndist = (hold & 31) + 1;
  3742.        hold >>>= 5;
  3743.        bits -= 5;
  3744.        state.ncode = (hold & 15) + 4;
  3745.        hold >>>= 4;
  3746.        bits -= 4;
  3747.        if (state.nlen > 286 || state.ndist > 30) {
  3748.         strm.msg = "too many length or distance symbols";
  3749.         state.mode = BAD;
  3750.         break
  3751.        }
  3752.        state.have = 0;
  3753.        state.mode = LENLENS;
  3754.       case LENLENS:
  3755.        while (state.have < state.ncode) {
  3756.         while (bits < 3) {
  3757.          if (have === 0) {
  3758.           break inf_leave
  3759.          }
  3760.          have--;
  3761.          hold += input[next++] << bits;
  3762.          bits += 8
  3763.         }
  3764.         state.lens[order[state.have++]] = hold & 7;
  3765.         hold >>>= 3;
  3766.         bits -= 3
  3767.        }
  3768.        while (state.have < 19) {
  3769.         state.lens[order[state.have++]] = 0
  3770.        }
  3771.        state.lencode = state.lendyn;
  3772.        state.lenbits = 7;
  3773.        opts = {
  3774.         bits: state.lenbits
  3775.        };
  3776.        ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
  3777.        state.lenbits = opts.bits;
  3778.        if (ret) {
  3779.         strm.msg = "invalid code lengths set";
  3780.         state.mode = BAD;
  3781.         break
  3782.        }
  3783.        state.have = 0;
  3784.        state.mode = CODELENS;
  3785.       case CODELENS:
  3786.        while (state.have < state.nlen + state.ndist) {
  3787.         for (;;) {
  3788.          here = state.lencode[hold & (1 << state.lenbits) - 1];
  3789.          here_bits = here >>> 24;
  3790.          here_op = here >>> 16 & 255;
  3791.          here_val = here & 65535;
  3792.          if (here_bits <= bits) {
  3793.           break
  3794.          }
  3795.          if (have === 0) {
  3796.           break inf_leave
  3797.          }
  3798.          have--;
  3799.          hold += input[next++] << bits;
  3800.          bits += 8
  3801.         }
  3802.         if (here_val < 16) {
  3803.          hold >>>= here_bits;
  3804.          bits -= here_bits;
  3805.          state.lens[state.have++] = here_val
  3806.         } else {
  3807.          if (here_val === 16) {
  3808.           n = here_bits + 2;
  3809.           while (bits < n) {
  3810.            if (have === 0) {
  3811.             break inf_leave
  3812.            }
  3813.            have--;
  3814.            hold += input[next++] << bits;
  3815.            bits += 8
  3816.           }
  3817.           hold >>>= here_bits;
  3818.           bits -= here_bits;
  3819.           if (state.have === 0) {
  3820.            strm.msg = "invalid bit length repeat";
  3821.            state.mode = BAD;
  3822.            break
  3823.           }
  3824.           len = state.lens[state.have - 1];
  3825.           copy = 3 + (hold & 3);
  3826.           hold >>>= 2;
  3827.           bits -= 2
  3828.          } else if (here_val === 17) {
  3829.           n = here_bits + 3;
  3830.           while (bits < n) {
  3831.            if (have === 0) {
  3832.             break inf_leave
  3833.            }
  3834.            have--;
  3835.            hold += input[next++] << bits;
  3836.            bits += 8
  3837.           }
  3838.           hold >>>= here_bits;
  3839.           bits -= here_bits;
  3840.           len = 0;
  3841.           copy = 3 + (hold & 7);
  3842.           hold >>>= 3;
  3843.           bits -= 3
  3844.          } else {
  3845.           n = here_bits + 7;
  3846.           while (bits < n) {
  3847.            if (have === 0) {
  3848.             break inf_leave
  3849.            }
  3850.            have--;
  3851.            hold += input[next++] << bits;
  3852.            bits += 8
  3853.           }
  3854.           hold >>>= here_bits;
  3855.           bits -= here_bits;
  3856.           len = 0;
  3857.           copy = 11 + (hold & 127);
  3858.           hold >>>= 7;
  3859.           bits -= 7
  3860.          }
  3861.          if (state.have + copy > state.nlen + state.ndist) {
  3862.           strm.msg = "invalid bit length repeat";
  3863.           state.mode = BAD;
  3864.           break
  3865.          }
  3866.          while (copy--) {
  3867.           state.lens[state.have++] = len
  3868.          }
  3869.         }
  3870.        }
  3871.        if (state.mode === BAD) {
  3872.         break
  3873.        }
  3874.        if (state.lens[256] === 0) {
  3875.         strm.msg = "invalid code -- missing end-of-block";
  3876.         state.mode = BAD;
  3877.         break
  3878.        }
  3879.        state.lenbits = 9;
  3880.        opts = {
  3881.         bits: state.lenbits
  3882.        };
  3883.        ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
  3884.        state.lenbits = opts.bits;
  3885.        if (ret) {
  3886.         strm.msg = "invalid literal/lengths set";
  3887.         state.mode = BAD;
  3888.         break
  3889.        }
  3890.        state.distbits = 6;
  3891.        state.distcode = state.distdyn;
  3892.        opts = {
  3893.         bits: state.distbits
  3894.        };
  3895.        ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
  3896.        state.distbits = opts.bits;
  3897.        if (ret) {
  3898.         strm.msg = "invalid distances set";
  3899.         state.mode = BAD;
  3900.         break
  3901.        }
  3902.        state.mode = LEN_;
  3903.        if (flush === Z_TREES) {
  3904.         break inf_leave
  3905.        }
  3906.       case LEN_:
  3907.        state.mode = LEN;
  3908.       case LEN:
  3909.        if (have >= 6 && left >= 258) {
  3910.         strm.next_out = put;
  3911.         strm.avail_out = left;
  3912.         strm.next_in = next;
  3913.         strm.avail_in = have;
  3914.         state.hold = hold;
  3915.         state.bits = bits;
  3916.         inflate_fast(strm, _out);
  3917.         put = strm.next_out;
  3918.         output = strm.output;
  3919.         left = strm.avail_out;
  3920.         next = strm.next_in;
  3921.         input = strm.input;
  3922.         have = strm.avail_in;
  3923.         hold = state.hold;
  3924.         bits = state.bits;
  3925.         if (state.mode === TYPE) {
  3926.          state.back = -1
  3927.         }
  3928.         break
  3929.        }
  3930.        state.back = 0;
  3931.        for (;;) {
  3932.         here = state.lencode[hold & (1 << state.lenbits) - 1];
  3933.         here_bits = here >>> 24;
  3934.         here_op = here >>> 16 & 255;
  3935.         here_val = here & 65535;
  3936.         if (here_bits <= bits) {
  3937.          break
  3938.         }
  3939.         if (have === 0) {
  3940.          break inf_leave
  3941.         }
  3942.         have--;
  3943.         hold += input[next++] << bits;
  3944.         bits += 8
  3945.        }
  3946.        if (here_op && (here_op & 240) === 0) {
  3947.         last_bits = here_bits;
  3948.         last_op = here_op;
  3949.         last_val = here_val;
  3950.         for (;;) {
  3951.          here = state.lencode[last_val + ((hold & (1 << last_bits + last_op) - 1) >> last_bits)];
  3952.          here_bits = here >>> 24;
  3953.          here_op = here >>> 16 & 255;
  3954.          here_val = here & 65535;
  3955.          if (last_bits + here_bits <= bits) {
  3956.           break
  3957.          }
  3958.          if (have === 0) {
  3959.           break inf_leave
  3960.          }
  3961.          have--;
  3962.          hold += input[next++] << bits;
  3963.          bits += 8
  3964.         }
  3965.         hold >>>= last_bits;
  3966.         bits -= last_bits;
  3967.         state.back += last_bits
  3968.        }
  3969.        hold >>>= here_bits;
  3970.        bits -= here_bits;
  3971.        state.back += here_bits;
  3972.        state.length = here_val;
  3973.        if (here_op === 0) {
  3974.         state.mode = LIT;
  3975.         break
  3976.        }
  3977.        if (here_op & 32) {
  3978.         state.back = -1;
  3979.         state.mode = TYPE;
  3980.         break
  3981.        }
  3982.        if (here_op & 64) {
  3983.         strm.msg = "invalid literal/length code";
  3984.         state.mode = BAD;
  3985.         break
  3986.        }
  3987.        state.extra = here_op & 15;
  3988.        state.mode = LENEXT;
  3989.       case LENEXT:
  3990.        if (state.extra) {
  3991.         n = state.extra;
  3992.         while (bits < n) {
  3993.          if (have === 0) {
  3994.           break inf_leave
  3995.          }
  3996.          have--;
  3997.          hold += input[next++] << bits;
  3998.          bits += 8
  3999.         }
  4000.         state.length += hold & (1 << state.extra) - 1;
  4001.         hold >>>= state.extra;
  4002.         bits -= state.extra;
  4003.         state.back += state.extra
  4004.        }
  4005.        state.was = state.length;
  4006.        state.mode = DIST;
  4007.       case DIST:
  4008.        for (;;) {
  4009.         here = state.distcode[hold & (1 << state.distbits) - 1];
  4010.         here_bits = here >>> 24;
  4011.         here_op = here >>> 16 & 255;
  4012.         here_val = here & 65535;
  4013.         if (here_bits <= bits) {
  4014.          break
  4015.         }
  4016.         if (have === 0) {
  4017.          break inf_leave
  4018.         }
  4019.         have--;
  4020.         hold += input[next++] << bits;
  4021.         bits += 8
  4022.        }
  4023.        if ((here_op & 240) === 0) {
  4024.         last_bits = here_bits;
  4025.         last_op = here_op;
  4026.         last_val = here_val;
  4027.         for (;;) {
  4028.          here = state.distcode[last_val + ((hold & (1 << last_bits + last_op) - 1) >> last_bits)];
  4029.          here_bits = here >>> 24;
  4030.          here_op = here >>> 16 & 255;
  4031.          here_val = here & 65535;
  4032.          if (last_bits + here_bits <= bits) {
  4033.           break
  4034.          }
  4035.          if (have === 0) {
  4036.           break inf_leave
  4037.          }
  4038.          have--;
  4039.          hold += input[next++] << bits;
  4040.          bits += 8
  4041.         }
  4042.         hold >>>= last_bits;
  4043.         bits -= last_bits;
  4044.         state.back += last_bits
  4045.        }
  4046.        hold >>>= here_bits;
  4047.        bits -= here_bits;
  4048.        state.back += here_bits;
  4049.        if (here_op & 64) {
  4050.         strm.msg = "invalid distance code";
  4051.         state.mode = BAD;
  4052.         break
  4053.        }
  4054.        state.offset = here_val;
  4055.        state.extra = here_op & 15;
  4056.        state.mode = DISTEXT;
  4057.       case DISTEXT:
  4058.        if (state.extra) {
  4059.         n = state.extra;
  4060.         while (bits < n) {
  4061.          if (have === 0) {
  4062.           break inf_leave
  4063.          }
  4064.          have--;
  4065.          hold += input[next++] << bits;
  4066.          bits += 8
  4067.         }
  4068.         state.offset += hold & (1 << state.extra) - 1;
  4069.         hold >>>= state.extra;
  4070.         bits -= state.extra;
  4071.         state.back += state.extra
  4072.        }
  4073.        if (state.offset > state.dmax) {
  4074.         strm.msg = "invalid distance too far back";
  4075.         state.mode = BAD;
  4076.         break
  4077.        }
  4078.        state.mode = MATCH;
  4079.       case MATCH:
  4080.        if (left === 0) {
  4081.         break inf_leave
  4082.        }
  4083.        copy = _out - left;
  4084.        if (state.offset > copy) {
  4085.         copy = state.offset - copy;
  4086.         if (copy > state.whave) {
  4087.          if (state.sane) {
  4088.           strm.msg = "invalid distance too far back";
  4089.           state.mode = BAD;
  4090.           break
  4091.          }
  4092.         }
  4093.         if (copy > state.wnext) {
  4094.          copy -= state.wnext;
  4095.          from = state.wsize - copy
  4096.         } else {
  4097.          from = state.wnext - copy
  4098.         }
  4099.         if (copy > state.length) {
  4100.          copy = state.length
  4101.         }
  4102.         from_source = state.window
  4103.        } else {
  4104.         from_source = output;
  4105.         from = put - state.offset;
  4106.         copy = state.length
  4107.        }
  4108.        if (copy > left) {
  4109.         copy = left
  4110.        }
  4111.        left -= copy;
  4112.        state.length -= copy;
  4113.        do {
  4114.         output[put++] = from_source[from++]
  4115.        } while (--copy);
  4116.        if (state.length === 0) {
  4117.         state.mode = LEN
  4118.        }
  4119.        break;
  4120.       case LIT:
  4121.        if (left === 0) {
  4122.         break inf_leave
  4123.        }
  4124.        output[put++] = state.length;
  4125.        left--;
  4126.        state.mode = LEN;
  4127.        break;
  4128.       case CHECK:
  4129.        if (state.wrap) {
  4130.         while (bits < 32) {
  4131.          if (have === 0) {
  4132.           break inf_leave
  4133.          }
  4134.          have--;
  4135.          hold |= input[next++] << bits;
  4136.          bits += 8
  4137.         }
  4138.         _out -= left;
  4139.         strm.total_out += _out;
  4140.         state.total += _out;
  4141.         if (_out) {
  4142.          strm.adler = state.check = state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)
  4143.         }
  4144.         _out = left;
  4145.         if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) {
  4146.          strm.msg = "incorrect data check";
  4147.          state.mode = BAD;
  4148.          break
  4149.         }
  4150.         hold = 0;
  4151.         bits = 0
  4152.        }
  4153.        state.mode = LENGTH;
  4154.       case LENGTH:
  4155.        if (state.wrap && state.flags) {
  4156.         while (bits < 32) {
  4157.          if (have === 0) {
  4158.           break inf_leave
  4159.          }
  4160.          have--;
  4161.          hold += input[next++] << bits;
  4162.          bits += 8
  4163.         }
  4164.         if (hold !== (state.total & 4294967295)) {
  4165.          strm.msg = "incorrect length check";
  4166.          state.mode = BAD;
  4167.          break
  4168.         }
  4169.         hold = 0;
  4170.         bits = 0
  4171.        }
  4172.        state.mode = DONE;
  4173.       case DONE:
  4174.        ret = Z_STREAM_END;
  4175.        break inf_leave;
  4176.       case BAD:
  4177.        ret = Z_DATA_ERROR;
  4178.        break inf_leave;
  4179.       case MEM:
  4180.        return Z_MEM_ERROR;
  4181.       case SYNC:
  4182.       default:
  4183.        return Z_STREAM_ERROR
  4184.      }
  4185.     }
  4186.     strm.next_out = put;
  4187.     strm.avail_out = left;
  4188.     strm.next_in = next;
  4189.     strm.avail_in = have;
  4190.     state.hold = hold;
  4191.     state.bits = bits;
  4192.     if (state.wsize || _out !== strm.avail_out && state.mode < BAD && (state.mode < CHECK || flush !== Z_FINISH)) {
  4193.      if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
  4194.       state.mode = MEM;
  4195.       return Z_MEM_ERROR
  4196.      }
  4197.     }
  4198.     _in -= strm.avail_in;
  4199.     _out -= strm.avail_out;
  4200.     strm.total_in += _in;
  4201.     strm.total_out += _out;
  4202.     state.total += _out;
  4203.     if (state.wrap && _out) {
  4204.      strm.adler = state.check = state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)
  4205.     }
  4206.     strm.data_type = state.bits + (state.last ? 64 : 0) + (state.mode === TYPE ? 128 : 0) + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
  4207.     if ((_in === 0 && _out === 0 || flush === Z_FINISH) && ret === Z_OK) {
  4208.      ret = Z_BUF_ERROR
  4209.     }
  4210.     return ret
  4211.    }
  4212.  
  4213.    function inflateEnd(strm) {
  4214.     if (!strm || !strm.state) {
  4215.      return Z_STREAM_ERROR
  4216.     }
  4217.     var state = strm.state;
  4218.     if (state.window) {
  4219.      state.window = null
  4220.     }
  4221.     strm.state = null;
  4222.     return Z_OK
  4223.    }
  4224.  
  4225.    function inflateGetHeader(strm, head) {
  4226.     var state;
  4227.     if (!strm || !strm.state) {
  4228.      return Z_STREAM_ERROR
  4229.     }
  4230.     state = strm.state;
  4231.     if ((state.wrap & 2) === 0) {
  4232.      return Z_STREAM_ERROR
  4233.     }
  4234.     state.head = head;
  4235.     head.done = false;
  4236.     return Z_OK
  4237.    }
  4238.    exports.inflateReset = inflateReset;
  4239.    exports.inflateReset2 = inflateReset2;
  4240.    exports.inflateResetKeep = inflateResetKeep;
  4241.    exports.inflateInit = inflateInit;
  4242.    exports.inflateInit2 = inflateInit2;
  4243.    exports.inflate = inflate;
  4244.    exports.inflateEnd = inflateEnd;
  4245.    exports.inflateGetHeader = inflateGetHeader;
  4246.    exports.inflateInfo = "pako inflate (from Nodeca project)"
  4247.   }, {
  4248.    "../utils/common": 2,
  4249.    "./adler32": 4,
  4250.    "./crc32": 6,
  4251.    "./inffast": 8,
  4252.    "./inftrees": 10
  4253.   }],
  4254.   10: [function(_dereq_, module, exports) {
  4255.    "use strict";
  4256.    var utils = _dereq_("../utils/common");
  4257.    var MAXBITS = 15;
  4258.    var ENOUGH_LENS = 852;
  4259.    var ENOUGH_DISTS = 592;
  4260.    var CODES = 0;
  4261.    var LENS = 1;
  4262.    var DISTS = 2;
  4263.    var lbase = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0];
  4264.    var lext = [16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78];
  4265.    var dbase = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0];
  4266.    var dext = [16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64];
  4267.    module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) {
  4268.     var bits = opts.bits;
  4269.     var len = 0;
  4270.     var sym = 0;
  4271.     var min = 0,
  4272.      max = 0;
  4273.     var root = 0;
  4274.     var curr = 0;
  4275.     var drop = 0;
  4276.     var left = 0;
  4277.     var used = 0;
  4278.     var huff = 0;
  4279.     var incr;
  4280.     var fill;
  4281.     var low;
  4282.     var mask;
  4283.     var next;
  4284.     var base = null;
  4285.     var base_index = 0;
  4286.     var end;
  4287.     var count = new utils.Buf16(MAXBITS + 1);
  4288.     var offs = new utils.Buf16(MAXBITS + 1);
  4289.     var extra = null;
  4290.     var extra_index = 0;
  4291.     var here_bits, here_op, here_val;
  4292.     for (len = 0; len <= MAXBITS; len++) {
  4293.      count[len] = 0
  4294.     }
  4295.     for (sym = 0; sym < codes; sym++) {
  4296.      count[lens[lens_index + sym]]++
  4297.     }
  4298.     root = bits;
  4299.     for (max = MAXBITS; max >= 1; max--) {
  4300.      if (count[max] !== 0) {
  4301.       break
  4302.      }
  4303.     }
  4304.     if (root > max) {
  4305.      root = max
  4306.     }
  4307.     if (max === 0) {
  4308.      table[table_index++] = 1 << 24 | 64 << 16 | 0;
  4309.      table[table_index++] = 1 << 24 | 64 << 16 | 0;
  4310.      opts.bits = 1;
  4311.      return 0
  4312.     }
  4313.     for (min = 1; min < max; min++) {
  4314.      if (count[min] !== 0) {
  4315.       break
  4316.      }
  4317.     }
  4318.     if (root < min) {
  4319.      root = min
  4320.     }
  4321.     left = 1;
  4322.     for (len = 1; len <= MAXBITS; len++) {
  4323.      left <<= 1;
  4324.      left -= count[len];
  4325.      if (left < 0) {
  4326.       return -1
  4327.      }
  4328.     }
  4329.     if (left > 0 && (type === CODES || max !== 1)) {
  4330.      return -1
  4331.     }
  4332.     offs[1] = 0;
  4333.     for (len = 1; len < MAXBITS; len++) {
  4334.      offs[len + 1] = offs[len] + count[len]
  4335.     }
  4336.     for (sym = 0; sym < codes; sym++) {
  4337.      if (lens[lens_index + sym] !== 0) {
  4338.       work[offs[lens[lens_index + sym]]++] = sym
  4339.      }
  4340.     }
  4341.     if (type === CODES) {
  4342.      base = extra = work;
  4343.      end = 19
  4344.     } else if (type === LENS) {
  4345.      base = lbase;
  4346.      base_index -= 257;
  4347.      extra = lext;
  4348.      extra_index -= 257;
  4349.      end = 256
  4350.     } else {
  4351.      base = dbase;
  4352.      extra = dext;
  4353.      end = -1
  4354.     }
  4355.     huff = 0;
  4356.     sym = 0;
  4357.     len = min;
  4358.     next = table_index;
  4359.     curr = root;
  4360.     drop = 0;
  4361.     low = -1;
  4362.     used = 1 << root;
  4363.     mask = used - 1;
  4364.     if (type === LENS && used > ENOUGH_LENS || type === DISTS && used > ENOUGH_DISTS) {
  4365.      return 1
  4366.     }
  4367.     var i = 0;
  4368.     for (;;) {
  4369.      i++;
  4370.      here_bits = len - drop;
  4371.      if (work[sym] < end) {
  4372.       here_op = 0;
  4373.       here_val = work[sym]
  4374.      } else if (work[sym] > end) {
  4375.       here_op = extra[extra_index + work[sym]];
  4376.       here_val = base[base_index + work[sym]]
  4377.      } else {
  4378.       here_op = 32 + 64;
  4379.       here_val = 0
  4380.      }
  4381.      incr = 1 << len - drop;
  4382.      fill = 1 << curr;
  4383.      min = fill;
  4384.      do {
  4385.       fill -= incr;
  4386.       table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val | 0
  4387.      } while (fill !== 0);
  4388.      incr = 1 << len - 1;
  4389.      while (huff & incr) {
  4390.       incr >>= 1
  4391.      }
  4392.      if (incr !== 0) {
  4393.       huff &= incr - 1;
  4394.       huff += incr
  4395.      } else {
  4396.       huff = 0
  4397.      }
  4398.      sym++;
  4399.      if (--count[len] === 0) {
  4400.       if (len === max) {
  4401.        break
  4402.       }
  4403.       len = lens[lens_index + work[sym]]
  4404.      }
  4405.      if (len > root && (huff & mask) !== low) {
  4406.       if (drop === 0) {
  4407.        drop = root
  4408.       }
  4409.       next += min;
  4410.       curr = len - drop;
  4411.       left = 1 << curr;
  4412.       while (curr + drop < max) {
  4413.        left -= count[curr + drop];
  4414.        if (left <= 0) {
  4415.         break
  4416.        }
  4417.        curr++;
  4418.        left <<= 1
  4419.       }
  4420.       used += 1 << curr;
  4421.       if (type === LENS && used > ENOUGH_LENS || type === DISTS && used > ENOUGH_DISTS) {
  4422.        return 1
  4423.       }
  4424.       low = huff & mask;
  4425.       table[low] = root << 24 | curr << 16 | next - table_index | 0
  4426.      }
  4427.     }
  4428.     if (huff !== 0) {
  4429.      table[next + huff] = len - drop << 24 | 64 << 16 | 0
  4430.     }
  4431.     opts.bits = root;
  4432.     return 0
  4433.    }
  4434.   }, {
  4435.    "../utils/common": 2
  4436.   }],
  4437.   11: [function(_dereq_, module, exports) {
  4438.    "use strict";
  4439.    module.exports = {
  4440.     2: "need dictionary",
  4441.     1: "stream end",
  4442.     0: "",
  4443.     "-1": "file error",
  4444.     "-2": "stream error",
  4445.     "-3": "data error",
  4446.     "-4": "insufficient memory",
  4447.     "-5": "buffer error",
  4448.     "-6": "incompatible version"
  4449.    }
  4450.   }, {}],
  4451.   12: [function(_dereq_, module, exports) {
  4452.    "use strict";
  4453.  
  4454.    function ZStream() {
  4455.     this.input = null;
  4456.     this.next_in = 0;
  4457.     this.avail_in = 0;
  4458.     this.total_in = 0;
  4459.     this.output = null;
  4460.     this.next_out = 0;
  4461.     this.avail_out = 0;
  4462.     this.total_out = 0;
  4463.     this.msg = "";
  4464.     this.state = null;
  4465.     this.data_type = 2;
  4466.     this.adler = 0
  4467.    }
  4468.    module.exports = ZStream
  4469.   }, {}]
  4470.  }, {}, [1])(1)
  4471. });
  4472. var swfobject = function() {
  4473.  var D = "undefined",
  4474.   r = "object",
  4475.   T = "Shockwave Flash",
  4476.   Z = "ShockwaveFlash.ShockwaveFlash",
  4477.   q = "application/x-shockwave-flash",
  4478.   S = "SWFObjectExprInst",
  4479.   x = "onreadystatechange",
  4480.   Q = window,
  4481.   h = document,
  4482.   t = navigator,
  4483.   V = false,
  4484.   X = [],
  4485.   o = [],
  4486.   P = [],
  4487.   K = [],
  4488.   I, p, E, B, L = false,
  4489.   a = false,
  4490.   m, G, j = true,
  4491.   l = false,
  4492.   O = function() {
  4493.    var ad = typeof h.getElementById != D && typeof h.getElementsByTagName != D && typeof h.createElement != D,
  4494.     ak = t.userAgent.toLowerCase(),
  4495.     ab = t.platform.toLowerCase(),
  4496.     ah = ab ? /win/.test(ab) : /win/.test(ak),
  4497.     af = ab ? /mac/.test(ab) : /mac/.test(ak),
  4498.     ai = /webkit/.test(ak) ? parseFloat(ak.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false,
  4499.     aa = t.appName === "Microsoft Internet Explorer",
  4500.     aj = [0, 0, 0],
  4501.     ae = null;
  4502.    if (typeof t.plugins != D && typeof t.plugins[T] == r) {
  4503.     ae = t.plugins[T].description;
  4504.     if (ae && (typeof t.mimeTypes != D && t.mimeTypes[q] && t.mimeTypes[q].enabledPlugin)) {
  4505.      V = true;
  4506.      aa = false;
  4507.      ae = ae.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
  4508.      aj[0] = n(ae.replace(/^(.*)\..*$/, "$1"));
  4509.      aj[1] = n(ae.replace(/^.*\.(.*)\s.*$/, "$1"));
  4510.      aj[2] = /[a-zA-Z]/.test(ae) ? n(ae.replace(/^.*[a-zA-Z]+(.*)$/, "$1")) : 0
  4511.     }
  4512.    } else {
  4513.     if (typeof Q.ActiveXObject != D) {
  4514.      try {
  4515.       var ag = new ActiveXObject(Z);
  4516.       if (ag) {
  4517.        ae = ag.GetVariable("$version");
  4518.        if (ae) {
  4519.         aa = true;
  4520.         ae = ae.split(" ")[1].split(",");
  4521.         aj = [n(ae[0]), n(ae[1]), n(ae[2])]
  4522.        }
  4523.       }
  4524.      } catch (ac) {}
  4525.     }
  4526.    }
  4527.    return {
  4528.     w3: ad,
  4529.     pv: aj,
  4530.     wk: ai,
  4531.     ie: aa,
  4532.     win: ah,
  4533.     mac: af
  4534.    }
  4535.   }(),
  4536.   i = function() {
  4537.    if (!O.w3) {
  4538.     return
  4539.    }
  4540.    if (typeof h.readyState != D && (h.readyState === "complete" || h.readyState === "interactive") || typeof h.readyState == D && (h.getElementsByTagName("body")[0] || h.body)) {
  4541.     f()
  4542.    }
  4543.    if (!L) {
  4544.     if (typeof h.addEventListener != D) {
  4545.      h.addEventListener("DOMContentLoaded", f, false)
  4546.     }
  4547.     if (O.ie) {
  4548.      h.attachEvent(x, function aa() {
  4549.       if (h.readyState == "complete") {
  4550.        h.detachEvent(x, aa);
  4551.        f()
  4552.       }
  4553.      });
  4554.      if (Q == top) {
  4555.       (function ac() {
  4556.        if (L) {
  4557.         return
  4558.        }
  4559.        try {
  4560.         h.documentElement.doScroll("left")
  4561.        } catch (ad) {
  4562.         setTimeout(ac, 0);
  4563.         return
  4564.        }
  4565.        f()
  4566.       })()
  4567.      }
  4568.     }
  4569.     if (O.wk) {
  4570.      (function ab() {
  4571.       if (L) {
  4572.        return
  4573.       }
  4574.       if (!/loaded|complete/.test(h.readyState)) {
  4575.        setTimeout(ab, 0);
  4576.        return
  4577.       }
  4578.       f()
  4579.      })()
  4580.     }
  4581.    }
  4582.   }();
  4583.  
  4584.  function f() {
  4585.   if (L || !document.getElementsByTagName("body")[0]) {
  4586.    return
  4587.   }
  4588.   try {
  4589.    var ac, ad = C("span");
  4590.    ad.style.display = "none";
  4591.    ac = h.getElementsByTagName("body")[0].appendChild(ad);
  4592.    ac.parentNode.removeChild(ac);
  4593.    ac = null;
  4594.    ad = null
  4595.   } catch (ae) {
  4596.    return
  4597.   }
  4598.   L = true;
  4599.   var aa = X.length;
  4600.   for (var ab = 0; ab < aa; ab++) {
  4601.    X[ab]()
  4602.   }
  4603.  }
  4604.  
  4605.  function M(aa) {
  4606.   if (L) {
  4607.    aa()
  4608.   } else {
  4609.    X[X.length] = aa
  4610.   }
  4611.  }
  4612.  
  4613.  function s(ab) {
  4614.   if (typeof Q.addEventListener != D) {
  4615.    Q.addEventListener("load", ab, false)
  4616.   } else {
  4617.    if (typeof h.addEventListener != D) {
  4618.     h.addEventListener("load", ab, false)
  4619.    } else {
  4620.     if (typeof Q.attachEvent != D) {
  4621.      g(Q, "onload", ab)
  4622.     } else {
  4623.      if (typeof Q.onload == "function") {
  4624.       var aa = Q.onload;
  4625.       Q.onload = function() {
  4626.        aa();
  4627.        ab()
  4628.       }
  4629.      } else {
  4630.       Q.onload = ab
  4631.      }
  4632.     }
  4633.    }
  4634.   }
  4635.  }
  4636.  
  4637.  function Y() {
  4638.   var aa = h.getElementsByTagName("body")[0];
  4639.   var ae = C(r);
  4640.   ae.setAttribute("style", "visibility: hidden;");
  4641.   ae.setAttribute("type", q);
  4642.   var ad = aa.appendChild(ae);
  4643.   if (ad) {
  4644.    var ac = 0;
  4645.    (function ab() {
  4646.     if (typeof ad.GetVariable != D) {
  4647.      try {
  4648.       var ag = ad.GetVariable("$version");
  4649.       if (ag) {
  4650.        ag = ag.split(" ")[1].split(",");
  4651.        O.pv = [n(ag[0]), n(ag[1]), n(ag[2])]
  4652.       }
  4653.      } catch (af) {
  4654.       O.pv = [8, 0, 0]
  4655.      }
  4656.     } else {
  4657.      if (ac < 10) {
  4658.       ac++;
  4659.       setTimeout(ab, 10);
  4660.       return
  4661.      }
  4662.     }
  4663.     aa.removeChild(ae);
  4664.     ad = null;
  4665.     H()
  4666.    })()
  4667.   } else {
  4668.    H()
  4669.   }
  4670.  }
  4671.  
  4672.  function H() {
  4673.   var aj = o.length;
  4674.   if (aj > 0) {
  4675.    for (var ai = 0; ai < aj; ai++) {
  4676.     var ab = o[ai].id;
  4677.     var ae = o[ai].callbackFn;
  4678.     var ad = {
  4679.      success: false,
  4680.      id: ab
  4681.     };
  4682.     if (O.pv[0] > 0) {
  4683.      var ah = c(ab);
  4684.      if (ah) {
  4685.       if (F(o[ai].swfVersion) && !(O.wk && O.wk < 312)) {
  4686.        w(ab, true);
  4687.        if (ae) {
  4688.         ad.success = true;
  4689.         ad.ref = z(ab);
  4690.         ad.id = ab;
  4691.         ae(ad)
  4692.        }
  4693.       } else {
  4694.        if (o[ai].expressInstall && A()) {
  4695.         var al = {};
  4696.         al.data = o[ai].expressInstall;
  4697.         al.width = ah.getAttribute("width") || "0";
  4698.         al.height = ah.getAttribute("height") || "0";
  4699.         if (ah.getAttribute("class")) {
  4700.          al.styleclass = ah.getAttribute("class")
  4701.         }
  4702.         if (ah.getAttribute("align")) {
  4703.          al.align = ah.getAttribute("align")
  4704.         }
  4705.         var ak = {};
  4706.         var aa = ah.getElementsByTagName("param");
  4707.         var af = aa.length;
  4708.         for (var ag = 0; ag < af; ag++) {
  4709.          if (aa[ag].getAttribute("name").toLowerCase() != "movie") {
  4710.           ak[aa[ag].getAttribute("name")] = aa[ag].getAttribute("value")
  4711.          }
  4712.         }
  4713.         R(al, ak, ab, ae)
  4714.        } else {
  4715.         b(ah);
  4716.         if (ae) {
  4717.          ae(ad)
  4718.         }
  4719.        }
  4720.       }
  4721.      }
  4722.     } else {
  4723.      w(ab, true);
  4724.      if (ae) {
  4725.       var ac = z(ab);
  4726.       if (ac && typeof ac.SetVariable != D) {
  4727.        ad.success = true;
  4728.        ad.ref = ac;
  4729.        ad.id = ac.id
  4730.       }
  4731.       ae(ad)
  4732.      }
  4733.     }
  4734.    }
  4735.   }
  4736.  }
  4737.  X[0] = function() {
  4738.   if (V) {
  4739.    Y()
  4740.   } else {
  4741.    H()
  4742.   }
  4743.  };
  4744.  
  4745.  function z(ac) {
  4746.   var aa = null,
  4747.    ab = c(ac);
  4748.   if (ab && ab.nodeName.toUpperCase() === "OBJECT") {
  4749.    if (typeof ab.SetVariable !== D) {
  4750.     aa = ab
  4751.    } else {
  4752.     aa = ab.getElementsByTagName(r)[0] || ab
  4753.    }
  4754.   }
  4755.   return aa
  4756.  }
  4757.  
  4758.  function A() {
  4759.   return !a && F("6.0.65") && (O.win || O.mac) && !(O.wk && O.wk < 312)
  4760.  }
  4761.  
  4762.  function R(ad, ae, aa, ac) {
  4763.   var ah = c(aa);
  4764.   aa = W(aa);
  4765.   a = true;
  4766.   E = ac || null;
  4767.   B = {
  4768.    success: false,
  4769.    id: aa
  4770.   };
  4771.   if (ah) {
  4772.    if (ah.nodeName.toUpperCase() == "OBJECT") {
  4773.     I = J(ah);
  4774.     p = null
  4775.    } else {
  4776.     I = ah;
  4777.     p = aa
  4778.    }
  4779.    ad.id = S;
  4780.    if (typeof ad.width == D || !/%$/.test(ad.width) && n(ad.width) < 310) {
  4781.     ad.width = "310"
  4782.    }
  4783.    if (typeof ad.height == D || !/%$/.test(ad.height) && n(ad.height) < 137) {
  4784.     ad.height = "137"
  4785.    }
  4786.    var ag = O.ie ? "ActiveX" : "PlugIn",
  4787.     af = "MMredirectURL=" + encodeURIComponent(Q.location.toString().replace(/&/g, "%26")) + "&MMplayerType=" + ag + "&MMdoctitle=" + encodeURIComponent(h.title.slice(0, 47) + " - Flash Player Installation");
  4788.    if (typeof ae.flashvars != D) {
  4789.     ae.flashvars += "&" + af
  4790.    } else {
  4791.     ae.flashvars = af
  4792.    }
  4793.    if (O.ie && ah.readyState != 4) {
  4794.     var ab = C("div");
  4795.     aa += "SWFObjectNew";
  4796.     ab.setAttribute("id", aa);
  4797.     ah.parentNode.insertBefore(ab, ah);
  4798.     ah.style.display = "none";
  4799.     y(ah)
  4800.    }
  4801.    u(ad, ae, aa)
  4802.   }
  4803.  }
  4804.  
  4805.  function b(ab) {
  4806.   if (O.ie && ab.readyState != 4) {
  4807.    ab.style.display = "none";
  4808.    var aa = C("div");
  4809.    ab.parentNode.insertBefore(aa, ab);
  4810.    aa.parentNode.replaceChild(J(ab), aa);
  4811.    y(ab)
  4812.   } else {
  4813.    ab.parentNode.replaceChild(J(ab), ab)
  4814.   }
  4815.  }
  4816.  
  4817.  function J(af) {
  4818.   var ae = C("div");
  4819.   if (O.win && O.ie) {
  4820.    ae.innerHTML = af.innerHTML
  4821.   } else {
  4822.    var ab = af.getElementsByTagName(r)[0];
  4823.    if (ab) {
  4824.     var ag = ab.childNodes;
  4825.     if (ag) {
  4826.      var aa = ag.length;
  4827.      for (var ad = 0; ad < aa; ad++) {
  4828.       if (!(ag[ad].nodeType == 1 && ag[ad].nodeName == "PARAM") && !(ag[ad].nodeType == 8)) {
  4829.        ae.appendChild(ag[ad].cloneNode(true))
  4830.       }
  4831.      }
  4832.     }
  4833.    }
  4834.   }
  4835.   return ae
  4836.  }
  4837.  
  4838.  function k(aa, ab) {
  4839.   var ac = C("div");
  4840.   ac.innerHTML = "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'><param name='movie' value='" + aa + "'>" + ab + "</object>";
  4841.   return ac.firstChild
  4842.  }
  4843.  
  4844.  function u(ai, ag, ab) {
  4845.   var aa, ad = c(ab);
  4846.   ab = W(ab);
  4847.   if (O.wk && O.wk < 312) {
  4848.    return aa
  4849.   }
  4850.   if (ad) {
  4851.    var ac = O.ie ? C("div") : C(r),
  4852.     af, ah, ae;
  4853.    if (typeof ai.id == D) {
  4854.     ai.id = ab
  4855.    }
  4856.    for (ae in ag) {
  4857.     if (ag.hasOwnProperty(ae) && ae.toLowerCase() !== "movie") {
  4858.      e(ac, ae, ag[ae])
  4859.     }
  4860.    }
  4861.    if (O.ie) {
  4862.     ac = k(ai.data, ac.innerHTML)
  4863.    }
  4864.    for (af in ai) {
  4865.     if (ai.hasOwnProperty(af)) {
  4866.      ah = af.toLowerCase();
  4867.      if (ah === "styleclass") {
  4868.       ac.setAttribute("class", ai[af])
  4869.      } else {
  4870.       if (ah !== "classid" && ah !== "data") {
  4871.        ac.setAttribute(af, ai[af])
  4872.       }
  4873.      }
  4874.     }
  4875.    }
  4876.    if (O.ie) {
  4877.     P[P.length] = ai.id
  4878.    } else {
  4879.     ac.setAttribute("type", q);
  4880.     ac.setAttribute("data", ai.data)
  4881.    }
  4882.    ad.parentNode.replaceChild(ac, ad);
  4883.    aa = ac
  4884.   }
  4885.   return aa
  4886.  }
  4887.  
  4888.  function e(ac, aa, ab) {
  4889.   var ad = C("param");
  4890.   ad.setAttribute("name", aa);
  4891.   ad.setAttribute("value", ab);
  4892.   ac.appendChild(ad)
  4893.  }
  4894.  
  4895.  function y(ac) {
  4896.   var ab = c(ac);
  4897.   if (ab && ab.nodeName.toUpperCase() == "OBJECT") {
  4898.    if (O.ie) {
  4899.     ab.style.display = "none";
  4900.     (function aa() {
  4901.      if (ab.readyState == 4) {
  4902.       for (var ad in ab) {
  4903.        if (typeof ab[ad] == "function") {
  4904.         ab[ad] = null
  4905.        }
  4906.       }
  4907.       ab.parentNode.removeChild(ab)
  4908.      } else {
  4909.       setTimeout(aa, 10)
  4910.      }
  4911.     })()
  4912.    } else {
  4913.     ab.parentNode.removeChild(ab)
  4914.    }
  4915.   }
  4916.  }
  4917.  
  4918.  function U(aa) {
  4919.   return aa && aa.nodeType && aa.nodeType === 1
  4920.  }
  4921.  
  4922.  function W(aa) {
  4923.   return U(aa) ? aa.id : aa
  4924.  }
  4925.  
  4926.  function c(ac) {
  4927.   if (U(ac)) {
  4928.    return ac
  4929.   }
  4930.   var aa = null;
  4931.   try {
  4932.    aa = h.getElementById(ac)
  4933.   } catch (ab) {}
  4934.   return aa
  4935.  }
  4936.  
  4937.  function C(aa) {
  4938.   return h.createElement(aa)
  4939.  }
  4940.  
  4941.  function n(aa) {
  4942.   return parseInt(aa, 10)
  4943.  }
  4944.  
  4945.  function g(ac, aa, ab) {
  4946.   ac.attachEvent(aa, ab);
  4947.   K[K.length] = [ac, aa, ab]
  4948.  }
  4949.  
  4950.  function F(ac) {
  4951.   ac += "";
  4952.   var ab = O.pv,
  4953.    aa = ac.split(".");
  4954.   aa[0] = n(aa[0]);
  4955.   aa[1] = n(aa[1]) || 0;
  4956.   aa[2] = n(aa[2]) || 0;
  4957.   return ab[0] > aa[0] || ab[0] == aa[0] && ab[1] > aa[1] || ab[0] == aa[0] && ab[1] == aa[1] && ab[2] >= aa[2] ? true : false
  4958.  }
  4959.  
  4960.  function v(af, ab, ag, ae) {
  4961.   var ad = h.getElementsByTagName("head")[0];
  4962.   if (!ad) {
  4963.    return
  4964.   }
  4965.   var aa = typeof ag == "string" ? ag : "screen";
  4966.   if (ae) {
  4967.    m = null;
  4968.    G = null
  4969.   }
  4970.   if (!m || G != aa) {
  4971.    var ac = C("style");
  4972.    ac.setAttribute("type", "text/css");
  4973.    ac.setAttribute("media", aa);
  4974.    m = ad.appendChild(ac);
  4975.    if (O.ie && typeof h.styleSheets != D && h.styleSheets.length > 0) {
  4976.     m = h.styleSheets[h.styleSheets.length - 1]
  4977.    }
  4978.    G = aa
  4979.   }
  4980.   if (m) {
  4981.    if (typeof m.addRule != D) {
  4982.     m.addRule(af, ab)
  4983.    } else {
  4984.     if (typeof h.createTextNode != D) {
  4985.      m.appendChild(h.createTextNode(af + " {" + ab + "}"))
  4986.     }
  4987.    }
  4988.   }
  4989.  }
  4990.  
  4991.  function w(ad, aa) {
  4992.   if (!j) {
  4993.    return
  4994.   }
  4995.   var ab = aa ? "visible" : "hidden",
  4996.    ac = c(ad);
  4997.   if (L && ac) {
  4998.    ac.style.visibility = ab
  4999.   } else {
  5000.    if (typeof ad === "string") {
  5001.     v("#" + ad, "visibility:" + ab)
  5002.    }
  5003.   }
  5004.  }
  5005.  
  5006.  function N(ab) {
  5007.   var ac = /[\\\"<>\.;]/;
  5008.   var aa = ac.exec(ab) != null;
  5009.   return aa && typeof encodeURIComponent != D ? encodeURIComponent(ab) : ab
  5010.  }
  5011.  var d = function() {
  5012.   if (O.ie) {
  5013.    window.attachEvent("onunload", function() {
  5014.     var af = K.length;
  5015.     for (var ae = 0; ae < af; ae++) {
  5016.      K[ae][0].detachEvent(K[ae][1], K[ae][2])
  5017.     }
  5018.     var ac = P.length;
  5019.     for (var ad = 0; ad < ac; ad++) {
  5020.      y(P[ad])
  5021.     }
  5022.     for (var ab in O) {
  5023.      O[ab] = null
  5024.     }
  5025.     O = null;
  5026.     for (var aa in swfobject) {
  5027.      swfobject[aa] = null
  5028.     }
  5029.     swfobject = null
  5030.    })
  5031.   }
  5032.  }();
  5033.  return {
  5034.   registerObject: function(ae, aa, ad, ac) {
  5035.    if (O.w3 && ae && aa) {
  5036.     var ab = {};
  5037.     ab.id = ae;
  5038.     ab.swfVersion = aa;
  5039.     ab.expressInstall = ad;
  5040.     ab.callbackFn = ac;
  5041.     o[o.length] = ab;
  5042.     w(ae, false)
  5043.    } else {
  5044.     if (ac) {
  5045.      ac({
  5046.       success: false,
  5047.       id: ae
  5048.      })
  5049.     }
  5050.    }
  5051.   },
  5052.   getObjectById: function(aa) {
  5053.    if (O.w3) {
  5054.     return z(aa)
  5055.    }
  5056.   },
  5057.   embedSWF: function(af, al, ai, ak, ab, ae, ad, ah, aj, ag) {
  5058.    var ac = W(al),
  5059.     aa = {
  5060.      success: false,
  5061.      id: ac
  5062.     };
  5063.    if (O.w3 && !(O.wk && O.wk < 312) && af && al && ai && ak && ab) {
  5064.     w(ac, false);
  5065.     M(function() {
  5066.      ai += "";
  5067.      ak += "";
  5068.      var an = {};
  5069.      if (aj && typeof aj === r) {
  5070.       for (var aq in aj) {
  5071.        an[aq] = aj[aq]
  5072.       }
  5073.      }
  5074.      an.data = af;
  5075.      an.width = ai;
  5076.      an.height = ak;
  5077.      var ar = {};
  5078.      if (ah && typeof ah === r) {
  5079.       for (var ao in ah) {
  5080.        ar[ao] = ah[ao]
  5081.       }
  5082.      }
  5083.      if (ad && typeof ad === r) {
  5084.       for (var am in ad) {
  5085.        if (ad.hasOwnProperty(am)) {
  5086.         var ap = l ? encodeURIComponent(am) : am,
  5087.          at = l ? encodeURIComponent(ad[am]) : ad[am];
  5088.         if (typeof ar.flashvars != D) {
  5089.          ar.flashvars += "&" + ap + "=" + at
  5090.         } else {
  5091.          ar.flashvars = ap + "=" + at
  5092.         }
  5093.        }
  5094.       }
  5095.      }
  5096.      if (F(ab)) {
  5097.       var au = u(an, ar, al);
  5098.       if (an.id == ac) {
  5099.        w(ac, true)
  5100.       }
  5101.       aa.success = true;
  5102.       aa.ref = au;
  5103.       aa.id = au.id
  5104.      } else {
  5105.       if (ae && A()) {
  5106.        an.data = ae;
  5107.        R(an, ar, al, ag);
  5108.        return
  5109.       } else {
  5110.        w(ac, true)
  5111.       }
  5112.      }
  5113.      if (ag) {
  5114.       ag(aa)
  5115.      }
  5116.     })
  5117.    } else {
  5118.     if (ag) {
  5119.      ag(aa)
  5120.     }
  5121.    }
  5122.   },
  5123.   switchOffAutoHideShow: function() {
  5124.    j = false
  5125.   },
  5126.   enableUriEncoding: function(aa) {
  5127.    l = typeof aa === D ? true : aa
  5128.   },
  5129.   ua: O,
  5130.   getFlashPlayerVersion: function() {
  5131.    return {
  5132.     major: O.pv[0],
  5133.     minor: O.pv[1],
  5134.     release: O.pv[2]
  5135.    }
  5136.   },
  5137.   hasFlashPlayerVersion: F,
  5138.   createSWF: function(ac, ab, aa) {
  5139.    if (O.w3) {
  5140.     return u(ac, ab, aa)
  5141.    } else {
  5142.     return undefined
  5143.    }
  5144.   },
  5145.   showExpressInstall: function(ac, ad, aa, ab) {
  5146.    if (O.w3 && A()) {
  5147.     R(ac, ad, aa, ab)
  5148.    }
  5149.   },
  5150.   removeSWF: function(aa) {
  5151.    if (O.w3) {
  5152.     y(aa)
  5153.    }
  5154.   },
  5155.   createCSS: function(ad, ac, ab, aa) {
  5156.    if (O.w3) {
  5157.     v(ad, ac, ab, aa)
  5158.    }
  5159.   },
  5160.   addDomLoadEvent: M,
  5161.   addLoadEvent: s,
  5162.   getQueryParamValue: function(ad) {
  5163.    var ac = h.location.search || h.location.hash;
  5164.    if (ac) {
  5165.     if (/\?/.test(ac)) {
  5166.      ac = ac.split("?")[1]
  5167.     }
  5168.     if (ad == null) {
  5169.      return N(ac)
  5170.     }
  5171.     var ab = ac.split("&");
  5172.     for (var aa = 0; aa < ab.length; aa++) {
  5173.      if (ab[aa].substring(0, ab[aa].indexOf("=")) == ad) {
  5174.       return N(ab[aa].substring(ab[aa].indexOf("=") + 1))
  5175.      }
  5176.     }
  5177.    }
  5178.    return ""
  5179.   },
  5180.   expressInstallCallback: function() {
  5181.    if (a) {
  5182.     var aa = c(S);
  5183.     if (aa && I) {
  5184.      aa.parentNode.replaceChild(I, aa);
  5185.      if (p) {
  5186.       w(p, true);
  5187.       if (O.ie) {
  5188.        I.style.display = "block"
  5189.       }
  5190.      }
  5191.      if (E) {
  5192.       E(B)
  5193.      }
  5194.     }
  5195.     a = false
  5196.    }
  5197.   },
  5198.   version: "2.3"
  5199.  }
  5200. }();
  5201. mat4.translation = function(out, vec) {
  5202.  mat4.identity(out);
  5203.  out[12] = vec[0];
  5204.  out[13] = vec[1];
  5205.  out[14] = vec[2];
  5206.  return out
  5207. };
  5208. mat4.rotationQuat = function(out, q) {
  5209.  mat4.identity(out);
  5210.  var xx = q[0] * q[0],
  5211.   yy = q[1] * q[1],
  5212.   zz = q[2] * q[2],
  5213.   xy = q[0] * q[1],
  5214.   zw = q[2] * q[3],
  5215.   zx = q[2] * q[0],
  5216.   yw = q[1] * q[3],
  5217.   yz = q[1] * q[2],
  5218.   xw = q[0] * q[3];
  5219.  out[0] = 1 - 2 * (yy + zz);
  5220.  out[1] = 2 * (xy + zw);
  5221.  out[2] = 2 * (zx - yw);
  5222.  out[4] = 2 * (xy - zw);
  5223.  out[5] = 1 - 2 * (zz + xx);
  5224.  out[6] = 2 * (yz + xw);
  5225.  out[8] = 2 * (zx + yw);
  5226.  out[9] = 2 * (yz - xw);
  5227.  out[10] = 1 - 2 * (yy + xx);
  5228.  return out
  5229. };
  5230. mat4.mulSlimDX = function(out, l, r) {
  5231.  var left = {
  5232.   M11: l[0],
  5233.   M12: l[1],
  5234.   M13: l[2],
  5235.   M14: l[3],
  5236.   M21: l[4],
  5237.   M22: l[5],
  5238.   M23: l[6],
  5239.   M24: l[7],
  5240.   M31: l[8],
  5241.   M32: l[9],
  5242.   M33: l[10],
  5243.   M34: l[11],
  5244.   M41: l[12],
  5245.   M42: l[13],
  5246.   M43: l[14],
  5247.   M44: l[15]
  5248.  };
  5249.  var right = {
  5250.   M11: r[0],
  5251.   M12: r[1],
  5252.   M13: r[2],
  5253.   M14: r[3],
  5254.   M21: r[4],
  5255.   M22: r[5],
  5256.   M23: r[6],
  5257.   M24: r[7],
  5258.   M31: r[8],
  5259.   M32: r[9],
  5260.   M33: r[10],
  5261.   M34: r[11],
  5262.   M41: r[12],
  5263.   M42: r[13],
  5264.   M43: r[14],
  5265.   M44: r[15]
  5266.  };
  5267.  out[0] = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
  5268.  out[1] = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
  5269.  out[2] = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
  5270.  out[3] = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
  5271.  out[4] = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
  5272.  out[5] = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
  5273.  out[6] = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
  5274.  out[7] = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
  5275.  out[8] = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
  5276.  out[9] = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
  5277.  out[10] = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
  5278.  out[11] = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
  5279.  out[12] = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
  5280.  out[13] = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
  5281.  out[14] = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
  5282.  out[15] = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
  5283.  return out
  5284. };
  5285. mat4.transformVec3 = function(out, v, m) {
  5286.  out[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12];
  5287.  out[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13];
  5288.  out[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14];
  5289.  return out
  5290. };
  5291. mat4.transformVec4 = function(out, v, m) {
  5292.  out[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
  5293.  out[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
  5294.  out[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
  5295.  out[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
  5296.  return out
  5297. };
  5298. mat4.extractEulerAngles = function(out, m) {
  5299.  out[0] = Math.atan2(m[6], m[10]);
  5300.  var c2 = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
  5301.  out[1] = Math.atan2(-m[2], c2);
  5302.  var s1 = Math.sin(out[0]),
  5303.   c1 = Math.cos(out[0]);
  5304.  out[2] = Math.atan2(s1 * m[8] - c1 * m[4], c1 * m[5] - s1 * m[9]);
  5305.  return out
  5306. };
  5307. mat4.invert2 = function(out, m) {
  5308.  var det = m[0] * (m[5] * m[10] - m[6] * m[9]) + m[4] * (m[2] * m[9] - m[1] * m[10]) + m[8] * (m[1] * m[6] - m[2] * m[5]);
  5309.  if (det == 0) return null;
  5310.  var invDet = 1 / det;
  5311.  out[0] = (m[5] * m[10] - m[6] * m[9]) * invDet;
  5312.  out[1] = (m[9] * m[2] - m[10] * m[1]) * invDet;
  5313.  out[2] = (m[1] * m[6] - m[2] * m[5]) * invDet;
  5314.  out[4] = (m[6] * m[8] - m[4] * m[10]) * invDet;
  5315.  out[5] = (m[10] * m[0] - m[8] * m[2]) * invDet;
  5316.  out[6] = (m[2] * m[4] - m[0] * m[6]) * invDet;
  5317.  out[8] = (m[4] * m[9] - m[5] * m[8]) * invDet;
  5318.  out[9] = (m[8] * m[1] - m[9] * m[0]) * invDet;
  5319.  out[10] = (m[0] * m[5] - m[1] * m[4]) * invDet;
  5320.  out[3] = out[0] * -m[3] + out[1] * -m[7] + out[2] * -m[11];
  5321.  out[7] = out[4] * -m[3] + out[5] * -m[7] + out[6] * -m[11];
  5322.  out[11] = out[8] * -m[3] + out[9] * -m[7] + out[10] * -m[11];
  5323.  out[12] = out[13] = out[14] = 0;
  5324.  out[15] = 1;
  5325.  return out
  5326. };
  5327. window.requestAnimFrame = function() {
  5328.  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
  5329.   window.setTimeout(callback, 1e3 / 60)
  5330.  }
  5331. }();
  5332. jQuery.support.cors = true;
  5333. if ($.ajaxTransport) {
  5334.  $.ajaxSetup({
  5335.   flatOptions: {
  5336.    renderer: true
  5337.   }
  5338.  });
  5339.  $.ajaxTransport("+binary", function(options, originalOptions, jqXHR) {
  5340.   if (window.FormData && (options.dataType && options.dataType == "binary" || options.data && (window.ArrayBuffer && options.data instanceof ArrayBuffer || window.Blob && options.data instanceof Blob))) {
  5341.    return {
  5342.     send: function(_, callback) {
  5343.      var xhr = new XMLHttpRequest,
  5344.       url = options.url,
  5345.       type = options.type,
  5346.       dataType = options.responseType || "blob",
  5347.       data = options.data || null;
  5348.      if (options.renderer) {
  5349.       xhr.addEventListener("progress", function(event) {
  5350.        if (event.lengthComputable) {
  5351.         if (!options.renderer.downloads[this.responseURL]) {
  5352.          options.renderer.downloads[this.responseURL] = {
  5353.           loaded: event.loaded,
  5354.           total: event.total
  5355.          }
  5356.         } else {
  5357.          options.renderer.downloads[this.responseURL].loaded = event.loaded
  5358.         }
  5359.         options.renderer.updateProgress()
  5360.        }
  5361.       })
  5362.      }
  5363.      xhr.addEventListener("load", function() {
  5364.       if (options.renderer) {
  5365.        delete options.renderer.downloads[this.responseURL];
  5366.        options.renderer.updateProgress()
  5367.       }
  5368.       var data = {};
  5369.       data[options.dataType] = xhr.response;
  5370.       callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders())
  5371.      });
  5372.      xhr.open(type, url, true);
  5373.      xhr.responseType = dataType;
  5374.      xhr.send(data)
  5375.     },
  5376.     abort: function() {
  5377.      jqXHR.abort()
  5378.     }
  5379.    }
  5380.   }
  5381.  })
  5382. } else {
  5383.  (function() {
  5384.   var httpData = $.httpData;
  5385.   $.httpData = function(xhr, type, s) {
  5386.    if (type == "binary") {
  5387.     return xhr.response
  5388.    } else {
  5389.     return httpData(xhr, type, s)
  5390.    }
  5391.   }
  5392.  })();
  5393.  $.ajaxSetup({
  5394.   beforeSend: function(xhr, options) {
  5395.    if (options.dataType == "binary") {
  5396.     xhr.responseType = options.responseType || "arraybuffer";
  5397.     xhr.addEventListener("progress", function(event) {
  5398.      if (!options.renderer) return;
  5399.      if (event.lengthComputable) {
  5400.       if (!options.renderer.downloads[this.responseURL]) {
  5401.        options.renderer.downloads[this.responseURL] = {
  5402.         loaded: event.loaded,
  5403.         total: event.total
  5404.        }
  5405.       } else {
  5406.        options.renderer.downloads[this.responseURL].loaded = event.loaded
  5407.       }
  5408.       options.renderer.updateProgress()
  5409.      }
  5410.     }, false);
  5411.     xhr.addEventListener("load", function() {
  5412.      if (!options.renderer) return;
  5413.      delete options.renderer.downloads[this.responseURL];
  5414.      options.renderer.updateProgress()
  5415.     }, false)
  5416.    }
  5417.   }
  5418.  })
  5419. }
  5420. Math.randomInt = function() {
  5421.  return Math.randomInt || function(min, max) {
  5422.   return Math.floor(Math.random() * (max - min)) + min
  5423.  }
  5424. }();
  5425. if (typeof Object.create != "function") {
  5426.  Object.create = function() {
  5427.   var obj = function() {};
  5428.   return function(prototype) {
  5429.    if (arguments.length > 1) {
  5430.     throw Error("Second argument not supported")
  5431.    }
  5432.    if (typeof prototype != "object") {
  5433.     throw TypeError("Argument must be an object")
  5434.    }
  5435.    obj.prototype = prototype;
  5436.    var result = new obj;
  5437.    obj.prototype = null;
  5438.    return result
  5439.   }
  5440.  }()
  5441. }
  5442. window.console = window.console || {
  5443.  log: function() {},
  5444.  error: function() {},
  5445.  warn: function() {}
  5446. };
  5447.  
  5448. function ZamModelViewer(opts) {
  5449.  var self = this;
  5450.  if (!opts.type || !self.validTypes[opts.type]) throw "Viewer error: Bad viewer type given";
  5451.  if (!opts.container) throw "Viewer error: Bad container given";
  5452.  if (!opts.aspect) throw "Viewer error: Bad aspect ratio given";
  5453.  if (!opts.contentPath) throw "Viewer error: No content path given";
  5454.  self.type = opts.type;
  5455.  self.container = opts.container;
  5456.  self.aspect = parseFloat(opts.aspect);
  5457.  self.renderer = null;
  5458.  self.options = opts;
  5459.  var width = parseInt(self.container.width());
  5460.  var height = Math.round(width / self.aspect);
  5461.  self.init(width, height)
  5462. }
  5463. ZamModelViewer.WEBGL = 1;
  5464. ZamModelViewer.FLASH = 2;
  5465. ZamModelViewer.TOR = 1;
  5466. ZamModelViewer.WOW = 2;
  5467. ZamModelViewer.LOL = 3;
  5468. ZamModelViewer.GW2 = 4;
  5469. ZamModelViewer.WILDSTAR = 5;
  5470. ZamModelViewer.HEROES = 6;
  5471. ZamModelViewer.DESTINY = 7;
  5472. ZamModelViewer.Models = {};
  5473. ZamModelViewer.prototype = {
  5474.  validTypes: {
  5475.   2: "Wowhead",
  5476.   3: "LolKing",
  5477.   6: "HeroKing",
  5478.   7: "DestinyDB"
  5479.  },
  5480.  destroy: function() {
  5481.   var self = this;
  5482.   if (self.renderer) self.renderer.destroy();
  5483.   self.options = null;
  5484.   self.container = null
  5485.  },
  5486.  init: function(width, height) {
  5487.   var self = this,
  5488.    glSupport = false;
  5489.   if (typeof window["Uint8Array"] !== undefined && typeof window["DataView"] !== undefined) {
  5490.    try {
  5491.     var canvas = document.createElement("canvas");
  5492.     var ctx = canvas.getContext("webgl", {
  5493.      alpha: false
  5494.     }) || canvas.getContext("experimental-webgl", {
  5495.      alpha: false
  5496.     });
  5497.     if (ctx) glSupport = true
  5498.    } catch (e) {}
  5499.   }
  5500.   if (!self.options.flash && glSupport) {
  5501.    self.mode = ZamModelViewer.WEBGL;
  5502.    self.renderer = new ZamModelViewer.WebGL(self)
  5503.   } else {
  5504.    self.mode = ZamModelViewer.FLASH;
  5505.    self.renderer = new ZamModelViewer.Flash(self)
  5506.   }
  5507.   self.renderer.resize(width, height);
  5508.   self.renderer.init()
  5509.  },
  5510.  method: function(name, params) {
  5511.   var self = this;
  5512.   if (params === undefined) params = [];
  5513.   if (self.renderer) return self.renderer.method(name, [].concat(params));
  5514.   return null
  5515.  },
  5516.  option: function(key, val) {
  5517.   var self = this;
  5518.   if (val !== undefined) {
  5519.    self.options[key] = val
  5520.   }
  5521.   return self.options[key]
  5522.  }
  5523. };
  5524. ZamModelViewer.isFullscreen = function() {
  5525.  if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) return true;
  5526.  return false
  5527. };
  5528. ZamModelViewer.requestFullscreen = function(e) {
  5529.  if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) return;
  5530.  if (e.requestFullscreen) {
  5531.   e.requestFullscreen()
  5532.  } else if (e.webkitRequestFullscreen) {
  5533.   e.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)
  5534.  } else if (e.mozRequestFullScreen) {
  5535.   e.mozRequestFullScreen()
  5536.  } else if (e.msRequestFullscreen) {
  5537.   e.msRequestFullscreen()
  5538.  }
  5539. };
  5540. ZamModelViewer.exitFullscreen = function() {
  5541.  if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) return;
  5542.  if (document.exitFullscreen) {
  5543.   document.exitFullscreen()
  5544.  } else if (document.webkitExitFullscreen) {
  5545.   document.webkitExitFullscreen()
  5546.  } else if (document.mozCancelFullScreen) {
  5547.   document.mozCancelFullScreen()
  5548.  } else if (document.msExitFullscreen) {
  5549.   document.msExitFullscreen()
  5550.  }
  5551. };
  5552. ZamModelViewer.DataView = function(buffer) {
  5553.  this.buffer = new DataView(buffer);
  5554.  this.position = 0
  5555. };
  5556. ZamModelViewer.DataView.prototype = {
  5557.  getBool: function() {
  5558.   var v = this.buffer.getUint8(this.position) != 0;
  5559.   this.position += 1;
  5560.   return v
  5561.  },
  5562.  getUint8: function() {
  5563.   var v = this.buffer.getUint8(this.position);
  5564.   this.position += 1;
  5565.   return v
  5566.  },
  5567.  getInt8: function() {
  5568.   var v = this.buffer.getInt8(this.position);
  5569.   this.position += 1;
  5570.   return v
  5571.  },
  5572.  getUint16: function() {
  5573.   var v = this.buffer.getUint16(this.position, true);
  5574.   this.position += 2;
  5575.   return v
  5576.  },
  5577.  getInt16: function() {
  5578.   var v = this.buffer.getInt16(this.position, true);
  5579.   this.position += 2;
  5580.   return v
  5581.  },
  5582.  getUint32: function() {
  5583.   var v = this.buffer.getUint32(this.position, true);
  5584.   this.position += 4;
  5585.   return v
  5586.  },
  5587.  getInt32: function() {
  5588.   var v = this.buffer.getInt32(this.position, true);
  5589.   this.position += 4;
  5590.   return v
  5591.  },
  5592.  getFloat: function() {
  5593.   var v = this.buffer.getFloat32(this.position, true);
  5594.   this.position += 4;
  5595.   return v
  5596.  },
  5597.  getString: function(len) {
  5598.   if (len === undefined) len = this.getUint16();
  5599.   var str = "";
  5600.   for (var i = 0; i < len; ++i) {
  5601.    str += String.fromCharCode(this.getUint8())
  5602.   }
  5603.   return str
  5604.  },
  5605.  setBool: function(v) {
  5606.   this.buffer.setUint8(this.position, v ? 1 : 0);
  5607.   this.position += 1
  5608.  },
  5609.  setUint8: function(v) {
  5610.   this.buffer.setUint8(this.position, v);
  5611.   this.position += 1
  5612.  },
  5613.  setInt8: function(v) {
  5614.   this.buffer.setInt8(this.position, v);
  5615.   this.position += 1
  5616.  },
  5617.  setUint16: function(v) {
  5618.   this.buffer.setUint16(this.position, v, true);
  5619.   this.position += 2
  5620.  },
  5621.  setInt16: function(v) {
  5622.   this.buffer.setInt16(this.position, v, true);
  5623.   this.position += 2
  5624.  },
  5625.  setUint32: function(v) {
  5626.   this.buffer.setUint32(this.position, v, true);
  5627.   this.position += 4
  5628.  },
  5629.  setInt32: function(v) {
  5630.   this.buffer.setInt32(this.position, v, true);
  5631.   this.position += 4
  5632.  },
  5633.  setFloat: function(v) {
  5634.   this.buffer.setFloat32(this.position, v, true);
  5635.   this.position += 4
  5636.  }
  5637. };
  5638. ZamModelViewer.WebGL = function(viewer) {
  5639.  var self = this;
  5640.  self.viewer = viewer;
  5641.  self.options = viewer.options;
  5642.  self.downloads = {};
  5643.  self.context = null;
  5644.  self.width = 0;
  5645.  self.height = 0;
  5646.  self.time = 0;
  5647.  self.delta = 0;
  5648.  self.models = [];
  5649.  self.screenshotDataURL = null;
  5650.  self.makeDataURL = false;
  5651.  self.azimuth = Math.PI * 1.5;
  5652.  self.zenith = Math.PI / 2;
  5653.  self.distance = 15;
  5654.  self.fov = 30;
  5655.  self.translation = [0, 0, 0];
  5656.  self.target = [0, 0, 0];
  5657.  self.eye = [0, 0, 0];
  5658.  self.up = [0, 0, 1];
  5659.  self.lookDir = vec3.create();
  5660.  self.fullscreen = false;
  5661.  self.projMatrix = mat4.create();
  5662.  self.viewMatrix = mat4.create();
  5663.  self.panningMatrix = mat4.create();
  5664.  self.viewOffset = vec3.create();
  5665.  if (!ZamModelViewer.WebGL.addedCss) {
  5666.   ZamModelViewer.WebGL.addedCss = true;
  5667.   $("head").append('<link rel="stylesheet" href="//cdn.zamimg.com/zmv/viewer.css" type="text/css" />')
  5668.  }
  5669. };
  5670. ZamModelViewer.WebGL.prototype = {
  5671.  updateProgress: function() {
  5672.   var self = this,
  5673.    totalSize = 0,
  5674.    totalLoaded = 0;
  5675.   for (var url in self.downloads) {
  5676.    totalSize += self.downloads[url].total;
  5677.    totalLoaded += self.downloads[url].loaded
  5678.   }
  5679.   if (totalSize <= 0) {
  5680.    if (self.progressShown) {
  5681.     self.progressBg.hide();
  5682.     self.progressBar.hide();
  5683.     self.progressShown = false
  5684.    }
  5685.   } else {
  5686.    if (!self.progressShown) {
  5687.     self.progressBg.show();
  5688.     self.progressBar.show();
  5689.     self.progressShown = true
  5690.    }
  5691.    var pct = totalLoaded / totalSize;
  5692.    self.progressBar.width(Math.round(self.width * pct) + "px")
  5693.   }
  5694.  },
  5695.  destroy: function() {
  5696.   var self = this;
  5697.   self.stop = true;
  5698.   if (self.canvas) {
  5699.    self.canvas.detach();
  5700.    self.progressBg.detach();
  5701.    self.progressBar.detach();
  5702.    self.canvas.off("mousedown touchstart", self.onMouseDown).off("DOMMouseScroll", self.onMouseScroll).off("mousewheel", self.onMouseWheel).off("dblclick", self.onDoubleClick).off("contextmenu", self.onContextMenu);
  5703.    $(window).off("resize", self.onFullscreen);
  5704.    $(document).off("mouseup touchend", self.onMouseUp).off("mousemove touchmove", self.onMouseMove);
  5705.    self.canvas = self.progressBg = self.progressBar = null
  5706.   }
  5707.   if (self.context) {
  5708.    var gl = self.context;
  5709.    if (self.bgTexture) gl.deleteTexture(self.bgTexture);
  5710.    self.bgTexture = null;
  5711.    if (self.program) gl.deleteProgram(self.program);
  5712.    self.program = null;
  5713.    if (self.vb) gl.deleteBuffer(self.vb);
  5714.    if (self.vs) gl.deleteShader(self.vs);
  5715.    if (self.fs) gl.deleteShader(self.fs);
  5716.    self.vb = self.vs = self.fs = null
  5717.   }
  5718.   if (self.bgImg) self.bgImg = null;
  5719.   for (var i = 0; i < self.models.length; ++i) {
  5720.    self.models[i].destroy();
  5721.    self.models[i] = null
  5722.   }
  5723.   self.models = []
  5724.  },
  5725.  method: function(name, params) {
  5726.   var self = this;
  5727.   if (self.models.length > 0 && self.models[0].external && self.models[0].external[name]) {
  5728.    return self.models[0].external[name].apply(self.models[0], params)
  5729.   } else {
  5730.    return null
  5731.   }
  5732.  },
  5733.  getTime: function() {
  5734.   if (window.performance && window.performance.now) return window.performance.now();
  5735.   else return Date.now()
  5736.  },
  5737.  draw: function() {
  5738.   var self = this,
  5739.    gl = self.context,
  5740.    i;
  5741.   var time = self.getTime();
  5742.   self.delta = (time - self.time) * .001;
  5743.   self.time = time;
  5744.   self.updateCamera();
  5745.   gl.viewport(0, 0, self.width, self.height);
  5746.   gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  5747.   if (self.bgTexture && self.program) {
  5748.    gl.useProgram(self.program);
  5749.    gl.activeTexture(gl.TEXTURE0);
  5750.    gl.bindTexture(gl.TEXTURE_2D, self.bgTexture);
  5751.    gl.uniform1i(self.uTexture, 0);
  5752.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  5753.    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
  5754.    gl.enableVertexAttribArray(self.aPosition);
  5755.    gl.vertexAttribPointer(self.aPosition, 2, gl.FLOAT, false, 16, 0);
  5756.    gl.enableVertexAttribArray(self.aTexCoord);
  5757.    gl.vertexAttribPointer(self.aTexCoord, 2, gl.FLOAT, false, 16, 8);
  5758.    gl.depthMask(false);
  5759.    gl.disable(gl.CULL_FACE);
  5760.    gl.blendFunc(gl.ONE, gl.ZERO);
  5761.    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  5762.    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  5763.    gl.enable(gl.CULL_FACE);
  5764.    gl.depthMask(true);
  5765.    gl.disableVertexAttribArray(self.aPosition);
  5766.    gl.disableVertexAttribArray(self.aTexCoord)
  5767.   }
  5768.   for (i = 0; i < self.models.length; ++i) self.models[i].draw()
  5769.  },
  5770.  updateCamera: function() {
  5771.   var self = this;
  5772.   var d = self.distance,
  5773.    a = self.azimuth,
  5774.    z = self.zenith;
  5775.   if (self.up[2] == 1) {
  5776.    self.eye[0] = -d * Math.sin(z) * Math.cos(a) + self.target[0];
  5777.    self.eye[1] = -d * Math.sin(z) * Math.sin(a) + self.target[1];
  5778.    self.eye[2] = -d * Math.cos(z) + self.target[2]
  5779.   } else {
  5780.    self.eye[0] = -d * Math.sin(z) * Math.cos(a) + self.target[0];
  5781.    self.eye[1] = -d * Math.cos(z) + self.target[1];
  5782.    self.eye[2] = -d * Math.sin(z) * Math.sin(a) + self.target[2]
  5783.   }
  5784.   vec3.subtract(self.lookDir, self.target, self.eye);
  5785.   vec3.normalize(self.lookDir, self.lookDir);
  5786.   mat4.lookAt(self.viewMatrix, self.eye, self.target, self.up);
  5787.   mat4.identity(self.panningMatrix);
  5788.   if (self.up[2] == 1) {
  5789.    vec3.set(self.viewOffset, self.translation[0], -self.translation[1], 0)
  5790.   } else {
  5791.    vec3.set(self.viewOffset, self.translation[0], 0, self.translation[1])
  5792.   }
  5793.   mat4.translate(self.panningMatrix, self.panningMatrix, self.viewOffset);
  5794.   mat4.multiply(self.viewMatrix, self.panningMatrix, self.viewMatrix)
  5795.  },
  5796.  init: function() {
  5797.   var self = this,
  5798.    gl = self.context,
  5799.    i;
  5800.   mat4.perspective(self.projMatrix, self.fov * .0174532925, self.viewer.aspect, .1, 5e3);
  5801.   self.updateCamera();
  5802.   gl.clearColor(0, 0, 0, 1);
  5803.   gl.enable(gl.DEPTH_TEST);
  5804.   gl.depthFunc(gl.LEQUAL);
  5805.   gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  5806.   gl.enable(gl.BLEND);
  5807.   if ((self.options.models || self.options.items) && ZamModelViewer.Models[self.viewer.type]) {
  5808.    var Model = ZamModelViewer.Models[self.viewer.type];
  5809.    var models = [].concat(self.options.models);
  5810.    if (models.length > 0) {
  5811.     for (i = 0; i < models.length; ++i) {
  5812.      self.models.push(new Model(self, self.viewer, models[i], i))
  5813.     }
  5814.    } else if (self.viewer.type == ZamModelViewer.DESTINY && self.options.items) {
  5815.     self.models.push(new Model(self, self.viewer))
  5816.    }
  5817.   }
  5818.  
  5819.   function tick() {
  5820.    if (self.stop) return;
  5821.    requestAnimFrame(tick);
  5822.    self.draw();
  5823.    if (self.makeDataURL !== false) {
  5824.     if (self.canvas[0].toDataURL) {
  5825.      if (!Array.isArray(self.makeDataURL)) {
  5826.       self.makeDataURL = []
  5827.      }
  5828.      self.screenshotDataURL = self.canvas[0].toDataURL.apply(self.canvas[0], self.makeDataURL)
  5829.     }
  5830.     self.makeDataURL = false
  5831.    }
  5832.   }
  5833.   tick()
  5834.  },
  5835.  resize: function(width, height) {
  5836.   var self = this;
  5837.   if (self.width === width) return;
  5838.   if (!self.fullscreen) {
  5839.    self.viewer.container.css({
  5840.     height: height + "px",
  5841.     position: "relative"
  5842.    })
  5843.   }
  5844.   self.width = width;
  5845.   self.height = height;
  5846.   if (!self.canvas) {
  5847.    self.canvas = $("<canvas/>");
  5848.    self.canvas.attr({
  5849.     width: width,
  5850.     height: height
  5851.    });
  5852.    self.viewer.container.append(self.canvas);
  5853.    self.context = self.canvas[0].getContext("webgl", {
  5854.     alpha: false
  5855.    }) || self.canvas[0].getContext("experimental-webgl", {
  5856.     alpha: false
  5857.    });
  5858.    self.progressBg = $("<div/>", {
  5859.     css: {
  5860.      display: "none",
  5861.      position: "absolute",
  5862.      bottom: 0,
  5863.      left: 0,
  5864.      right: 0,
  5865.      height: "10px",
  5866.      backgroundColor: "#000"
  5867.     }
  5868.    });
  5869.    self.progressBar = $("<div/>", {
  5870.     css: {
  5871.      display: "none",
  5872.      position: "absolute",
  5873.      bottom: 0,
  5874.      left: 0,
  5875.      width: 0,
  5876.      height: "10px",
  5877.      backgroundColor: "#ccc"
  5878.     }
  5879.    });
  5880.    self.viewer.container.append(self.progressBg);
  5881.    self.viewer.container.append(self.progressBar);
  5882.    if (!self.context) {
  5883.     alert("No WebGL support, sorry! You should totally use Chrome.");
  5884.     self.canvas.detach();
  5885.     self.canvas = null;
  5886.     return
  5887.    }
  5888.    self.toggleSize = function(event) {
  5889.     if (!self.resized) {
  5890.      self.restoreWidth = self.width;
  5891.      self.restoreHeight = self.height;
  5892.      self.resized = true;
  5893.      self.resize(640, 480);
  5894.      mat4.perspective(self.projMatrix, self.fov * .0174532925, 640 / 480, .1, 5e3)
  5895.     } else {
  5896.      self.resized = false;
  5897.      self.resize(self.restoreWidth, self.restoreHeight);
  5898.      mat4.perspective(self.projMatrix, self.fov * .0174532925, self.viewer.aspect, .1, 5e3)
  5899.     }
  5900.    };
  5901.    self.onDoubleClick = function(event) {
  5902.     if (ZamModelViewer.isFullscreen()) {
  5903.      ZamModelViewer.exitFullscreen()
  5904.     } else {
  5905.      ZamModelViewer.requestFullscreen(self.canvas[0])
  5906.     }
  5907.    };
  5908.    self.onFullscreen = function(event) {
  5909.     if (!self.fullscreen && ZamModelViewer.isFullscreen()) {
  5910.      self.restoreWidth = self.width;
  5911.      self.restoreHeight = self.height;
  5912.      self.fullscreen = true;
  5913.      var $window = $(window);
  5914.      self.resize($window.width(), $window.height());
  5915.      mat4.perspective(self.projMatrix, self.fov * .0174532925, $window.width() / $window.height(), .1, 5e3)
  5916.     } else if (self.fullscreen && !ZamModelViewer.isFullscreen()) {
  5917.      self.fullscreen = false;
  5918.      self.resize(self.restoreWidth, self.restoreHeight);
  5919.      mat4.perspective(self.projMatrix, self.fov * .0174532925, self.viewer.aspect, .1, 5e3)
  5920.     }
  5921.    };
  5922.    self.onMouseDown = function(event) {
  5923.     if (event.which == 3 || event.ctrlKey) {
  5924.      self.rightMouseDown = true
  5925.     } else {
  5926.      self.mouseDown = true
  5927.     }
  5928.     if (event.type == "touchstart") {
  5929.      self.mouseX = event.originalEvent.touches[0].clientX;
  5930.      self.mouseY = event.originalEvent.touches[0].clientY
  5931.     } else {
  5932.      self.mouseX = event.clientX;
  5933.      self.mouseY = event.clientY
  5934.     }
  5935.     $("body").addClass("unselectable")
  5936.    };
  5937.    self.onMouseScroll = function(event) {
  5938.     if (event.originalEvent.detail > 0) {
  5939.      self.distance *= 1.25
  5940.     } else {
  5941.      self.distance *= .75
  5942.     }
  5943.     event.preventDefault();
  5944.     return false
  5945.    };
  5946.    self.onMouseWheel = function(event) {
  5947.     if (event.originalEvent.wheelDelta < 0) {
  5948.      self.distance *= 1.25
  5949.     } else {
  5950.      self.distance *= .75
  5951.     }
  5952.     event.preventDefault();
  5953.     return false
  5954.    };
  5955.    self.onMouseUp = function(event) {
  5956.     if (self.mouseDown || self.rightMouseDown) {
  5957.      $("body").removeClass("unselectable");
  5958.      self.mouseDown = false;
  5959.      self.rightMouseDown = false
  5960.     }
  5961.    };
  5962.    self.onMouseMove = function(event) {
  5963.     if (!self.mouseDown && !self.rightMouseDown || self.mouseX === undefined) return;
  5964.     var x, y;
  5965.     if (event.type == "touchmove") {
  5966.      event.preventDefault();
  5967.      x = event.originalEvent.touches[0].clientX;
  5968.      y = event.originalEvent.touches[0].clientY
  5969.     } else {
  5970.      x = event.clientX;
  5971.      y = event.clientY
  5972.     }
  5973.     var dx = (x - self.mouseX) / self.width * Math.PI * 2;
  5974.     var dy = (y - self.mouseY) / self.width * Math.PI * 2;
  5975.     if (self.mouseDown) {
  5976.      if (self.up[2] == 1) {
  5977.       self.azimuth -= dx
  5978.      } else {
  5979.       self.azimuth += dx
  5980.      }
  5981.      self.zenith += dy;
  5982.      var pi2 = Math.PI * 2;
  5983.      while (self.azimuth < 0) self.azimuth += pi2;
  5984.      while (self.azimuth > pi2) self.azimuth -= pi2;
  5985.      if (self.zenith < 1e-4) self.zenith = 1e-4;
  5986.      if (self.zenith >= Math.PI) self.zenith = Math.PI - 1e-4
  5987.     } else {
  5988.      self.translation[0] += dx;
  5989.      self.translation[1] += dy
  5990.     }
  5991.     self.mouseX = x;
  5992.     self.mouseY = y
  5993.    };
  5994.    self.onContextMenu = function(event) {
  5995.     return false
  5996.    };
  5997.    self.canvas.on("mousedown touchstart", self.onMouseDown).on("DOMMouseScroll", self.onMouseScroll).on("mousewheel", self.onMouseWheel).on("dblclick", self.onDoubleClick).on("contextmenu", self.onContextMenu);
  5998.    $(window).on("resize", self.onFullscreen);
  5999.    $(document).on("mouseup touchend", self.onMouseUp).on("mousemove touchmove", self.onMouseMove)
  6000.   } else {
  6001.    self.canvas.attr({
  6002.     width: width,
  6003.     height: height
  6004.    });
  6005.    self.canvas.css({
  6006.     width: width + "px",
  6007.     height: height + "px"
  6008.    });
  6009.    self.context.viewport(0, 0, self.drawingBufferWidth, self.drawingBufferHeight)
  6010.   }
  6011.   if (self.options.background) {
  6012.    self.loadBackground()
  6013.   }
  6014.  },
  6015.  loadBackground: function() {
  6016.   var self = this,
  6017.    gl = self.context;
  6018.   var initVb = function() {
  6019.    self.vb = gl.createBuffer();
  6020.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  6021.    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(16), gl.DYNAMIC_DRAW);
  6022.    var vs = self.compileShader(gl.VERTEX_SHADER, self.vertShader);
  6023.    var fs = self.compileShader(gl.FRAGMENT_SHADER, self.fragShader);
  6024.    var program = gl.createProgram();
  6025.    gl.attachShader(program, vs);
  6026.    gl.attachShader(program, fs);
  6027.    gl.linkProgram(program);
  6028.    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  6029.     console.error("Error linking shaders");
  6030.     return
  6031.    }
  6032.    self.vs = vs;
  6033.    self.fs = fs;
  6034.    self.program = program;
  6035.    self.uTexture = gl.getUniformLocation(program, "uTexture");
  6036.    self.aPosition = gl.getAttribLocation(program, "aPosition");
  6037.    self.aTexCoord = gl.getAttribLocation(program, "aTexCoord")
  6038.   };
  6039.   var updateVb = function() {
  6040.    var u = self.width / self.bgImg.width,
  6041.     v = self.height / self.bgImg.height;
  6042.    var vbData = [-1, -1, 0, v, 1, -1, u, v, -1, 1, 0, 0, 1, 1, u, 0];
  6043.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  6044.    gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array(vbData))
  6045.   };
  6046.   if (!self.bgImg) {
  6047.    self.bgImg = new Image;
  6048.    self.bgImg.crossOrigin = "";
  6049.    self.bgImg.onload = function() {
  6050.     self.bgImg.loaded = true;
  6051.     self.bgTexture = gl.createTexture();
  6052.     gl.bindTexture(gl.TEXTURE_2D, self.bgTexture);
  6053.     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.bgImg);
  6054.     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  6055.     if (!self.vb) initVb();
  6056.     updateVb()
  6057.    };
  6058.    self.bgImg.onerror = function() {
  6059.     self.bgImg = null
  6060.    };
  6061.    self.bgImg.src = self.options.contentPath + self.options.background
  6062.   } else if (self.bgImg.loaded) {
  6063.    if (!self.vb) initVb();
  6064.    updateVb()
  6065.   }
  6066.  },
  6067.  vertShader: "    attribute vec2 aPosition;    attribute vec2 aTexCoord;        varying vec2 vTexCoord;        void main(void) {        vTexCoord = aTexCoord;        gl_Position = vec4(aPosition, 0, 1);    }    ",
  6068.  fragShader: "    precision mediump float;    varying vec2 vTexCoord;        uniform sampler2D uTexture;        void main(void) {        gl_FragColor = texture2D(uTexture, vTexCoord);    }    ",
  6069.  compileShader: function(type, source) {
  6070.   var self = this,
  6071.    gl = self.context;
  6072.   var shader = gl.createShader(type);
  6073.   gl.shaderSource(shader, source);
  6074.   gl.compileShader(shader);
  6075.   if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  6076.    throw "Shader compile error: " + gl.getShaderInfoLog(shader)
  6077.   }
  6078.   return shader
  6079.  }
  6080. };
  6081. ZamModelViewer.Flash = function(viewer) {
  6082.  var self = this;
  6083.  self.viewer = viewer;
  6084.  self.options = viewer.options;
  6085.  self.width = 0;
  6086.  self.height = 0;
  6087.  self.div = null;
  6088.  self.object = null;
  6089.  self.divId = "sjfdlkjsfesl32"
  6090. };
  6091. ZamModelViewer.Flash.prototype = {
  6092.  destroy: function() {
  6093.   var self = this;
  6094.   if (self.div) {
  6095.    self.div.detach();
  6096.    self.div = null
  6097.   }
  6098.   if (self.object) {
  6099.    self.object.detach();
  6100.    self.object = null
  6101.   }
  6102.  },
  6103.  method: function(name, params) {
  6104.   var self = this,
  6105.    object = $("#" + self.divId);
  6106.   if (object.length > 0) {
  6107.    return object[0][name].apply(object[0], params)
  6108.   } else {
  6109.    return null
  6110.   }
  6111.  },
  6112.  resize: function(width, height) {
  6113.   var self = this;
  6114.   if (self.width === width) return;
  6115.   self.viewer.container.css({
  6116.    height: height + "px"
  6117.   });
  6118.   self.width = width;
  6119.   self.height = height;
  6120.   if (!self.div) {
  6121.    self.div = $("<div/>", {
  6122.     id: self.divId
  6123.    });
  6124.    self.viewer.container.append(self.div)
  6125.   }
  6126.  },
  6127.  init: function() {
  6128.   var self = this,
  6129.    opts = self.options;
  6130.   var model = opts.models;
  6131.   var flashVars = {
  6132.    modelType: model.type,
  6133.    model: model.id,
  6134.    container: self.divId,
  6135.    contentPath: opts.contentPath
  6136.   };
  6137.   var params = {
  6138.    quality: "high",
  6139.    allowscriptaccess: "always",
  6140.    allowfullscreen: true,
  6141.    menu: false,
  6142.    bgcolor: "#181818",
  6143.    wmode: "direct"
  6144.   };
  6145.   if (opts.background) flashVars.background = opts.background;
  6146.   if (opts.cls !== undefined) flashVars.cls = opts.cls;
  6147.   if (opts.hd !== undefined) flashVars.hd = opts.hd;
  6148.   if (opts.sk !== undefined) flashVars.sk = opts.sk;
  6149.   if (opts.ha !== undefined) flashVars.ha = opts.ha;
  6150.   if (opts.hc !== undefined) flashVars.hc = opts.hc;
  6151.   if (opts.fa !== undefined) flashVars.fa = opts.fa;
  6152.   if (opts.fc !== undefined) flashVars.fc = opts.fc;
  6153.   if (opts.fh !== undefined) flashVars.fh = opts.fh;
  6154.   if (opts.items) {
  6155.    var items = opts.items;
  6156.    var equipList = [];
  6157.    if ($.isArray(items)) {
  6158.     for (var i = 0; i < items.length; ++i) {
  6159.      equipList.push(items[i][0]);
  6160.      equipList.push(items[i][1])
  6161.     }
  6162.    } else {
  6163.     for (var slot in items) {
  6164.      equipList.push(slot);
  6165.      equipList.push(items[slot])
  6166.     }
  6167.    }
  6168.    flashVars.equipList = equipList.join(",")
  6169.   }
  6170.   self.object = $("#" + self.divId);
  6171.   self.object.html("<b>WebGL not supported by your browser, please go to https://get.webgl.org/ for support.</b>")
  6172.  }
  6173. };
  6174. ZamModelViewer.Wow = function() {};
  6175. ZamModelViewer.Wow.Model = function(renderer, viewer, model, index, skipLoad) {
  6176.  var self = this;
  6177.  self.Texture = ZamModelViewer.Wow.Texture;
  6178.  self.renderer = renderer;
  6179.  self.viewer = viewer;
  6180.  self.model = model;
  6181.  self.modelIndex = index;
  6182.  self.modelPath = null;
  6183.  self.loaded = false;
  6184.  self.opts = self.viewer.options;
  6185.  self.mount = null;
  6186.  self.isMount = self.opts.mount && self.opts.mount.type == ZamModelViewer.Wow.Types.NPC && self.opts.mount.id == self.model.id;
  6187.  if (self.model.type == ZamModelViewer.Wow.Types.CHARACTER) {
  6188.   if (self.opts.mount && self.opts.mount.type == ZamModelViewer.Wow.Types.NPC && self.opts.mount.id) {
  6189.    self.opts.mount.parent = self;
  6190.    self.mount = new ZamModelViewer.Wow.Model(renderer, viewer, self.opts.mount, 0)
  6191.   }
  6192.  }
  6193.  self.race = -1;
  6194.  self.gender = -1;
  6195.  self.class = self.opts.cls ? parseInt(self.opts.cls) : -1;
  6196.  self.meta = null;
  6197.  self.skinIndex = 0;
  6198.  self.hairIndex = 0;
  6199.  self.hairColorIndex = 0;
  6200.  self.faceIndex = 0;
  6201.  self.faceFeatureIndex = 0;
  6202.  self.faceColorIndex = 0;
  6203.  self.HornsIndex = 0;
  6204.  self.EyePatchIndex = 0;
  6205.  self.TattoosIndex = 0;
  6206.  self.hairVis = true;
  6207.  self.faceVis = true;
  6208.  self.hairMesh = null;
  6209.  self.parent = self.model.parent || null;
  6210.  self.items = {};
  6211.  self.needsCompositing = false;
  6212.  self.textureOverrides = {};
  6213.  self.compositeImage = null;
  6214.  self.compositeTexture = null;
  6215.  self.npcTexture = null;
  6216.  self.specialTextures = {};
  6217.  self.bakedTextures = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
  6218.  self.isHD = false;
  6219.  self.sheathMain = -1;
  6220.  self.sheathOff = -1;
  6221.  self.numGeosets = 26;
  6222.  self.geosets = new Array(self.numGeosets);
  6223.  self.time = 0;
  6224.  self.frame = 0;
  6225.  self.animationList = null;
  6226.  self.currentAnimation = null;
  6227.  self.animStartTime = 0;
  6228.  self.slotAttachments = {};
  6229.  self.matrix = mat4.create();
  6230.  self.vbData = null;
  6231.  self.vb = null;
  6232.  self.ib = null;
  6233.  self.shaderReady = false;
  6234.  self.vs = null;
  6235.  self.fs = null;
  6236.  self.program = null;
  6237.  self.uniforms = null;
  6238.  self.attribs = null;
  6239.  self.ambientColor = [.35, .35, .35, 1];
  6240.  self.primaryColor = [1, 1, 1, 1];
  6241.  self.secondaryColor = [.35, .35, .35, 1];
  6242.  self.lightDir1 = vec3.create();
  6243.  self.lightDir2 = vec3.create();
  6244.  self.lightDir3 = vec3.create();
  6245.  vec3.normalize(self.lightDir1, [5, -3, 3]);
  6246.  vec3.normalize(self.lightDir2, [5, 5, 5]);
  6247.  vec3.normalize(self.lightDir3, [-5, -5, -5]);
  6248.  self.boundsSet = false;
  6249.  self.animBounds = false;
  6250.  self.boundsMin = [0, 0, 0];
  6251.  self.boundsMax = [0, 0, 0];
  6252.  self.boundsCenter = [0, 0, 0];
  6253.  self.boundsSize = [0, 0, 0];
  6254.  self.vertices = null;
  6255.  self.indices = null;
  6256.  self.animations = null;
  6257.  self.animLookup = null;
  6258.  self.bones = null;
  6259.  self.boneLookup = null;
  6260.  self.keyBoneLookup = null;
  6261.  self.meshes = null;
  6262.  self.texUnits = null;
  6263.  self.texUnitLookup = null;
  6264.  self.renderFlags = null;
  6265.  self.materials = null;
  6266.  self.materialLookup = null;
  6267.  self.textureAnims = null;
  6268.  self.textureAnimLookup = null;
  6269.  self.textureReplacements = null;
  6270.  self.attachments = null;
  6271.  self.attachmentLookup = null;
  6272.  self.colors = null;
  6273.  self.alphas = null;
  6274.  self.alphaLookup = null;
  6275.  self.particleEmitters = null;
  6276.  self.ribbonEmitters = null;
  6277.  self.skins = null;
  6278.  self.faces = null;
  6279.  self.hairs = null;
  6280.  self.tmpMat = mat4.create();
  6281.  self.tmpVec = vec3.create();
  6282.  self.tmpVec3 = vec3.create();
  6283.  self.tmpVec4 = vec4.create();
  6284.  self.mountMat = mat4.create();
  6285.  if (!skipLoad) {
  6286.   self.load()
  6287.  }
  6288. };
  6289. ZamModelViewer.Models[ZamModelViewer.WOW] = ZamModelViewer.Wow.Model;
  6290. ZamModelViewer.Wow.Model.prototype = {
  6291.  external: {
  6292.   getNumAnimations: function() {
  6293.    var model = this.mount ? this.mount : this;
  6294.    return model.animations ? model.animations.length : 0
  6295.   },
  6296.   getAnimation: function(idx) {
  6297.    var model = this.mount ? this.mount : this;
  6298.    if (model.animations && idx > -1 && idx < model.animations.length) {
  6299.     return model.animations[idx].name
  6300.    } else {
  6301.     return ""
  6302.    }
  6303.   },
  6304.   setAnimation: function(name) {
  6305.    var model = this.mount ? this.mount : this;
  6306.    model.setAnimation(name)
  6307.   },
  6308.   resetAnimation: function() {
  6309.    var model = this.mount ? this.mount : this;
  6310.    model.setAnimation("Stand")
  6311.   },
  6312.   attachList: function(list) {
  6313.    var equip = list.split(",");
  6314.    var items = [];
  6315.    for (var i = 0; i < equip.length; i += 2) {
  6316.     items.push([equip[i], equip[i + 1]])
  6317.    }
  6318.    for (var i in items) {
  6319.     var item = [parseInt(items[i][0]), parseInt(items[i][1])];
  6320.     this.opts.items.push(item)
  6321.    }
  6322.    this.loadItems(items);
  6323.    this.needsCompositing = true;
  6324.    if (this.dhmodel) {
  6325.     this.dhmodel.destroy();
  6326.     this.dhloaded = 0;
  6327.     this.loadDH(this.meta.DHGeosetsHDModel)
  6328.    }
  6329.    this.setup()
  6330.   },
  6331.   clearSlots: function(list) {
  6332.    var slots = list.split(",");
  6333.    for (var i = 0; i < slots.length; ++i) {
  6334.     this.removeSlot(slots[i]);
  6335.     var items = [];
  6336.     for (var i in this.opts.items) {
  6337.      if (this.opts.items[i].indexOf(parseInt(slots[i])) != 0) items.push(this.opts.items[i])
  6338.     }
  6339.     this.opts.items = items
  6340.    }
  6341.    this.needsCompositing = true;
  6342.    if (this.dhmodel) {
  6343.     this.dhmodel.destroy();
  6344.     this.dhloaded = 0;
  6345.     this.loadDH(this.meta.DHGeosetsHDModel)
  6346.    }
  6347.    this.setup()
  6348.   },
  6349.   setAppearance: function(hairStyle, hairColor, faceType, skinColor, features, featuresColor, horns, eyepatch, tattoos, sheathMain, sheathOff) {
  6350.    this.skinIndex = skinColor;
  6351.    this.hairIndex = hairStyle;
  6352.    this.hairColorIndex = hairColor;
  6353.    this.faceIndex = faceType;
  6354.    this.faceFeatureIndex = features;
  6355.    this.faceColorIndex = featuresColor;
  6356.    this.HornsIndex = horns;
  6357.    this.EyePatchIndex = eyepatch;
  6358.    this.TattoosIndex = tattoos;
  6359.    var Region = ZamModelViewer.Wow.Regions;
  6360.    var destroyTexture = function(array, key) {
  6361.     array[key].destroy();
  6362.     delete array[key]
  6363.    };
  6364.    if (this.specialTextures[1]) destroyTexture(this.specialTextures, 1);
  6365.    if (this.specialTextures[6]) destroyTexture(this.specialTextures, 6);
  6366.    if (this.specialTextures[8]) destroyTexture(this.specialTextures, 8);
  6367.    if (this.bakedTextures[Region.LegUpper][1]) destroyTexture(this.bakedTextures[Region.LegUpper], 1);
  6368.    if (this.bakedTextures[Region.TorsoUpper][1]) destroyTexture(this.bakedTextures[Region.TorsoUpper], 1);
  6369.    if (this.bakedTextures[Region.FaceLower][1]) destroyTexture(this.bakedTextures[Region.FaceLower], 1);
  6370.    if (this.bakedTextures[Region.FaceUpper][1]) destroyTexture(this.bakedTextures[Region.FaceUpper], 1);
  6371.    if (this.bakedTextures[Region.FaceLower][2]) destroyTexture(this.bakedTextures[Region.FaceLower], 2);
  6372.    if (this.bakedTextures[Region.FaceUpper][2]) destroyTexture(this.bakedTextures[Region.FaceUpper], 2);
  6373.    if (this.bakedTextures[Region.FaceLower][3]) destroyTexture(this.bakedTextures[Region.FaceLower], 3);
  6374.    if (this.bakedTextures[Region.FaceUpper][3]) destroyTexture(this.bakedTextures[Region.FaceUpper], 3);
  6375.    if (this.bakedTextures[Region.Base][1]) destroyTexture(this.bakedTextures[Region.Base], 1);
  6376.    this.sheathMain = sheathMain;
  6377.    this.sheathOff = sheathOff;
  6378.    this.updateSlotMap();
  6379.    this.needsCompositing = true;
  6380.    if (this.dhmodel) {
  6381.     this.dhmodel.destroy();
  6382.     this.dhloaded = 0;
  6383.     this.loadDH(this.meta.DHGeosetsHDModel)
  6384.    }
  6385.    this.setup()
  6386.   },
  6387.   isLoaded: function() {
  6388.    if (this.mount) {
  6389.     return this.mount.loaded && this.loaded
  6390.    } else {
  6391.     return this.loaded
  6392.    }
  6393.   }
  6394.  },
  6395.  setMatrix: function(parent, bone, attach, extra) {
  6396.   var self = this;
  6397.   mat4.copy(self.matrix, parent);
  6398.   mat4.multiply(self.matrix, self.matrix, bone);
  6399.   if (attach) mat4.translate(self.matrix, self.matrix, attach);
  6400.   if (extra) mat4.multiply(self.matrix, self.matrix, extra)
  6401.  },
  6402.  setAnimation: function(name) {
  6403.   var self = this,
  6404.    anim, Wow = ZamModelViewer.Wow;
  6405.   self.animationList = [];
  6406.   for (var i = 0; i < self.animations.length; ++i) {
  6407.    anim = self.animations[i];
  6408.    if (!anim.name) continue;
  6409.    if (anim.name == name && name == "Stand") {
  6410.     if (self.race == Wow.Races.PANDAREN && self.gender == Wow.Genders.MALE && anim.length == 11900) continue;
  6411.     self.animationList.push(anim)
  6412.    } else if (anim.name == name) {
  6413.     self.animationList.push(anim)
  6414.    }
  6415.   }
  6416.   self.animStartTime = 0;
  6417.   self.currentAnimation = self.animationList.length > 0 ? self.animationList[0] : null;
  6418.   if (name != "Stand" && !self.currentAnimation) {
  6419.    self.setAnimation("Stand")
  6420.   }
  6421.  },
  6422.  updateBuffers: function(fillVb) {
  6423.   var self = this,
  6424.    i, j, vertLength = 8,
  6425.    gl = self.renderer.context;
  6426.   if (!self.vertices || !self.indices) return;
  6427.   var vbLength = self.vertices.length * vertLength;
  6428.   if (!self.vbData) self.vbData = new Float32Array(vbLength);
  6429.   if (fillVb) {
  6430.    var vbData = self.vbData,
  6431.     verts = self.vertices;
  6432.    for (i = 0, j = 0; i < vbLength; ++j) {
  6433.     vbData[i + 0] = verts[j].transPosition[0];
  6434.     vbData[i + 1] = verts[j].transPosition[1];
  6435.     vbData[i + 2] = verts[j].transPosition[2];
  6436.     vbData[i + 3] = verts[j].transNormal[0];
  6437.     vbData[i + 4] = verts[j].transNormal[1];
  6438.     vbData[i + 5] = verts[j].transNormal[2];
  6439.     vbData[i + 6] = verts[j].u;
  6440.     vbData[i + 7] = verts[j].v;
  6441.     i += 8
  6442.    }
  6443.   }
  6444.   if (!self.vb) {
  6445.    self.vb = gl.createBuffer();
  6446.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  6447.    gl.bufferData(gl.ARRAY_BUFFER, self.vbData, gl.DYNAMIC_DRAW);
  6448.    self.ib = gl.createBuffer();
  6449.    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  6450.    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(self.indices), gl.STATIC_DRAW)
  6451.   } else {
  6452.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  6453.    gl.bufferSubData(gl.ARRAY_BUFFER, 0, self.vbData)
  6454.   }
  6455.  },
  6456.  updateBounds: function() {
  6457.   var self = this,
  6458.    t, m, color = [1, 1, 1, 1],
  6459.    Wow = ZamModelViewer.Wow;
  6460.   var min = self.boundsMin,
  6461.    max = self.boundsMax,
  6462.    pos, tmp = self.tmpVec;
  6463.   vec3.set(min, 9999, 9999, 999);
  6464.   vec3.set(max, -9999, -9999, -9999);
  6465.   if (!self.texUnits) {
  6466.    mat4.identity(self.matrix);
  6467.    self.renderer.distance = 1;
  6468.    return false
  6469.   }
  6470.   for (var i = 0; i < self.texUnits.length; ++i) {
  6471.    t = self.texUnits[i];
  6472.    if (!t.show) continue;
  6473.    color[0] = color[1] = color[2] = color[3] = 1;
  6474.    if (self.currentAnimation) {
  6475.     if (t.color) t.color.getValue(self.currentAnimation.index, self.time, color);
  6476.     if (t.alpha) color[3] *= t.alpha.getValue(self.currentAnimation.index, self.time)
  6477.    }
  6478.    if (color[3] < .01) continue;
  6479.    m = t.mesh;
  6480.    for (var j = 0; j < m.indexCount; ++j) {
  6481.     pos = self.vertices[self.indices[m.indexStart + j]].transPosition;
  6482.     vec3.min(min, min, pos);
  6483.     vec3.max(max, max, pos)
  6484.    }
  6485.   }
  6486.   if (self.mount && self.mount.loaded) {
  6487.    if (self.mount.updateBounds()) {
  6488.     vec3.copy(min, vec3.scale(min, self.mount.boundsMin, 1.1));
  6489.     vec3.copy(max, vec3.scale(max, self.mount.boundsMax, 1.1));
  6490.     max[2] *= 1.75
  6491.    }
  6492.   }
  6493.   if (self.model.type == Wow.Types.NPC) {
  6494.    vec3.scale(min, min, self.meta.Scale);
  6495.    vec3.scale(max, max, self.meta.Scale)
  6496.   }
  6497.   vec3.subtract(self.boundsSize, max, min);
  6498.   vec3.scaleAndAdd(self.boundsCenter, min, self.boundsSize, .5);
  6499.   var hSize = self.boundsSize[2],
  6500.    wSize, dSize, scale = self.meta ? self.meta.Scale : 1;
  6501.   if (self.model.type != Wow.Types.ITEM) {
  6502.    wSize = self.boundsSize[1];
  6503.    dSize = self.boundsSize[0]
  6504.   } else {
  6505.    wSize = self.boundsSize[0];
  6506.    dSize = self.boundsSize[1]
  6507.   }
  6508.   if (!self.parent) {
  6509.    var ratio = self.renderer.width / self.renderer.height;
  6510.    var hTan = 2 * Math.tan(self.renderer.fov / 2 * .0174532925);
  6511.    var wTan = hTan * ratio;
  6512.    var hDist = hSize * 1.2 / hTan;
  6513.    var wDist = wSize * 1.2 / wTan;
  6514.    self.renderer.distance = Math.max(Math.max(hDist, wDist), dSize * 2)
  6515.   }
  6516.   mat4.identity(self.matrix);
  6517.   if (self.model.type != Wow.Types.ITEM) {
  6518.    mat4.rotateZ(self.matrix, self.matrix, Math.PI / 2)
  6519.   }
  6520.   mat4.translate(self.matrix, self.matrix, vec3.negate(tmp, self.boundsCenter));
  6521.   vec3.set(self.tmpVec, scale, scale, scale);
  6522.   mat4.scale(self.matrix, self.matrix, self.tmpVec);
  6523.   return true
  6524.  },
  6525.  disabledMeshes: {
  6526.   146273: {
  6527.    1: true
  6528.   },
  6529.   319730: {
  6530.    1: true
  6531.   }
  6532.  },
  6533.  setup: function() {
  6534.   var self = this,
  6535.    i, Wow = ZamModelViewer.Wow;
  6536.   if (self.model.type != Wow.Types.CHARACTER && self.model.type != Wow.Types.NPC && self.model.type != Wow.Types.HUMANOIDNPC || self.race < 1) {
  6537.    if (self.texUnits) {
  6538.     if (self.modelPath == 1276975 || self.modelPath == 1276976 || self.modelPath == 1276977 || self.modelPath == 1276978) {
  6539.      if (self.parent.dhloaded == 0) {
  6540.       self.slot = 6;
  6541.       var HASPANTS = false;
  6542.       for (var i in self.parent.opts.items) {
  6543.        if (self.parent.opts.items[i].indexOf(7) == 0) HASPANTS = true
  6544.       }
  6545.       for (i = 0; i < self.texUnits.length; ++i) {
  6546.        if (self.texUnits[i].meshId == 1401 && !HASPANTS) self.texUnits[i].show = true;
  6547.        else self.texUnits[i].show = false
  6548.       }
  6549.      }
  6550.      if (self.parent.dhloaded == 1) {
  6551.       self.slot = 1;
  6552.       for (i = 0; i < self.texUnits.length; ++i) {
  6553.        if (self.parent.HornsIndex > 0 && self.texUnits[i].meshId == 2400 + self.parent.HornsIndex) self.texUnits[i].show = true;
  6554.        else self.texUnits[i].show = false
  6555.       }
  6556.      }
  6557.      if (self.parent.dhloaded == 2) {
  6558.       self.slot = 1;
  6559.       for (i = 0; i < self.texUnits.length; ++i) {
  6560.        if (self.parent.EyePatchIndex > 0 && self.texUnits[i].meshId == 2500 + self.parent.EyePatchIndex) self.texUnits[i].show = true;
  6561.        else self.texUnits[i].show = false
  6562.       }
  6563.      }
  6564.      if (self.parent.dhloaded == 3) {
  6565.       self.slot = 25;
  6566.       for (i = 0; i < self.texUnits.length; ++i) {
  6567.        if (self.texUnits[i].meshId == 2301) self.texUnits[i].show = true;
  6568.        else self.texUnits[i].show = false
  6569.       }
  6570.      }
  6571.      self.parent.dhloaded = self.parent.dhloaded + 1
  6572.     } else if (self.modelPath == 982557) {
  6573.      for (i = 0; i < self.texUnits.length; ++i) {
  6574.       self.texUnits[i].show = self.texUnits[i].meshId == 0
  6575.      }
  6576.     } else if (self.disabledMeshes[self.modelPath] !== undefined) {
  6577.      var mesh = self.disabledMeshes[self.modelPath];
  6578.      for (i = 0; i < self.texUnits.length; ++i) {
  6579.       self.texUnits[i].show = mesh[i] === undefined
  6580.      }
  6581.     } else {
  6582.      for (i = 0; i < self.texUnits.length; ++i) {
  6583.       self.texUnits[i].show = true
  6584.      }
  6585.     }
  6586.    }
  6587.    return
  6588.   }
  6589.   if ((self.race == Wow.Races.BROKEN || self.race == Wow.Races.TUSKARR) && self.hairIndex == 0) {
  6590.    self.hairIndex = 1
  6591.   }
  6592.   if (self.model.type == Wow.Types.CHARACTER && self.race == Wow.Races.DWARF && self.opts.fh == undefined) {
  6593.    self.faceFeatureIndex = 3
  6594.   }
  6595.   var skin, face, features, featureTexture, hair, hairTexture, dk = self.class == Wow.Classes.DEATHKNIGHT;
  6596.   var skins, faces, textures, tattoo;
  6597.   skins = self.skins;
  6598.   if (skins) {
  6599.    if (self.skinIndex >= skins.length) self.skinIndex = 0;
  6600.    if (self.skinIndex < skins.length) skin = skins[self.skinIndex];
  6601.    if (skin) {
  6602.     if (false && dk) {
  6603.      faces = Wow.Skin.GetFaces(skin.faces, true, dk, skin.skinFlags);
  6604.      if (self.faceIndex >= faces.length) self.faceIndex = 0;
  6605.      if (self.faceIndex < faces.length) face = faces[self.faceIndex]
  6606.     } else if (self.faceIndex < skins.length) {
  6607.      faces = Wow.Skin.GetFaces(skins[self.faceIndex].faces, true, dk, 0);
  6608.      var index = self.skinIndex;
  6609.      if (index >= faces.length) index = faces.length - 1;
  6610.      if (index < faces.length) face = faces[index]
  6611.     }
  6612.    }
  6613.   }
  6614.   if (self.faces) {
  6615.    if (self.faceFeatureIndex >= self.faces.length) self.faceFeatureIndex = faces.length - 1;
  6616.    if (self.faceFeatureIndex < self.faces.length) features = self.faces[self.faceFeatureIndex];
  6617.    if (features) {
  6618.     if (self.class == Wow.Classes.DEMONHUNTER) textures = features.textures;
  6619.     else textures = Wow.Face.GetTextures(features.textures, true, dk);
  6620.     if (self.faceColorIndex >= textures.length) self.faceColorIndex = textures.length - 1;
  6621.     if (self.faceColorIndex < textures.length) featureTexture = textures[self.faceColorIndex]
  6622.    }
  6623.   }
  6624.   if (self.hairs) {
  6625.    if (self.hairIndex >= self.hairs.length) self.hairIndex = 0;
  6626.    if (self.hairIndex < self.hairs.length) hair = self.hairs[self.hairIndex];
  6627.    if (hair) {
  6628.     if (self.class == Wow.Classes.DEMONHUNTER) textures = hair.textures;
  6629.     else textures = Wow.Hair.GetTextures(hair.textures, true, dk);
  6630.     if (self.hairColorIndex >= textures.length) self.hairColorIndex = 0;
  6631.     if (self.hairColorIndex < textures.length) hairTexture = textures[self.hairColorIndex]
  6632.    }
  6633.   }
  6634.   if (self.tattoos && self.class == Wow.Classes.DEMONHUNTER) {
  6635.    if (self.TattoosIndex >= self.tattoos.length) self.TattoosIndex = 0;
  6636.    if (self.TattoosIndex < self.tattoos.length) tattoo = self.tattoos[self.TattoosIndex]
  6637.   }
  6638.   var Region = ZamModelViewer.Wow.Regions;
  6639.   if (!self.npcTexture) {
  6640.    self.needsCompositing = true;
  6641.    if (skin) {
  6642.     if (skin.base && !self.specialTextures[1]) self.specialTextures[1] = new self.Texture(self, 1, skin.base);
  6643.     if (skin.panties && !self.bakedTextures[Region.LegUpper][1]) self.bakedTextures[Region.LegUpper][1] = new self.Texture(self, Region.LegUpper, skin.panties);
  6644.     if (skin.bra && !self.bakedTextures[Region.TorsoUpper][1]) self.bakedTextures[Region.TorsoUpper][1] = new self.Texture(self, Region.TorsoUpper, skin.bra);
  6645.     if (tattoo && !self.bakedTextures[Region.Base][1] && tattoo.texture != 0) {
  6646.      self.bakedTextures[Region.Base][1] = new self.Texture(self, Region.FaceLower, tattoo.texture)
  6647.     }
  6648.    }
  6649.    if (face) {
  6650.     if (face.lower && !self.bakedTextures[Region.FaceLower][1]) self.bakedTextures[Region.FaceLower][1] = new self.Texture(self, Region.FaceLower, face.lower);
  6651.     if (face.upper && !self.bakedTextures[Region.FaceUpper][1]) self.bakedTextures[Region.FaceUpper][1] = new self.Texture(self, Region.FaceUpper, face.upper)
  6652.    }
  6653.    if (featureTexture) {
  6654.     if (featureTexture.lower && !self.bakedTextures[Region.FaceLower][2]) self.bakedTextures[Region.FaceLower][2] = new self.Texture(self, Region.FaceLower, featureTexture.lower);
  6655.     if (featureTexture.upper && !self.bakedTextures[Region.FaceUpper][2]) self.bakedTextures[Region.FaceUpper][2] = new self.Texture(self, Region.FaceUpper, featureTexture.upper)
  6656.    }
  6657.    if (hairTexture) {
  6658.     if (hairTexture.lower && !self.bakedTextures[Region.FaceLower][3]) self.bakedTextures[Region.FaceLower][3] = new self.Texture(self, Region.FaceLower, hairTexture.lower);
  6659.     if (hairTexture.upper && !self.bakedTextures[Region.FaceUpper][3]) self.bakedTextures[Region.FaceUpper][3] = new self.Texture(self, Region.FaceUpper, hairTexture.upper)
  6660.    }
  6661.   }
  6662.   if (skin && skin.fur && !self.specialTextures[8]) self.specialTextures[8] = new self.Texture(self, 8, skin.fur);
  6663.   if (hairTexture && hairTexture.texture && !self.specialTextures[6]) self.specialTextures[6] = new self.Texture(self, 6, hairTexture.texture);
  6664.   else if (hairTexture && !hairTexture.texture && !self.specialTextures[6] && self.hairIndex == 0 && self.hairs.length > 1) {
  6665.    hair = self.hairs[1];
  6666.    if (self.hairColorIndex >= hair.textures.length) self.hairColorIndex = 0;
  6667.    if (self.hairColorIndex < hair.textures.length) {
  6668.     hairTexture = hair.textures[self.hairColorIndex];
  6669.     if (hairTexture.texture) self.specialTextures[6] = new self.Texture(self, 6, hairTexture.texture)
  6670.    }
  6671.   }
  6672.   self.updateMeshes()
  6673.  },
  6674.  updateMeshes: function() {
  6675.   var self = this,
  6676.    i, j, u, Wow = ZamModelViewer.Wow,
  6677.    Races = Wow.Races,
  6678.    Genders = Wow.Genders,
  6679.    Slots = Wow.Slots;
  6680.   if (!self.texUnits || self.texUnits.length == 0) return;
  6681.   var showHair = true;
  6682.   if (self.hairMesh) showHair = self.hairMesh.show;
  6683.   for (i = 0; i < self.texUnits.length; ++i) {
  6684.    self.texUnits[i].show = self.texUnits[i].meshId == 0
  6685.   }
  6686.   for (i = 0; i < self.numGeosets; ++i) {
  6687.    self.geosets[i] = 1
  6688.   }
  6689.   self.geosets[7] = 2;
  6690.   if (self.faceVis) {
  6691.    if (self.faces && self.faceFeatureIndex < self.faces.length) {
  6692.     var face = self.faces[self.faceFeatureIndex];
  6693.     self.geosets[1] = face.geoset1;
  6694.     self.geosets[2] = face.geoset2;
  6695.     self.geosets[3] = face.geoset3
  6696.    }
  6697.   }
  6698.   if (self.race == Races.GOBLIN) {
  6699.    if (self.geosets[1] == 1) self.geosets[1] = 2;
  6700.    if (self.geosets[2] == 1) self.geosets[2] = 2;
  6701.    if (self.geosets[3] == 1) self.geosets[3] = 2
  6702.   }
  6703.   var slot, item, hasRobe = false,
  6704.    hasBoots = false,
  6705.    hasHelm = false;
  6706.   for (slot in self.items) {
  6707.    item = self.items[slot];
  6708.    if (item.slot == Slots.ROBE) hasRobe = true;
  6709.    else if (item.slot == Slots.BOOTS) hasBoots = true;
  6710.    else if (item.slot == Slots.HEAD) hasHelm = true;
  6711.    if (!item.geosets) continue;
  6712.    for (j = 0; j < item.geosets.length; ++j) {
  6713.     self.geosets[item.geosets[j].index] = item.geosets[j].value
  6714.    }
  6715.    if (self.geosets[13] == 1) self.geosets[13] += item.geoC;
  6716.    if (item.slot == Slots.BELT) self.geosets[18] = 1 + item.geoA;
  6717.    if (self.race == Races.PANDAREN && item.slot == Slots.PANTS) self.geosets[14] = 0
  6718.   }
  6719.   if (self.geosets[13] == 2) self.geosets[5] = self.geosets[12] = 0;
  6720.   if (self.geosets[4] > 1) self.geosets[8] = 0;
  6721.   if (self.isHD && hasBoots) self.geosets[20] = 2;
  6722.   if (!hasHelm) {
  6723.    showHair = true;
  6724.    self.hairVis = self.faceVis = true
  6725.   } else {
  6726.    showHair = self.hairVis
  6727.   }
  6728.   if (showHair && self.hairs && self.hairIndex < self.hairs.length) {
  6729.    self.hairMesh = null;
  6730.    var hair = self.hairs[self.hairIndex];
  6731.    for (i = 0; i < self.texUnits.length; ++i) {
  6732.     u = self.texUnits[i];
  6733.     if (u.meshId != 0 && u.meshId == hair.geoset) {
  6734.      u.show = true;
  6735.      self.hairMesh = u
  6736.     }
  6737.    }
  6738.   }
  6739.   var a, b;
  6740.   for (i = 0; i < self.texUnits.length; ++i) {
  6741.    u = self.texUnits[i];
  6742.    if (self.race != Races.HUMAN && !((self.race == Races.DRAENEI || self.race == Races.SCOURGE) && self.gender == Genders.FEMALE) && u.meshId == 0 && u.mesh.indexCount < 36) {
  6743.     u.show = false;
  6744.     continue
  6745.    }
  6746.    if (u.meshId == 1 && (!self.hairVis || self.gender == Genders.MALE && self.hairIndex == 0 && (self.race == Races.HUMAN || self.race == Races.GNOME || self.race == Races.TROLL))) {
  6747.     u.show = true
  6748.    }
  6749.    for (j = 1; j < self.numGeosets; ++j) {
  6750.     a = j * 100;
  6751.     b = (j + 1) * 100;
  6752.     if (u.meshId > a && u.meshId < b) u.show = u.meshId == a + self.geosets[j]
  6753.    }
  6754.    if (self.race == Races.SCOURGE && !self.isHD) {
  6755.     if (self.gender == Genders.FEMALE) {
  6756.      if (u.mesh == 49 || u.mesh == 51) u.show = true
  6757.     } else {
  6758.      if (u.mesh == 62) u.show = true
  6759.     }
  6760.    } else if (self.race == Races.GOBLIN) {
  6761.     if (self.gender == Genders.FEMALE && u.mesh == 0 || self.gender == Genders.MALE && u.mesh == 3) u.show = false
  6762.    } else if (self.race == Races.WORGEN) {
  6763.     if (self.gender == Genders.MALE) {
  6764.      if (u.mesh == 5 || u.mesh == 3 || u.mesh >= 36 && u.mesh <= 47) u.show = false
  6765.     } else {
  6766.      if (u.mesh == 2 || u.mesh == 3 || u.mesh >= 58 && u.mesh <= 69) u.show = false
  6767.     }
  6768.    } else if (self.race == Races.PANDAREN) {
  6769.     if (self.gender == Genders.FEMALE) {
  6770.      if (hasRobe && u.meshId == 1401) u.show = false
  6771.     }
  6772.    } else if (self.race == Races.NIGHTELF) {
  6773.     if (self.class != Wow.Classes.DEATHKNIGHT && u.meshId == 1702) u.show = true
  6774.    }
  6775.    if (self.race == Races.BLOODELF || self.race == Races.NIGHTELF) {
  6776.     if (u.meshId == 2301) u.show = true
  6777.    }
  6778.    if (self.class == Wow.Classes.DEATHKNIGHT) {
  6779.     if (u.meshId == 1703) u.show = true
  6780.    }
  6781.   }
  6782.   var attach;
  6783.   if (self.dhmodel) {
  6784.    var dhmodel = self.dhmodel;
  6785.    if (dhmodel.models) {
  6786.     for (i = 0; i < dhmodel.models.length; ++i) {
  6787.      if (self.slotAttachments[dhmodel.models[i].model.slot]) {
  6788.       attach = self.attachments[self.slotAttachments[dhmodel.models[i].model.slot]];
  6789.       var newattach = JSON.parse(JSON.stringify(attach));
  6790.       dhmodel.models[i].bone = newattach.bone;
  6791.       dhmodel.models[i].attachment = newattach;
  6792.       if (self.gender == Genders.MALE && self.race == Races.NIGHTELF && self.isHD) dhmodel.models[i].attachment.position = [.012, 0, .018];
  6793.       else {
  6794.        if (dhmodel.models[i].model.slot == 6 && self.gender == Genders.FEMALE && self.race == Races.BLOODELF) dhmodel.models[i].attachment.position = [-.032, 0, -.65];
  6795.        else if (dhmodel.models[i].model.slot == 6 && self.gender == Genders.MALE && self.race == Races.NIGHTELF && !self.isHD) dhmodel.models[i].attachment.position = [-.015, 0, -.18];
  6796.        else if (dhmodel.models[i].model.slot == 6) dhmodel.models[i].attachment.position = [-.032, 0, -.4];
  6797.        else dhmodel.models[i].attachment.position = [0, 0, 0]
  6798.       }
  6799.      }
  6800.     }
  6801.    }
  6802.   }
  6803.   var attach;
  6804.   for (slot in self.items) {
  6805.    item = self.items[slot];
  6806.    if (!item.models) continue;
  6807.    for (i = 0; i < item.models.length; ++i) {
  6808.     if (self.slotAttachments[item.slot] && self.slotAttachments[item.slot].length > i) {
  6809.      attach = self.attachments[self.slotAttachments[item.slot][i]];
  6810.      item.models[i].bone = attach.bone;
  6811.      item.models[i].attachment = attach
  6812.     }
  6813.    }
  6814.   }
  6815.   if (self.hairMesh) self.hairMesh.show = showHair && self.hairVis
  6816.  },
  6817.  compositeTextures: function() {
  6818.   var self = this,
  6819.    i, j, Region = ZamModelViewer.Wow.Regions,
  6820.    Classes = ZamModelViewer.Wow.Classes,
  6821.    Slots = ZamModelViewer.Wow.Slots,
  6822.    Races = ZamModelViewer.Wow.Races,
  6823.    item, t;
  6824.   for (i = 0; i < 11; ++i) {
  6825.    for (j in self.bakedTextures[i]) {
  6826.     if (!self.bakedTextures[i][j].ready()) return
  6827.    }
  6828.   }
  6829.   for (i in self.items) {
  6830.    item = self.items[i];
  6831.    if (!item.loaded) {
  6832.     return
  6833.    } else if (item.textures) {
  6834.     for (j = 0; j < item.textures.length; ++j) {
  6835.      if (item.textures[j].texture && !item.textures[j].texture.ready()) return
  6836.     }
  6837.    }
  6838.   }
  6839.   for (var i in self.specialTextures) {
  6840.    if (self.specialTextures[i] && !self.specialTextures[i].ready()) return
  6841.   }
  6842.   if (!self.compositeImage) {
  6843.    self.compositeImage = document.createElement("canvas");
  6844.    self.compositeImage.width = self.specialTextures[1].mergedImg.width;
  6845.    self.compositeImage.height = self.specialTextures[1].mergedImg.height
  6846.   }
  6847.   var ctx = self.compositeImage.getContext("2d");
  6848.   ctx.drawImage(self.specialTextures[1].mergedImg, 0, 0, self.compositeImage.width, self.compositeImage.height);
  6849.   var w = self.compositeImage.width,
  6850.    h = self.compositeImage.height,
  6851.    regions = Region.old,
  6852.    r;
  6853.   if (w != h) regions = Region.new;
  6854.   for (i = 1; i <= 3; ++i) {
  6855.    if (self.bakedTextures[Region.FaceLower][i]) {
  6856.     if (!self.bakedTextures[Region.FaceLower][i].ready()) return;
  6857.     r = regions[Region.FaceLower];
  6858.     ctx.drawImage(self.bakedTextures[Region.FaceLower][i].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6859.    }
  6860.    if (self.bakedTextures[Region.FaceUpper][i]) {
  6861.     if (!self.bakedTextures[Region.FaceUpper][i].ready()) return;
  6862.     r = regions[Region.FaceUpper];
  6863.     ctx.drawImage(self.bakedTextures[Region.FaceUpper][i].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6864.    }
  6865.   }
  6866.   if (self.isHD) {
  6867.    for (i = 2; i <= 3; ++i) {
  6868.     if (self.bakedTextures[Region.FaceLower][i]) {
  6869.      if (!self.bakedTextures[Region.FaceLower][i].ready()) return;
  6870.      r = regions[Region.FaceLower2];
  6871.      if (r) ctx.drawImage(self.bakedTextures[Region.FaceLower][i].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6872.     }
  6873.    }
  6874.   }
  6875.   var drawBra = true,
  6876.    drawPanties = true,
  6877.    uniqueSlot;
  6878.   for (i in self.items) {
  6879.    uniqueSlot = self.items[i].uniqueSlot;
  6880.    if (uniqueSlot == Slots.SHIRT || uniqueSlot == Slots.CHEST || uniqueSlot == Slots.TABARD) drawBra = false;
  6881.    if (uniqueSlot == Slots.PANTS) drawPanties = false
  6882.   }
  6883.   if (drawBra && self.bakedTextures[Region.TorsoUpper][1]) {
  6884.    if (!self.bakedTextures[Region.TorsoUpper][1].ready()) return;
  6885.    r = regions[Region.TorsoUpper];
  6886.    ctx.drawImage(self.bakedTextures[Region.TorsoUpper][1].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6887.   }
  6888.   if (drawPanties && self.bakedTextures[Region.LegUpper][1]) {
  6889.    if (!self.bakedTextures[Region.LegUpper][1].ready()) return;
  6890.    r = regions[Region.LegUpper];
  6891.    ctx.drawImage(self.bakedTextures[Region.LegUpper][1].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6892.   }
  6893.   if (self.TattoosIndex > 0 && self.class == Classes.DEMONHUNTER) {
  6894.    if (self.bakedTextures[Region.Base][1]) {
  6895.     if (!self.bakedTextures[Region.Base][1].ready()) return;
  6896.     r = regions[Region.Base];
  6897.     ctx.drawImage(self.bakedTextures[Region.Base][1].mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6898.    }
  6899.   }
  6900.   var items = [];
  6901.   for (i in self.items) {
  6902.    items.push(self.items[i])
  6903.   }
  6904.   if (self.dhmodel) items.push(self.dhmodel);
  6905.   items.sort(function(a, b) {
  6906.    return a.sortValue - b.sortValue
  6907.   });
  6908.   for (i = 0; i < items.length; ++i) {
  6909.    item = items[i];
  6910.    if (!item.textures) continue;
  6911.    for (j = 0; j < item.textures.length; ++j) {
  6912.     t = item.textures[j];
  6913.     if (t.gender != self.gender || !t.texture || !t.texture.ready()) continue;
  6914.     if (t.region > 0) {
  6915.      if ((self.race == Races.TAUREN || self.race == Races.TROLL || self.race == Races.DRAENEI || self.race == Races.BROKEN || self.race == Races.WORGEN) && t.region == Region.Foot) continue;
  6916.      r = regions[t.region];
  6917.      ctx.drawImage(t.texture.mergedImg, w * r.x, h * r.y, w * r.w, h * r.h)
  6918.     }
  6919.    }
  6920.   }
  6921.   var gl = self.renderer.context;
  6922.   if (self.compositeTexture) gl.deleteTexture(self.compositeTexture);
  6923.   self.compositeTexture = gl.createTexture();
  6924.   gl.bindTexture(gl.TEXTURE_2D, self.compositeTexture);
  6925.   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.compositeImage);
  6926.   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  6927.   self.needsCompositing = false
  6928.  },
  6929.  loadItems: function(items) {
  6930.   var self = this;
  6931.   if ($.isArray(items)) {
  6932.    for (var i = 0; i < items.length; ++i) {
  6933.     self.addItem(items[i][0], items[i][1])
  6934.    }
  6935.   } else {
  6936.    for (var slot in items) {
  6937.     self.addItem(parseInt(slot), items[slot])
  6938.    }
  6939.   }
  6940.  },
  6941.  loadDH: function(model) {
  6942.   var self = this,
  6943.    Wow = ZamModelViewer.Wow;
  6944.   self.dhloaded = 0;
  6945.   self.dhmodel = new Wow.HornModel(self, 23, model, self.race, self.gender)
  6946.  },
  6947.  addItem: function(slot, id) {
  6948.   var self = this,
  6949.    Wow = ZamModelViewer.Wow;
  6950.   var item = new Wow.Item(self, slot, id, self.race, self.gender);
  6951.   var uniqueSlot = item.uniqueSlot;
  6952.   var altSlot = Wow.SlotAlternate[slot];
  6953.   if (!self.items[uniqueSlot] || altSlot == 0) {
  6954.    self.items[uniqueSlot] = item
  6955.   } else {
  6956.    item.uniqueSlot = altSlot;
  6957.    self.items[altSlot] = item
  6958.   }
  6959.  },
  6960.  removeSlot: function(slot) {
  6961.   var self = this;
  6962.   if (self.items[slot]) {
  6963.    if (self.items[slot].models) {
  6964.     for (var i = 0; i < self.items[slot].models.length; ++i) {
  6965.      if (self.items[slot].models[i].model) self.items[slot].models[i].model.destroy()
  6966.     }
  6967.    }
  6968.    self.items[slot] = null;
  6969.    delete self.items[slot]
  6970.   }
  6971.  },
  6972.  updateSlotMap: function() {
  6973.   var self = this,
  6974.    i;
  6975.   self.slotAttachments = {};
  6976.   if (self.attachments && self.attachmentLookup) {
  6977.    var slotMap = {
  6978.     1: [11],
  6979.     3: [6, 5],
  6980.     22: [2],
  6981.     21: [1],
  6982.     17: [1],
  6983.     15: [2],
  6984.     25: [1],
  6985.     13: [1],
  6986.     14: [0],
  6987.     23: [2],
  6988.     6: [53],
  6989.     26: [1]
  6990.    };
  6991.    var sheathStandardOverrides = {
  6992.     21: 26,
  6993.     22: 27,
  6994.     15: 28,
  6995.     17: 26,
  6996.     25: 32,
  6997.     13: 32,
  6998.     23: 33,
  6999.     14: 28,
  7000.     26: 26
  7001.    };
  7002.    var SheathWeaponOverrides = {
  7003.     0: {
  7004.      21: 26,
  7005.      22: 27
  7006.     },
  7007.     1: {
  7008.      21: 26,
  7009.      22: 27
  7010.     },
  7011.     2: {
  7012.      21: 30,
  7013.      22: 31
  7014.     },
  7015.     3: {
  7016.      21: 33,
  7017.      22: 32
  7018.     },
  7019.     4: {
  7020.      21: 26,
  7021.      22: 27,
  7022.      15: 28
  7023.     },
  7024.     5: {
  7025.      21: 26
  7026.     },
  7027.     6: {
  7028.      21: 26,
  7029.      22: 27
  7030.     },
  7031.     7: {
  7032.      21: 26,
  7033.      22: 27
  7034.     },
  7035.     8: {
  7036.      21: 26,
  7037.      22: 27
  7038.     }
  7039.    };
  7040.    for (var slot in slotMap) {
  7041.     for (i = 0; i < slotMap[slot].length; ++i) {
  7042.      var att = slotMap[slot][i];
  7043.      if ((self.sheathMain >= 0 || self.sheathOff >= 0 || self.mount) && sheathStandardOverrides[slot]) att = sheathStandardOverrides[slot];
  7044.      if (self.sheathMain >= 0 && slot == 21 && SheathWeaponOverrides[self.sheathMain][slot]) att = SheathWeaponOverrides[self.sheathMain][slot];
  7045.      if (self.sheathOff >= 0 && slot == 22 && SheathWeaponOverrides[self.sheathOff][slot]) att = SheathWeaponOverrides[self.sheathOff][slot];
  7046.      if (att >= self.attachmentLookup.length || self.attachmentLookup[att] == -1) continue;
  7047.      if (!self.slotAttachments[slot]) self.slotAttachments[slot] = [];
  7048.      self.slotAttachments[slot].push(self.attachmentLookup[att])
  7049.     }
  7050.    }
  7051.   }
  7052.  },
  7053.  onLoaded: function() {
  7054.   var self = this,
  7055.    i;
  7056.   if (self.texUnits) {
  7057.    for (i = 0; i < self.texUnits.length; ++i) self.texUnits[i].setup(self);
  7058.    self.sortedTexUnits = self.texUnits.concat();
  7059.    self.sortedTexUnits.sort(function(a, b) {
  7060.     if (a.meshId == b.meshId) return a.meshIndex - b.meshIndex;
  7061.     else return a.meshId - b.meshId
  7062.    })
  7063.   }
  7064.   self.updateSlotMap();
  7065.   if (self.modelPath == 982557) {
  7066.    self.setAnimation("StealthStand")
  7067.   } else if (self.mount) {
  7068.    if (ZamModelViewer.Wow.StandingMounts[self.mount.model.id]) {
  7069.     self.setAnimation("StealthStand")
  7070.    } else {
  7071.     self.setAnimation("Mount")
  7072.    }
  7073.   } else {
  7074.    self.setAnimation("Stand")
  7075.   }
  7076.   self.updateBuffers(true);
  7077.   self.updateBounds();
  7078.   self.setup();
  7079.   self.loaded = true;
  7080.   if (self.isMount && self.parent.loaded) {
  7081.    self.parent.updateBounds()
  7082.   }
  7083.   if (self.parent && self.parent.loaded) {
  7084.    self.parent.updateMeshes()
  7085.   }
  7086.  }
  7087. };
  7088. ZamModelViewer.Wow.ReversedModels = {
  7089.  147259: true
  7090. };
  7091. ZamModelViewer.Wow.ReversedItems = {
  7092.  139260: true,
  7093.  45146: true
  7094. };
  7095. ZamModelViewer.Wow.StandingMounts = {
  7096.  28060: true,
  7097.  28063: true,
  7098.  28082: true,
  7099.  41903: true,
  7100.  42147: true,
  7101.  44808: true,
  7102.  45271: true
  7103. };
  7104. ZamModelViewer.Wow.Types = {
  7105.  ITEM: 1,
  7106.  HELM: 2,
  7107.  SHOULDER: 4,
  7108.  NPC: 8,
  7109.  CHARACTER: 16,
  7110.  HUMANOIDNPC: 32,
  7111.  OBJECT: 64,
  7112.  ARMOR: 128,
  7113.  PATH: 256
  7114. };
  7115. ZamModelViewer.Wow.Classes = {
  7116.  WARRIOR: 1,
  7117.  PALADIN: 2,
  7118.  HUNTER: 3,
  7119.  ROGUE: 4,
  7120.  PRIEST: 5,
  7121.  DEATHKNIGHT: 6,
  7122.  SHAMAN: 7,
  7123.  MAGE: 8,
  7124.  WARLOCK: 9,
  7125.  MONK: 10,
  7126.  DRUID: 11,
  7127.  DEMONHUNTER: 12
  7128. };
  7129. ZamModelViewer.Wow.Genders = {
  7130.  MALE: 0,
  7131.  FEMALE: 1,
  7132.  0: "male",
  7133.  1: "female"
  7134. };
  7135. ZamModelViewer.Wow.Races = {
  7136.  HUMAN: 1,
  7137.  ORC: 2,
  7138.  DWARF: 3,
  7139.  NIGHTELF: 4,
  7140.  SCOURGE: 5,
  7141.  TAUREN: 6,
  7142.  GNOME: 7,
  7143.  TROLL: 8,
  7144.  GOBLIN: 9,
  7145.  BLOODELF: 10,
  7146.  DRAENEI: 11,
  7147.  FELORC: 12,
  7148.  NAGA: 13,
  7149.  BROKEN: 14,
  7150.  SKELETON: 15,
  7151.  VRYKUL: 16,
  7152.  TUSKARR: 17,
  7153.  FORESTTROLL: 18,
  7154.  TAUNKA: 19,
  7155.  NORTHRENDSKELETON: 20,
  7156.  ICETROLL: 21,
  7157.  WORGEN: 22,
  7158.  WORGENHUMAN: 23,
  7159.  PANDAREN: 24,
  7160.  1: "human",
  7161.  2: "orc",
  7162.  3: "dwarf",
  7163.  4: "nightelf",
  7164.  5: "scourge",
  7165.  6: "tauren",
  7166.  7: "gnome",
  7167.  8: "troll",
  7168.  9: "goblin",
  7169.  10: "bloodelf",
  7170.  11: "draenei",
  7171.  12: "felorc",
  7172.  13: "naga_",
  7173.  14: "broken",
  7174.  15: "skeleton",
  7175.  16: "vrykul",
  7176.  17: "tuskarr",
  7177.  18: "foresttroll",
  7178.  19: "taunka",
  7179.  20: "northrendskeleton",
  7180.  21: "icetroll",
  7181.  22: "worgen",
  7182.  23: "human",
  7183.  24: "pandaren",
  7184.  25: "pandaren",
  7185.  26: "pandaren"
  7186. };
  7187. ZamModelViewer.Wow.UniqueSlots = [0, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 21, 22, 22, 16, 21, 0, 19, 5, 21, 22, 22, 0, 21, 21];
  7188. ZamModelViewer.Wow.SlotOrder = [0, 16, 0, 15, 1, 8, 10, 5, 6, 6, 7, 0, 0, 17, 18, 19, 14, 20, 0, 9, 8, 21, 22, 23, 0, 24, 25];
  7189. ZamModelViewer.Wow.SlotAlternate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  7190. ZamModelViewer.Wow.SlotType = [0, 2, 0, 4, 128, 128, 128, 128, 128, 128, 128, 0, 0, 1, 1, 1, 128, 1, 0, 128, 128, 1, 1, 1, 0, 1, 1];
  7191. ZamModelViewer.Wow.Slots = {
  7192.  HEAD: 1,
  7193.  SHOULDER: 3,
  7194.  SHIRT: 4,
  7195.  CHEST: 5,
  7196.  BELT: 6,
  7197.  PANTS: 7,
  7198.  BOOTS: 8,
  7199.  BRACERS: 9,
  7200.  HANDS: 10,
  7201.  ONEHAND: 13,
  7202.  SHIELD: 14,
  7203.  BOW: 15,
  7204.  CAPE: 16,
  7205.  TWOHAND: 17,
  7206.  TABARD: 19,
  7207.  ROBE: 20,
  7208.  RIGHTHAND: 21,
  7209.  LEFTHAND: 22,
  7210.  OFFHAND: 23,
  7211.  THROWN: 25,
  7212.  RANGED: 26
  7213. };
  7214. ZamModelViewer.Wow.Regions = {
  7215.  Base: 0,
  7216.  ArmUpper: 1,
  7217.  ArmLower: 2,
  7218.  Hand: 3,
  7219.  FaceUpper: 4,
  7220.  FaceLower: 5,
  7221.  TorsoUpper: 6,
  7222.  TorsoLower: 7,
  7223.  LegUpper: 8,
  7224.  LegLower: 9,
  7225.  Foot: 10,
  7226.  FaceLower2: 11,
  7227.  old: [{
  7228.   x: 0,
  7229.   y: 0,
  7230.   w: 1,
  7231.   h: 1
  7232.  }, {
  7233.   x: 0,
  7234.   y: 0,
  7235.   w: .5,
  7236.   h: .25
  7237.  }, {
  7238.   x: 0,
  7239.   y: .25,
  7240.   w: .5,
  7241.   h: .25
  7242.  }, {
  7243.   x: 0,
  7244.   y: .5,
  7245.   w: .5,
  7246.   h: .125
  7247.  }, {
  7248.   x: 0,
  7249.   y: .625,
  7250.   w: .5,
  7251.   h: .125
  7252.  }, {
  7253.   x: 0,
  7254.   y: .75,
  7255.   w: .5,
  7256.   h: .25
  7257.  }, {
  7258.   x: .5,
  7259.   y: 0,
  7260.   w: .5,
  7261.   h: .25
  7262.  }, {
  7263.   x: .5,
  7264.   y: .25,
  7265.   w: .5,
  7266.   h: .125
  7267.  }, {
  7268.   x: .5,
  7269.   y: .375,
  7270.   w: .5,
  7271.   h: .25
  7272.  }, {
  7273.   x: .5,
  7274.   y: .625,
  7275.   w: .5,
  7276.   h: .25
  7277.  }, {
  7278.   x: .5,
  7279.   y: .875,
  7280.   w: .5,
  7281.   h: .125
  7282.  }],
  7283.  "new": [{
  7284.   x: 0,
  7285.   y: 0,
  7286.   w: .5,
  7287.   h: 1
  7288.  }, {
  7289.   x: 0,
  7290.   y: 0,
  7291.   w: .25,
  7292.   h: .25
  7293.  }, {
  7294.   x: 0,
  7295.   y: .25,
  7296.   w: .25,
  7297.   h: .25
  7298.  }, {
  7299.   x: 0,
  7300.   y: .5,
  7301.   w: .25,
  7302.   h: .125
  7303.  }, {
  7304.   x: .5,
  7305.   y: 0,
  7306.   w: .5,
  7307.   h: 1
  7308.  }, {
  7309.   x: 0,
  7310.   y: .75,
  7311.   w: .25,
  7312.   h: .25
  7313.  }, {
  7314.   x: .25,
  7315.   y: 0,
  7316.   w: .25,
  7317.   h: .25
  7318.  }, {
  7319.   x: .25,
  7320.   y: .25,
  7321.   w: .25,
  7322.   h: .125
  7323.  }, {
  7324.   x: .25,
  7325.   y: .375,
  7326.   w: .25,
  7327.   h: .25
  7328.  }, {
  7329.   x: .25,
  7330.   y: .625,
  7331.   w: .25,
  7332.   h: .25
  7333.  }, {
  7334.   x: .25,
  7335.   y: .875,
  7336.   w: .25,
  7337.   h: .125
  7338.  }, {
  7339.   x: .5,
  7340.   y: 0,
  7341.   w: .5,
  7342.   h: 1
  7343.  }]
  7344. };
  7345. ZamModelViewer.Wow.Model.prototype.load = function() {
  7346.  var self = this,
  7347.   Type = ZamModelViewer.Wow.Types;
  7348.  if (!self.model || !self.model.type || !self.model.id) return;
  7349.  self._load(self.model.type, self.model.id)
  7350. };
  7351. ZamModelViewer.Wow.Model.prototype._load = function(type, id) {
  7352.  var self = this,
  7353.   Type = ZamModelViewer.Wow.Types,
  7354.   url = null;
  7355.  if (type == Type.ITEM) url = "meta/item/";
  7356.  else if (type == Type.HELM) url = "meta/armor/1/";
  7357.  else if (type == Type.SHOULDER) url = "meta/armor/3/";
  7358.  else if (type == Type.NPC || type == Type.HUMANOIDNPC) url = "meta/npc/";
  7359.  else if (type == Type.OBJECT) url = "meta/object/";
  7360.  else if (type == Type.CHARACTER) url = "meta/character/";
  7361.  if (url) {
  7362.   url = self.opts.contentPath + url + id + ".json";
  7363.   (function(type) {
  7364.    $.getJSON(url, function(data) {
  7365.     self.loadMeta(data, type)
  7366.    })
  7367.   })(type)
  7368.  } else if (type == Type.PATH) {
  7369.   self.modelPath = id;
  7370.   if (!self.meta) self.meta = {};
  7371.   url = self.opts.contentPath + "mo3/" + id + ".mo3";
  7372.   $.ajax({
  7373.    url: url,
  7374.    type: "GET",
  7375.    dataType: "binary",
  7376.    responseType: "arraybuffer",
  7377.    processData: false,
  7378.    renderer: self.renderer,
  7379.    success: function(buffer) {
  7380.     self.loadMo3(buffer)
  7381.    },
  7382.    error: function(xhr, status, error) {
  7383.     console.log(error)
  7384.    }
  7385.   })
  7386.  }
  7387. };
  7388. ZamModelViewer.Wow.Model.prototype.loadMeta = function(meta, type) {
  7389.  var self = this,
  7390.   Type = ZamModelViewer.Wow.Types,
  7391.   model, i;
  7392.  if (!type) type = self.model.type;
  7393.  if (!self.meta) self.meta = meta;
  7394.  if (type == Type.CHARACTER) {
  7395.   model = meta.Model;
  7396.   if (self.opts.hd && meta.HDModel) {
  7397.    model = meta.HDModel;
  7398.    self.isHD = true
  7399.   }
  7400.   if (self.opts.sheathMain) self.sheathMain = self.opts.sheathMain;
  7401.   if (self.opts.sheathOff) self.sheathOff = self.opts.sheathOff;
  7402.   if (self.isHD && self.meta.HDTexture) {
  7403.    self.npcTexture = new self.Texture(self, -1, self.meta.HDTexture)
  7404.   } else if (self.meta.Texture) {
  7405.    self.npcTexture = new self.Texture(self, -1, self.meta.Texture)
  7406.   }
  7407.   self.race = meta.Race;
  7408.   self.gender = meta.Gender;
  7409.   self._load(Type.PATH, model);
  7410.   if (self.opts.cls) self.class = parseInt(self.opts.cls);
  7411.   if (self.meta.DHGeosetsHDModel && self.class == 12) {
  7412.    self.loadDH(self.meta.DHGeosetsHDModel)
  7413.   }
  7414.   if (self.meta.Equipment) {
  7415.    self.loadItems(self.meta.Equipment)
  7416.   }
  7417.   if (self.opts.items) {
  7418.    self.loadItems(self.opts.items)
  7419.   }
  7420.   if (self.model.type != Type.CHARACTER && self.meta.Race > 0) {
  7421.    self.skinIndex = parseInt(self.meta.SkinColor);
  7422.    self.hairIndex = parseInt(self.meta.HairStyle);
  7423.    self.hairColorIndex = parseInt(self.meta.HairColor);
  7424.    self.faceIndex = parseInt(self.meta.FaceType);
  7425.    self.faceFeatureIndex = parseInt(self.meta.FacialHair);
  7426.    self.faceColorIndex = self.hairColorIndex;
  7427.    self.HornsIndex = 0;
  7428.    self.EyePatchIndex = 0;
  7429.    self.TattoosIndex = 0
  7430.   } else {
  7431.    if (self.opts.sk) self.skinIndex = parseInt(self.opts.sk);
  7432.    if (self.opts.ha) self.hairIndex = parseInt(self.opts.ha);
  7433.    if (self.opts.hc) self.hairColorIndex = parseInt(self.opts.hc);
  7434.    if (self.opts.fa) self.faceIndex = parseInt(self.opts.fa);
  7435.    if (self.opts.fh) self.faceFeatureIndex = parseInt(self.opts.fh);
  7436.    if (self.opts.fc) self.faceColorIndex = parseInt(self.opts.fc);
  7437.    if (self.opts.ho) self.HornsIndex = parseInt(self.opts.ho);
  7438.    if (self.opts.ep) self.EyePatchIndex = parseInt(self.opts.ep);
  7439.    if (self.opts.ta) self.TattoosIndex = parseInt(self.opts.ta)
  7440.   }
  7441.  } else if (type == Type.HELM) {
  7442.   var race = 1;
  7443.   var gender = 0;
  7444.   if (self.parent) {
  7445.    race = self.parent.race;
  7446.    gender = self.parent.gender;
  7447.    self.parent.hairVis = meta.ShowHair == 0;
  7448.    self.parent.faceVis = meta.ShowFacial1 == 0
  7449.   }
  7450.   if (meta.RaceModels[gender] && meta.RaceModels[gender][race]) {
  7451.    self._load(Type.PATH, meta.RaceModels[gender][race])
  7452.   }
  7453.   if (meta.Textures) {
  7454.    for (i in meta.Textures) {
  7455.     self.textureOverrides[i] = new self.Texture(self, parseInt(i), meta.Textures[i])
  7456.    }
  7457.   }
  7458.  } else if (type == Type.SHOULDER) {
  7459.   if (self.model.shoulder == 1 || self.model.shoulder === undefined && meta.Model) {
  7460.    if (meta.Model) self._load(Type.PATH, meta.Model);
  7461.    if (meta.Textures) {
  7462.     for (i in meta.Textures) {
  7463.      self.textureOverrides[i] = new self.Texture(self, parseInt(i), meta.Textures[i])
  7464.     }
  7465.    }
  7466.   } else if (self.model.shoulder == 2 || self.model.shoulder === undefined && meta.Model2) {
  7467.    if (meta.Model2) self._load(Type.PATH, meta.Model2);
  7468.    if (meta.Textures2) {
  7469.     for (i in meta.Textures2) {
  7470.      self.textureOverrides[i] = new self.Texture(self, parseInt(i), meta.Textures2[i])
  7471.     }
  7472.    }
  7473.   }
  7474.  } else {
  7475.   if (meta.Textures) {
  7476.    for (i in meta.Textures) {
  7477.     self.textureOverrides[i] = new self.Texture(self, parseInt(i), meta.Textures[i])
  7478.    }
  7479.   } else if (meta.GenderTextures && self.parent) {
  7480.    var g = self.parent.gender;
  7481.    for (i in meta.GenderTextures[g]) {
  7482.     self.textureOverrides[i] = new self.Texture(self, parseInt(i), meta.GenderTextures[g][i])
  7483.    }
  7484.   }
  7485.   if (self.opts.hd && meta.HDModel) {
  7486.    self._load(Type.PATH, meta.HDModel)
  7487.   } else if (meta.Model) {
  7488.    self._load(Type.PATH, meta.Model)
  7489.   } else if (meta.GenderModels && self.parent && meta.GenderModels[self.parent.gender]) {
  7490.    self._load(Type.PATH, meta.GenderModels[self.parent.gender])
  7491.   } else if (meta.Race > 0) {
  7492.    model = ZamModelViewer.Wow.Races[meta.Race] + ZamModelViewer.Wow.Genders[meta.Gender];
  7493.    self.race = meta.Race;
  7494.    self.gender = meta.Gender;
  7495.    self._load(Type.CHARACTER, model)
  7496.   }
  7497.  }
  7498. };
  7499. ZamModelViewer.Wow.Model.prototype.loadMo3 = function(buffer) {
  7500.  if (!buffer) {
  7501.   console.error("Bad buffer for DataView");
  7502.   return
  7503.  }
  7504.  var self = this,
  7505.   r = new ZamModelViewer.DataView(buffer),
  7506.   i, Wow = ZamModelViewer.Wow;
  7507.  var magic = r.getUint32();
  7508.  if (magic != 604210112) {
  7509.   console.log("Bad magic value");
  7510.   return
  7511.  }
  7512.  var version = r.getUint32();
  7513.  if (version < 2e3) {
  7514.   console.log("Bad version");
  7515.   return
  7516.  }
  7517.  var ofsVertices = r.getUint32();
  7518.  var ofsIndices = r.getUint32();
  7519.  var ofsSequences = r.getUint32();
  7520.  var ofsAnimations = r.getUint32();
  7521.  var ofsAnimLookup = r.getUint32();
  7522.  var ofsBones = r.getUint32();
  7523.  var ofsBoneLookup = r.getUint32();
  7524.  var ofsKeyBoneLookup = r.getUint32();
  7525.  var ofsMeshes = r.getUint32();
  7526.  var ofsTexUnits = r.getUint32();
  7527.  var ofsTexUnitLookup = r.getUint32();
  7528.  var ofsRenderFlags = r.getUint32();
  7529.  var ofsMaterials = r.getUint32();
  7530.  var ofsMaterialLookup = r.getUint32();
  7531.  var ofsTextureAnims = r.getUint32();
  7532.  var ofsTexAnimLookup = r.getUint32();
  7533.  var ofsTexReplacements = r.getUint32();
  7534.  var ofsAttachments = r.getUint32();
  7535.  var ofsAttachmentLookup = r.getUint32();
  7536.  var ofsColors = r.getUint32();
  7537.  var ofsAlphas = r.getUint32();
  7538.  var ofsAlphaLookup = r.getUint32();
  7539.  var ofsParticleEmitters = r.getUint32();
  7540.  var ofsRibbonEmitters = r.getUint32();
  7541.  var hasCharData = r.getBool();
  7542.  var ofsSkinColors = r.getUint32();
  7543.  var ofsFaceTypes = r.getUint32();
  7544.  var ofsFacialStyles = r.getUint32();
  7545.  var ofsFacialColors = r.getUint32();
  7546.  var ofsHairStyles = r.getUint32();
  7547.  var ofsHairColors = r.getUint32();
  7548.  var ofsHornStyles = r.getUint32();
  7549.  var ofsBlindfolds = r.getUint32();
  7550.  var ofsColoredHands = r.getUint32();
  7551.  var ofsTattoos = r.getUint32();
  7552.  var uncompressedSize = r.getUint32();
  7553.  var compressedData = new Uint8Array(buffer, r.position);
  7554.  var data = null;
  7555.  try {
  7556.   data = pako.inflate(compressedData)
  7557.  } catch (err) {
  7558.   console.log("Decompression error: " + err);
  7559.   return
  7560.  }
  7561.  if (data.length < uncompressedSize) {
  7562.   console.log("Unexpected data size", data.length, uncompressedSize);
  7563.   return
  7564.  }
  7565.  r = new ZamModelViewer.DataView(data.buffer);
  7566.  r.position = ofsVertices;
  7567.  var numVertices = r.getInt32();
  7568.  if (numVertices > 0) {
  7569.   self.vertices = new Array(numVertices);
  7570.   for (i = 0; i < numVertices; ++i) {
  7571.    self.vertices[i] = new Wow.Vertex(r)
  7572.   }
  7573.  }
  7574.  r.position = ofsIndices;
  7575.  var numIndices = r.getInt32();
  7576.  if (numIndices > 0) {
  7577.   self.indices = new Array(numIndices);
  7578.   for (i = 0; i < numIndices; ++i) {
  7579.    self.indices[i] = r.getUint16()
  7580.   }
  7581.  }
  7582.  r.position = ofsAnimations;
  7583.  var numAnims = r.getInt32();
  7584.  if (numAnims > 0) {
  7585.   self.animations = new Array(numAnims);
  7586.   for (i = 0; i < numAnims; ++i) {
  7587.    self.animations[i] = new Wow.Animation(r)
  7588.   }
  7589.  }
  7590.  r.position = ofsAnimLookup;
  7591.  var numAnimLookup = r.getInt32();
  7592.  if (numAnimLookup > 0) {
  7593.   self.animLookup = new Array(numAnimLookup);
  7594.   for (i = 0; i < numAnimLookup; ++i) {
  7595.    self.animLookup[i] = r.getInt16()
  7596.   }
  7597.  }
  7598.  r.position = ofsBones;
  7599.  var numBones = r.getInt32();
  7600.  if (numBones > 0) {
  7601.   self.bones = new Array(numBones);
  7602.   for (i = 0; i < numBones; ++i) {
  7603.    self.bones[i] = new Wow.Bone(self, i, r)
  7604.   }
  7605.  }
  7606.  r.position = ofsBoneLookup;
  7607.  var numBoneLookup = r.getInt32();
  7608.  if (numBoneLookup > 0) {
  7609.   self.boneLookup = new Array(numBoneLookup);
  7610.   for (i = 0; i < numBoneLookup; ++i) {
  7611.    self.boneLookup[i] = r.getInt16()
  7612.   }
  7613.  }
  7614.  r.position = ofsKeyBoneLookup;
  7615.  var numKeyBoneLookup = r.getInt32();
  7616.  if (numKeyBoneLookup > 0) {
  7617.   self.keyBoneLookup = new Array(numKeyBoneLookup);
  7618.   for (i = 0; i < numKeyBoneLookup; ++i) {
  7619.    self.keyBoneLookup[i] = r.getInt16()
  7620.   }
  7621.  }
  7622.  r.position = ofsMeshes;
  7623.  var numMeshes = r.getInt32();
  7624.  if (numMeshes > 0) {
  7625.   self.meshes = new Array(numMeshes);
  7626.   for (i = 0; i < numMeshes; ++i) {
  7627.    self.meshes[i] = new Wow.Mesh(r)
  7628.   }
  7629.  }
  7630.  r.position = ofsTexUnits;
  7631.  var numTexUnits = r.getInt32();
  7632.  if (numTexUnits > 0) {
  7633.   self.texUnits = new Array(numTexUnits);
  7634.   for (i = 0; i < numTexUnits; ++i) {
  7635.    self.texUnits[i] = new Wow.TexUnit(r)
  7636.   }
  7637.  }
  7638.  r.position = ofsTexUnitLookup;
  7639.  var numTexUnitLookup = r.getInt32();
  7640.  if (numTexUnitLookup > 0) {
  7641.   self.texUnitLookup = new Array(numTexUnitLookup);
  7642.   for (i = 0; i < numTexUnitLookup; ++i) {
  7643.    self.texUnitLookup[i] = r.getInt16()
  7644.   }
  7645.  }
  7646.  r.position = ofsRenderFlags;
  7647.  var numRenderFlags = r.getInt32();
  7648.  if (numRenderFlags > 0) {
  7649.   self.renderFlags = new Array(numRenderFlags);
  7650.   for (i = 0; i < numRenderFlags; ++i) {
  7651.    self.renderFlags[i] = new Wow.RenderFlag(r)
  7652.   }
  7653.  }
  7654.  r.position = ofsMaterials;
  7655.  var numMaterials = r.getInt32();
  7656.  if (numMaterials > 0) {
  7657.   self.materials = new Array(numMaterials);
  7658.   for (i = 0; i < numMaterials; ++i) {
  7659.    self.materials[i] = new Wow.Material(self, i, r)
  7660.   }
  7661.  }
  7662.  r.position = ofsMaterialLookup;
  7663.  var numMaterialLookup = r.getInt32();
  7664.  if (numMaterialLookup > 0) {
  7665.   self.materialLookup = new Array(numMaterialLookup);
  7666.   for (i = 0; i < numMaterialLookup; ++i) {
  7667.    self.materialLookup[i] = r.getInt16()
  7668.   }
  7669.  }
  7670.  r.position = ofsTextureAnims;
  7671.  var numTextureAnims = r.getInt32();
  7672.  if (numTextureAnims > 0) {
  7673.   self.textureAnims = new Array(numTextureAnims);
  7674.   for (i = 0; i < numTextureAnims; ++i) {
  7675.    self.textureAnims[i] = new Wow.TextureAnimation(r)
  7676.   }
  7677.  }
  7678.  r.position = ofsTexAnimLookup;
  7679.  var numTexAnimLookup = r.getInt32();
  7680.  if (numTexAnimLookup > 0) {
  7681.   self.textureAnimLookup = new Array(numTexAnimLookup);
  7682.   for (i = 0; i < numTexAnimLookup; ++i) {
  7683.    self.textureAnimLookup[i] = r.getInt16()
  7684.   }
  7685.  }
  7686.  r.position = ofsTexReplacements;
  7687.  var numTexReplacements = r.getInt32();
  7688.  if (numTexReplacements > 0) {
  7689.   self.textureReplacements = new Array(numTexReplacements);
  7690.   for (i = 0; i < numTexReplacements; ++i) {
  7691.    self.textureReplacements[i] = r.getInt16()
  7692.   }
  7693.  }
  7694.  r.position = ofsAttachments;
  7695.  var numAttachments = r.getInt32();
  7696.  if (numAttachments > 0) {
  7697.   self.attachments = new Array(numAttachments);
  7698.   for (i = 0; i < numAttachments; ++i) {
  7699.    self.attachments[i] = new Wow.Attachment(r)
  7700.   }
  7701.  }
  7702.  r.position = ofsAttachmentLookup;
  7703.  var numAttachmentLookup = r.getInt32();
  7704.  if (numAttachmentLookup > 0) {
  7705.   self.attachmentLookup = new Array(numAttachmentLookup);
  7706.   for (i = 0; i < numAttachmentLookup; ++i) {
  7707.    self.attachmentLookup[i] = r.getInt16()
  7708.   }
  7709.  }
  7710.  r.position = ofsColors;
  7711.  var numColors = r.getInt32();
  7712.  if (numColors > 0) {
  7713.   self.colors = new Array(numColors);
  7714.   for (i = 0; i < numColors; ++i) {
  7715.    self.colors[i] = new Wow.Color(r)
  7716.   }
  7717.  }
  7718.  r.position = ofsAlphas;
  7719.  var numAlphas = r.getInt32();
  7720.  if (numAlphas > 0) {
  7721.   self.alphas = new Array(numAlphas);
  7722.   for (i = 0; i < numAlphas; ++i) {
  7723.    self.alphas[i] = new Wow.Alpha(r)
  7724.   }
  7725.  }
  7726.  r.position = ofsAlphaLookup;
  7727.  var numAlphaLookup = r.getInt32();
  7728.  if (numAlphaLookup > 0) {
  7729.   self.alphaLookup = new Array(numAlphaLookup);
  7730.   for (i = 0; i < numAlphaLookup; ++i) {
  7731.    self.alphaLookup[i] = r.getInt16()
  7732.   }
  7733.  }
  7734.  r.position = ofsParticleEmitters;
  7735.  var numParticleEmitters = r.getInt32();
  7736.  if (numParticleEmitters > 0) {
  7737.   self.particleEmitters = new Array(numParticleEmitters);
  7738.   for (i = 0; i < numParticleEmitters; ++i) {
  7739.    self.particleEmitters[i] = new Wow.ParticleEmitter(self, r)
  7740.   }
  7741.  }
  7742.  r.position = ofsRibbonEmitters;
  7743.  var numRibbonEmitters = r.getInt32();
  7744.  if (numRibbonEmitters > 0) {
  7745.   self.ribbonEmitters = new Array(numRibbonEmitters);
  7746.   for (i = 0; i < numRibbonEmitters; ++i) {
  7747.    self.ribbonEmitters[i] = new Wow.RibbonEmitter(self, r)
  7748.   }
  7749.  }
  7750.  if (hasCharData) {
  7751.   r.position = ofsSkinColors;
  7752.   var numSkinColors = r.getInt32();
  7753.   if (numSkinColors > 0) {
  7754.    self.skins = new Array(numSkinColors);
  7755.    for (i = 0; i < numSkinColors; ++i) {
  7756.     self.skins[i] = new Wow.Skin(r, version)
  7757.    }
  7758.    r.position = ofsFaceTypes;
  7759.    for (i = 0; i < numSkinColors; ++i) {
  7760.     self.skins[i].readFaces(r, version)
  7761.    }
  7762.   }
  7763.   r.position = ofsFacialStyles;
  7764.   var numFaceStyles = r.getInt32();
  7765.   if (numFaceStyles > 0) {
  7766.    self.faces = new Array(numFaceStyles);
  7767.    for (i = 0; i < numFaceStyles; ++i) {
  7768.     self.faces[i] = new Wow.Face(r)
  7769.    }
  7770.    data.position = ofsFacialColors;
  7771.    for (i = 0; i < numFaceStyles; ++i) {
  7772.     self.faces[i].readTextures(r, version)
  7773.    }
  7774.   }
  7775.   r.position = ofsHairStyles;
  7776.   var numHairStyles = r.getInt32();
  7777.   if (numHairStyles > 0) {
  7778.    self.hairs = new Array(numHairStyles);
  7779.    for (i = 0; i < numHairStyles; ++i) {
  7780.     self.hairs[i] = new Wow.Hair(r)
  7781.    }
  7782.    data.position = ofsHairColors;
  7783.    for (i = 0; i < numHairStyles; ++i) {
  7784.     self.hairs[i].readTextures(r, version)
  7785.    }
  7786.   }
  7787.   r.position = ofsHornStyles;
  7788.   var numHorns = r.getInt32();
  7789.   if (numHorns > 0) {
  7790.    self.horns = new Array(numHorns);
  7791.    for (i = 0; i < numHorns; ++i) {
  7792.     self.horns[i] = new Wow.Horns(r)
  7793.    }
  7794.   }
  7795.   r.position = ofsBlindfolds;
  7796.   var numBlindfolds = r.getInt32();
  7797.   if (numBlindfolds > 0) {
  7798.    self.blindFolds = new Array(numBlindfolds);
  7799.    for (i = 0; i < numBlindfolds; ++i) {
  7800.     self.blindFolds[i] = new Wow.Blindfolds(r)
  7801.    }
  7802.   }
  7803.   r.position = ofsColoredHands;
  7804.   var numColoredHands = r.getInt32();
  7805.   if (numColoredHands > 0) {
  7806.    self.coloredHands = new Array(numColoredHands);
  7807.    for (i = 0; i < numColoredHands; ++i) {
  7808.     self.coloredHands[i] = new Wow.ColoredHands(r)
  7809.    }
  7810.   }
  7811.   r.position = ofsTattoos;
  7812.   var numTattoos = r.getInt32();
  7813.   if (numTattoos > 0) {
  7814.    self.tattoos = new Array(numTattoos);
  7815.    for (i = 0; i < numTattoos; ++i) {
  7816.     self.tattoos[i] = new Wow.Tattoos(r)
  7817.    }
  7818.   }
  7819.  }
  7820.  self.onLoaded()
  7821. };
  7822. ZamModelViewer.Wow.Model.prototype.update = function() {
  7823.  var self = this,
  7824.   i, j;
  7825.  if (!self.loaded || !self.texUnits) return;
  7826.  self.frame++;
  7827.  self.time = self.renderer.time;
  7828.  if (self.animationList && self.animationList.length > 0) {
  7829.   if (self.animStartTime == 0) self.animStartTime = self.time;
  7830.   if (self.time - self.animStartTime >= self.currentAnimation.length) {
  7831.    var nextAnim = Math.max(0, Math.randomInt(0, self.animationList.length + 3) - 3);
  7832.    self.currentAnimation = self.animationList[nextAnim];
  7833.    self.animStartTime = self.time
  7834.   }
  7835.  }
  7836.  var numUnits = self.texUnits.length,
  7837.   count, start, u;
  7838.  for (i = 0; i < numUnits; ++i) {
  7839.   u = self.texUnits[i];
  7840.   if (!u.show) continue;
  7841.   count = u.mesh.indexCount;
  7842.   start = u.mesh.indexStart;
  7843.   for (j = 0; j < count; ++j) self.vertices[self.indices[start + j]].frame = self.frame
  7844.  }
  7845.  var numBones = self.bones.length,
  7846.   animTime = self.time - self.animStartTime,
  7847.   vb = self.vbData;
  7848.  if (self.bones && self.animations) {
  7849.   for (i = 0; i < numBones; ++i) self.bones[i].updated = false;
  7850.   for (i = 0; i < numBones; ++i) self.bones[i].update(animTime);
  7851.   if (self.vertices) {
  7852.    var numVerts = self.vertices.length,
  7853.     v, b, w, idx, tmpVec3 = self.tmpVec3,
  7854.     tmpVec4 = self.tmpVec4;
  7855.    for (i = 0; i < numVerts; ++i) {
  7856.     v = self.vertices[i];
  7857.     if (v.frame != self.frame) continue;
  7858.     idx = i * 8;
  7859.     vb[idx] = vb[idx + 1] = vb[idx + 2] = vb[idx + 3] = vb[idx + 4] = vb[idx + 5] = 0;
  7860.     for (j = 0; j < 4; ++j) {
  7861.      w = v.weights[j] / 255;
  7862.      if (w > 0) {
  7863.       b = self.bones[v.bones[j]];
  7864.       vec3.transformMat4(tmpVec3, v.position, b.matrix);
  7865.       vec4.transformMat4(tmpVec4, v.normal, b.matrix);
  7866.       vb[idx + 0] += tmpVec3[0] * w;
  7867.       vb[idx + 1] += tmpVec3[1] * w;
  7868.       vb[idx + 2] += tmpVec3[2] * w;
  7869.       vb[idx + 3] += tmpVec4[0] * w;
  7870.       vb[idx + 4] += tmpVec4[1] * w;
  7871.       vb[idx + 5] += tmpVec4[2] * w
  7872.      }
  7873.     }
  7874.     v.transPosition[0] = vb[idx + 0];
  7875.     v.transPosition[1] = vb[idx + 1];
  7876.     v.transPosition[2] = vb[idx + 2];
  7877.     v.transNormal[0] = vb[idx + 3];
  7878.     v.transNormal[1] = vb[idx + 4];
  7879.     v.transNormal[2] = vb[idx + 5]
  7880.    }
  7881.    self.updateBuffers(false);
  7882.    if (!self.animBounds) {
  7883.     self.animBounds = true;
  7884.     self.updateBounds()
  7885.    }
  7886.   }
  7887.  }
  7888. };
  7889. ZamModelViewer.Wow.Model.prototype.draw = function(flipWinding) {
  7890.  var self = this,
  7891.   gl = self.renderer.context,
  7892.   i, Wow = ZamModelViewer.Wow,
  7893.   Races = Wow.Races,
  7894.   Genders = Wow.Genders;
  7895.  if (self.mount) {
  7896.   self.mount.draw();
  7897.   if (self.mount.loaded) {
  7898.    var attach = self.mount.attachments[self.mount.attachmentLookup[0]];
  7899.    var scale = 1 / self.mount.meta.Scale;
  7900.    vec3.set(self.tmpVec, scale, scale, scale);
  7901.    mat4.identity(self.tmpMat);
  7902.    mat4.scale(self.tmpMat, self.tmpMat, self.tmpVec);
  7903.    self.setMatrix(self.mount.matrix, self.mount.bones[attach.bone].matrix, attach.position, self.tmpMat)
  7904.   }
  7905.  }
  7906.  var upsideDown = Wow.ReversedModels[self.model.id];
  7907.  if (upsideDown && !self.parent) {
  7908.   mat4.identity(self.matrix);
  7909.   vec3.set(self.tmpVec, 1, 1, -1);
  7910.   mat4.scale(self.matrix, self.matrix, self.tmpVec);
  7911.   flipWinding = true
  7912.  }
  7913.  if (self.meta && self.meta.ItemClass == 2 && (self.meta.ItemSubClass == 13 || self.meta.ItemSubClass == 9) && !self.parent) {
  7914.   mat4.identity(self.matrix);
  7915.   vec3.set(self.tmpVec, 1, -1, 1);
  7916.   mat4.scale(self.matrix, self.matrix, self.tmpVec);
  7917.   flipWinding = true
  7918.  }
  7919.  if (!self.loaded || !self.texUnits) return;
  7920.  self.update();
  7921.  if (!self.shaderReady) self.initShader();
  7922.  if (!self.program) return;
  7923.  if (self.needsCompositing) self.compositeTextures();
  7924.  gl.useProgram(self.program);
  7925.  gl.uniformMatrix4fv(self.uniforms.vModelMatrix, false, self.matrix);
  7926.  gl.uniformMatrix4fv(self.uniforms.vViewMatrix, false, self.renderer.viewMatrix);
  7927.  gl.uniformMatrix4fv(self.uniforms.vProjMatrix, false, self.renderer.projMatrix);
  7928.  gl.uniform3fv(self.uniforms.vCameraPos, self.renderer.eye);
  7929.  gl.uniform4fv(self.uniforms.fAmbientColor, self.ambientColor);
  7930.  gl.uniform4fv(self.uniforms.fPrimaryColor, self.primaryColor);
  7931.  gl.uniform4fv(self.uniforms.fSecondaryColor, self.secondaryColor);
  7932.  gl.uniform3fv(self.uniforms.fLightDir1, self.lightDir1);
  7933.  gl.uniform3fv(self.uniforms.fLightDir2, self.lightDir2);
  7934.  gl.uniform3fv(self.uniforms.fLightDir3, self.lightDir3);
  7935.  gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  7936.  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  7937.  for (i in self.attribs) {
  7938.   var a = self.attribs[i];
  7939.   gl.enableVertexAttribArray(a.loc);
  7940.   gl.vertexAttribPointer(a.loc, a.size, a.type, false, a.stride, a.offset)
  7941.  }
  7942.  if (flipWinding) gl.frontFace(gl.CW);
  7943.  for (i = 0; i < self.sortedTexUnits.length; ++i) {
  7944.   if (!self.sortedTexUnits[i].show) continue;
  7945.   self.sortedTexUnits[i].draw()
  7946.  }
  7947.  if (flipWinding) gl.frontFace(gl.CCW);
  7948.  if (self.dhmodel) {
  7949.   var item = self.dhmodel;
  7950.   if (item.models) {
  7951.    for (var j = 0; j < item.models.length; ++j) {
  7952.     if (item.models[j].model && item.models[j].bone > -1 && item.models[j].bone < self.bones.length) {
  7953.      mat4.identity(self.tmpMat);
  7954.      if (self.dhmodel.models[j].model.slot == 6 && !(self.gender == Genders.MALE && self.race == Races.NIGHTELF && self.isHD)) {
  7955.       mat4.identity(self.tmpMat);
  7956.       if (self.gender == Genders.FEMALE && self.race == Races.NIGHTELF) vec3.set(self.tmpVec, 1.3, 1.3, 1.3);
  7957.       if (self.gender == Genders.FEMALE && self.race == Races.BLOODELF) vec3.set(self.tmpVec, 1.55, 1.55, 1.55);
  7958.       if (self.gender == Genders.MALE && self.race == Races.BLOODELF) vec3.set(self.tmpVec, 1.3, 1.3, 1.3);
  7959.       if (self.gender == Genders.MALE && self.race == Races.NIGHTELF) vec3.set(self.tmpVec, 1.15, 1.15, 1.15);
  7960.       mat4.scale(self.tmpMat, self.tmpMat, self.tmpVec)
  7961.      }
  7962.      item.models[j].model.setMatrix(self.matrix, self.bones[item.models[j].bone].matrix, item.models[j].attachment.position, self.tmpMat);
  7963.      item.models[j].model.update();
  7964.      item.models[j].model.draw(winding)
  7965.     }
  7966.    }
  7967.   }
  7968.  }
  7969.  for (i in self.items) {
  7970.   var item = self.items[i];
  7971.   if (!item.models) continue;
  7972.   for (var j = 0; j < item.models.length; ++j) {
  7973.    if (item.models[j].model && item.models[j].bone > -1 && item.models[j].bone < self.bones.length) {
  7974.     var winding = false,
  7975.      reversed = item.models[j].model.model.type == Wow.Types.ITEM && Wow.ReversedItems[item.models[j].model.model.id];
  7976.     var upsideDown = Wow.ReversedModels[item.models[j].model.model.id];
  7977.     if (j == 1 && item.models[j].model.model.type == Wow.Types.SHOULDER) reversed = true;
  7978.     if (upsideDown) {
  7979.      mat4.identity(self.tmpMat);
  7980.      vec3.set(self.tmpVec, 1, 1, -1);
  7981.      mat4.scale(self.tmpMat, self.tmpMat, self.tmpVec);
  7982.      winding = true
  7983.     } else if (reversed && item.slot != Wow.Slots.LEFTHAND || !reversed && item.slot == Wow.Slots.LEFTHAND) {
  7984.      mat4.identity(self.tmpMat);
  7985.      vec3.set(self.tmpVec, 1, -1, 1);
  7986.      mat4.scale(self.tmpMat, self.tmpMat, self.tmpVec);
  7987.      winding = true
  7988.     } else {
  7989.      mat4.identity(self.tmpMat)
  7990.     }
  7991.     item.models[j].model.setMatrix(self.matrix, self.bones[item.models[j].bone].matrix, item.models[j].attachment.position, self.tmpMat);
  7992.     item.models[j].model.update();
  7993.     item.models[j].model.draw(winding)
  7994.    }
  7995.   }
  7996.  }
  7997.  if (self.particleEmitters) {
  7998.   for (i = 0; i < self.particleEmitters.length; ++i) {
  7999.    self.particleEmitters[i].update(self.currentAnimation.index, self.time, self.renderer.delta);
  8000.    self.particleEmitters[i].draw()
  8001.   }
  8002.  }
  8003.  if (self.ribbonEmitters) {
  8004.   for (i = 0; i < self.ribbonEmitters.length; ++i) {
  8005.    self.ribbonEmitters[i].update(self.currentAnimation.index, self.time);
  8006.    self.ribbonEmitters[i].draw()
  8007.   }
  8008.  }
  8009.  for (i in self.attribs) {
  8010.   gl.disableVertexAttribArray(self.attribs[i].loc)
  8011.  }
  8012. };
  8013. ZamModelViewer.Wow.Model.prototype.initShader = function() {
  8014.  var self = this,
  8015.   gl = self.renderer.context;
  8016.  self.shaderReady = true;
  8017.  var vs = self.renderer.compileShader(gl.VERTEX_SHADER, self.vertShader);
  8018.  var fs = self.renderer.compileShader(gl.FRAGMENT_SHADER, self.fragShader);
  8019.  var program = gl.createProgram();
  8020.  gl.attachShader(program, vs);
  8021.  gl.attachShader(program, fs);
  8022.  gl.linkProgram(program);
  8023.  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  8024.   console.error("Error linking shaders");
  8025.   return
  8026.  }
  8027.  self.vs = vs;
  8028.  self.fs = fs;
  8029.  self.program = program;
  8030.  self.uniforms = {
  8031.   vModelMatrix: gl.getUniformLocation(program, "uModelMatrix"),
  8032.   vViewMatrix: gl.getUniformLocation(program, "uViewMatrix"),
  8033.   vProjMatrix: gl.getUniformLocation(program, "uProjMatrix"),
  8034.   vCameraPos: gl.getUniformLocation(program, "uCameraPos"),
  8035.   vTextureMatrix: gl.getUniformLocation(program, "uTextureMatrix"),
  8036.   vTextureMatrix2: gl.getUniformLocation(program, "uTextureMatrix2"),
  8037.   vTextureMatrix3: gl.getUniformLocation(program, "uTextureMatrix3"),
  8038.   vTextureMatrix3: gl.getUniformLocation(program, "uTextureMatrix4"),
  8039.   fHasTexture: gl.getUniformLocation(program, "uHasTexture"),
  8040.   fHasTexture2: gl.getUniformLocation(program, "uHasTexture2"),
  8041.   fHasTexture3: gl.getUniformLocation(program, "uHasTexture3"),
  8042.   fHasTexture3: gl.getUniformLocation(program, "uHasTexture4"),
  8043.   fHasAlpha: gl.getUniformLocation(program, "uHasAlpha"),
  8044.   fBlendMode: gl.getUniformLocation(program, "uBlendMode"),
  8045.   fUnlit: gl.getUniformLocation(program, "uUnlit"),
  8046.   fColor: gl.getUniformLocation(program, "uColor"),
  8047.   fAmbientColor: gl.getUniformLocation(program, "uAmbientColor"),
  8048.   fPrimaryColor: gl.getUniformLocation(program, "uPrimaryColor"),
  8049.   fSecondaryColor: gl.getUniformLocation(program, "uSecondaryColor"),
  8050.   fLightDir1: gl.getUniformLocation(program, "uLightDir1"),
  8051.   fLightDir2: gl.getUniformLocation(program, "uLightDir2"),
  8052.   fLightDir3: gl.getUniformLocation(program, "uLightDir3"),
  8053.   fTexture: gl.getUniformLocation(program, "uTexture"),
  8054.   fTexture2: gl.getUniformLocation(program, "uTexture2"),
  8055.   fTexture3: gl.getUniformLocation(program, "uTexture3"),
  8056.   fTexture3: gl.getUniformLocation(program, "uTexture4"),
  8057.   fAlpha: gl.getUniformLocation(program, "uAlpha")
  8058.  };
  8059.  self.attribs = {
  8060.   position: {
  8061.    loc: gl.getAttribLocation(program, "aPosition"),
  8062.    type: gl.FLOAT,
  8063.    size: 3,
  8064.    offset: 0,
  8065.    stride: 32
  8066.   },
  8067.   normal: {
  8068.    loc: gl.getAttribLocation(program, "aNormal"),
  8069.    type: gl.FLOAT,
  8070.    size: 3,
  8071.    offset: 12,
  8072.    stride: 32
  8073.   },
  8074.   texcoord: {
  8075.    loc: gl.getAttribLocation(program, "aTexCoord"),
  8076.    type: gl.FLOAT,
  8077.    size: 2,
  8078.    offset: 24,
  8079.    stride: 32
  8080.   }
  8081.  }
  8082. };
  8083. ZamModelViewer.Wow.Model.prototype.vertShader = "    attribute vec3 aPosition;    attribute vec3 aNormal;    attribute vec2 aTexCoord;        varying vec3 vNormal;    varying vec2 vTexCoord;    varying vec2 vTexCoord2;    varying vec2 vTexCoord3;    varying vec2 vTexCoord4;        uniform mat4 uModelMatrix;    uniform mat4 uPanningMatrix;    uniform mat4 uViewMatrix;    uniform mat4 uProjMatrix;    uniform mat4 uTextureMatrix;    uniform mat4 uTextureMatrix2;    uniform mat4 uTextureMatrix3;    uniform mat4 uTextureMatrix4;    uniform vec3 uCameraPos;    uniform bool uHasTexture;    uniform bool uHasTexture2;    uniform bool uHasTexture3;    uniform bool uHasTexture4;        void main(void) {        gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition, 1);                if(uHasTexture) vTexCoord = (uTextureMatrix * vec4(aTexCoord, 0, 1)).st;        if(uHasTexture2)  vTexCoord2 = (uTextureMatrix2 * vec4(aTexCoord, 0, 1)).st;        if(uHasTexture3) vTexCoord3 = (uTextureMatrix3 * vec4(aTexCoord, 0, 1)).st;        if(uHasTexture4) vTexCoord4 = (uTextureMatrix4 * vec4(aTexCoord, 0, 1)).st;        vNormal = mat3(uViewMatrix * uModelMatrix) * aNormal;    }";
  8084. ZamModelViewer.Wow.Model.prototype.fragShader = "    precision mediump float;        varying vec3 vNormal;    varying vec2 vTexCoord;    varying vec2 vTexCoord2;    varying vec2 vTexCoord3;    varying vec2 vTexCoord4;        uniform bool uHasTexture;    uniform bool uHasTexture2;    uniform bool uHasTexture3;    uniform bool uHasTexture4;    uniform bool uHasAlpha;    uniform int uBlendMode;    uniform bool uUnlit;    uniform vec4 uColor;    uniform vec4 uAmbientColor;    uniform vec4 uPrimaryColor;    uniform vec4 uSecondaryColor;    uniform vec3 uLightDir1;    uniform vec3 uLightDir2;    uniform vec3 uLightDir3;    uniform sampler2D uTexture;    uniform sampler2D uTexture2;    uniform sampler2D uTexture3;    uniform sampler2D uTexture4;    uniform sampler2D uAlpha;        void main(void) {        vec4 color = vec4(1, 1, 1, 1);        if (uHasTexture) {            color = texture2D(uTexture, vTexCoord.st);        }        if (uHasTexture2) {            color *= texture2D(uTexture2, vTexCoord2.st);        }        if (uHasTexture3) {            color *= texture2D(uTexture3, vTexCoord3.st);        }        if (uHasTexture4) {            color *= texture2D(uTexture4, vTexCoord4.st);        }                if (uBlendMode == 7) {            vec4 color2 = vec4(4, 4, 4, 4);            color *= color2;        }        if ((uBlendMode == 1 || uBlendMode == 2 || uBlendMode == 4 || uBlendMode == 7) && uHasAlpha) {            color.a = texture2D(uAlpha, vTexCoord.st).a;        }                color *= uColor;                if (uBlendMode == 1) {            if (color.a < 0.7) {                discard;            }        }                if (!uUnlit) {            vec4 litColor = uAmbientColor;            vec3 normal = normalize(vNormal);                        float dp = max(0.0, dot(normal, uLightDir1));            litColor += uPrimaryColor * dp;                        dp = max(0.0, dot(normal, uLightDir2));            litColor += uSecondaryColor * dp;                        dp = max(0.0, dot(normal, uLightDir3));            litColor += uSecondaryColor * dp;                        litColor = clamp(litColor, vec4(0,0,0,0), vec4(1,1,1,1));            color *= litColor;        }                gl_FragColor = color;    }";
  8085. ZamModelViewer.Wow.Model.prototype.destroy = function() {
  8086.  var self = this;
  8087.  if (!self.renderer) return;
  8088.  var gl = self.renderer.context,
  8089.   i, j;
  8090.  if (self.program) gl.deleteProgram(self.program);
  8091.  if (self.vs) gl.deleteShader(self.vs);
  8092.  if (self.fs) gl.deleteShader(self.fs);
  8093.  if (self.vb) gl.deleteBuffer(self.vb);
  8094.  if (self.ib) gl.deleteBuffer(self.ib);
  8095.  self.program = null;
  8096.  self.vs = null;
  8097.  self.fs = null;
  8098.  self.vb = null;
  8099.  self.ib = null;
  8100.  self.vbData = null;
  8101.  self.uniforms = null;
  8102.  self.attribs = null;
  8103.  if (self.compositeTexture) gl.deleteTexture(self.compositeTexture);
  8104.  if (self.npcTexture) self.npcTexture.destroy();
  8105.  if (self.bakedTextures) {
  8106.   for (i = 0; i < 11; ++i) {
  8107.    for (j in self.bakedTextures[i]) {
  8108.     self.bakedTextures[i][j].destroy()
  8109.    }
  8110.   }
  8111.  }
  8112.  if (self.specialTextures) {
  8113.   for (i in self.specialTextures) {
  8114.    self.specialTextures[i].destroy()
  8115.   }
  8116.  }
  8117.  if (self.textureOverrides) {
  8118.   for (i in self.textureOverrides) {
  8119.    self.textureOverrides[i].destroy()
  8120.   }
  8121.  }
  8122.  if (self.indices) self.indices = null;
  8123.  if (self.animLookup) self.animLookup = null;
  8124.  if (self.boneLookup) self.boneLookup = null;
  8125.  if (self.keyBoneLookup) self.keyBoneLookup = null;
  8126.  if (self.texUnitLookup) self.texUnitLookup = null;
  8127.  if (self.materialLookup) self.materialLookup = null;
  8128.  if (self.textureAnimLookup) self.textureAnimLookup = null;
  8129.  if (self.textureReplacements) self.textureReplacements = null;
  8130.  if (self.attachmentLookup) self.attachmentLookup = null;
  8131.  if (self.alphaLookup) self.alphaLookup = null;
  8132.  if (self.renderFlags)
  8133.   for (i = 0; i < self.renderFlags.length; ++i) self.renderFlags[i] = null;
  8134.  self.renderFlags = null;
  8135.  var destroyArray = function(key) {
  8136.   if (self[key]) {
  8137.    var arr = self[key];
  8138.    for (var i = 0; i < arr.length; ++i) {
  8139.     if (arr[i] && arr[i].destroy) arr[i].destroy();
  8140.     arr[i] = null
  8141.    }
  8142.    self[key] = null
  8143.   }
  8144.  };
  8145.  destroyArray("vertices");
  8146.  destroyArray("animations");
  8147.  destroyArray("bones");
  8148.  destroyArray("meshes");
  8149.  destroyArray("texUnits");
  8150.  destroyArray("materials");
  8151.  destroyArray("textureAnims");
  8152.  destroyArray("attachments");
  8153.  destroyArray("colors");
  8154.  destroyArray("alphas");
  8155.  destroyArray("particleEmitters");
  8156.  destroyArray("ribbonEmitters");
  8157.  destroyArray("skins");
  8158.  destroyArray("faces");
  8159.  destroyArray("hairs");
  8160.  if (self.items) {
  8161.   for (i in self.items) {
  8162.    self.items[i].destroy();
  8163.    self.items[i] = null
  8164.   }
  8165.  }
  8166.  if (self.dhmodel) {
  8167.   self.dhmodel.destroy();
  8168.   self.dhmodel = null
  8169.  }
  8170.  if (self.mount) self.mount.destroy();
  8171.  self.mount = null;
  8172.  self.renderer = null;
  8173.  self.viewer = null;
  8174.  self.model = null;
  8175.  self.items = null;
  8176.  self.textureOverrides = null;
  8177.  self.specialTextures = null;
  8178.  self.bakedTextures = null;
  8179.  self.geosets = null;
  8180.  self.slotAttachments = null;
  8181.  self.matrix = null;
  8182.  self.ambientColor = null;
  8183.  self.primaryColor = null;
  8184.  self.secondaryColor = null;
  8185.  self.lightDir1 = null;
  8186.  self.lightDir2 = null;
  8187.  self.lightDir3 = null;
  8188.  self.boundsMin = null;
  8189.  self.boundsMax = null;
  8190.  self.boundsCenter = null;
  8191.  self.boundsSize = null;
  8192.  self.tmpMat = null;
  8193.  self.tmpVec = null;
  8194.  self.tmpVec2 = null;
  8195.  self.tmpVec3 = null;
  8196.  self.tmpVec4 = null;
  8197.  self.mountMat = null
  8198. };
  8199. (function() {
  8200.  ZamModelViewer.Wow.Animated = function() {};
  8201.  ZamModelViewer.Wow.Animated.prototype = {
  8202.   destroy: function() {
  8203.    var self = this;
  8204.    if (self.data)
  8205.     for (var i = 0; i < self.data.length; ++i) self.data[i] = null;
  8206.    self.times = null;
  8207.    self.data = null;
  8208.    return null
  8209.   },
  8210.   createValue: function() {
  8211.    return this.defaultValue
  8212.   },
  8213.   defaultValue: 0,
  8214.   setDefault: function(v) {
  8215.    this.defaultValue = v
  8216.   },
  8217.   interpolate: function(v1, v2, r, result) {
  8218.    result = v1 + (v2 - v1) * r;
  8219.    return result
  8220.   },
  8221.   set: function(result, value) {
  8222.    result = value;
  8223.    return result
  8224.   },
  8225.   getDefault: function(r) {
  8226.    r = this.defaultValue;
  8227.    return r
  8228.   },
  8229.   readValue: function(r) {
  8230.    return r.getInt32()
  8231.   },
  8232.   getValue: function(time, result) {
  8233.    var self = this;
  8234.    if (result === undefined) result = self.createValue();
  8235.    else result = self.getDefault(result);
  8236.    if (self.type != 0 || self.data.length > 1) {
  8237.     if (self.times.length > 1) {
  8238.      var maxTime = self.times[self.times.length - 1];
  8239.      if (maxTime > 0 && time > maxTime) time %= maxTime;
  8240.      var idx = 0,
  8241.       numTimes = self.times.length;
  8242.      for (var i = 0; i < numTimes; ++i) {
  8243.       if (time >= self.times[i] && time < self.times[i + 1]) {
  8244.        idx = i;
  8245.        break
  8246.       }
  8247.      }
  8248.      var t1 = self.times[idx],
  8249.       t2 = self.times[idx + 1],
  8250.       r = 0;
  8251.      if (t1 != t2) r = (time - t1) / (t2 - t1);
  8252.      if (self.type == 1) return self.interpolate(self.data[idx], self.data[idx + 1], r, result);
  8253.      else {
  8254.       result = self.set(result, self.data[idx]);
  8255.       return result
  8256.      }
  8257.     } else if (self.data.length > 0) {
  8258.      result = self.set(result, self.data[0]);
  8259.      return result
  8260.     } else {
  8261.      return result
  8262.     }
  8263.    } else {
  8264.     if (self.data.length == 0) return result;
  8265.     else {
  8266.      result = self.set(result, self.data[0]);
  8267.      return result
  8268.     }
  8269.    }
  8270.   },
  8271.   read: function(r) {
  8272.    var self = this,
  8273.     i;
  8274.    self.type = r.getInt16();
  8275.    self.seq = r.getInt16();
  8276.    self.used = r.getBool();
  8277.    var numTimes = r.getInt32();
  8278.    self.times = new Array(numTimes);
  8279.    for (i = 0; i < numTimes; ++i) {
  8280.     self.times[i] = r.getInt32()
  8281.    }
  8282.    var numData = r.getInt32();
  8283.    self.data = new Array(numData);
  8284.    for (i = 0; i < numData; ++i) {
  8285.     self.data[i] = self.readValue(r)
  8286.    }
  8287.   }
  8288.  };
  8289.  ZamModelViewer.Wow.Animated.destroySet = function(dataset) {
  8290.   if (!dataset || dataset.length == 0) return;
  8291.   for (var i = 0; i < dataset.length; ++i) {
  8292.    dataset[i].destroy();
  8293.    dataset[i] = null
  8294.   }
  8295.   return null
  8296.  };
  8297.  ZamModelViewer.Wow.Animated.getValue = function(type, dataset, anim, time, result) {
  8298.   if (!result) result = type.createValue();
  8299.   else result = type.getDefault(result);
  8300.   if (!dataset || dataset.length == 0) return result;
  8301.   if (anim >= dataset.length) anim = 0;
  8302.   return dataset[anim].getValue(time, result)
  8303.  };
  8304.  ZamModelViewer.Wow.Animated.isUsed = function(dataset, anim) {
  8305.   if (!dataset || dataset.length == 0) return false;
  8306.   if (anim >= dataset.length) anim = 0;
  8307.   return dataset[anim].used
  8308.  };
  8309.  ZamModelViewer.Wow.AnimatedVec3 = function(r) {
  8310.   var self = this;
  8311.   self.read(r)
  8312.  };
  8313.  ZamModelViewer.Wow.AnimatedVec3.prototype = new ZamModelViewer.Wow.Animated;
  8314.  ZamModelViewer.Wow.AnimatedVec3.prototype.constructor = ZamModelViewer.Wow.AnimatedVec3;
  8315.  ZamModelViewer.Wow.AnimatedVec3.prototype.createValue = function() {
  8316.   return vec3.clone(this.defaultValue)
  8317.  };
  8318.  ZamModelViewer.Wow.AnimatedVec3.prototype.defaultValue = vec3.create();
  8319.  ZamModelViewer.Wow.AnimatedVec3.prototype.getDefault = function(result) {
  8320.   vec3.copy(result, this.defaultValue);
  8321.   return result
  8322.  };
  8323.  ZamModelViewer.Wow.AnimatedVec3.prototype.interpolate = function(v1, v2, r, result) {
  8324.   return vec3.lerp(result, v1, v2, r)
  8325.  };
  8326.  ZamModelViewer.Wow.AnimatedVec3.prototype.set = function(result, value) {
  8327.   result[0] = value[0];
  8328.   result[1] = value[1];
  8329.   result[2] = value[2]
  8330.  };
  8331.  ZamModelViewer.Wow.AnimatedVec3.prototype.readValue = function(r) {
  8332.   return vec3.set(vec3.create(), r.getFloat(), r.getFloat(), r.getFloat())
  8333.  };
  8334.  ZamModelViewer.Wow.AnimatedVec3.getValue = function(dataset, anim, time, result) {
  8335.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.AnimatedVec3.prototype, dataset, anim, time, result)
  8336.  };
  8337.  ZamModelViewer.Wow.AnimatedVec3.readSet = function(r) {
  8338.   var count = r.getInt32();
  8339.   var data = new Array(count);
  8340.   for (var i = 0; i < count; ++i) data[i] = new ZamModelViewer.Wow.AnimatedVec3(r);
  8341.   return data
  8342.  };
  8343.  ZamModelViewer.Wow.AnimatedQuat = function(r) {
  8344.   var self = this;
  8345.   self.read(r)
  8346.  };
  8347.  ZamModelViewer.Wow.AnimatedQuat.prototype = new ZamModelViewer.Wow.Animated;
  8348.  ZamModelViewer.Wow.AnimatedQuat.prototype.constructor = ZamModelViewer.Wow.AnimatedQuat;
  8349.  ZamModelViewer.Wow.AnimatedQuat.prototype.createValue = function() {
  8350.   return quat.clone(this.defaultValue)
  8351.  };
  8352.  ZamModelViewer.Wow.AnimatedQuat.prototype.defaultValue = quat.create();
  8353.  ZamModelViewer.Wow.AnimatedQuat.prototype.getDefault = function(result) {
  8354.   quat.copy(result, this.defaultValue);
  8355.   return result
  8356.  };
  8357.  ZamModelViewer.Wow.AnimatedQuat.prototype.interpolate = function(v1, v2, r, result) {
  8358.   return quat.slerp(result, v1, v2, r)
  8359.  };
  8360.  ZamModelViewer.Wow.AnimatedQuat.prototype.set = function(result, value) {
  8361.   result[0] = value[0];
  8362.   result[1] = value[1];
  8363.   result[2] = value[2];
  8364.   result[3] = value[3]
  8365.  };
  8366.  ZamModelViewer.Wow.AnimatedQuat.prototype.readValue = function(r) {
  8367.   return quat.set(quat.create(), r.getFloat(), r.getFloat(), r.getFloat(), r.getFloat())
  8368.  };
  8369.  ZamModelViewer.Wow.AnimatedQuat.getValue = function(dataset, anim, time, result) {
  8370.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.AnimatedQuat.prototype, dataset, anim, time, result)
  8371.  };
  8372.  ZamModelViewer.Wow.AnimatedUint16 = function(r) {
  8373.   var self = this;
  8374.   self.read(r)
  8375.  };
  8376.  ZamModelViewer.Wow.AnimatedUint16.prototype = new ZamModelViewer.Wow.Animated;
  8377.  ZamModelViewer.Wow.AnimatedUint16.prototype.constructor = ZamModelViewer.Wow.AnimatedUint16;
  8378.  ZamModelViewer.Wow.AnimatedUint16.prototype.readValue = function(r) {
  8379.   return r.getUint16()
  8380.  };
  8381.  ZamModelViewer.Wow.AnimatedUint16.getValue = function(dataset, anim, time, result) {
  8382.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.AnimatedUint16.prototype, dataset, anim, time, result)
  8383.  };
  8384.  ZamModelViewer.Wow.AnimatedUint16.readSet = function(r) {
  8385.   var count = r.getInt32();
  8386.   var data = new Array(count);
  8387.   for (var i = 0; i < count; ++i) data[i] = new ZamModelViewer.Wow.AnimatedUint16(r);
  8388.   return data
  8389.  };
  8390.  ZamModelViewer.Wow.AnimatedFloat = function(r) {
  8391.   var self = this;
  8392.   self.read(r)
  8393.  };
  8394.  ZamModelViewer.Wow.AnimatedFloat.prototype = new ZamModelViewer.Wow.Animated;
  8395.  ZamModelViewer.Wow.AnimatedFloat.prototype.constructor = ZamModelViewer.Wow.AnimatedFloat;
  8396.  ZamModelViewer.Wow.AnimatedFloat.prototype.readValue = function(r) {
  8397.   return r.getFloat()
  8398.  };
  8399.  ZamModelViewer.Wow.AnimatedFloat.getValue = function(dataset, anim, time, result) {
  8400.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.AnimatedFloat.prototype, dataset, anim, time, result)
  8401.  };
  8402.  ZamModelViewer.Wow.AnimatedFloat.readSet = function(r) {
  8403.   var count = r.getInt32();
  8404.   var data = new Array(count);
  8405.   for (var i = 0; i < count; ++i) data[i] = new ZamModelViewer.Wow.AnimatedFloat(r);
  8406.   return data
  8407.  };
  8408.  ZamModelViewer.Wow.AnimatedUint8 = function(r) {
  8409.   var self = this;
  8410.   self.read(r)
  8411.  };
  8412.  ZamModelViewer.Wow.AnimatedUint8.prototype = new ZamModelViewer.Wow.Animated;
  8413.  ZamModelViewer.Wow.AnimatedUint8.prototype.constructor = ZamModelViewer.Wow.AnimatedUint8;
  8414.  ZamModelViewer.Wow.AnimatedUint8.prototype.readValue = function(r) {
  8415.   return r.getUint8()
  8416.  };
  8417.  ZamModelViewer.Wow.AnimatedUint8.getValue = function(dataset, anim, time, result) {
  8418.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.AnimatedUint8.prototype, dataset, anim, time, result)
  8419.  };
  8420.  ZamModelViewer.Wow.AnimatedUint8.readSet = function(r) {
  8421.   var count = r.getInt32();
  8422.   var data = new Array(count);
  8423.   for (var i = 0; i < count; ++i) data[i] = new ZamModelViewer.Wow.AnimatedUint8(r);
  8424.   return data
  8425.  };
  8426.  ZamModelViewer.Wow.SAnimated = function() {};
  8427.  ZamModelViewer.Wow.SAnimated.prototype = {
  8428.   destroy: function() {
  8429.    var self = this;
  8430.    for (var i = 0; i < self.data.length; ++i) self.data[i] = null;
  8431.    self.times = null;
  8432.    self.data = null;
  8433.    return null
  8434.   },
  8435.   createValue: function() {
  8436.    return this.defaultValue
  8437.   },
  8438.   defaultValue: 0,
  8439.   setDefault: function(v) {
  8440.    this.defaultValue = v
  8441.   },
  8442.   interpolate: function(v1, v2, r, result) {
  8443.    result = v1 + (v2 - v1) * r;
  8444.    return result
  8445.   },
  8446.   set: function(result, value) {
  8447.    result = value;
  8448.    return result
  8449.   },
  8450.   getDefault: function(r) {
  8451.    r = this.defaultValue;
  8452.    return r
  8453.   },
  8454.   readValue: function(r) {
  8455.    return r.getInt32()
  8456.   },
  8457.   getValue: function(time, result) {
  8458.    var self = this;
  8459.    if (result === undefined) result = self.createValue();
  8460.    else result = self.getDefault(result);
  8461.    if (self.data.length > 1 && self.times.length > 1) {
  8462.     var maxTime = self.times[self.times.length - 1];
  8463.     if (maxTime > 0 && time > maxTime) time %= maxTime;
  8464.     var idx = 0,
  8465.      numTimes = self.times.length;
  8466.     for (var i = 0; i < numTimes; ++i) {
  8467.      if (time >= self.times[i] && time < self.times[i + 1]) {
  8468.       idx = i;
  8469.       break
  8470.      }
  8471.     }
  8472.     var t1 = self.times[idx],
  8473.      t2 = self.times[idx + 1],
  8474.      r = 0;
  8475.     if (t1 != t2) r = (time - t1) / (t2 - t1);
  8476.     return self.interpolate(self.data[idx], self.data[idx + 1], r, result)
  8477.    } else if (self.data.length > 0) {
  8478.     result = self.set(result, self.data[0]);
  8479.     return result
  8480.    } else {
  8481.     return result
  8482.    }
  8483.   },
  8484.   read: function(r) {
  8485.    var self = this,
  8486.     i;
  8487.    var numTimes = r.getInt32();
  8488.    self.times = new Array(numTimes);
  8489.    for (i = 0; i < numTimes; ++i) {
  8490.     self.times[i] = r.getUint32()
  8491.    }
  8492.    var numData = r.getInt32();
  8493.    self.data = new Array(numData);
  8494.    for (i = 0; i < numData; ++i) {
  8495.     self.data[i] = self.readValue(r)
  8496.    }
  8497.   }
  8498.  };
  8499.  ZamModelViewer.Wow.SAnimatedVec2 = function(r) {
  8500.   var self = this;
  8501.   self.read(r)
  8502.  };
  8503.  ZamModelViewer.Wow.SAnimatedVec2.prototype = new ZamModelViewer.Wow.SAnimated;
  8504.  ZamModelViewer.Wow.SAnimatedVec2.prototype.constructor = ZamModelViewer.Wow.SAnimatedVec2;
  8505.  ZamModelViewer.Wow.SAnimatedVec2.prototype.createValue = function() {
  8506.   return vec2.clone(this.defaultValue)
  8507.  };
  8508.  ZamModelViewer.Wow.SAnimatedVec2.prototype.defaultValue = vec2.create();
  8509.  ZamModelViewer.Wow.SAnimatedVec2.prototype.getDefault = function(result) {
  8510.   vec2.copy(result, this.defaultValue);
  8511.   return result
  8512.  };
  8513.  ZamModelViewer.Wow.SAnimatedVec2.prototype.interpolate = function(v1, v2, r, result) {
  8514.   return vec2.lerp(result, v1, v2, r)
  8515.  };
  8516.  ZamModelViewer.Wow.SAnimatedVec2.prototype.set = function(result, value) {
  8517.   result[0] = value[0];
  8518.   result[1] = value[1];
  8519.   result[2] = value[2]
  8520.  };
  8521.  ZamModelViewer.Wow.SAnimatedVec2.prototype.readValue = function(r) {
  8522.   return vec2.set(vec2.create(), r.getFloat(), r.getFloat())
  8523.  };
  8524.  ZamModelViewer.Wow.SAnimatedVec2.getValue = function(dataset, anim, time, result) {
  8525.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.SAnimatedVec2.prototype, dataset, anim, time, result)
  8526.  };
  8527.  ZamModelViewer.Wow.SAnimatedVec3 = function(r) {
  8528.   var self = this;
  8529.   self.read(r)
  8530.  };
  8531.  ZamModelViewer.Wow.SAnimatedVec3.prototype = new ZamModelViewer.Wow.SAnimated;
  8532.  ZamModelViewer.Wow.SAnimatedVec3.prototype.constructor = ZamModelViewer.Wow.SAnimatedVec3;
  8533.  ZamModelViewer.Wow.SAnimatedVec3.prototype.createValue = function() {
  8534.   return vec3.clone(this.defaultValue)
  8535.  };
  8536.  ZamModelViewer.Wow.SAnimatedVec3.prototype.defaultValue = vec3.create();
  8537.  ZamModelViewer.Wow.SAnimatedVec3.prototype.getDefault = function(result) {
  8538.   vec3.copy(result, this.defaultValue);
  8539.   return result
  8540.  };
  8541.  ZamModelViewer.Wow.SAnimatedVec3.prototype.interpolate = function(v1, v2, r, result) {
  8542.   return vec3.lerp(result, v1, v2, r)
  8543.  };
  8544.  ZamModelViewer.Wow.SAnimatedVec3.prototype.set = function(result, value) {
  8545.   result[0] = value[0];
  8546.   result[1] = value[1];
  8547.   result[2] = value[2]
  8548.  };
  8549.  ZamModelViewer.Wow.SAnimatedVec3.prototype.readValue = function(r) {
  8550.   return vec3.set(vec3.create(), r.getFloat(), r.getFloat(), r.getFloat())
  8551.  };
  8552.  ZamModelViewer.Wow.SAnimatedVec3.getValue = function(dataset, anim, time, result) {
  8553.   return ZamModelViewer.Wow.Animated.getValue(ZamModelViewer.Wow.SAnimatedVec3.prototype, dataset, anim, time, result)
  8554.  };
  8555.  ZamModelViewer.Wow.SAnimatedUint16 = function(r) {
  8556.   var self = this;
  8557.   self.read(r)
  8558.  };
  8559.  ZamModelViewer.Wow.SAnimatedUint16.prototype = new ZamModelViewer.Wow.SAnimated;
  8560.  ZamModelViewer.Wow.SAnimatedUint16.prototype.constructor = ZamModelViewer.Wow.SAnimatedUint16;
  8561.  ZamModelViewer.Wow.SAnimatedUint16.prototype.readValue = function(r) {
  8562.   return r.getUint16()
  8563.  };
  8564.  ZamModelViewer.Wow.SAnimatedUint16.getValue = function(dataset, anim, time, result) {
  8565.   return ZamModelViewer.Wow.SAnimated.getValue(ZamModelViewer.Wow.SAnimatedUint16.prototype, dataset, anim, time, result)
  8566.  }
  8567. })();
  8568. ZamModelViewer.Wow.Texture = function(model, index, file) {
  8569.  var self = this,
  8570.   gl = model.renderer.context;
  8571.  self.model = model;
  8572.  self.index = index;
  8573.  self.url = model.opts.contentPath + "textures/" + file + ".png";
  8574.  self.texture = null;
  8575.  self.alphaTexture = null;
  8576.  self.img = self.alphaImg = self.mergedImg = null;
  8577.  self.loaded = false;
  8578.  (function(self, gl) {
  8579.   self.mergedImg = new Image;
  8580.   self.mergedImg.crossOrigin = "";
  8581.   self.mergedImg.onload = function() {
  8582.    self.splitImages()
  8583.   };
  8584.   self.mergedImg.onerror = function() {
  8585.    self.mergedImg = null
  8586.   };
  8587.   self.mergedImg.src = self.url
  8588.  })(self, gl)
  8589. };
  8590. ZamModelViewer.Wow.Texture.prototype = {
  8591.  ready: function() {
  8592.   return this.loaded
  8593.  },
  8594.  destroy: function() {
  8595.   var self = this;
  8596.   if (!self.model) return;
  8597.   var gl = self.model.renderer.context;
  8598.   if (self.texture) gl.deleteTexture(self.texture);
  8599.   if (self.alphaTexture) gl.deleteTexture(self.alphaTexture);
  8600.   self.texture = null;
  8601.   self.alphaTexture = null;
  8602.   self.img = self.alphaImg = self.mergedImg = null;
  8603.   self.model = null
  8604.  },
  8605.  splitImages: function() {
  8606.   var self = this,
  8607.    gl = self.model.renderer.context;
  8608.   var width = self.mergedImg.width,
  8609.    height = self.mergedImg.height;
  8610.   var canvas = document.createElement("canvas");
  8611.   canvas.width = width;
  8612.   canvas.height = height;
  8613.   var ctx = canvas.getContext("2d");
  8614.   ctx.drawImage(self.mergedImg, 0, 0, width, height);
  8615.   var rgba = ctx.getImageData(0, 0, width, height),
  8616.    p = rgba.data;
  8617.   var hasAlpha = false,
  8618.    alphaVal, i;
  8619.   for (i = 0; i < p.length; i += 4) {
  8620.    alphaVal = p[i + 3];
  8621.    if (!hasAlpha && alphaVal != 255) hasAlpha = true
  8622.   }
  8623.   self.texture = gl.createTexture();
  8624.   gl.bindTexture(gl.TEXTURE_2D, self.texture);
  8625.   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.mergedImg);
  8626.   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  8627.   if (hasAlpha) {
  8628.    self.alphaTexture = gl.createTexture();
  8629.    gl.bindTexture(gl.TEXTURE_2D, self.alphaTexture);
  8630.    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.mergedImg);
  8631.    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
  8632.   }
  8633.   self.loaded = true
  8634.  }
  8635. };
  8636. ZamModelViewer.Wow.Item = function(model, slot, id, race, gender) {
  8637.  var self = this;
  8638.  self.model = model;
  8639.  self.slot = slot;
  8640.  self.uniqueSlot = ZamModelViewer.Wow.UniqueSlots[slot];
  8641.  self.sortValue = ZamModelViewer.Wow.SlotOrder[slot];
  8642.  self.models = null;
  8643.  self.geosets = null;
  8644.  self.textures = null;
  8645.  self.geoA = 0;
  8646.  self.geoB = 0;
  8647.  self.geoC = 0;
  8648.  self.loaded = false;
  8649.  if (id) {
  8650.   self.load(id, race, gender)
  8651.  }
  8652. };
  8653. ZamModelViewer.Wow.Item.prototype = {
  8654.  destroy: function() {
  8655.   var self = this,
  8656.    i;
  8657.   self.model = null;
  8658.   if (self.models) {
  8659.    for (i = 0; i < self.models.length; ++i) {
  8660.     if (self.models[i].model) self.models[i].model.destroy();
  8661.     self.models[i].model = null;
  8662.     self.models[i].attachment = null;
  8663.     self.models[i] = null
  8664.    }
  8665.    self.models = null
  8666.   }
  8667.   if (self.textures) {
  8668.    for (i = 0; i < self.textures; ++i) {
  8669.     if (self.textures[i].texture) self.textures[i].texture.destroy();
  8670.     self.textures[i].texture = null;
  8671.     self.textures[i] = null
  8672.    }
  8673.    self.textures = null
  8674.   }
  8675.   self.geosets = null
  8676.  },
  8677.  load: function(id, race, gender) {
  8678.   var self = this,
  8679.    Wow = ZamModelViewer.Wow;
  8680.   self.id = id;
  8681.   if (self.slot == Wow.Slots.SHOULDER) {
  8682.    self.models = new Array(2)
  8683.   } else if (Wow.SlotType[self.slot] != Wow.Types.ARMOR) {
  8684.    self.models = new Array(1)
  8685.   }
  8686.   if (self.models) {
  8687.    for (var i = 0; i < self.models.length; ++i) {
  8688.     self.models[i] = {
  8689.      race: race,
  8690.      gender: gender,
  8691.      bone: -1,
  8692.      attachment: null,
  8693.      model: null
  8694.     };
  8695.     var modelInfo = {
  8696.      type: Wow.SlotType[self.slot],
  8697.      id: self.id,
  8698.      parent: self.model
  8699.     };
  8700.     if (self.slot == Wow.Slots.SHOULDER) {
  8701.      modelInfo.shoulder = i + 1
  8702.     }
  8703.     self.models[i].model = new Wow.Model(self.model.renderer, self.model.viewer, modelInfo, i)
  8704.    }
  8705.    self.loaded = true
  8706.   } else {
  8707.    var url = self.model.opts.contentPath + "meta/armor/" + self.slot + "/" + self.id + ".json";
  8708.    $.getJSON(url, function(data) {
  8709.     self.loadMeta(data)
  8710.    })
  8711.   }
  8712.  },
  8713.  loadMeta: function(meta) {
  8714.   var self = this,
  8715.    Wow = ZamModelViewer.Wow;
  8716.   self.slot = parseInt(meta.Slot);
  8717.   if (meta.Geosets) {
  8718.    self.geosets = [];
  8719.    for (var idx in meta.Geosets) {
  8720.     self.geosets.push({
  8721.      index: parseInt(idx),
  8722.      value: meta.Geosets[idx]
  8723.     })
  8724.    }
  8725.   }
  8726.   if (meta.GenderTextures) {
  8727.    self.textures = [];
  8728.    for (var g in meta.GenderTextures) {
  8729.     var gender = parseInt(g);
  8730.     if (g != self.model.gender) {
  8731.      var textures = meta.GenderTextures[g];
  8732.      for (var r in textures) {
  8733.       var region = parseInt(r);
  8734.       var texture = {
  8735.        region: region,
  8736.        gender: self.model.gender,
  8737.        file: textures[r],
  8738.        texture: null
  8739.       };
  8740.       if (region > 0) {
  8741.        texture.texture = new Wow.Texture(self.model, r, textures[r])
  8742.       } else if (self.slot == Wow.Slots.CAPE) {
  8743.        self.model.textureOverrides[2] = new Wow.Texture(self.model, 2, textures[r])
  8744.       }
  8745.       self.textures.push(texture)
  8746.      }
  8747.     }
  8748.    }
  8749.   }
  8750.   self.geoA = meta.GeosetA;
  8751.   self.geoB = meta.GeosetB;
  8752.   self.geoC = meta.GeosetC;
  8753.   if (self.slot == Wow.Slots.HEAD) {
  8754.    self.model.hairVis = meta.ShowHair == 0;
  8755.    self.model.faceVis = meta.ShowFacial1 == 0
  8756.   } else if (self.slot == Wow.Slots.BELT && meta.GenderModels && meta.GenderModels[self.model.gender]) {
  8757.    var model = {
  8758.     race: 0,
  8759.     gender: 0,
  8760.     bone: -1,
  8761.     attachment: null,
  8762.     model: null
  8763.    };
  8764.    var modelInfo = {
  8765.     type: Wow.SlotType[self.slot],
  8766.     id: self.id,
  8767.     parent: self.model
  8768.    };
  8769.    model.model = new Wow.Model(self.model.renderer, self.model.viewer, modelInfo, 0, true);
  8770.    model.model.loadMeta(meta, Wow.Types.ARMOR);
  8771.    self.models = [model]
  8772.   } else if (self.slot == Wow.Slots.PANTS && self.geoC > 0) {
  8773.    self.sortValue += 2
  8774.   } else if (self.slot == Wow.Slots.HANDS && self.geoA > 0) {
  8775.    self.sortValue += 2
  8776.   }
  8777.   self.loaded = true;
  8778.   self.model.updateMeshes()
  8779.  }
  8780. };
  8781. ZamModelViewer.Wow.Vertex = function(r) {
  8782.  var self = this;
  8783.  self.position = [r.getFloat(), r.getFloat(), r.getFloat()];
  8784.  self.normal = [r.getFloat(), r.getFloat(), r.getFloat(), 0];
  8785.  self.u = r.getFloat();
  8786.  self.v = r.getFloat();
  8787.  self.weights = [r.getUint8(), r.getUint8(), r.getUint8(), r.getUint8()];
  8788.  self.bones = [r.getUint8(), r.getUint8(), r.getUint8(), r.getUint8()];
  8789.  self.transPosition = vec3.clone(self.position);
  8790.  self.transNormal = vec4.clone(self.normal)
  8791. };
  8792. ZamModelViewer.Wow.Vertex.prototype = {
  8793.  destroy: function() {
  8794.   var self = this;
  8795.   self.position = null;
  8796.   self.normal = null;
  8797.   self.weights = null;
  8798.   self.bones = null;
  8799.   self.transPosition = null;
  8800.   self.transNormal = null
  8801.  }
  8802. };
  8803. ZamModelViewer.Wow.Animation = function(r) {
  8804.  var self = this,
  8805.   Wow = ZamModelViewer.Wow;
  8806.  self.id = r.getUint16();
  8807.  self.subId = r.getUint16();
  8808.  self.flags = r.getUint32();
  8809.  self.length = r.getUint32();
  8810.  self.speed = r.getFloat();
  8811.  self.next = r.getInt16();
  8812.  self.index = r.getUint16();
  8813.  self.available = r.getBool();
  8814.  if (self.available) {
  8815.   self.dbcFlags = r.getUint32();
  8816.   self.name = r.getString();
  8817.   var numData = r.getInt32();
  8818.   if (numData > 0) {
  8819.    self.translation = new Array(numData);
  8820.    self.rotation = new Array(numData);
  8821.    self.scale = new Array(numData);
  8822.    for (var i = 0; i < numData; ++i) {
  8823.     self.translation[i] = new Wow.AnimatedVec3(r);
  8824.     self.rotation[i] = new Wow.AnimatedQuat(r);
  8825.     self.scale[i] = new Wow.AnimatedVec3(r)
  8826.    }
  8827.   }
  8828.  }
  8829. };
  8830. ZamModelViewer.Wow.Animation.prototype = {
  8831.  destroy: function() {
  8832.   var self = this;
  8833.   if (!self.translation) return;
  8834.   for (var i = 0; i < self.translation.length; ++i) {
  8835.    self.translation[i].destroy();
  8836.    self.translation[i] = null;
  8837.    self.rotation[i].destroy();
  8838.    self.rotation[i] = null;
  8839.    self.scale[i].destroy();
  8840.    self.scale[i] = null
  8841.   }
  8842.   self.translation = null;
  8843.   self.rotation = null;
  8844.   self.scale = null
  8845.  }
  8846. };
  8847. ZamModelViewer.Wow.Bone = function(model, index, r) {
  8848.  var self = this;
  8849.  self.model = model;
  8850.  self.index = index;
  8851.  self.keyId = r.getInt32();
  8852.  self.parent = r.getInt16();
  8853.  self.mesh = r.getUint16();
  8854.  self.flags = r.getUint32();
  8855.  self.pivot = [r.getFloat(), r.getFloat(), r.getFloat()];
  8856.  self.transformedPivot = vec3.create();
  8857.  self.matrix = mat4.create();
  8858.  self.tmpVec = vec3.create();
  8859.  self.tmpQuat = quat.create();
  8860.  self.tmpMat = mat4.create();
  8861.  self.hidden = false;
  8862.  self.updated = false
  8863. };
  8864. ZamModelViewer.Wow.Bone.prototype = {
  8865.  destroy: function() {
  8866.   var self = this;
  8867.   self.model = null;
  8868.   self.pivot = null;
  8869.   self.transformedPivot = null;
  8870.   self.matrix = null;
  8871.   self.tmpVec = null;
  8872.   self.tmpQuat = null;
  8873.   self.tmpMat = null
  8874.  },
  8875.  hide: function() {
  8876.   var self = this;
  8877.   self.hidden = true;
  8878.   for (var i = 0; i < 16; ++i) self.matrix[i] = 0
  8879.  },
  8880.  update: function(time) {
  8881.   var self = this,
  8882.    Wow = ZamModelViewer.Wow;
  8883.   if (self.hidden) {
  8884.    self.hide();
  8885.    return
  8886.   }
  8887.   if (self.model.model.type == Wow.Types.CHARACTER && !self.model.isHD) {
  8888.    if (self.model.race == Wow.Races.HUMAN && self.model.gender == Wow.Genders.MALE && self.index == 24) {
  8889.     self.hide()
  8890.    }
  8891.   }
  8892.   if (self.updated) return;
  8893.   self.updated = true;
  8894.   if (!self.model || !self.model.animations) return;
  8895.   mat4.identity(self.matrix);
  8896.   var anim = self.model.currentAnimation;
  8897.   if (!anim || !anim.translation || !anim.rotation || !anim.scale) return;
  8898.   var billboard = (self.flags & 8) > 0;
  8899.   if (anim.translation[self.index].used || anim.rotation[self.index].used || anim.scale[self.index].used || billboard) {
  8900.    mat4.translate(self.matrix, self.matrix, self.pivot);
  8901.    if (anim.translation[self.index].used) {
  8902.     anim.translation[self.index].getValue(time, self.tmpVec);
  8903.     mat4.translate(self.matrix, self.matrix, self.tmpVec)
  8904.    }
  8905.    if (anim.rotation[self.index].used) {
  8906.     anim.rotation[self.index].getValue(time, self.tmpQuat);
  8907.     mat4.fromQuat(self.tmpMat, self.tmpQuat);
  8908.     mat4.transpose(self.tmpMat, self.tmpMat);
  8909.     mat4.multiply(self.matrix, self.matrix, self.tmpMat)
  8910.    }
  8911.    if (anim.scale[self.index].used) {
  8912.     anim.scale[self.index].getValue(time, self.tmpVec);
  8913.     if (self.tmpVec[0] > 10 || Math.abs(self.tmpVec[0]) < 1e-4) self.tmpVec[0] = 1;
  8914.     if (self.tmpVec[1] > 10 || Math.abs(self.tmpVec[1]) < 1e-4) self.tmpVec[1] = 1;
  8915.     if (self.tmpVec[2] > 10 || Math.abs(self.tmpVec[2]) < 1e-4) self.tmpVec[2] = 1;
  8916.     mat4.scale(self.matrix, self.matrix, self.tmpVec)
  8917.    }
  8918.    if (billboard) {
  8919.     var yRot = -self.model.renderer.zenith + Math.PI / 2;
  8920.     var zRot;
  8921.     if (self.model.model.type == Wow.Types.ITEM) {
  8922.      zRot = self.model.renderer.azimuth - Math.PI
  8923.     } else {
  8924.      zRot = self.model.renderer.azimuth - Math.PI * 1.5
  8925.     }
  8926.     mat4.identity(self.matrix);
  8927.     mat4.translate(self.matrix, self.matrix, self.pivot);
  8928.     mat4.rotateZ(self.matrix, self.matrix, zRot);
  8929.     mat4.rotateY(self.matrix, self.matrix, yRot)
  8930.    }
  8931.    mat4.translate(self.matrix, self.matrix, vec3.negate(self.tmpVec, self.pivot))
  8932.   }
  8933.   if (self.parent > -1) {
  8934.    self.model.bones[self.parent].update(time);
  8935.    mat4.multiply(self.matrix, self.model.bones[self.parent].matrix, self.matrix)
  8936.   }
  8937.   vec3.transformMat4(self.transformedPivot, self.pivot, self.matrix)
  8938.  }
  8939. };
  8940. ZamModelViewer.Wow.Mesh = function(r) {
  8941.  var self = this;
  8942.  self.id = r.getUint16();
  8943.  self.indexWrap = r.getUint16();
  8944.  self.vertexStart = r.getUint16();
  8945.  self.vertexCount = r.getUint16();
  8946.  self.indexStart = r.getUint16() + self.indexWrap * 65536;
  8947.  self.indexCount = r.getUint16();
  8948.  self.centerOfMass = [r.getFloat(), r.getFloat(), r.getFloat()];
  8949.  self.centerBounds = [r.getFloat(), r.getFloat(), r.getFloat()];
  8950.  self.radius = r.getFloat()
  8951. };
  8952. ZamModelViewer.Wow.Mesh.prototype = {
  8953.  destroy: function() {
  8954.   var self = this;
  8955.   self.centerOfMass = null;
  8956.   self.centerBounds = null
  8957.  }
  8958. };
  8959. ZamModelViewer.Wow.TexUnit = function(r) {
  8960.  var self = this;
  8961.  self.flags = r.getUint8();
  8962.  self.flags2 = r.getUint8();
  8963.  self.shading = r.getUint16();
  8964.  self.meshIndex = r.getUint16();
  8965.  self.colorIndex = r.getInt16();
  8966.  self.renderFlagIndex = r.getUint16();
  8967.  self.opcount = r.getUint16();
  8968.  self.materialIndex = r.getInt16();
  8969.  self.texUnitIndex = r.getUint16();
  8970.  self.alphaIndex = r.getInt16();
  8971.  self.textureAnimIndex = r.getInt16();
  8972.  self.show = true;
  8973.  self.model = null;
  8974.  self.mesh = null;
  8975.  self.meshId = 0;
  8976.  self.renderFlag = null;
  8977.  self.material = [];
  8978.  self.textureAnim = [];
  8979.  self.color = null;
  8980.  self.alpha = null;
  8981.  self.unlit = false;
  8982.  self.cull = false;
  8983.  self.noZWrite = false;
  8984.  self.tmpColor = vec4.create();
  8985.  self.tmpVec = vec3.create();
  8986.  self.tmpQuat = quat.create()
  8987. };
  8988. ZamModelViewer.Wow.TexUnit.prototype = {
  8989.  destroy: function() {
  8990.   var self = this;
  8991.   self.model = null;
  8992.   self.mesh = null;
  8993.   self.renderFlag = null;
  8994.   self.material = null;
  8995.   self.textureAnim = null;
  8996.   self.color = null;
  8997.   self.alpha = null;
  8998.   self.tmpColor = null;
  8999.   self.textureMatrix = null;
  9000.   self.tmpVec = null;
  9001.   self.tmpQuat = null
  9002.  },
  9003.  draw: function() {
  9004.   var self = this,
  9005.    gl = self.model.renderer.context,
  9006.    anim = self.model.currentAnimation.index,
  9007.    time = self.model.time;
  9008.   self.tmpColor[0] = self.tmpColor[1] = self.tmpColor[2] = self.tmpColor[3] = 1;
  9009.   if (self.color) {
  9010.    self.color.getValue(anim, time, self.tmpColor)
  9011.   }
  9012.   if (self.alpha) {
  9013.    self.tmpColor[3] *= self.alpha.getValue(anim, time)
  9014.   }
  9015.   if (self.tmpColor[3] <= .001) return;
  9016.   var blend = self.renderFlag.blend;
  9017.   if (self.meshId > 1500 && self.meshId < 1600) blend = 0;
  9018.   gl.uniform4fv(self.model.uniforms.fColor, self.tmpColor);
  9019.   gl.uniform1i(self.model.uniforms.fBlendMode, blend);
  9020.   gl.uniform1i(self.model.uniforms.fUnlit, self.unlit);
  9021.   var count = 0;
  9022.   var texture2 = null;
  9023.   var texture3 = null;
  9024.   var texture4 = null;
  9025.   var texture1 = null,
  9026.    aTex = null;
  9027.   for (var i in self.material) {
  9028.    var alphaTexture = null;
  9029.    var texture = null;
  9030.    if (self.material[i]) {
  9031.     if (self.material[i].type == 1) {
  9032.      if (self.model.npcTexture) {
  9033.       texture = self.model.npcTexture.texture;
  9034.       alphaTexture = self.model.npcTexture.alphaTexture
  9035.      } else if (self.model.compositeTexture) {
  9036.       texture = self.model.compositeTexture
  9037.      }
  9038.     } else if (self.material[i].texture) {
  9039.      texture = self.material[i].texture.texture;
  9040.      alphaTexture = self.material[i].texture.alphaTexture
  9041.     } else if (((self.model.model.type < 8 || self.model.model.type > 32) && self.material[i].type == 2 || self.material[i].type >= 11) && self.model.textureOverrides[self.material[i].index]) {
  9042.      texture = self.model.textureOverrides[self.material[i].index].texture;
  9043.      alphaTexture = self.model.textureOverrides[self.material[i].index].alphaTexture
  9044.     } else if (self.material[i].type != -1 && self.model.textureOverrides[self.material[i].type]) {
  9045.      texture = self.model.textureOverrides[self.material[i].type].texture;
  9046.      alphaTexture = self.model.textureOverrides[self.material[i].type].alphaTexture
  9047.     } else if (self.material[i].type != -1 && self.model.specialTextures[self.material[i].type]) {
  9048.      texture = self.model.specialTextures[self.material[i].type].texture;
  9049.      alphaTexture = self.model.specialTextures[self.material[i].type].alphaTexture
  9050.     } else if (!self.material[i].filename) {
  9051.      var mat = self.model.materials[self.materialIndex + count];
  9052.      if (mat.texture) {
  9053.       texture = mat.texture.texture;
  9054.       alphaTexture = mat.texture.alphaTexture
  9055.      }
  9056.     }
  9057.    }
  9058.    if (i == 0) {
  9059.     texture1 = texture;
  9060.     aTex = alphaTexture
  9061.    }
  9062.    if (i == 1) texture2 = texture;
  9063.    if (i == 2) texture3 = texture;
  9064.    if (i == 3) texture4 = texture;
  9065.    count++
  9066.   }
  9067.   if (texture1) {
  9068.    gl.activeTexture(gl.TEXTURE0);
  9069.    gl.bindTexture(gl.TEXTURE_2D, texture1);
  9070.    gl.uniform1i(self.model.uniforms.fTexture, 0)
  9071.   }
  9072.   if (texture2) {
  9073.    gl.activeTexture(gl.TEXTURE0);
  9074.    gl.bindTexture(gl.TEXTURE_2D, texture2);
  9075.    gl.uniform1i(self.model.uniforms.fTexture2, 0)
  9076.   }
  9077.   if (texture3) {
  9078.    gl.activeTexture(gl.TEXTURE0);
  9079.    gl.bindTexture(gl.TEXTURE_2D, texture3);
  9080.    gl.uniform1i(self.model.uniforms.fTexture3, 0)
  9081.   }
  9082.   if (texture4) {
  9083.    gl.activeTexture(gl.TEXTURE0);
  9084.    gl.bindTexture(gl.TEXTURE_2D, texture4);
  9085.    gl.uniform1i(self.model.uniforms.fTexture4, 0)
  9086.   }
  9087.   if (aTex) {
  9088.    gl.activeTexture(gl.TEXTURE1);
  9089.    gl.bindTexture(gl.TEXTURE_2D, aTex);
  9090.    gl.uniform1i(self.model.uniforms.fAlpha, 1)
  9091.   }
  9092.   gl.uniform1i(self.model.uniforms.fHasTexture, texture ? 1 : 0);
  9093.   gl.uniform1i(self.model.uniforms.fHasTexture2, texture2 ? 1 : 0);
  9094.   gl.uniform1i(self.model.uniforms.fHasTexture3, texture3 ? 1 : 0);
  9095.   gl.uniform1i(self.model.uniforms.fHasTexture4, texture4 ? 1 : 0);
  9096.   gl.uniform1i(self.model.uniforms.fHasAlpha, aTex ? 1 : 0);
  9097.   for (var i in self.textureAnim) {
  9098.    self.textureMatrix = mat4.create();
  9099.    mat4.identity(self.textureMatrix);
  9100.    if (self.textureAnim[i]) {
  9101.     var rotTrans = false;
  9102.     if (self.textureAnim[i].translation) {
  9103.      ZamModelViewer.Wow.AnimatedVec3.getValue(self.textureAnim[i].translation, anim, time, self.tmpVec);
  9104.      rotTrans = true
  9105.     } else {
  9106.      vec3.set(self.tmpVec, 0, 0, 0)
  9107.     }
  9108.     if (self.textureAnim[i].rotation) {
  9109.      ZamModelViewer.Wow.AnimatedQuat.getValue(self.textureAnim[i].rotation, anim, time, self.tmpQuat);
  9110.      rotTrans = true
  9111.     } else {
  9112.      quat.set(self.tmpQuat, 0, 0, 0, 1)
  9113.     }
  9114.     if (rotTrans) mat4.fromRotationTranslation(self.textureMatrix, self.tmpQuat, self.tmpVec);
  9115.     if (self.textureAnim[i].scale && ZamModelViewer.Wow.Animated.isUsed(self.textureAnim[i].scale, anim)) {
  9116.      ZamModelViewer.Wow.AnimatedVec3.getValue(self.textureAnim[i].scale, anim, time, self.tmpVec);
  9117.      mat4.scale(self.textureMatrix, self.textureMatrix, self.tmpVec)
  9118.     }
  9119.    }
  9120.    if (i == 0) gl.uniformMatrix4fv(self.model.uniforms.vTextureMatrix, false, self.textureMatrix);
  9121.    if (i == 1) gl.uniformMatrix4fv(self.model.uniforms.vTextureMatrix2, false, self.textureMatrix);
  9122.    if (i == 2) gl.uniformMatrix4fv(self.model.uniforms.vTextureMatrix3, false, self.textureMatrix);
  9123.    if (i == 3) gl.uniformMatrix4fv(self.model.uniforms.vTextureMatrix4, false, self.textureMatrix)
  9124.   }
  9125.   if (blend == 0 || blend == 1) {
  9126.    gl.blendFunc(gl.ONE, gl.ZERO)
  9127.   } else if (blend == 2) {
  9128.    if (self.flags == 130 && self.flags2 > 2 && self.flags2 < 6) gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
  9129.    else if (self.flags == 130) gl.blendFunc(gl.ONE, gl.ONE);
  9130.    else if (self.flags == 146) gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  9131.    else gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  9132.   } else if (blend == 3) {
  9133.    gl.blendFunc(gl.SRC_COLOR, gl.ONE)
  9134.   } else if (blend == 4) {
  9135.    if (self.opcount == 1 || self.opcount == 2) {
  9136.     if (self.flags == 144 && self.flags2 == 0) gl.blendFunc(gl.ONE, gl.ONE);
  9137.     else gl.blendFunc(gl.SRC_ALPHA, gl.ONE)
  9138.    } else {
  9139.     gl.blendFunc(gl.DST_COLOR, gl.SRC_ALPHA)
  9140.    }
  9141.   } else if (blend == 5) {
  9142.    if (self.opcount == 1) {
  9143.     gl.blendFunc(gl.ZERO, gl.SRC_COLOR)
  9144.    } else {
  9145.     gl.blendFunc(gl.DST_COLOR, gl.SRC_COLOR)
  9146.    }
  9147.   } else if (blend == 6) {
  9148.    gl.blendFunc(gl.DST_COLOR, gl.SRC_COLOR)
  9149.   } else {
  9150.    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
  9151.   }
  9152.   if (self.cull) {
  9153.    gl.enable(gl.CULL_FACE)
  9154.   } else {
  9155.    gl.disable(gl.CULL_FACE)
  9156.   }
  9157.   if (self.noZWrite) {
  9158.    gl.depthMask(false)
  9159.   } else {
  9160.    gl.depthMask(true)
  9161.   }
  9162.   gl.drawElements(gl.TRIANGLES, self.mesh.indexCount, gl.UNSIGNED_SHORT, self.mesh.indexStart * 2)
  9163.  },
  9164.  setup: function(model) {
  9165.   var self = this;
  9166.   self.model = model;
  9167.   self.mesh = model.meshes[self.meshIndex];
  9168.   self.meshId = self.mesh.id;
  9169.   if (model.renderFlags && self.renderFlagIndex < model.renderFlags.length) {
  9170.    self.renderFlag = model.renderFlags[self.renderFlagIndex]
  9171.   } else self.renderFlag = {
  9172.    flags: 0,
  9173.    blend: 0
  9174.   };
  9175.   self.unlit = (self.renderFlag.flags & 1) > 0;
  9176.   self.cull = (self.renderFlag.flags & 4) == 0;
  9177.   self.noZWrite = self.renderFlag.flags >= 16 && self.renderFlag.blend != 7 && self.renderFlag.flags != 17 || (self.flags2 == 10 || self.flags2 == 20) || self.renderFlag.flags == 17 && self.flags2 == 0 || self.renderFlag.flags == 21 && self.flags == 128 && self.flags2 == 0 && self.renderFlag.blend == 7;
  9178.   self.flip = self.renderFlag.flags == 16 && self.flags == 128 && self.flags2 < 10 || self.renderFlag.flags != 16 && self.flags == 128 && self.flags2 < 10 && self.flags2 != 0 || self.flags == 130 || self.renderFlag.flags == 21 && self.flags == 128 && self.flags2 == 0 && self.renderFlag.blend == 7;
  9179.   self.multiTexture = self.renderFlag.flags >= 16;
  9180.   if (self.flags == 128 && self.flags2 == 1 && self.renderFlag.flags == 17 && self.renderFlag.blend == 2) {
  9181.    self.noZWrite = true
  9182.   }
  9183.   if (self.flags == 128 && self.flags2 == 3) {
  9184.    self.flip = false;
  9185.    self.noZWrite = true
  9186.   }
  9187.   if (self.flags == 128 && self.flags2 == 4) {
  9188.    self.flip = false;
  9189.    self.noZWrite = true
  9190.   }
  9191.   if (self.renderFlag.flags == 21 && self.renderFlag.blend == 2 && self.flags == 128 && self.flags2 == 1) {
  9192.    self.flip = false
  9193.   }
  9194.   for (var i = 0; i < self.opcount; i++) {
  9195.    if (self.multiTexture || i == 0) {
  9196.     if (self.materialIndex > -1 && self.materialIndex < model.materialLookup.length) {
  9197.      var matIdx = model.materialLookup[self.materialIndex + i];
  9198.      if (matIdx > -1 && matIdx < model.materials.length) {
  9199.       self.material.splice(i, 0, model.materials[matIdx])
  9200.      }
  9201.     }
  9202.     if (self.textureAnimIndex > -1 && self.textureAnimIndex < model.textureAnimLookup.length) {
  9203.      var animIdx = model.textureAnimLookup[self.textureAnimIndex + i];
  9204.      if (animIdx > -1 && model.textureAnims && animIdx < model.textureAnims.length) {
  9205.       self.textureAnim.splice(i, 0, model.textureAnims[animIdx])
  9206.      } else self.textureAnim.splice(i, 0, null)
  9207.     }
  9208.    }
  9209.   }
  9210.   if (self.flip) {
  9211.    self.material = self.material.reverse();
  9212.    self.textureAnim = self.textureAnim.reverse()
  9213.   }
  9214.   if (model.colors && self.colorIndex > -1 && self.colorIndex < model.colors.length) {
  9215.    self.color = model.colors[self.colorIndex]
  9216.   }
  9217.   if (self.alphaIndex > -1 && self.alphaIndex < model.alphaLookup.length) {
  9218.    var alphaIdx = model.alphaLookup[self.alphaIndex];
  9219.    if (alphaIdx > -1 && alphaIdx < model.alphas.length) {
  9220.     self.alpha = model.alphas[alphaIdx]
  9221.    }
  9222.   }
  9223.  }
  9224. };
  9225. ZamModelViewer.Wow.RenderFlag = function(r) {
  9226.  var self = this;
  9227.  self.flags = r.getUint16();
  9228.  self.blend = r.getUint16()
  9229. };
  9230. ZamModelViewer.Wow.Material = function(model, index, r) {
  9231.  var self = this;
  9232.  self.model = model;
  9233.  self.index = index;
  9234.  self.type = r.getInt32();
  9235.  self.flags = r.getUint32();
  9236.  self.filename = r.getUint32();
  9237.  self.texture = null;
  9238.  self.load()
  9239. };
  9240. ZamModelViewer.Wow.Material.prototype = {
  9241.  destroy: function() {
  9242.   var self = this;
  9243.   self.model = null;
  9244.   if (self.texture) self.texture.destroy();
  9245.   self.texture = null
  9246.  },
  9247.  load: function() {
  9248.   var self = this;
  9249.   if (self.filename == 0) return;
  9250.   self.texture = new ZamModelViewer.Wow.Texture(self.model, 0, self.filename)
  9251.  }
  9252. };
  9253. ZamModelViewer.Wow.TextureAnimation = function(r) {
  9254.  var Wow = ZamModelViewer.Wow;
  9255.  var self = this,
  9256.   i;
  9257.  var numTrans = r.getInt32();
  9258.  if (numTrans > 0) {
  9259.   self.translation = new Array(numTrans);
  9260.   for (i = 0; i < numTrans; ++i) self.translation[i] = new Wow.AnimatedVec3(r)
  9261.  } else self.translation = null;
  9262.  var numRot = r.getInt32();
  9263.  if (numRot > 0) {
  9264.   self.rotation = new Array(numRot);
  9265.   for (i = 0; i < numRot; ++i) self.rotation[i] = new Wow.AnimatedQuat(r)
  9266.  } else self.rotation = null;
  9267.  var numScale = r.getInt32();
  9268.  if (numScale > 0) {
  9269.   self.scale = new Array(numScale);
  9270.   for (i = 0; i < numScale; ++i) self.scale[i] = new Wow.AnimatedVec3(r)
  9271.  } else self.scale = null
  9272. };
  9273. ZamModelViewer.Wow.TextureAnimation.prototype = {
  9274.  destroy: function() {
  9275.   var self = this,
  9276.    i;
  9277.   if (self.translation) {
  9278.    for (i = 0; i < self.translation.length; ++i) self.translation[i] = self.translation[i].destroy();
  9279.    self.translation = null
  9280.   }
  9281.   if (self.rotation) {
  9282.    for (i = 0; i < self.rotation.length; ++i) self.rotation[i] = self.rotation[i].destroy();
  9283.    self.rotation = null
  9284.   }
  9285.   if (self.scale) {
  9286.    for (i = 0; i < self.scale.length; ++i) self.scale[i] = self.scale[i].destroy();
  9287.    self.scale = null
  9288.   }
  9289.  }
  9290. };
  9291. ZamModelViewer.Wow.Attachment = function(r) {
  9292.  var self = this;
  9293.  self.id = r.getInt32();
  9294.  self.bone = r.getInt32();
  9295.  self.position = [r.getFloat(), r.getFloat(), r.getFloat()];
  9296.  self.slot = -1
  9297. };
  9298. ZamModelViewer.Wow.Attachment.prototype = {
  9299.  destroy: function() {
  9300.   var self = this;
  9301.   self.position = null
  9302.  }
  9303. };
  9304. ZamModelViewer.Wow.Color = function(r) {
  9305.  var Wow = ZamModelViewer.Wow;
  9306.  var self = this,
  9307.   i;
  9308.  var numRgb = r.getInt32();
  9309.  if (numRgb > 0) {
  9310.   self.rgb = new Array(numRgb);
  9311.   for (i = 0; i < numRgb; ++i) {
  9312.    self.rgb[i] = new Wow.AnimatedVec3(r)
  9313.   }
  9314.  }
  9315.  var numAlpha = r.getInt32();
  9316.  if (numAlpha > 0) {
  9317.   self.alpha = new Array(numAlpha);
  9318.   for (i = 0; i < numAlpha; ++i) {
  9319.    self.alpha[i] = new Wow.AnimatedUint16(r)
  9320.   }
  9321.  }
  9322. };
  9323. ZamModelViewer.Wow.Color.prototype = {
  9324.  destroy: function() {
  9325.   var self = this,
  9326.    i;
  9327.   if (self.rgb) {
  9328.    for (i = 0; i < self.rgb.length; ++i) self.rgb[i] = self.rgb[i].destroy();
  9329.    self.rgb = null
  9330.   }
  9331.   if (self.alpha) {
  9332.    for (i = 0; i < self.alpha.length; ++i) self.alpha[i] = self.alpha[i].destroy();
  9333.    self.alpha = null
  9334.   }
  9335.  },
  9336.  rgbUsed: function(anim) {
  9337.   var self = this;
  9338.   if (!self.rgb) return false;
  9339.   if (anim < self.rgb.length) return self.rgb[anim].used;
  9340.   else return self.rgb[0].used
  9341.  },
  9342.  alphaUsed: function(anim) {
  9343.   var self = this;
  9344.   if (!self.alpha) return false;
  9345.   if (anim < self.alpha.length) return self.alpha[anim].used;
  9346.   else return self.alpha[0].used
  9347.  },
  9348.  used: function(anim) {
  9349.   var self = this;
  9350.   return self.rgbUsed(anim) || self.alphaUsed(anim)
  9351.  },
  9352.  getValue: function(anim, time, result) {
  9353.   var self = this;
  9354.   if (!result) result = [1, 1, 1, 1];
  9355.   else result[0] = result[1] = result[2] = result[3] = 1;
  9356.   if (self.rgbUsed(anim)) ZamModelViewer.Wow.AnimatedVec3.getValue(self.rgb, anim, time, result);
  9357.   if (self.alphaUsed(anim)) result[3] = ZamModelViewer.Wow.AnimatedUint16.getValue(self.alpha, anim, time, result[3]) / 32767;
  9358.   return result
  9359.  }
  9360. };
  9361. ZamModelViewer.Wow.Alpha = function(r) {
  9362.  var self = this;
  9363.  var count = r.getInt32();
  9364.  self.data = new Array(count);
  9365.  for (var i = 0; i < count; ++i) {
  9366.   self.data[i] = new ZamModelViewer.Wow.AnimatedUint16(r)
  9367.  }
  9368. };
  9369. ZamModelViewer.Wow.Alpha.prototype = {
  9370.  destroy: function() {
  9371.   var self = this;
  9372.   for (var i = 0; i < self.data.length; ++i) self.data[i] = self.data[i].destroy();
  9373.   self.data = null
  9374.  },
  9375.  used: function(anim) {
  9376.   var self = this;
  9377.   if (self.data.length == 0) return false;
  9378.   if (anim < self.data.length) return self.data[anim].used;
  9379.   else return self.data[0].used
  9380.  },
  9381.  getValue: function(anim, time) {
  9382.   var self = this,
  9383.    a = 1;
  9384.   if (self.used(anim)) {
  9385.    var val = ZamModelViewer.Wow.AnimatedUint16.getValue(self.data, anim, time, a);
  9386.    a = val / 32767
  9387.   }
  9388.   if (a > 1) a = 1;
  9389.   else if (a < 0) a = 0;
  9390.   return a
  9391.  }
  9392. };
  9393. ZamModelViewer.Wow.ParticleEmitter = function(model, r) {
  9394.  var self = this,
  9395.   Wow = ZamModelViewer.Wow;
  9396.  self.model = model;
  9397.  self.id = r.getInt32();
  9398.  self.flags = r.getUint32();
  9399.  self.colorIndex = r.getUint16();
  9400.  self.position = [r.getFloat(), r.getFloat(), r.getFloat()];
  9401.  self.boneId = r.getInt16();
  9402.  self.textureId = r.getInt16();
  9403.  if ((self.flags & 268435456) != 0) {
  9404.   self.textureIds = [0, 0, 0];
  9405.   self.textureIds[0] = self.textureId & 31;
  9406.   self.textureIds[1] = self.textureId >> 5 & 31;
  9407.   self.textureIds[2] = self.textureId >> 10 & 31
  9408.  }
  9409.  self.blendMode = r.getUint8();
  9410.  self.emitterType = r.getUint8();
  9411.  self.particleType = r.getUint8() & 3;
  9412.  self.headTail = r.getUint8();
  9413.  self.tileRotation = r.getUint16();
  9414.  self.tileRows = r.getUint16();
  9415.  self.tileColumns = r.getUint16();
  9416.  self.scale = [r.getFloat(), r.getFloat(), r.getFloat()];
  9417.  self.slowdown = r.getFloat();
  9418.  self.rotation = [r.getFloat(), r.getFloat(), r.getFloat()];
  9419.  self.modelRot1 = [r.getFloat(), r.getFloat(), r.getFloat()];
  9420.  self.modelRot2 = [r.getFloat(), r.getFloat(), r.getFloat()];
  9421.  self.modelTranslation = [r.getFloat(), r.getFloat(), r.getFloat()];
  9422.  self.modelPath = r.getString();
  9423.  self.particlePath = r.getString();
  9424.  self.emissionSpeed = Wow.AnimatedFloat.readSet(r);
  9425.  self.speedVariation = Wow.AnimatedFloat.readSet(r);
  9426.  self.verticalRange = Wow.AnimatedFloat.readSet(r);
  9427.  self.horizontalRange = Wow.AnimatedFloat.readSet(r);
  9428.  self.gravity = Wow.AnimatedFloat.readSet(r);
  9429.  self.lifespan = Wow.AnimatedFloat.readSet(r);
  9430.  self.emissionRate = Wow.AnimatedFloat.readSet(r);
  9431.  self.areaLength = Wow.AnimatedFloat.readSet(r);
  9432.  self.areaWidth = Wow.AnimatedFloat.readSet(r);
  9433.  self.gravity2 = Wow.AnimatedFloat.readSet(r);
  9434.  self.color = new Wow.SAnimatedVec3(r);
  9435.  self.alpha = new Wow.SAnimatedUint16(r);
  9436.  self.size = new Wow.SAnimatedVec2(r);
  9437.  self.intensity = new Wow.SAnimatedUint16(r);
  9438.  self.enabled = Wow.AnimatedUint8.readSet(r);
  9439.  self.bone = self.model.bones[self.boneId];
  9440.  self.maxParticles = 500;
  9441.  self.particles = new Array(self.maxParticles);
  9442.  self.unusedParticles = new Array(self.maxParticles);
  9443.  for (var i = self.maxParticles - 1, j = 0; i >= 0; --i, ++j) self.unusedParticles[i] = j;
  9444.  self.nextParticle = self.maxParticles - 1;
  9445.  self.numParticles = 0;
  9446.  self.spawnRemainder = 0;
  9447.  self.tmpColors = [vec4.create(), vec4.create(), vec4.create()];
  9448.  self.spreadMat = mat4.create();
  9449.  self.tmpMat = mat4.create();
  9450.  self.init()
  9451. };
  9452. ZamModelViewer.Wow.ParticleEmitter.prototype = {
  9453.  destroy: function() {
  9454.   var self = this,
  9455.    gl = self.model.renderer.context,
  9456.    Animated = ZamModelViewer.Wow.Animated;
  9457.   if (self.program) gl.deleteProgram(self.program);
  9458.   if (self.vs) gl.deleteShader(self.vs);
  9459.   if (self.fs) gl.deleteShader(self.fs);
  9460.   if (self.vb) gl.deleteBuffer(self.vb);
  9461.   if (self.ib) gl.deleteBuffer(self.ib);
  9462.   self.program = null;
  9463.   self.vs = null;
  9464.   self.fs = null;
  9465.   self.vb = null;
  9466.   self.ib = null;
  9467.   self.vbData = null;
  9468.   self.texture = null;
  9469.   self.attribs = null;
  9470.   self.uniforms = null;
  9471.   self.model = null;
  9472.   self.bone = null;
  9473.   self.position = null;
  9474.   self.scale = null;
  9475.   self.rotation = null;
  9476.   self.modelRot1 = null;
  9477.   self.modelRot2 = null;
  9478.   self.modelTranslation = null;
  9479.   self.emissionSpeed = Animated.destroySet(self.emissionSpeed);
  9480.   self.speedVariation = Animated.destroySet(self.speedVariation);
  9481.   self.verticalRange = Animated.destroySet(self.verticalRange);
  9482.   self.horizontalRange = Animated.destroySet(self.horizontalRange);
  9483.   self.gravity = Animated.destroySet(self.gravity);
  9484.   self.lifespan = Animated.destroySet(self.lifespan);
  9485.   self.emissionRate = Animated.destroySet(self.emissionRate);
  9486.   self.areaLength = Animated.destroySet(self.areaLength);
  9487.   self.areaWidth = Animated.destroySet(self.areaWidth);
  9488.   self.gravity2 = Animated.destroySet(self.gravity2);
  9489.   self.enabled = Animated.destroySet(self.enabled);
  9490.   self.color = self.color.destroy();
  9491.   self.alpha = self.alpha.destroy();
  9492.   self.size = self.size.destroy();
  9493.   self.intensity = self.intensity.destroy();
  9494.   self.particles = null;
  9495.   self.unusedParticles = null;
  9496.   self.tmpColors[0] = self.tmpColors[1] = self.tmpColors[2] = null;
  9497.   self.tmpColors = null;
  9498.   self.spreadMat = null;
  9499.   self.tmpMat = null
  9500.  },
  9501.  updateBuffers: function() {
  9502.   var self = this,
  9503.    gl = self.model.renderer.context,
  9504.    i, j;
  9505.   if (!self.vbData) {
  9506.    self.vbData = new Float32Array(self.maxParticles * 11);
  9507.    var ibData = new Uint16Array(self.maxParticles * 6);
  9508.    var vert = 0;
  9509.    for (i = 0; i < self.maxParticles; ++i) {
  9510.     ibData[i * 6 + 0] = vert;
  9511.     ibData[i * 6 + 1] = vert + 1;
  9512.     ibData[i * 6 + 2] = vert + 2;
  9513.     ibData[i * 6 + 3] = vert + 2;
  9514.     ibData[i * 6 + 4] = vert + 1;
  9515.     ibData[i * 6 + 5] = vert + 3;
  9516.     vert += 4
  9517.    }
  9518.    self.ib = gl.createBuffer();
  9519.    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  9520.    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, ibData, gl.STATIC_DRAW)
  9521.   }
  9522.   self.numParticles = 0;
  9523.   var p, idx = 0,
  9524.    tc, vbData = self.vbData;
  9525.   if (self.particleType == 0 || self.particleType == 2) {
  9526.    for (i = 0; i < self.maxParticles; ++i) {
  9527.     p = self.particles[i];
  9528.     if (!p || p.maxLife == 0) continue;
  9529.     tc = self.textureCoords[p.tile];
  9530.     for (j = 0; j < 4; ++j) {
  9531.      vbData[idx + 0] = p.position[0];
  9532.      vbData[idx + 1] = p.position[1];
  9533.      vbData[idx + 2] = p.position[2];
  9534.      vbData[idx + 3] = p.color[0];
  9535.      vbData[idx + 4] = p.color[1];
  9536.      vbData[idx + 5] = p.color[2];
  9537.      vbData[idx + 6] = p.color[3];
  9538.      vbData[idx + 7] = tc[j].x;
  9539.      vbData[idx + 8] = tc[j].y;
  9540.      vbData[idx + 9] = tc[j].z * p.size[0];
  9541.      vbData[idx + 10] = tc[j].w * p.size[1];
  9542.      idx += 11
  9543.     }
  9544.     self.numParticles++
  9545.    }
  9546.   } else {
  9547.    for (i = 0; i < self.maxParticles; ++i) {
  9548.     p = self.particles[i];
  9549.     if (!p || p.maxLife == 0) continue;
  9550.     tc = self.textureCoords[p.tile];
  9551.     vbData[idx + 0] = p.position[0];
  9552.     vbData[idx + 1] = p.position[1];
  9553.     vbData[idx + 2] = p.position[2];
  9554.     vbData[idx + 11] = p.position[0];
  9555.     vbData[idx + 12] = p.position[1];
  9556.     vbData[idx + 13] = p.position[2];
  9557.     vbData[idx + 22] = p.origin[0];
  9558.     vbData[idx + 23] = p.origin[1];
  9559.     vbData[idx + 24] = p.origin[2];
  9560.     vbData[idx + 33] = p.origin[0];
  9561.     vbData[idx + 34] = p.origin[1];
  9562.     vbData[idx + 35] = p.origin[2];
  9563.     for (j = 0; j < 4; ++j) {
  9564.      vbData[idx + 3] = p.color[0];
  9565.      vbData[idx + 4] = p.color[1];
  9566.      vbData[idx + 5] = p.color[2];
  9567.      vbData[idx + 6] = p.color[3];
  9568.      vbData[idx + 7] = tc[j].x;
  9569.      vbData[idx + 8] = tc[j].y;
  9570.      vbData[idx + 9] = tc[j].z * p.size[0];
  9571.      vbData[idx + 10] = tc[j].w * p.size[1];
  9572.      idx += 11
  9573.     }
  9574.     self.numParticles++
  9575.    }
  9576.   }
  9577.   if (!self.vb) {
  9578.    self.vb = gl.createBuffer();
  9579.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  9580.    gl.bufferData(gl.ARRAY_BUFFER, self.vbData, gl.DYNAMIC_DRAW)
  9581.   } else {
  9582.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  9583.    gl.bufferSubData(gl.ARRAY_BUFFER, 0, self.vbData)
  9584.   }
  9585.  },
  9586.  draw: function() {
  9587.   var self = this,
  9588.    gl = self.model.renderer.context,
  9589.    i;
  9590.   if (self.numParticles == 0) return;
  9591.   if (!self.shaderReady) self.initShader();
  9592.   if (!self.program) return;
  9593.   if (!self.texture) {
  9594.    if ((self.flags & 268435456) != 0) {
  9595.     for (i = 0; i < self.textureIds.length; i++) {
  9596.      var textureId = self.textureIds[i];
  9597.      if (textureId > -1 && textureId < self.model.materials.length) {
  9598.       var mat = self.model.materials[textureId];
  9599.       if (mat && mat.texture && mat.texture.texture && (!mat.texture.alphaImg || mat.texture.alphaTexture)) {
  9600.        if (i == 0) self.texture = mat.texture;
  9601.        else if (i == 1) self.texture2 = mat.texture;
  9602.        else self.texture3 = mat.texture
  9603.       }
  9604.      }
  9605.     }
  9606.    } else if (self.textureId > -1 && self.textureId < self.model.materials.length) {
  9607.     var mat = self.model.materials[self.textureId];
  9608.     if (mat.texture && mat.texture.texture && (!mat.texture.alphaImg || mat.texture.alphaTexture)) {
  9609.      self.texture = mat.texture
  9610.     }
  9611.    }
  9612.   }
  9613.   if (!self.texture) return;
  9614.   gl.useProgram(self.program);
  9615.   gl.uniformMatrix4fv(self.uniforms.vModelMatrix, false, self.model.matrix);
  9616.   gl.uniformMatrix4fv(self.uniforms.vViewMatrix, false, self.model.renderer.viewMatrix);
  9617.   gl.uniformMatrix4fv(self.uniforms.vProjMatrix, false, self.model.renderer.projMatrix);
  9618.   gl.uniform1i(self.uniforms.fBlendMode, self.blendMode);
  9619.   if (self.texture) {
  9620.    gl.activeTexture(gl.TEXTURE0);
  9621.    gl.bindTexture(gl.TEXTURE_2D, self.texture.texture);
  9622.    gl.uniform1i(self.uniforms.fTexture, 0)
  9623.   }
  9624.   if (self.texture && self.texture.alphaTexture) {
  9625.    gl.activeTexture(gl.TEXTURE1);
  9626.    gl.bindTexture(gl.TEXTURE_2D, self.texture.alphaTexture);
  9627.    gl.uniform1i(self.uniforms.fAlpha, 1)
  9628.   }
  9629.   if (self.texture2) {
  9630.    gl.activeTexture(gl.TEXTURE2);
  9631.    gl.bindTexture(gl.TEXTURE_2D, self.texture2.texture);
  9632.    gl.uniform1i(self.uniforms.fTexture2, 2)
  9633.   }
  9634.   if (self.texture3) {
  9635.    gl.activeTexture(gl.TEXTURE3);
  9636.    gl.bindTexture(gl.TEXTURE_2D, self.texture3.texture);
  9637.    gl.uniform1i(self.uniforms.fTexture3, 3)
  9638.   }
  9639.   gl.uniform1i(self.uniforms.fHasTexture, self.texture ? 1 : 0);
  9640.   gl.uniform1i(self.uniforms.fHasTexture2, self.texture2 ? 1 : 0);
  9641.   gl.uniform1i(self.uniforms.fHasTexture3, self.texture3 ? 1 : 0);
  9642.   gl.uniform1i(self.uniforms.fHasAlpha, self.texture && self.texture.alphaTexture ? 1 : 0);
  9643.   var blend = self.blendMode;
  9644.   if (blend == 0 || blend == 1) {
  9645.    gl.blendFunc(gl.ONE, gl.ZERO)
  9646.   } else if (blend == 2) {
  9647.    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  9648.   } else if (blend == 3) {
  9649.    gl.blendFunc(gl.SRC_COLOR, gl.ONE)
  9650.   } else if (blend == 4) {
  9651.    gl.blendFunc(gl.SRC_ALPHA, gl.ONE)
  9652.   } else if (blend == 5 || blend == 6) {
  9653.    gl.blendFunc(gl.DST_COLOR, gl.SRC_COLOR)
  9654.   } else {
  9655.    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
  9656.   }
  9657.   gl.disable(gl.CULL_FACE);
  9658.   gl.depthMask(false);
  9659.   gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  9660.   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  9661.   for (i in self.attribs) {
  9662.    var a = self.attribs[i];
  9663.    gl.enableVertexAttribArray(a.loc);
  9664.    gl.vertexAttribPointer(a.loc, a.size, a.type, false, a.stride, a.offset)
  9665.   }
  9666.   gl.drawElements(gl.TRIANGLES, self.numParticles * 6, gl.UNSIGNED_SHORT, 0);
  9667.   for (i in self.attribs) {
  9668.    gl.disableVertexAttribArray(self.attribs[i].loc)
  9669.   }
  9670.  },
  9671.  initShader: function() {
  9672.   var self = this,
  9673.    gl = self.model.renderer.context;
  9674.   self.shaderReady = true;
  9675.   var vs = self.model.renderer.compileShader(gl.VERTEX_SHADER, self.vertShader);
  9676.   var fs = self.model.renderer.compileShader(gl.FRAGMENT_SHADER, self.fragShader);
  9677.   var program = gl.createProgram();
  9678.   gl.attachShader(program, vs);
  9679.   gl.attachShader(program, fs);
  9680.   gl.linkProgram(program);
  9681.   if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  9682.    console.error("Error linking shaders");
  9683.    return
  9684.   }
  9685.   self.vs = vs;
  9686.   self.fs = fs;
  9687.   self.program = program;
  9688.   self.uniforms = {
  9689.    vModelMatrix: gl.getUniformLocation(program, "uModelMatrix"),
  9690.    vViewMatrix: gl.getUniformLocation(program, "uViewMatrix"),
  9691.    vProjMatrix: gl.getUniformLocation(program, "uProjMatrix"),
  9692.    fHasTexture: gl.getUniformLocation(program, "uHasTexture"),
  9693.    fHasTexture2: gl.getUniformLocation(program, "uHasTexture2"),
  9694.    fHasTexture3: gl.getUniformLocation(program, "uHasTexture3"),
  9695.    fHasAlpha: gl.getUniformLocation(program, "uHasAlpha"),
  9696.    fBlendMode: gl.getUniformLocation(program, "uBlendMode"),
  9697.    fTexture: gl.getUniformLocation(program, "uTexture"),
  9698.    fTexture2: gl.getUniformLocation(program, "uTexture2"),
  9699.    fTexture3: gl.getUniformLocation(program, "uTexture3"),
  9700.    fAlpha: gl.getUniformLocation(program, "uAlpha")
  9701.   };
  9702.   self.attribs = {
  9703.    position: {
  9704.     loc: gl.getAttribLocation(program, "aPosition"),
  9705.     type: gl.FLOAT,
  9706.     size: 3,
  9707.     offset: 0,
  9708.     stride: 44
  9709.    },
  9710.    normal: {
  9711.     loc: gl.getAttribLocation(program, "aColor"),
  9712.     type: gl.FLOAT,
  9713.     size: 4,
  9714.     offset: 12,
  9715.     stride: 44
  9716.    },
  9717.    texcoord: {
  9718.     loc: gl.getAttribLocation(program, "aTexCoord"),
  9719.     type: gl.FLOAT,
  9720.     size: 4,
  9721.     offset: 28,
  9722.     stride: 44
  9723.    }
  9724.   }
  9725.  },
  9726.  vertShader: "        attribute vec3 aPosition;        attribute vec4 aColor;        attribute vec4 aTexCoord;                varying vec4 vColor;        varying vec2 vTexCoord;                uniform mat4 uModelMatrix;        uniform mat4 uViewMatrix;        uniform mat4 uProjMatrix;                void main(void) {            vec4 pos = uViewMatrix * uModelMatrix * vec4(aPosition, 1);            pos.xy += aTexCoord.zw;            gl_Position = uProjMatrix * pos;                        vTexCoord = aTexCoord.xy;            vColor = aColor;        }    ",
  9727.  fragShader: "        precision mediump float;                varying vec4 vColor;        varying vec2 vTexCoord;                uniform bool uHasTexture;        uniform bool uHasTexture2;        uniform bool uHasTexture3;        uniform bool uHasAlpha;        uniform int uBlendMode;        uniform sampler2D uTexture;        uniform sampler2D uTexture2;        uniform sampler2D uTexture3;        uniform sampler2D uAlpha;                void main(void) {            vec4 color = vec4(1, 1, 1, 1);            if (uHasTexture) {                color = texture2D(uTexture, vTexCoord.st);            }            if (uHasTexture2) {                color *= texture2D(uTexture2, vTexCoord.st);            }            if (uHasTexture3) {                color *= texture2D(uTexture3, vTexCoord.st);            }            if (uBlendMode == 7) {                vec4 color2 = vec4(4, 4, 4, 4);                color *= color2;            }            if ((uBlendMode == 1 || uBlendMode == 2 || uBlendMode == 4 || uBlendMode == 7) && uHasAlpha) {                color.a = texture2D(uAlpha, vTexCoord.st).a;            }            color *= vColor;                        if (uBlendMode == 1) {                if (color.a < 0.7) { discard; }            }                        gl_FragColor = color;        }    ",
  9728.  update: function(anim, time, delta) {
  9729.   var self = this,
  9730.    Wow = ZamModelViewer.Wow;
  9731.   var grav = Wow.AnimatedFloat.getValue(self.gravity, anim, time);
  9732.   var deaccel = Wow.AnimatedFloat.getValue(self.gravity2, anim, time);
  9733.   var speed, i, j;
  9734.   if (self.emitterType == 1 || self.emitterType == 2) {
  9735.    var rate = Wow.AnimatedFloat.getValue(self.emissionRate, anim, time);
  9736.    var life = Wow.AnimatedFloat.getValue(self.lifespan, anim, time);
  9737.    var toSpawn = 0;
  9738.    if (life != 0) toSpawn = delta * rate / life + self.spawnRemainder;
  9739.    else toSpawn = self.spawnRemainder;
  9740.    if (toSpawn < 1) {
  9741.     self.spawnRemainder = toSpawn;
  9742.     if (self.spawnRemainder < 0) self.spawnRemainder = 0
  9743.    } else {
  9744.     var count = Math.min(Math.floor(toSpawn), self.nextParticle + 1);
  9745.     self.spawnRemainder = toSpawn - count;
  9746.     var en = true;
  9747.     if (Wow.Animated.isUsed(self.enabled, anim)) en = Wow.AnimatedUint8.getValue(self.enabled, anim, time) != 0;
  9748.     if (en && count > 0) {
  9749.      var w = Wow.AnimatedFloat.getValue(self.areaWidth, anim, time) * .5;
  9750.      var l = Wow.AnimatedFloat.getValue(self.areaLength, anim, time) * .5;
  9751.      speed = Wow.AnimatedFloat.getValue(self.emissionSpeed, anim, time);
  9752.      var vary = Wow.AnimatedFloat.getValue(self.speedVariation, anim, time);
  9753.      if (self.emitterType == 1) {
  9754.       for (i = 0; i < count; ++i) self.spawnPlaneParticle(w, l, speed, vary, life)
  9755.      } else {
  9756.       var vSpread = Wow.AnimatedFloat.getValue(self.verticalRange, anim, time);
  9757.       var hSpread = Wow.AnimatedFloat.getValue(self.horizontalRange, anim, time);
  9758.       for (i = 0; i < count; ++i) self.spawnSphereParticle(w, l, speed, vary, vSpread, hSpread)
  9759.      }
  9760.     }
  9761.    }
  9762.    if (isNaN(self.spawnRemainder)) self.spawnRemainder = 0
  9763.   }
  9764.   speed = 1;
  9765.   var gravDelta = grav * delta;
  9766.   var deaccelDelta = deaccel * delta;
  9767.   var speedDelta = speed * delta;
  9768.   var p, lifePos, limit, v, s1, s2, s3;
  9769.   s1 = self.size.data[0];
  9770.   if (self.size.data.length > 2) {
  9771.    s2 = self.size.data[1];
  9772.    s3 = self.size.data[2]
  9773.   } else if (self.size.data.length > 1) {
  9774.    s2 = self.size.data[1];
  9775.    s3 = s2
  9776.   } else {
  9777.    s3 = s2 = s1
  9778.   }
  9779.   for (i = 0; i < self.maxParticles; ++i) {
  9780.    p = self.particles[i];
  9781.    if (!p || p.maxLife == 0) continue;
  9782.    p.life += delta;
  9783.    lifePos = p.life / p.maxLife;
  9784.    if (lifePos >= 1) {
  9785.     p.maxLife = 0;
  9786.     self.nextParticle++;
  9787.     self.unusedParticles[self.nextParticle] = p.index;
  9788.     continue
  9789.    }
  9790.    vec3.scaleAndAdd(p.speed, p.speed, p.down, gravDelta);
  9791.    vec3.scaleAndAdd(p.speed, p.speed, p.direction, -deaccelDelta);
  9792.    if (self.slowdown > 0) {
  9793.     speed = Math.exp(-1 * self.slowdown * p.life);
  9794.     speedDelta = speed * delta
  9795.    }
  9796.    vec3.scaleAndAdd(p.position, p.position, p.speed, speedDelta);
  9797.    if (lifePos <= .5) {
  9798.     vec2.lerp(p.size, s1, s2, lifePos / .5)
  9799.    } else {
  9800.     vec2.lerp(p.size, s2, s3, (lifePos - .5) / .5)
  9801.    }
  9802.    vec2.multiply(p.size, p.size, self.scale);
  9803.    limit = Math.min(3, self.color.data.length);
  9804.    for (j = 0; j < limit; ++j) {
  9805.     v = self.color.data[j];
  9806.     vec4.set(self.tmpColors[j], v[0] / 255, v[1] / 255, v[2] / 255, self.alpha.data[j] / 32767)
  9807.    }
  9808.    if (limit < 3) {
  9809.     v = self.color.data[limit - 1];
  9810.     for (j = limit; j < 3; ++j) vec4.set(self.tmpColors[j], v[0] / 255, v[1] / 255, v[2] / 255, self.alpha.data[j] / 32767)
  9811.    }
  9812.    if (lifePos <= .5) {
  9813.     vec4.lerp(p.color, self.tmpColors[0], self.tmpColors[1], lifePos / .5)
  9814.    } else {
  9815.     vec4.lerp(p.color, self.tmpColors[1], self.tmpColors[2], (lifePos - .5) / .5)
  9816.    }
  9817.   }
  9818.   self.updateBuffers()
  9819.  },
  9820.  getNextParticle: function() {
  9821.   var self = this;
  9822.   if (self.nextParticle < 0) return null;
  9823.   var index = self.unusedParticles[self.nextParticle];
  9824.   if (!self.particles[index]) {
  9825.    self.particles[index] = {
  9826.     index: index,
  9827.     position: vec3.create(),
  9828.     origin: vec3.create(),
  9829.     speed: vec4.create(),
  9830.     direction: vec4.create(),
  9831.     down: vec3.create(),
  9832.     color: vec4.create(),
  9833.     size: vec2.create(),
  9834.     life: 0,
  9835.     maxLife: 0,
  9836.     tile: 0
  9837.    }
  9838.   }
  9839.   self.nextParticle--;
  9840.   return self.particles[index]
  9841.  },
  9842.  spawnPlaneParticle: function(width, height, speed, vary, life) {
  9843.   var self = this,
  9844.    p = self.getNextParticle();
  9845.   if (!p) return null;
  9846.   vec3.copy(p.position, self.position);
  9847.   p.position[0] += -width / 2 + width * Math.random();
  9848.   p.position[1] += -height / 2 + height * Math.random();
  9849.   vec3.transformMat4(p.position, p.position, self.bone.matrix);
  9850.   vec4.set(p.direction, 0, 0, 1, 0);
  9851.   vec4.transformMat4(p.direction, p.direction, self.bone.matrix);
  9852.   vec3.normalize(p.direction, p.direction);
  9853.   vec4.copy(p.speed, p.direction);
  9854.   var v1 = speed - speed * vary,
  9855.    v2 = speed + speed * vary;
  9856.   vec4.scale(p.speed, p.speed, v1 + (v2 - v1) * Math.random());
  9857.   vec3.set(p.down, 0, 0, -1);
  9858.   p.life = 0;
  9859.   p.maxLife = life;
  9860.   if (!p.maxLife) p.maxLife = 1;
  9861.   vec3.copy(p.origin, p.position);
  9862.   p.tile = Math.floor(Math.random() * self.tileRows * self.tileColumns);
  9863.   vec4.set(p.color, 1, 1, 1, 1);
  9864.   return p
  9865.  },
  9866.  spawnSphereParticle: function(width, height, speed, vary, spread, spread2, life) {
  9867.   var self = this,
  9868.    p = self.getNextParticle();
  9869.   if (!p) return null;
  9870.   var radius = Math.random(),
  9871.    t = 0;
  9872.   if (spread == 0) {
  9873.    t = Math.random() * Math.PI * 2 - Math.PI
  9874.   } else {
  9875.    t = Math.random() * spread * 2 - spread
  9876.   }
  9877.   self.calcSpread(spread * 2, spread * 2, width, height);
  9878.   if ((self.flags & 57) == 57 || (self.flags & 313) == 313) {
  9879.    vec3.copy(p.position, self.position);
  9880.    vec4.set(p.direction, width * Math.cos(t) * 1.6, height * Math.sin(t) * 1.6, 0, 0);
  9881.    vec3.add(p.position, p.position, p.direction);
  9882.    vec3.transformMat4(p.position, p.position, self.bone.matrix);
  9883.    if (vec3.squaredLength(p.direction) == 0) {
  9884.     vec4.set(p.speed, 0, 0, 0, 0)
  9885.    } else {
  9886.     vec4.transformMat4(p.direction, p.direction, self.bone.matrix);
  9887.     vec3.normalize(p.direction, p.direction);
  9888.     vec3.copy(p.speed, p.direction);
  9889.     vec3.scale(p.speed, p.speed, speed * (1 + Math.random() * vary * 2 - vary))
  9890.    }
  9891.   } else {
  9892.    vec4.set(p.direction, 0, 0, 1, 0);
  9893.    vec4.transformMat4(p.direction, p.direction, self.spreadMat);
  9894.    vec3.scale(p.direction, p.direction, radius);
  9895.    vec3.copy(p.position, self.position);
  9896.    vec3.add(p.position, p.position, p.direction);
  9897.    vec3.transformMat4(p.position, p.position, self.bone.matrix);
  9898.    if (vec3.squaredLength(p.direction) == 0 && (self.flags & 256) == 0) {
  9899.     vec4.set(p.speed, 0, 0, 0, 0);
  9900.     vec4.set(p.direction, 0, 0, 1, 0);
  9901.     vec4.transformMat4(p.direction, p.direction, self.bone.matrix);
  9902.     vec3.normalize(p.direction, p.direction)
  9903.    } else {
  9904.     if ((self.flags & 256) > 0) {
  9905.      vec4.set(p.direction, 0, 0, 1, 0);
  9906.      vec4.transformMat4(p.direction, p.direction, self.bone.matrix)
  9907.     }
  9908.     vec3.normalize(p.direction, p.direction);
  9909.     vec4.copy(p.speed, p.direction);
  9910.     vec3.scale(p.speed, p.speed, speed * (1 + Math.random() * vary * 2 - vary))
  9911.    }
  9912.   }
  9913.   vec3.set(p.down, 0, 0, -1);
  9914.   p.life = 0;
  9915.   p.maxLife = life;
  9916.   if (!p.maxLife) p.maxLife = 1;
  9917.   vec3.copy(p.origin, p.position);
  9918.   p.tile = Math.floor(Math.random() * self.tileRows * self.tileColumns);
  9919.   vec4.set(p.color, 1, 1, 1, 1);
  9920.   return p
  9921.  },
  9922.  calcSpread: function(spread1, spread2, width, height) {
  9923.   var self = this,
  9924.    mat = this.spreadMat,
  9925.    tmpMat = this.tmpMat;
  9926.   var a0 = (Math.random() * (spread1 * 2) - spread1) / 2,
  9927.    a1 = (Math.random() * (spread2 * 2) - spread2) / 2;
  9928.   var c0 = Math.cos(a0),
  9929.    c1 = Math.cos(a1),
  9930.    s0 = Math.sin(a0),
  9931.    s1 = Math.sin(a1);
  9932.   mat4.identity(mat);
  9933.   mat4.identity(tmpMat);
  9934.   tmpMat[5] = tmpMat[10] = c0;
  9935.   tmpMat[9] = s0;
  9936.   tmpMat[6] = -s0;
  9937.   mat4.multiply(mat, mat, tmpMat);
  9938.   mat4.identity(tmpMat);
  9939.   tmpMat[0] = tmpMat[10] = c1;
  9940.   tmpMat[2] = s1;
  9941.   tmpMat[8] = -s1;
  9942.   mat4.multiply(mat, mat, tmpMat);
  9943.   var size = Math.abs(c0) * height * Math.abs(s0) * width;
  9944.   mat[0] *= size;
  9945.   mat[1] *= size;
  9946.   mat[2] *= size;
  9947.   mat[4] *= size;
  9948.   mat[5] *= size;
  9949.   mat[6] *= size;
  9950.   mat[8] *= size;
  9951.   mat[9] *= size;
  9952.   mat[10] *= size;
  9953.   mat4.multiply(mat, self.bone.matrix, mat);
  9954.   return mat
  9955.  },
  9956.  init: function() {
  9957.   var self = this;
  9958.   if (self.scale.z == 519) self.scale.z = 1.5;
  9959.   var numTiles = self.tileRows * self.tileColumns;
  9960.   self.textureCoords = new Array(numTiles);
  9961.   var a = {
  9962.     x: 0,
  9963.     y: 0
  9964.    },
  9965.    b = {
  9966.     x: 0,
  9967.     y: 0
  9968.    };
  9969.   var i, x, y;
  9970.   for (i = 0; i < numTiles; ++i) {
  9971.    x = i % self.tileColumns;
  9972.    y = Math.floor(i / self.tileColumns);
  9973.    a.x = x * (1 / self.tileColumns);
  9974.    b.x = (x + 1) * (1 / self.tileColumns);
  9975.    a.y = y * (1 / self.tileRows);
  9976.    b.y = (y + 1) * (1 / self.tileRows);
  9977.    self.textureCoords[i] = [{
  9978.     x: a.x,
  9979.     y: a.y,
  9980.     z: -1,
  9981.     w: 1
  9982.    }, {
  9983.     x: b.x,
  9984.     y: a.y,
  9985.     z: 1,
  9986.     w: 1
  9987.    }, {
  9988.     x: a.x,
  9989.     y: b.y,
  9990.     z: -1,
  9991.     w: -1
  9992.    }, {
  9993.     x: b.x,
  9994.     y: b.y,
  9995.     z: 1,
  9996.     w: -1
  9997.    }]
  9998.   }
  9999.  }
  10000. };
  10001. ZamModelViewer.Wow.RibbonEmitter = function(model, r) {
  10002.  var self = this,
  10003.   Wow = ZamModelViewer.Wow,
  10004.   i;
  10005.  self.model = model;
  10006.  self.id = r.getInt32();
  10007.  self.boneId = r.getInt32();
  10008.  self.position = [r.getFloat(), r.getFloat(), r.getFloat()];
  10009.  self.resolution = r.getFloat();
  10010.  self.length = r.getFloat();
  10011.  self.emissionAngle = r.getFloat();
  10012.  self.s1 = r.getInt16();
  10013.  self.s2 = r.getInt16();
  10014.  var count = r.getInt32();
  10015.  if (count > 0) {
  10016.   self.textureIds = new Array(count);
  10017.   for (i = 0; i < count; ++i) {
  10018.    self.textureIds[i] = r.getInt32()
  10019.   }
  10020.  }
  10021.  self.color = Wow.AnimatedVec3.readSet(r);
  10022.  self.alpha = Wow.AnimatedUint16.readSet(r);
  10023.  self.above = Wow.AnimatedFloat.readSet(r);
  10024.  self.below = Wow.AnimatedFloat.readSet(r);
  10025.  self.bone = self.model.bones[self.boneId];
  10026.  self.maxSegments = 50;
  10027.  self.segments = new Array(self.maxSegments);
  10028.  for (i = 0; i < self.maxSegments; ++i) {
  10029.   self.segments[i] = {
  10030.    position: vec3.create(),
  10031.    start: vec3.create(),
  10032.    up: vec4.create(),
  10033.    length: 0
  10034.   }
  10035.  }
  10036.  self.currentSegment = 0;
  10037.  self.numSegments = 0;
  10038.  self.totalLength = self.resolution / self.length;
  10039.  self.currentPosition = vec3.clone(self.position);
  10040.  self.currentColor = vec4.create();
  10041.  self.currentAbove = 0;
  10042.  self.currentBelow = 0;
  10043.  self.currentLength = 0;
  10044.  self.tmpPosition = vec3.create();
  10045.  self.tmpUp = vec4.create();
  10046.  self.tmpVec = vec4.create()
  10047. };
  10048. ZamModelViewer.Wow.RibbonEmitter.prototype = {
  10049.  destroy: function() {
  10050.   var self = this,
  10051.    gl = self.model.renderer.context,
  10052.    Animated = ZamModelViewer.Wow.Animated;
  10053.   if (self.program) gl.deleteProgram(self.program);
  10054.   if (self.vs) gl.deleteShader(self.vs);
  10055.   if (self.fs) gl.deleteShader(self.fs);
  10056.   if (self.vb) gl.deleteBuffer(self.vb);
  10057.   if (self.ib) gl.deleteBuffer(self.ib);
  10058.   self.program = null;
  10059.   self.vs = null;
  10060.   self.fs = null;
  10061.   self.vb = null;
  10062.   self.ib = null;
  10063.   self.vbData = null;
  10064.   self.uniforms = null;
  10065.   self.attribs = null;
  10066.   self.texture = null;
  10067.   self.model = null;
  10068.   self.bone = null;
  10069.   self.position = null;
  10070.   self.textureIds = null;
  10071.   for (var i = 0; i < self.maxSegments; ++i) {
  10072.    self.segments[i].position = null;
  10073.    self.segments[i].start = null;
  10074.    self.segments[i].up = null;
  10075.    self.segments[i] = null
  10076.   }
  10077.   self.segments = null;
  10078.   self.currentPosition = null;
  10079.   self.currentColor = null;
  10080.   self.tmpPosition = null;
  10081.   self.tmpUp = null;
  10082.   self.tmpVec = null;
  10083.   self.color = Animated.destroySet(self.color);
  10084.   self.alpha = Animated.destroySet(self.alpha);
  10085.   self.above = Animated.destroySet(self.above);
  10086.   self.below = Animated.destroySet(self.below)
  10087.  },
  10088.  updateBuffers: function() {
  10089.   var self = this,
  10090.    gl = self.model.renderer.context,
  10091.    i, j;
  10092.   if (!self.vbData) {
  10093.    self.vbData = new Float32Array((self.maxSegments * 2 + 2) * 5);
  10094.    var ibData = new Uint16Array(self.maxSegments * 6);
  10095.    var vert = 0;
  10096.    for (i = 0; i < self.maxSegments; ++i) {
  10097.     ibData[i * 6 + 0] = vert;
  10098.     ibData[i * 6 + 1] = vert + 1;
  10099.     ibData[i * 6 + 2] = vert + 2;
  10100.     ibData[i * 6 + 3] = vert + 2;
  10101.     ibData[i * 6 + 4] = vert + 1;
  10102.     ibData[i * 6 + 5] = vert + 3;
  10103.     vert += 2
  10104.    }
  10105.    self.ib = gl.createBuffer();
  10106.    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  10107.    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, ibData, gl.STATIC_DRAW)
  10108.   }
  10109.   if (self.numSegments == 0) return;
  10110.   var s = self.segments[self.currentSegment],
  10111.    n = 0,
  10112.    u, u2, l = 0,
  10113.    vbData = self.vbData;
  10114.   var above = self.currentAbove,
  10115.    below = self.currentBelow;
  10116.   vbData[n] = s.start[0] + s.up[0] * above;
  10117.   vbData[n + 1] = s.start[1] + s.up[1] * above;
  10118.   vbData[n + 2] = s.start[2] + s.up[2] * above;
  10119.   vbData[n + 3] = 1;
  10120.   vbData[n + 4] = 0;
  10121.   n += 5;
  10122.   vbData[n] = s.start[0] - s.up[0] * below;
  10123.   vbData[n + 1] = s.start[1] - s.up[1] * below;
  10124.   vbData[n + 2] = s.start[2] - s.up[2] * below;
  10125.   vbData[n + 3] = 1;
  10126.   vbData[n + 4] = 1;
  10127.   n += 5;
  10128.   for (i = 0; i < self.numSegments; ++i) {
  10129.    s = self.segments[(self.currentSegment + i) % self.maxSegments];
  10130.    u = 1 - (self.currentLength != 0 ? l / self.currentLength : 0);
  10131.    u2 = 1 - (self.currentLength != 0 ? (l + s.length) / self.currentLength : 1);
  10132.    vbData[n] = s.position[0] + s.up[0] * above;
  10133.    vbData[n + 1] = s.position[1] + s.up[1] * above;
  10134.    vbData[n + 2] = s.position[2] + s.up[2] * above;
  10135.    vbData[n + 3] = u2;
  10136.    vbData[n + 4] = 0;
  10137.    n += 5;
  10138.    vbData[n] = s.position[0] - s.up[0] * below;
  10139.    vbData[n + 1] = s.position[1] - s.up[1] * below;
  10140.    vbData[n + 2] = s.position[2] - s.up[2] * below;
  10141.    vbData[n + 3] = u2;
  10142.    vbData[n + 4] = 1;
  10143.    n += 5;
  10144.    l += s.length
  10145.   }
  10146.   if (!self.vb) {
  10147.    self.vb = gl.createBuffer();
  10148.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  10149.    gl.bufferData(gl.ARRAY_BUFFER, self.vbData, gl.DYNAMIC_DRAW)
  10150.   } else {
  10151.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  10152.    gl.bufferSubData(gl.ARRAY_BUFFER, 0, self.vbData)
  10153.   }
  10154.  },
  10155.  draw: function() {
  10156.   var self = this,
  10157.    gl = self.model.renderer.context,
  10158.    i;
  10159.   if (self.numSegments == 0) return;
  10160.   if (!self.shaderReady) self.initShader();
  10161.   if (!self.program) return;
  10162.   if (!self.texture && self.textureIds[0] > -1 && self.textureIds[0] < self.model.materials.length) {
  10163.    var mat = self.model.materials[self.textureIds[0]];
  10164.    if (mat.texture && mat.texture.texture && (!mat.texture.alphaImg || mat.texture.alphaTexture)) {
  10165.     self.texture = mat.texture
  10166.    }
  10167.   }
  10168.   if (!self.texture) return;
  10169.   gl.useProgram(self.program);
  10170.   gl.uniformMatrix4fv(self.uniforms.vModelMatrix, false, self.model.matrix);
  10171.   gl.uniformMatrix4fv(self.uniforms.vViewMatrix, false, self.model.renderer.viewMatrix);
  10172.   gl.uniformMatrix4fv(self.uniforms.vProjMatrix, false, self.model.renderer.projMatrix);
  10173.   gl.uniform4fv(self.uniforms.fColor, self.currentColor);
  10174.   if (self.texture) {
  10175.    gl.activeTexture(gl.TEXTURE0);
  10176.    gl.bindTexture(gl.TEXTURE_2D, self.texture.texture);
  10177.    gl.uniform1i(self.uniforms.fTexture, 0)
  10178.   }
  10179.   if (self.texture && self.texture.alphaTexture) {
  10180.    gl.activeTexture(gl.TEXTURE1);
  10181.    gl.bindTexture(gl.TEXTURE_2D, self.texture.alphaTexture);
  10182.    gl.uniform1i(self.uniforms.fAlpha, 1)
  10183.   }
  10184.   gl.uniform1i(self.uniforms.fHasTexture, self.texture ? 1 : 0);
  10185.   gl.uniform1i(self.uniforms.fHasAlpha, self.texture && self.texture.alphaTexture ? 1 : 0);
  10186.   gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
  10187.   gl.disable(gl.CULL_FACE);
  10188.   gl.depthMask(false);
  10189.   gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  10190.   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  10191.   for (i in self.attribs) {
  10192.    var a = self.attribs[i];
  10193.    gl.enableVertexAttribArray(a.loc);
  10194.    gl.vertexAttribPointer(a.loc, a.size, a.type, false, a.stride, a.offset)
  10195.   }
  10196.   gl.drawElements(gl.TRIANGLES, self.numSegments * 6, gl.UNSIGNED_SHORT, 0);
  10197.   for (i in self.attribs) {
  10198.    gl.disableVertexAttribArray(self.attribs[i].loc)
  10199.   }
  10200.  },
  10201.  initShader: function() {
  10202.   var self = this,
  10203.    gl = self.model.renderer.context;
  10204.   self.shaderReady = true;
  10205.   var vs = self.model.renderer.compileShader(gl.VERTEX_SHADER, self.vertShader);
  10206.   var fs = self.model.renderer.compileShader(gl.FRAGMENT_SHADER, self.fragShader);
  10207.   var program = gl.createProgram();
  10208.   gl.attachShader(program, vs);
  10209.   gl.attachShader(program, fs);
  10210.   gl.linkProgram(program);
  10211.   if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  10212.    console.error("Error linking shaders");
  10213.    return
  10214.   }
  10215.   self.vs = vs;
  10216.   self.fs = fs;
  10217.   self.program = program;
  10218.   self.uniforms = {
  10219.    vModelMatrix: gl.getUniformLocation(program, "uModelMatrix"),
  10220.    vViewMatrix: gl.getUniformLocation(program, "uViewMatrix"),
  10221.    vProjMatrix: gl.getUniformLocation(program, "uProjMatrix"),
  10222.    fHasTexture: gl.getUniformLocation(program, "uHasTexture"),
  10223.    fHasAlpha: gl.getUniformLocation(program, "uHasAlpha"),
  10224.    fTexture: gl.getUniformLocation(program, "uTexture"),
  10225.    fAlpha: gl.getUniformLocation(program, "uAlpha"),
  10226.    fColor: gl.getUniformLocation(program, "uColor")
  10227.   };
  10228.   self.attribs = {
  10229.    position: {
  10230.     loc: gl.getAttribLocation(program, "aPosition"),
  10231.     type: gl.FLOAT,
  10232.     size: 3,
  10233.     offset: 0,
  10234.     stride: 20
  10235.    },
  10236.    texcoord: {
  10237.     loc: gl.getAttribLocation(program, "aTexCoord"),
  10238.     type: gl.FLOAT,
  10239.     size: 2,
  10240.     offset: 12,
  10241.     stride: 20
  10242.    }
  10243.   }
  10244.  },
  10245.  vertShader: "        attribute vec3 aPosition;        attribute vec2 aTexCoord;                varying vec2 vTexCoord;                uniform mat4 uModelMatrix;        uniform mat4 uViewMatrix;        uniform mat4 uProjMatrix;                void main(void) {            gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition, 1);                        vTexCoord = aTexCoord;        }    ",
  10246.  fragShader: "        precision mediump float;                varying vec2 vTexCoord;                uniform bool uHasTexture;        uniform bool uHasAlpha;        uniform sampler2D uTexture;        uniform sampler2D uAlpha;        uniform vec4 uColor;                void main(void) {            vec4 color = vec4(1, 1, 1, 1);            if (uHasTexture) {                color = texture2D(uTexture, vTexCoord.st);            }            if (uHasAlpha) {                color.a = texture2D(uAlpha, vTexCoord.st).a;            }                        gl_FragColor = color * uColor;        }    ",
  10247.  update: function(anim, time) {
  10248.   var self = this,
  10249.    Wow = ZamModelViewer.Wow,
  10250.    i, s;
  10251.   vec3.transformMat4(self.tmpPosition, self.position, self.bone.matrix);
  10252.   vec4.set(self.tmpUp, 0, 0, 1, 0);
  10253.   vec4.transformMat4(self.tmpUp, self.tmpUp, self.bone.matrix);
  10254.   vec3.normalize(self.tmpUp, self.tmpUp);
  10255.   if (self.numSegments == 0) {
  10256.    s = self.pushSegment();
  10257.    vec3.copy(s.start, self.tmpPosition);
  10258.    vec3.copy(s.position, self.tmpPosition);
  10259.    vec4.copy(s.up, self.tmpUp);
  10260.    s.length = 0
  10261.   } else {
  10262.    var currIdx = (self.currentSegment + self.numSegments - 1) % self.maxSegments;
  10263.    s = self.segments[currIdx];
  10264.    vec3.copy(s.position, self.tmpPosition);
  10265.    vec4.copy(s.up, self.tmpUp);
  10266.    vec3.subtract(self.tmpVec, s.position, self.currentPosition);
  10267.    s.length += vec3.length(self.tmpVec);
  10268.    if (s.length >= self.length) {
  10269.     s = self.pushSegment();
  10270.     vec3.copy(s.start, self.tmpPosition);
  10271.     vec3.copy(s.position, self.tmpPosition);
  10272.     vec4.copy(s.up, self.tmpUp);
  10273.     s.length = 0
  10274.    }
  10275.   }
  10276.   self.currentLength = 0;
  10277.   var idx;
  10278.   for (i = 0; i < self.numSegments; ++i) {
  10279.    idx = (self.currentSegment + i) % self.maxSegments;
  10280.    self.currentLength += self.segments[idx].length
  10281.   }
  10282.   if (self.currentLength > self.totalLength + .1) {
  10283.    self.currentLength -= self.segments[self.currentSegment].length;
  10284.    self.shiftSegment()
  10285.   }
  10286.   vec3.copy(self.currentPosition, self.tmpPosition);
  10287.   Wow.AnimatedVec3.getValue(self.color, anim, time, self.currentColor);
  10288.   self.currentColor[3] = Wow.AnimatedUint16.getValue(self.alpha, anim, time) / 32767;
  10289.   self.currentAbove = Wow.AnimatedFloat.getValue(self.above, anim, time);
  10290.   self.currentBelow = Wow.AnimatedFloat.getValue(self.below, anim, time);
  10291.   self.updateBuffers()
  10292.  },
  10293.  pushSegment: function() {
  10294.   var self = this;
  10295.   if (self.numSegments < self.maxSegments) {
  10296.    self.numSegments++
  10297.   } else {
  10298.    self.currentSegment = (self.currentSegment + 1) % self.maxSegments
  10299.   }
  10300.   return self.segments[self.currentSegment]
  10301.  },
  10302.  popSegment: function() {
  10303.   var self = this;
  10304.   self.numSegments--
  10305.  },
  10306.  shiftSegment: function() {
  10307.   var self = this;
  10308.   self.currentSegment = (self.currentSegment + 1) % self.maxSegments;
  10309.   self.numSegments--
  10310.  }
  10311. };
  10312. ZamModelViewer.Wow.Skin = function(r, version) {
  10313.  var self = this;
  10314.  self.skinFlags = version > 2e3 ? r.getUint32() : 0;
  10315.  self.base = r.getUint32();
  10316.  self.fur = r.getUint32();
  10317.  self.underwearFlags = version > 2e3 ? r.getUint32() : 0;
  10318.  self.panties = r.getUint32();
  10319.  self.bra = r.getUint32();
  10320.  self.faces = null
  10321. };
  10322. ZamModelViewer.Wow.Skin._lastFaces = null;
  10323. ZamModelViewer.Wow.Skin.GetSkins = function(skins, playerOnly, dk) {
  10324.  if (!skins) return [];
  10325.  var list = [];
  10326.  for (var i = 0; i < skins.length; ++i) {
  10327.   if (playerOnly && (skins[i].skinFlags & 3) > 0) {
  10328.    if ((skins[i].skinFlags & 4) > 0) {
  10329.     if (dk) list.push(skins[i])
  10330.    } else {
  10331.     list.push(skins[i])
  10332.    }
  10333.   } else if (!playerOnly || skins[i].skinFlags == 0) {
  10334.    list.push(skins[i])
  10335.   }
  10336.  }
  10337.  return list
  10338. };
  10339. ZamModelViewer.Wow.Skin.GetFaces = function(faces, playerOnly, dk, skinFlags) {
  10340.  if (!faces || dk && (skinFlags & 4) > 0) return [];
  10341.  var list = [];
  10342.  for (var i = 0; i < faces.length; ++i) {
  10343.   if (playerOnly && (faces[i].flags & 3) > 0) {
  10344.    if ((faces[i].flags & 4) > 0) {
  10345.     if (dk) list.push(faces[i])
  10346.    } else {
  10347.     list.push(faces[i])
  10348.    }
  10349.   } else if (!playerOnly || faces[i].flags == 0) {
  10350.    list.push(faces[i])
  10351.   }
  10352.  }
  10353.  return list
  10354. };
  10355. ZamModelViewer.Wow.Skin.prototype = {
  10356.  destroy: function() {
  10357.   var self = this;
  10358.   if (self.faces) {
  10359.    for (var i = 0; i < self.faces.length; ++i) self.faces[i] = null;
  10360.    self.faces = null
  10361.   }
  10362.  },
  10363.  readFaces: function(r, version) {
  10364.   var self = this;
  10365.   var count = r.getInt32();
  10366.   if (count == 0 && ZamModelViewer.Wow.Skin._lastFaces) {
  10367.    self.faces = ZamModelViewer.Wow.Skin._lastFaces
  10368.   } else if (count > 0) {
  10369.    self.faces = new Array(count);
  10370.    for (var i = 0; i < count; ++i) {
  10371.     self.faces[i] = {
  10372.      flags: version > 2e3 ? r.getUint32() : 0,
  10373.      lower: r.getUint32(),
  10374.      upper: r.getUint32()
  10375.     };
  10376.     ZamModelViewer.Wow.Skin._lastFaces = self.faces[i]
  10377.    }
  10378.   }
  10379.  }
  10380. };
  10381. ZamModelViewer.Wow.Face = function(r) {
  10382.  var self = this;
  10383.  self.geoset1 = r.getInt32();
  10384.  self.geoset2 = r.getInt32();
  10385.  self.geoset3 = r.getInt32();
  10386.  self.textures = null
  10387. };
  10388. ZamModelViewer.Wow.Face.GetTextures = function(textures, playerOnly, dk) {
  10389.  if (!textures) return [];
  10390.  var list = [];
  10391.  for (var i = 0; i < textures.length; ++i) {
  10392.   if (playerOnly && (textures[i].flags & 3) > 0) {
  10393.    if ((textures[i].flags & 4) > 0) {
  10394.     if (dk) list.push(textures[i])
  10395.    } else {
  10396.     list.push(textures[i])
  10397.    }
  10398.   } else if (!playerOnly || textures[i].flags == 0) {
  10399.    list.push(textures[i])
  10400.   }
  10401.  }
  10402.  return list
  10403. };
  10404. ZamModelViewer.Wow.Face.prototype = {
  10405.  destroy: function() {
  10406.   var self = this;
  10407.   if (self.textures) {
  10408.    for (var i = 0; i < self.textures.length; ++i) self.textures[i] = null;
  10409.    self.textures = null
  10410.   }
  10411.  },
  10412.  readTextures: function(r, version) {
  10413.   var self = this;
  10414.   var count = r.getInt32();
  10415.   if (count > 0) {
  10416.    self.textures = new Array(count);
  10417.    for (var i = 0; i < count; ++i) {
  10418.     self.textures[i] = {
  10419.      flags: version > 2e3 ? r.getUint32() : 0,
  10420.      lower: r.getUint32(),
  10421.      upper: r.getUint32()
  10422.     }
  10423.    }
  10424.   }
  10425.  }
  10426. };
  10427. ZamModelViewer.Wow.Hair = function(r) {
  10428.  var self = this;
  10429.  self.geoset = r.getUint8();
  10430.  self.textures = null
  10431. };
  10432. ZamModelViewer.Wow.Hair.GetTextures = function(textures, playerOnly, dk) {
  10433.  if (!textures) return [];
  10434.  var list = [];
  10435.  for (var i = 0; i < textures.length; ++i) {
  10436.   if (textures[i].flags != 0) {
  10437.    if (playerOnly && (textures[i].flags & 3) > 0) {
  10438.     if ((textures[i].flags & 4) > 0) {
  10439.      if (dk) list.push(textures[i])
  10440.     } else {
  10441.      list.push(textures[i])
  10442.     }
  10443.    } else if (!playerOnly || textures[i].flags == 0) {
  10444.     list.push(textures[i])
  10445.    }
  10446.   }
  10447.  }
  10448.  return list
  10449. };
  10450. ZamModelViewer.Wow.Hair.prototype = {
  10451.  destroy: function() {
  10452.   var self = this;
  10453.   if (self.textures) {
  10454.    for (var i = 0; i < self.textures.length; ++i) self.textures[i] = null;
  10455.    self.textures = null
  10456.   }
  10457.  },
  10458.  readTextures: function(r, version) {
  10459.   var self = this;
  10460.   var count = r.getInt32();
  10461.   if (count > 0) {
  10462.    self.textures = new Array(count);
  10463.    for (var i = 0; i < count; ++i) {
  10464.     self.textures[i] = {
  10465.      flags: version > 2e3 ? r.getUint32() : 0,
  10466.      texture: r.getUint32(),
  10467.      lower: r.getUint32(),
  10468.      upper: r.getUint32()
  10469.     };
  10470.     if (self.textures[i].upper > 0 && self.textures[i].lower > 0) {
  10471.      var str = ""
  10472.     }
  10473.    }
  10474.   }
  10475.  }
  10476. };
  10477. ZamModelViewer.Wow.Horns = function(r) {
  10478.  this.geoset = r.getUint8()
  10479. };
  10480. ZamModelViewer.Wow.Horns.prototype = {
  10481.  destroy: function() {
  10482.   this.geoset = null
  10483.  }
  10484. };
  10485. ZamModelViewer.Wow.Blindfolds = function(r) {
  10486.  this.geoset = r.getUint8()
  10487. };
  10488. ZamModelViewer.Wow.Blindfolds.prototype = {
  10489.  destroy: function() {
  10490.   this.geoset = null
  10491.  }
  10492. };
  10493. ZamModelViewer.Wow.ColoredHands = function(r) {
  10494.  this.colorIndex = r.getUint8()
  10495. };
  10496. ZamModelViewer.Wow.ColoredHands.prototype = {
  10497.  destroy: function() {
  10498.   this.colorIndex = null
  10499.  }
  10500. };
  10501. ZamModelViewer.Wow.Tattoos = function(r) {
  10502.  this.texture = r.getInt32()
  10503. };
  10504. ZamModelViewer.Wow.Tattoos.prototype = {
  10505.  destroy: function() {
  10506.   this.texture = null
  10507.  }
  10508. };
  10509. ZamModelViewer.Wow.HornModel = function(model, slot, id, race, gender) {
  10510.  var self = this;
  10511.  self.model = model;
  10512.  self.slot = slot;
  10513.  self.uniqueSlot = ZamModelViewer.Wow.UniqueSlots[slot];
  10514.  self.sortValue = ZamModelViewer.Wow.SlotOrder[slot];
  10515.  self.models = null;
  10516.  self.geosets = null;
  10517.  self.textures = null;
  10518.  self.geoA = 0;
  10519.  self.geoB = 0;
  10520.  self.geoC = 0;
  10521.  self.loaded = false;
  10522.  if (id) {
  10523.   self.load(id, race, gender)
  10524.  }
  10525. };
  10526. ZamModelViewer.Wow.HornModel.prototype = {
  10527.  destroy: function() {
  10528.   var self = this,
  10529.    i;
  10530.   self.model = null;
  10531.   if (self.models) {
  10532.    for (i = 0; i < self.models.length; ++i) {
  10533.     if (self.models[i].model) self.models[i].model.destroy();
  10534.     self.models[i].model = null;
  10535.     self.models[i].attachment = null;
  10536.     self.models[i] = null
  10537.    }
  10538.    self.models = null
  10539.   }
  10540.   if (self.textures) {
  10541.    for (i = 0; i < self.textures; ++i) {
  10542.     if (self.textures[i].texture) self.textures[i].texture.destroy();
  10543.     self.textures[i].texture = null;
  10544.     self.textures[i] = null
  10545.    }
  10546.    self.textures = null
  10547.   }
  10548.   self.geosets = null
  10549.  },
  10550.  load: function(id, race, gender) {
  10551.   var self = this,
  10552.    Wow = ZamModelViewer.Wow;
  10553.   self.id = id;
  10554.   self.meta = {};
  10555.   self.models = new Array(3);
  10556.   var slotMap = {
  10557.    0: 6,
  10558.    1: 1,
  10559.    2: 1,
  10560.    3: 10
  10561.   };
  10562.   if (self.models) {
  10563.    for (var i = 0; i < self.models.length; ++i) {
  10564.     self.models[i] = {
  10565.      race: race,
  10566.      gender: gender,
  10567.      bone: -1,
  10568.      attachment: null,
  10569.      model: null
  10570.     };
  10571.     var modelInfo = {
  10572.      type: 256,
  10573.      id: self.id,
  10574.      parent: self.model
  10575.     };
  10576.     modelInfo.shoulder = i + 1;
  10577.     self.models[i].model = new Wow.Model(self.model.renderer, self.model.viewer, modelInfo, i);
  10578.     self.models[i].slot = slotMap[i]
  10579.    }
  10580.    self.loaded = true
  10581.   }
  10582.  }
  10583. };
  10584. ZamModelViewer.Destiny = function() {};
  10585. ZamModelViewer.Destiny.Model = function(renderer, viewer, model, index, parent) {
  10586.  var self = this;
  10587.  self.renderer = renderer;
  10588.  self.viewer = viewer;
  10589.  self.model = model;
  10590.  self.modelPath = null;
  10591.  self.loaded = false;
  10592.  self.opts = self.viewer.options;
  10593.  self.gender = self.opts.gender ? parseInt(self.opts.gender) : 0;
  10594.  self.meta = null;
  10595.  self.index = index;
  10596.  self.parent = parent || null;
  10597.  self.models = null;
  10598.  self.textureLookup = {};
  10599.  self.textures = null;
  10600.  self.geometry = null;
  10601.  self.genderGeometry = [null, null];
  10602.  self.genderTextures = [null, null];
  10603.  self.dyeGeometry = null;
  10604.  self.dyeTextures = null;
  10605.  self.gear = null;
  10606.  self.matrix = mat4.create();
  10607.  self.ib = null;
  10608.  self.shaderReady = false;
  10609.  self.vs = null;
  10610.  self.fs = null;
  10611.  self.program = null;
  10612.  self.uniforms = null;
  10613.  self.attribs = null;
  10614.  self.ambientColor = [.35, .35, .35, 1];
  10615.  self.primaryColor = [1, 1, 1, 1];
  10616.  self.secondaryColor = [.35, .35, .35, 1];
  10617.  self.lightDir1 = vec3.create();
  10618.  self.lightDir2 = vec3.create();
  10619.  self.lightDir3 = vec3.create();
  10620.  vec3.normalize(self.lightDir1, [-3, -3, -4]);
  10621.  vec3.normalize(self.lightDir2, [3, 1, -3]);
  10622.  vec3.normalize(self.lightDir3, [-3, -1, -5]);
  10623.  self.lightIntensity = vec4.set(vec4.create(), .7, .15, .15, .25);
  10624.  self.animBounds = false;
  10625.  self.boundsCenter = [0, 0, 0];
  10626.  self.boundsSize = [0, 0, 0];
  10627.  self.boundsMin = [0, 0, 0];
  10628.  self.boundsMax = [0, 0, 0];
  10629.  self.tmpMat = mat4.create();
  10630.  self.tmpVec = vec3.create();
  10631.  self.load()
  10632. };
  10633. ZamModelViewer.Models[ZamModelViewer.DESTINY] = ZamModelViewer.Destiny.Model;
  10634. ZamModelViewer.Destiny.Model.prototype = {
  10635.  destroy: function() {
  10636.   var self = this,
  10637.    gl = self.renderer.context,
  10638.    i, j;
  10639.   if (self.program) gl.deleteProgram(self.program);
  10640.   if (self.vs) gl.deleteShader(self.vs);
  10641.   if (self.fs) gl.deleteShader(self.fs);
  10642.   if (self.textures) {
  10643.    for (i = 0; i < self.textures.length; ++i) {
  10644.     self.textures[i].destroy()
  10645.    }
  10646.   }
  10647.   if (self.models) {
  10648.    for (i = 0; i < self.models.length; ++i) {
  10649.     self.models[i].destroy()
  10650.    }
  10651.   }
  10652.   if (self.geometry) {
  10653.    for (i = 0; i < self.geometry.length; ++i) {
  10654.     self.geometry[i].destroy()
  10655.    }
  10656.   }
  10657.  },
  10658.  update: function() {
  10659.   var self = this,
  10660.    i;
  10661.   var delta = self.renderer.delta;
  10662.   if (self.skeleton) self.skeleton.update(delta);
  10663.   if (self.models) {
  10664.    for (i = 0; i < self.models.length; ++i) {
  10665.     self.models[i].update()
  10666.    }
  10667.   } else if (self.geometry && self.parent && self.parent.skeleton) {
  10668.    for (i = 0; i < self.geometry.length; ++i) {
  10669.     self.geometry[i].update()
  10670.    }
  10671.   }
  10672.  },
  10673.  draw: function() {
  10674.   var self = this,
  10675.    gl = self.renderer.context,
  10676.    i;
  10677.   if (!self.loaded) return;
  10678.   if (!self.shaderReady) self.initShader();
  10679.   if (!self.program) return;
  10680.   self.update();
  10681.   gl.useProgram(self.program);
  10682.   gl.frontFace(gl.CW);
  10683.   gl.disable(gl.CULL_FACE);
  10684.   if (self.parent) {
  10685.    gl.uniformMatrix4fv(self.uniforms.vModelMatrix, false, self.parent.matrix)
  10686.   } else {
  10687.    gl.uniformMatrix4fv(self.uniforms.vModelMatrix, false, self.matrix)
  10688.   }
  10689.   gl.uniformMatrix4fv(self.uniforms.vViewMatrix, false, self.renderer.viewMatrix);
  10690.   gl.uniformMatrix4fv(self.uniforms.vProjMatrix, false, self.renderer.projMatrix);
  10691.   gl.uniform4fv(self.uniforms.fLightIntensity, self.lightIntensity);
  10692.   gl.uniform3fv(self.uniforms.fLightDir1, self.lightDir1);
  10693.   gl.uniform3fv(self.uniforms.fLightDir2, self.lightDir2);
  10694.   gl.uniform3fv(self.uniforms.fLightDir3, self.lightDir3);
  10695.   gl.uniform3fv(self.uniforms.fCameraPos, self.renderer.eye);
  10696.   gl.uniform1i(self.uniforms.fHasParent, !!self.parent);
  10697.   if (self.models) {
  10698.    for (i = 0; i < self.models.length; ++i) {
  10699.     self.models[i].draw()
  10700.    }
  10701.   } else if (self.geometry) {
  10702.    var delta = self.renderer.delta;
  10703.    for (i = 0; i < self.geometry.length; ++i) {
  10704.     self.geometry[i].draw(delta)
  10705.    }
  10706.   }
  10707.  },
  10708.  updateBounds: function() {
  10709.   var self = this,
  10710.    i, j, m, g;
  10711.   var min = vec3.set(self.boundsMin, 9999, 9999, 9999),
  10712.    max = vec3.set(self.boundsMax, -9999, -9999, -9999);
  10713.   if (!self.models) {
  10714.    for (i = 0; i < self.geometry.length; ++i) {
  10715.     g = self.geometry[i];
  10716.     for (j = 0; j < g.meshes.length; ++j) {
  10717.      m = g.meshes[j];
  10718.      min = vec3.min(min, min, m.boundsMin);
  10719.      max = vec3.max(max, max, m.boundsMax)
  10720.     }
  10721.    }
  10722.   } else {
  10723.    for (i = 0; i < self.models.length; ++i) {
  10724.     m = self.models[i];
  10725.     if (!m.loaded) continue;
  10726.     min = vec3.min(min, min, m.boundsMin);
  10727.     max = vec3.max(max, max, m.boundsMax)
  10728.    }
  10729.   }
  10730.   vec3.subtract(self.boundsSize, max, min);
  10731.   vec3.scaleAndAdd(self.boundsCenter, min, self.boundsSize, .5);
  10732.   var hSize = self.boundsSize[2],
  10733.    wSize = self.boundsSize[0],
  10734.    dSize = self.boundsSize[1];
  10735.   if (!self.parent) {
  10736.    if (self.opts.dist) {
  10737.     self.renderer.distance = self.opts.dist
  10738.    } else {
  10739.     var ratio = self.renderer.width / self.renderer.height;
  10740.     var hTan = 2 * Math.tan(self.renderer.fov / 2 * .0174532925);
  10741.     var wTan = hTan * ratio;
  10742.     var hDist = hSize * 1.2 / hTan;
  10743.     var wDist = wSize * 1.2 / wTan;
  10744.     self.renderer.distance = Math.max(Math.max(hDist, wDist), dSize * 1.25)
  10745.    }
  10746.    mat4.identity(self.matrix);
  10747.    mat4.rotateZ(self.matrix, self.matrix, Math.PI / 2);
  10748.    mat4.translate(self.matrix, self.matrix, vec3.negate(self.tmpVec, self.boundsCenter))
  10749.   } else {
  10750.    self.parent.updateBounds()
  10751.   }
  10752.  }
  10753. };
  10754. ZamModelViewer.Destiny.Model.prototype.load = function() {
  10755.  var self = this;
  10756.  if (self.model) {
  10757.   self._load(self.model)
  10758.  } else if (self.opts.items) {
  10759.   var items;
  10760.   if ($.isArray(self.opts.items)) {
  10761.    items = self.opts.items
  10762.   } else {
  10763.    items = self.opts.items.split(";")
  10764.   }
  10765.   var excludeIdx = items.indexOf("4248210736");
  10766.   if (excludeIdx > -1) items.splice(excludeIdx, 1);
  10767.   $.getJSON(self.opts.contentPath + "skeleton.json", function(data) {
  10768.    self.skeleton = new ZamModelViewer.Destiny.Skeleton(self, data)
  10769.   });
  10770.   self.models = new Array(items.length);
  10771.   for (var i = 0; i < items.length; ++i) {
  10772.    self.models[i] = new ZamModelViewer.Destiny.Model(self.renderer, self.viewer, items[i], i, self)
  10773.   }
  10774.   self.loaded = true
  10775.  }
  10776. };
  10777. ZamModelViewer.Destiny.Model.prototype._load = function(id) {
  10778.  var self = this;
  10779.  var url = self.opts.contentPath + "geom/mobile/" + id + ".geom";
  10780.  if (self.opts.cacheBuster) {
  10781.   url += "?" + self.opts.cacheBuster
  10782.  } else {
  10783.   url += "?1"
  10784.  }
  10785.  $.ajax({
  10786.   url: url,
  10787.   type: "GET",
  10788.   dataType: "binary",
  10789.   responseType: "arraybuffer",
  10790.   processData: false,
  10791.   renderer: self.renderer,
  10792.   success: function(buffer) {
  10793.    self.loadGeom(buffer)
  10794.   },
  10795.   error: function(xhr, status, error) {
  10796.    console.log(error)
  10797.   }
  10798.  })
  10799. };
  10800. ZamModelViewer.Destiny.Model.prototype.loadGeom = function(buffer) {
  10801.  if (!buffer) {
  10802.   console.error("Bad buffer for DataView");
  10803.   return
  10804.  }
  10805.  var self = this,
  10806.   r = new ZamModelViewer.DataView(buffer),
  10807.   D = ZamModelViewer.Destiny,
  10808.   i;
  10809.  var magic = r.getUint32();
  10810.  if (magic != 572728357) {
  10811.   console.log("Bad magic value");
  10812.   return
  10813.  }
  10814.  var compressedData = new Uint8Array(buffer, r.position);
  10815.  var data = null;
  10816.  try {
  10817.   data = pako.inflate(compressedData)
  10818.  } catch (err) {
  10819.   console.log("Decompression error: " + err);
  10820.   return
  10821.  }
  10822.  r = new ZamModelViewer.DataView(data.buffer);
  10823.  var numTextures = r.getInt32();
  10824.  self.textures = new Array(numTextures);
  10825.  for (i = 0; i < numTextures; ++i) {
  10826.   var tex = r.getString();
  10827.   self.textures[i] = new D.Texture(self, "textures/mobile/" + tex);
  10828.   self.textureLookup[tex] = i
  10829.  }
  10830.  var numGeometry = r.getInt32();
  10831.  self.geometry = new Array(numGeometry);
  10832.  for (i = 0; i < numGeometry; ++i) {
  10833.   self.geometry[i] = new D.Geometry(self, r)
  10834.  }
  10835.  var numMaleGeom = r.getInt32();
  10836.  self.genderGeometry[0] = new Array(numMaleGeom);
  10837.  for (i = 0; i < numMaleGeom; ++i) {
  10838.   self.genderGeometry[0][i] = r.getInt32()
  10839.  }
  10840.  var numMaleTextures = r.getInt32();
  10841.  self.genderTextures[0] = new Array(numMaleTextures);
  10842.  for (i = 0; i < numMaleTextures; ++i) {
  10843.   self.genderTextures[0][i] = r.getInt32()
  10844.  }
  10845.  var numFemaleGeom = r.getInt32();
  10846.  self.genderGeometry[1] = new Array(numFemaleGeom);
  10847.  for (i = 0; i < numFemaleGeom; ++i) {
  10848.   self.genderGeometry[1][i] = r.getInt32()
  10849.  }
  10850.  var numFemaleTextures = r.getInt32();
  10851.  self.genderTextures[1] = new Array(numFemaleTextures);
  10852.  for (i = 0; i < numFemaleTextures; ++i) {
  10853.   self.genderTextures[1][i] = r.getInt32()
  10854.  }
  10855.  var numDyeGeom = r.getInt32();
  10856.  self.dyeGeometry = new Array(numDyeGeom);
  10857.  for (i = 0; i < numDyeGeom; ++i) {
  10858.   self.dyeGeometry[i] = r.getInt32()
  10859.  }
  10860.  var numDyeTextures = r.getInt32();
  10861.  self.dyeTextures = new Array(numDyeTextures);
  10862.  for (i = 0; i < numDyeTextures; ++i) {
  10863.   self.dyeTextures[i] = r.getInt32()
  10864.  }
  10865.  var gearLen = r.getInt32();
  10866.  var gearStr = r.getString(gearLen);
  10867.  self.gear = JSON.parse(gearStr);
  10868.  if (self.gear) {
  10869.   if (self.gear.locked_dyes && self.gear.locked_dyes.length > 0) {
  10870.    self.dyeLocked = true;
  10871.    self.dyeInfo = self.gear.locked_dyes
  10872.   } else if (self.gear.custom_dyes && self.gear.custom_dyes.length > 0) {
  10873.    self.dyeInfo = self.gear.custom_dyes;
  10874.    if (self.parent) self.parent.dyeInfo = self.dyeInfo
  10875.   } else if (self.gear.default_dyes && self.gear.default_dyes.length > 0) {
  10876.    self.dyeInfo = self.gear.default_dyes
  10877.   }
  10878.  }
  10879.  if (numGeometry > 0 && numMaleGeom == 0 && numFemaleGeom == 0) {
  10880.   for (i = 0; i < numGeometry; ++i) {
  10881.    self.geometry[i].show = true
  10882.   }
  10883.  } else {
  10884.   var geom = self.genderGeometry[self.gender];
  10885.   for (i = 0; i < geom.length; ++i) {
  10886.    self.geometry[geom[i]].show = true
  10887.   }
  10888.  }
  10889.  self.loaded = true;
  10890.  self.updateBounds()
  10891. };
  10892. ZamModelViewer.Destiny.Model.prototype.initShader = function() {
  10893.  var self = this,
  10894.   gl = self.renderer.context;
  10895.  self.shaderReady = true;
  10896.  var vs = self.renderer.compileShader(gl.VERTEX_SHADER, self.vertShader);
  10897.  var fs = self.renderer.compileShader(gl.FRAGMENT_SHADER, self.fragShader);
  10898.  var program = gl.createProgram();
  10899.  gl.attachShader(program, vs);
  10900.  gl.attachShader(program, fs);
  10901.  gl.linkProgram(program);
  10902.  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  10903.   console.error("Error linking shaders");
  10904.   return
  10905.  }
  10906.  self.vs = vs;
  10907.  self.fs = fs;
  10908.  self.program = program;
  10909.  self.uniforms = {
  10910.   vModelMatrix: gl.getUniformLocation(program, "uModelMatrix"),
  10911.   vViewMatrix: gl.getUniformLocation(program, "uViewMatrix"),
  10912.   vProjMatrix: gl.getUniformLocation(program, "uProjMatrix"),
  10913.   vHasColor: gl.getUniformLocation(program, "uvHasColor"),
  10914.   fHasColor: gl.getUniformLocation(program, "ufHasColor"),
  10915.   fHasParent: gl.getUniformLocation(program, "uHasParent"),
  10916.   fHasDiffuse: gl.getUniformLocation(program, "uHasDiffuse"),
  10917.   fHasNormal: gl.getUniformLocation(program, "uHasNormal"),
  10918.   fHasStack: gl.getUniformLocation(program, "uHasStack"),
  10919.   fLit: gl.getUniformLocation(program, "uLit"),
  10920.   fDiffuse: gl.getUniformLocation(program, "uDiffuse"),
  10921.   fNormal: gl.getUniformLocation(program, "uNormal"),
  10922.   fStack: gl.getUniformLocation(program, "uStack"),
  10923.   fColor: gl.getUniformLocation(program, "uColor"),
  10924.   fLightIntensity: gl.getUniformLocation(program, "uLightIntensity"),
  10925.   fLightDir1: gl.getUniformLocation(program, "uLightDir1"),
  10926.   fLightDir2: gl.getUniformLocation(program, "uLightDir2"),
  10927.   fLightDir3: gl.getUniformLocation(program, "uLightDir3"),
  10928.   fCameraPos: gl.getUniformLocation(program, "uCameraPos")
  10929.  };
  10930.  self.attribs = {
  10931.   position: gl.getAttribLocation(program, "aPosition"),
  10932.   normal: gl.getAttribLocation(program, "aNormal"),
  10933.   tangent: gl.getAttribLocation(program, "aTangent"),
  10934.   color: gl.getAttribLocation(program, "aColor"),
  10935.   texcoord: gl.getAttribLocation(program, "aTexCoords")
  10936.  }
  10937. };
  10938. ZamModelViewer.Destiny.Model.prototype.vertShader = "    attribute vec3 aPosition;    attribute vec4 aNormal;    attribute vec4 aTangent;    attribute vec2 aTexCoords;    attribute vec4 aColor;        varying vec3 vPosition;    varying vec3 vNormal;    varying vec3 vTangent;    varying vec3 vBinormal;    varying vec2 vTexCoords;    varying vec4 vColor;        uniform mat4 uModelMatrix;    uniform mat4 uViewMatrix;    uniform mat4 uProjMatrix;    uniform bool uvHasColor;        void main(void) {        gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition, 1);        vPosition = (uViewMatrix * uModelMatrix * vec4(aPosition, 1)).xyz;                vTexCoords = aTexCoords;        vec4 normal = normalize(aNormal);        vec4 tangent = normalize(aTangent);        vec4 binormal = vec4(cross(normal.xyz, tangent.xyz) * tangent.w, 1);                vNormal = mat3(uViewMatrix * uModelMatrix) * normal.xyz;        vTangent = mat3(uViewMatrix * uModelMatrix) * tangent.xyz;        vBinormal = mat3(uViewMatrix * uModelMatrix) * binormal.xyz;                if (uvHasColor) {            vColor = aColor;        }    }";
  10939. ZamModelViewer.Destiny.Model.prototype.fragShader = "    precision mediump float;        varying vec3 vPosition;    varying vec3 vNormal;    varying vec3 vTangent;    varying vec3 vBinormal;    varying vec2 vTexCoords;    varying vec4 vColor;        uniform bool ufHasColor;    uniform bool uHasParent;    uniform bool uHasDiffuse;    uniform bool uHasNormal;    uniform bool uHasStack;    uniform bool uLit;    uniform sampler2D uDiffuse;    uniform sampler2D uNormal;    uniform sampler2D uStack;    uniform vec4 uColor;    uniform vec3 uLightDir1;    uniform vec3 uLightDir2;    uniform vec3 uLightDir3;    uniform vec4 uLightIntensity;    uniform vec3 uCameraPos;        vec3 saturate(vec3 value) {        return clamp(value, 0.0, 1.0);    }        float saturate(float value) {        return clamp(value, 0.0, 1.0);    }        void main(void) {        vec4 color = vec4(1, 0, 1, 1);        if (uHasDiffuse) { color.rgb = texture2D(uDiffuse, vTexCoords).rgb; }        vec3 tintColor = vec3(1.0, 1.0, 1.0);        vec3 stackColor = vec3(1.0, 1.0, 1.0);        float specExponent = 255.0;        vec3 specColor = vec3(0.2, 0.2, 0.2);                if (uHasStack) {            color.rgb = pow(color.rgb, vec3(2.2, 2.2, 2.2));            stackColor = texture2D(uStack, vTexCoords).rgb;                        if (uHasParent && stackColor.b < 0.05) { discard; }                        tintColor = uColor.rgb * saturate(color.rgb * 4.0) + saturate(color.rgb - 0.25);            color.rgb = tintColor * stackColor.r + color.rgb * (1.0 - stackColor.r);            float invGamma = 1.0 / 2.2;            color.rgb = pow(color.rgb, vec3(invGamma, invGamma, invGamma));                        specExponent = stackColor.g * 255.0;        }                if (uHasNormal && uLit) {            vec3 normalMap = texture2D(uNormal, vTexCoords).rgb;            vec3 tNormal = normalize(vNormal);            vec3 tTangent = normalize(vTangent);            vec3 tBinormal = normalize(vBinormal);                        vec3 normal = mat3(tTangent, tBinormal, tNormal) * normalize(normalMap * 2.0 - vec3(1.0, 1.0, 1.0));            vec3 cameraDir = normalize(uCameraPos - vPosition);                        vec3 litColor = color.rgb * uLightIntensity.a;                        float facing = -1.0 + 2.0 * float(gl_FrontFacing);            float NdotL = saturate(dot(normal, uLightDir1) * facing);            float RdotV = max(0.0, dot(normal * NdotL * 2.0 - uLightDir1, cameraDir));                        vec3 specular = saturate(specColor * pow(RdotV, specExponent)) * stackColor.g * uLightIntensity.x * NdotL * 0.5;            litColor += color.rgb * NdotL * uLightIntensity.x + specular;                        NdotL = saturate(dot(normal, uLightDir2) * facing);            RdotV = max(0.0, dot(normal * NdotL * 2.0 - uLightDir2, cameraDir));                        specular = saturate(specColor * pow(RdotV, specExponent)) * stackColor.g * uLightIntensity.y * NdotL * 0.5;            litColor += color.rgb * NdotL * uLightIntensity.y + specular;                        NdotL = saturate(dot(normal, uLightDir3) * facing);            RdotV = max(0.0, dot(normal * NdotL * 2.0 - uLightDir3, cameraDir));                        specular = saturate(specColor * pow(RdotV, specExponent)) * stackColor.g * uLightIntensity.z * NdotL * 0.5;            litColor += color.rgb * NdotL * uLightIntensity.z + specular;                        color.rgb = saturate(litColor);        }                gl_FragColor = color;    }";
  10940. ZamModelViewer.Destiny.Geometry = function(model, r) {
  10941.  var self = this,
  10942.   D = ZamModelViewer.Destiny,
  10943.   i;
  10944.  self.model = model;
  10945.  self.name = r.getString();
  10946.  var numMeshes = r.getInt32();
  10947.  self.meshes = new Array(numMeshes);
  10948.  for (i = 0; i < numMeshes; ++i) {
  10949.   self.meshes[i] = new D.Mesh(self, r)
  10950.  }
  10951.  var numPlates = r.getInt32();
  10952.  self.plates = new Array(numPlates);
  10953.  for (i = 0; i < numPlates; ++i) {
  10954.   self.plates[i] = new D.TexturePlate(self, r)
  10955.  }
  10956.  self.show = false
  10957. };
  10958. ZamModelViewer.Destiny.Geometry.prototype = {
  10959.  destroy: function() {
  10960.   var self = this,
  10961.    i;
  10962.   for (i = 0; i < self.meshes.length; ++i) {
  10963.    self.meshes[i].destroy()
  10964.   }
  10965.   for (i = 0; i < self.plates.length; ++i) {
  10966.    self.plates[i].destroy()
  10967.   }
  10968.  },
  10969.  update: function() {
  10970.   var self = this,
  10971.    i;
  10972.   if (!self.show) return;
  10973.   for (i = 0; i < self.meshes.length; ++i) {
  10974.    self.meshes[i].update()
  10975.   }
  10976.  },
  10977.  draw: function(delta) {
  10978.   var self = this,
  10979.    i;
  10980.   if (!self.show) return;
  10981.   for (i = 0; i < self.meshes.length; ++i) {
  10982.    self.meshes[i].draw(delta, true)
  10983.   }
  10984.   for (i = 0; i < self.meshes.length; ++i) {
  10985.    self.meshes[i].draw(delta)
  10986.   }
  10987.  },
  10988.  load: function() {
  10989.   var self = this,
  10990.    i;
  10991.   for (i = 0; i < self.plates.length; ++i) {
  10992.    self.plates[i].load()
  10993.   }
  10994.  }
  10995. };
  10996. ZamModelViewer.Destiny.Mesh = function(geometry, r) {
  10997.  var self = this,
  10998.   D = ZamModelViewer.Destiny,
  10999.   i, j;
  11000.  self.geometry = geometry;
  11001.  self.model = self.geometry.model;
  11002.  self.renderer = self.model.renderer;
  11003.  var gl = self.renderer.context;
  11004.  var numVbs = r.getInt32();
  11005.  self.vbs = new Array(numVbs);
  11006.  for (i = 0; i < numVbs; ++i) {
  11007.   self.vbs[i] = new D.VertexBuffer(self.model, r);
  11008.   if (!self.posInfo) {
  11009.    self.posInfo = self.vbs[i].getTypeData(D.VertexBuffer.Types.Position);
  11010.    if (self.posInfo && self.vbs[i].positions) self.positions = self.vbs[i].positions
  11011.   }
  11012.   if (!self.normInfo) {
  11013.    self.normInfo = self.vbs[i].getTypeData(D.VertexBuffer.Types.Normal);
  11014.    if (self.normInfo && self.vbs[i].normals) self.normals = self.vbs[i].normals
  11015.   }
  11016.   if (!self.tanInfo) {
  11017.    self.tanInfo = self.vbs[i].getTypeData(D.VertexBuffer.Types.Tangent);
  11018.    if (self.tanInfo && self.vbs[i].tangents) self.tangents = self.vbs[i].tangents
  11019.   }
  11020.   if (self.vbs[i].hasBlendWeights) self.weights = self.vbs[i].weights;
  11021.   if (self.vbs[i].hasBlendIndices) self.indices = self.vbs[i].indices
  11022.  }
  11023.  var numIndices = r.getInt32();
  11024.  var indices = new Uint16Array(numIndices);
  11025.  for (i = 0; i < numIndices; ++i) {
  11026.   indices[i] = r.getUint16()
  11027.  }
  11028.  self.boundsMin = [r.getFloat(), r.getFloat(), r.getFloat()];
  11029.  self.boundsMax = [r.getFloat(), r.getFloat(), r.getFloat()];
  11030.  self.offset = [r.getFloat(), r.getFloat(), r.getFloat()];
  11031.  self.scale = [r.getFloat(), r.getFloat(), r.getFloat()];
  11032.  self.ibData = [];
  11033.  var indexStart, indexCount, numTris;
  11034.  var numParts = r.getInt32();
  11035.  self.parts = new Array(numParts);
  11036.  for (i = 0; i < numParts; ++i) {
  11037.   self.parts[i] = new D.MeshPart(r);
  11038.   numTris = 0;
  11039.   indexStart = self.parts[i].indexStart;
  11040.   indexCount = self.parts[i].indexCount;
  11041.   self.parts[i].firstIndex = self.ibData.length;
  11042.   if (self.parts[i].primitive == 5) {
  11043.    for (j = 0; j < indexCount; ++j) {
  11044.     self.ibData.push(indices[indexStart + j])
  11045.    }
  11046.    numTris = indexCount
  11047.   } else if (self.parts[i].primitive == 3) {
  11048.    for (j = 0; j < indexCount; ++j) {
  11049.     self.ibData.push(indices[indexStart + j])
  11050.    }
  11051.    numTris = indexCount / 3
  11052.   } else {
  11053.    console.error("unhandled primitive type")
  11054.   }
  11055.   self.parts[i].triangleCount = numTris;
  11056.   self.tmpVec = vec4.create()
  11057.  }
  11058.  self.ib = gl.createBuffer();
  11059.  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  11060.  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(self.ibData), gl.STATIC_DRAW)
  11061. };
  11062. ZamModelViewer.Destiny.Mesh.prototype = {
  11063.  destroy: function() {
  11064.   var self = this,
  11065.    gl = self.renderer.context,
  11066.    i;
  11067.   if (self.ib) {
  11068.    gl.deleteBuffer(self.ib);
  11069.    self.ib = null
  11070.   }
  11071.   for (i = 0; i < self.vbs.length; ++i) {
  11072.    self.vbs[i].destroy()
  11073.   }
  11074.  },
  11075.  hasAllTextures: function() {
  11076.   var self = this;
  11077.   if (!self.texture && (!self.geometry.plates || self.geometry.plates.length > 0)) return false;
  11078.   if (!self.normalTexture && (!self.geometry.plates || self.geometry.plates.length > 1)) return false;
  11079.   if (!self.stackTexture && (!self.geometry.plates || self.geometry.plates.length > 2)) return false;
  11080.   for (var i = 0; i < self.parts.length; ++i) {
  11081.    if (self.parts[i].diffuse && !self.parts[i].diffuse.texture) return false;
  11082.    if (self.parts[i].normal && !self.parts[i].normal.texture) return false;
  11083.    if (self.parts[i].stack && !self.parts[i].stack.texture) return false
  11084.   }
  11085.   return true
  11086.  },
  11087.  getSlot: function(type) {
  11088.   var self = this,
  11089.    o, base = 0;
  11090.   for (var i = 0; i < self.vbs.length; ++i) {
  11091.    o = self.vbs[i].getSlot(type);
  11092.    if (o) {
  11093.     for (var idx in o) {
  11094.      o[idx] += base
  11095.     }
  11096.     return 0
  11097.    } else {
  11098.     base += self.vbs[i].vbSlots
  11099.    }
  11100.   }
  11101.   return null
  11102.  },
  11103.  update: function() {
  11104.   var self = this;
  11105.   if (!self.posInfo || !self.model.parent || !self.model.parent.skeleton) return;
  11106.   var i, j, w, b, sk = self.model.parent.skeleton,
  11107.    tmpVec = self.tmpVec;
  11108.   var posStride = self.posInfo.stride,
  11109.    posCount = self.posInfo.count,
  11110.    posBuffer = self.posInfo.buffer,
  11111.    posOfs = self.posInfo.offset;
  11112.   var nrmStride = self.normInfo.stride,
  11113.    nrmCount = self.normInfo.count,
  11114.    nrmBuffer = self.normInfo.buffer,
  11115.    nrmOfs = self.normInfo.offset;
  11116.   var tanStride = self.tanInfo.stride,
  11117.    tanCount = self.tanInfo.count,
  11118.    tanBuffer = self.tanInfo.buffer,
  11119.    tanOfs = self.tanInfo.offset;
  11120.   for (i = 0; i < posCount; ++i, posOfs += posStride, nrmOfs += nrmStride, tanOfs += tanStride) {
  11121.    posBuffer[posOfs + 0] = posBuffer[posOfs + 1] = posBuffer[posOfs + 2] = 0;
  11122.    nrmBuffer[nrmOfs + 0] = nrmBuffer[nrmOfs + 1] = nrmBuffer[nrmOfs + 2] = 0;
  11123.    tanBuffer[tanOfs + 0] = tanBuffer[tanOfs + 1] = tanBuffer[tanOfs + 2] = 0;
  11124.    if (self.weights) {
  11125.     for (j = 0; j < 4; ++j) {
  11126.      b = self.indices[i][j];
  11127.      w = self.weights[i][j] / 255;
  11128.      if (w == 0) continue;
  11129.      vec3.transformMat4(tmpVec, self.positions[i], sk.finalMats[b]);
  11130.      posBuffer[posOfs] += tmpVec[0] * w;
  11131.      posBuffer[posOfs + 1] += tmpVec[1] * w;
  11132.      posBuffer[posOfs + 2] += tmpVec[2] * w;
  11133.      vec4.transformMat4(tmpVec, self.normals[i], sk.finalMats[b]);
  11134.      nrmBuffer[nrmOfs] += tmpVec[0] * w;
  11135.      nrmBuffer[nrmOfs + 1] += tmpVec[1] * w;
  11136.      nrmBuffer[nrmOfs + 2] += tmpVec[2] * w;
  11137.      vec4.transformMat4(tmpVec, self.tangents[i], sk.finalMats[b]);
  11138.      tanBuffer[tanOfs] += tmpVec[0] * w;
  11139.      tanBuffer[tanOfs + 1] += tmpVec[1] * w;
  11140.      tanBuffer[tanOfs + 2] += tmpVec[2] * w
  11141.     }
  11142.    } else if (self.indices) {
  11143.     for (j = 0; j < 2; ++j) {
  11144.      b = self.indices[i][j];
  11145.      w = self.indices[i][j + 2] / 255;
  11146.      if (w == 0) continue;
  11147.      vec3.transformMat4(tmpVec, self.positions[i], sk.finalMats[b]);
  11148.      posBuffer[posOfs] += tmpVec[0] * w;
  11149.      posBuffer[posOfs + 1] += tmpVec[1] * w;
  11150.      posBuffer[posOfs + 2] += tmpVec[2] * w;
  11151.      vec4.transformMat4(tmpVec, self.normals[i], sk.finalMats[b]);
  11152.      nrmBuffer[nrmOfs] += tmpVec[0] * w;
  11153.      nrmBuffer[nrmOfs + 1] += tmpVec[1] * w;
  11154.      nrmBuffer[nrmOfs + 2] += tmpVec[2] * w;
  11155.      vec4.transformMat4(tmpVec, self.tangents[i], sk.finalMats[b]);
  11156.      tanBuffer[tanOfs] += tmpVec[0] * w;
  11157.      tanBuffer[tanOfs + 1] += tmpVec[1] * w;
  11158.      tanBuffer[tanOfs + 2] += tmpVec[2] * w
  11159.     }
  11160.    } else {
  11161.     b = self.positions[i][3] | 0;
  11162.     vec3.transformMat4(tmpVec, self.positions[i], sk.finalMats[b]);
  11163.     posBuffer[posOfs] = tmpVec[0];
  11164.     posBuffer[posOfs + 1] = tmpVec[1];
  11165.     posBuffer[posOfs + 2] = tmpVec[2];
  11166.     vec4.transformMat4(tmpVec, self.normals[i], sk.finalMats[b]);
  11167.     nrmBuffer[nrmOfs] = tmpVec[0];
  11168.     nrmBuffer[nrmOfs + 1] = tmpVec[1];
  11169.     nrmBuffer[nrmOfs + 2] = tmpVec[2];
  11170.     vec4.transformMat4(tmpVec, self.tangents[i], sk.finalMats[b]);
  11171.     tanBuffer[tanOfs] = tmpVec[0];
  11172.     tanBuffer[tanOfs + 1] = tmpVec[1];
  11173.     tanBuffer[tanOfs + 2] = tmpVec[2]
  11174.    }
  11175.   }
  11176.   self.posInfo.vb.updateBuffers()
  11177.  }
  11178. };
  11179. ZamModelViewer.Destiny.Mesh.prototype.draw = function(delta, depthOnly) {
  11180.  var self = this,
  11181.   gl = self.renderer.context,
  11182.   i, p, t;
  11183.  if (!self.hasTextures) {
  11184.   for (i = 0; i < self.parts.length; ++i) {
  11185.    p = self.parts[i];
  11186.    if (p.diffuseTexture && !p.diffuse && self.model.textureLookup[p.diffuseTexture] !== undefined) {
  11187.     t = self.model.textures[self.model.textureLookup[p.diffuseTexture]];
  11188.     if (!t.img && !t.error) t.load();
  11189.     p.diffuse = t
  11190.    } else if (p.normalTexture && !p.normal && self.model.textureLookup[p.normalTexture] !== undefined) {
  11191.     t = self.model.textures[self.model.textureLookup[p.normalTexture]];
  11192.     if (!t.img && !t.error) t.load();
  11193.     p.normal = t
  11194.    } else if (p.stackTexture && !p.stack && self.model.textureLookup[p.stackTexture] !== undefined) {
  11195.     t = self.model.textures[self.model.textureLookup[p.stackTexture]];
  11196.     if (!t.img && !t.error) t.load();
  11197.     p.stack = t
  11198.    }
  11199.   }
  11200.   self.geometry.load();
  11201.   if (self.geometry.plates.length > 0) {
  11202.    p = self.geometry.plates[0];
  11203.    if (!self.texture && p.texture != null && p.texture.texture) self.texture = p.texture;
  11204.    p = self.geometry.plates[1];
  11205.    if (!self.normalTexture && p.texture != null && p.texture.texture) self.normalTexture = p.texture;
  11206.    p = self.geometry.plates[2];
  11207.    if (!self.stackTexture && p.texture != null && p.texture.texture) self.stackTexture = p.texture
  11208.   }
  11209.   if (self.hasAllTextures()) self.hasTextures = true
  11210.  }
  11211.  for (i = 0; i < self.vbs.length; ++i) {
  11212.   self.vbs[i].enable()
  11213.  }
  11214.  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.ib);
  11215.  var hasColor = self.getSlot(ZamModelViewer.Destiny.VertexBuffer.Types.Color) != null;
  11216.  gl.uniform1i(self.model.uniforms.vHasColor, hasColor);
  11217.  gl.uniform1i(self.model.uniforms.fHasColor, hasColor);
  11218.  self.drawParts(depthOnly);
  11219.  for (i = 0; i < self.vbs.length; ++i) {
  11220.   self.vbs[i].disable()
  11221.  }
  11222. };
  11223. ZamModelViewer.Destiny.Mesh.prototype.drawParts = function(depthOnly) {
  11224.  var self = this,
  11225.   gl = self.renderer.context,
  11226.   dyes = self.model.dyeInfo,
  11227.   resetBlending = false,
  11228.   resetMask = false;
  11229.  if (!self.model.dyeLocked && self.model.parent && self.model.parent.dyeInfo) dyes = self.model.parent.dyeInfo;
  11230.  var i, j, k, p, alphaHadTexture = false;
  11231.  for (i = 0; i < self.parts.length; ++i) {
  11232.   p = self.parts[i];
  11233.   if (self.geometry.name == "482021716-1" && p.indexCount == 330 && p.flags == 0) continue;
  11234.   if (p.lodName.indexOf("0") == -1) continue;
  11235.   if (!depthOnly) {
  11236.    if ((p.flags & 32) > 0 || (p.flags & 64) > 0) continue
  11237.   } else {
  11238.    if ((p.flags & 32) == 0) continue
  11239.   }
  11240.   if ((p.flags & 32) > 0) {
  11241.    if (!resetBlending) {
  11242.     resetBlending = true;
  11243.     gl.blendFunc(gl.SRC_COLOR, gl.ONE);
  11244.     gl.depthMask(false)
  11245.    }
  11246.    if (p.diffuseTexture) alphaHadTexture = true;
  11247.    else if (alphaHadTexture) continue
  11248.   } else {
  11249.    if (resetBlending) {
  11250.     resetBlending = false;
  11251.     gl.blendFunc(gl.ONE, gl.ZERO);
  11252.     gl.depthMask(true)
  11253.    }
  11254.    if (resetMask) {
  11255.     resetMask = false;
  11256.     gl.colorMask(true, true, true, true)
  11257.    }
  11258.   }
  11259.   var hasDiffuse = true,
  11260.    hasNormal = true,
  11261.    hasStack = true;
  11262.   gl.activeTexture(gl.TEXTURE0);
  11263.   if (p.diffuse) {
  11264.    if (p.diffuse.texture) {
  11265.     gl.bindTexture(gl.TEXTURE_2D, p.diffuse.texture)
  11266.    } else hasDiffuse = false
  11267.   } else if (self.texture && self.texture.texture) {
  11268.    gl.bindTexture(gl.TEXTURE_2D, self.texture.texture)
  11269.   } else hasDiffuse = false;
  11270.   gl.activeTexture(gl.TEXTURE1);
  11271.   if (p.normal) {
  11272.    if (p.normal.texture) {
  11273.     gl.bindTexture(gl.TEXTURE_2D, p.normal.texture)
  11274.    } else hasNormal = false
  11275.   } else if (self.normalTexture && self.normalTexture.texture) {
  11276.    gl.bindTexture(gl.TEXTURE_2D, self.normalTexture.texture)
  11277.   } else hasNormal = false;
  11278.   gl.activeTexture(gl.TEXTURE2);
  11279.   if (p.stack) {
  11280.    if (p.stack.texture) {
  11281.     gl.bindTexture(gl.TEXTURE_2D, p.stack.texture)
  11282.    } else hasStack = false
  11283.   } else if (self.stackTexture && self.stackTexture.texture) {
  11284.    gl.bindTexture(gl.TEXTURE_2D, self.stackTexture.texture)
  11285.   } else hasStack = false;
  11286.   if (dyes) {
  11287.    for (j = 0; j < dyes.length; ++j) {
  11288.     if (dyes[j].slot_type_index == p.dyeIndex) {
  11289.      var dye = dyes[j].material_properties;
  11290.      if (p.usePrimaryColor)
  11291.       for (k = 0; k < 4; ++k) self.tmpVec[k] = dye.primary_color[k];
  11292.      else
  11293.       for (k = 0; k < 4; ++k) self.tmpVec[k] = dye.secondary_color[k];
  11294.      break
  11295.     }
  11296.    }
  11297.   }
  11298.   if (!hasDiffuse) {
  11299.    continue
  11300.   }
  11301.   gl.uniform1i(self.model.uniforms.fHasDiffuse, hasDiffuse);
  11302.   gl.uniform1i(self.model.uniforms.fHasNormal, hasNormal);
  11303.   gl.uniform1i(self.model.uniforms.fHasStack, hasStack);
  11304.   gl.uniform1i(self.model.uniforms.fLit, (p.flags & 32) == 0);
  11305.   if (hasDiffuse) gl.uniform1i(self.model.uniforms.fDiffuse, 0);
  11306.   if (hasNormal) gl.uniform1i(self.model.uniforms.fNormal, 1);
  11307.   if (hasStack) gl.uniform1i(self.model.uniforms.fStack, 2);
  11308.   gl.uniform4fv(self.model.uniforms.fColor, self.tmpVec);
  11309.   if (p.primitive == 5) {
  11310.    gl.drawElements(gl.TRIANGLE_STRIP, p.triangleCount, gl.UNSIGNED_SHORT, p.firstIndex * 2)
  11311.   } else {
  11312.    gl.drawElements(gl.TRIANGLES, p.triangleCount * 3, gl.UNSIGNED_SHORT, p.firstIndex * 2)
  11313.   }
  11314.  }
  11315.  if (resetBlending) {
  11316.   gl.blendFunc(gl.ONE, gl.ZERO);
  11317.   gl.depthMask(true)
  11318.  }
  11319.  if (resetMask) {
  11320.   gl.colorMask(true, true, true, true)
  11321.  }
  11322. };
  11323. ZamModelViewer.Destiny.MeshPart = function(r) {
  11324.  var self = this,
  11325.   i;
  11326.  self.indexStart = r.getUint16();
  11327.  self.indexCount = r.getUint16();
  11328.  self.indexMin = r.getUint16();
  11329.  self.indexMax = r.getUint16();
  11330.  self.flags = r.getUint32();
  11331.  self.primitive = r.getInt32();
  11332.  var dyeIndex = r.getInt32();
  11333.  self.externalId = r.getUint32();
  11334.  self.lod = r.getInt32();
  11335.  self.lodName = r.getString();
  11336.  self.usePrimaryColor = true;
  11337.  switch (dyeIndex) {
  11338.   case 0:
  11339.    self.dyeIndex = 0;
  11340.    break;
  11341.   case 1:
  11342.    self.dyeIndex = 0;
  11343.    self.usePrimaryColor = false;
  11344.    break;
  11345.   case 2:
  11346.    self.dyeIndex = 1;
  11347.    break;
  11348.   case 3:
  11349.    self.dyeIndex = 1;
  11350.    self.usePrimaryColor = false;
  11351.    break;
  11352.   case 4:
  11353.    self.dyeIndex = 2;
  11354.    break;
  11355.   case 5:
  11356.    self.dyeIndex = 2;
  11357.    self.usePrimaryColor = false;
  11358.    break;
  11359.   case 6:
  11360.   case 7:
  11361.    self.dyeIndex = 3;
  11362.    break
  11363.  }
  11364.  var numTextures = r.getInt32();
  11365.  self.textures = new Array(numTextures);
  11366.  for (i = 0; i < numTextures; ++i) {
  11367.   self.textures[i] = r.getString();
  11368.   if (self.textures[i].indexOf(".") == -1) self.textures[i] += ".png"
  11369.  }
  11370.  if (numTextures >= 5) {
  11371.   self.diffuseTexture = self.textures[0];
  11372.   self.normalTexture = self.textures[2];
  11373.   self.stackTexture = self.textures[4]
  11374.  } else if (numTextures > 0 && self.textures[0].indexOf("detail") == -1) {
  11375.   self.diffuseTexture = self.textures[0]
  11376.  }
  11377. };
  11378. ZamModelViewer.Destiny.Texture = function(model, url) {
  11379.  var self = this;
  11380.  self.model = model;
  11381.  self.url = model.opts.contentPath + url;
  11382.  if (model.opts.cacheBuster) {
  11383.   self.url += "?" + model.opts.cacheBuster
  11384.  } else {
  11385.   self.url += "?1"
  11386.  }
  11387.  self.texture = null
  11388. };
  11389. ZamModelViewer.Destiny.Texture.prototype = {
  11390.  destroy: function() {
  11391.   var self = this,
  11392.    gl = self.model.renderer.context;
  11393.   if (self.texture) gl.deleteTexture(self.texture);
  11394.   self.img = null
  11395.  },
  11396.  load: function() {
  11397.   var self = this,
  11398.    gl = self.model.renderer.context;
  11399.   (function(self, gl) {
  11400.    self.img = new Image;
  11401.    self.img.crossOrigin = "";
  11402.    self.img.onload = function() {
  11403.     self.img.loaded = true;
  11404.     self.texture = gl.createTexture();
  11405.     gl.bindTexture(gl.TEXTURE_2D, self.texture);
  11406.     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.img);
  11407.     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
  11408.    };
  11409.    self.img.onerror = function() {
  11410.     self.img = null;
  11411.     self.error = true
  11412.    };
  11413.    self.img.src = self.url
  11414.   })(self, gl)
  11415.  }
  11416. };
  11417. ZamModelViewer.Destiny.TexturePlate = function(geom, r) {
  11418.  var self = this,
  11419.   D = ZamModelViewer.Destiny;
  11420.  self.geometry = geom;
  11421.  self.model = geom.model;
  11422.  self.name = r.getString();
  11423.  self.id = r.getString();
  11424.  self.index = r.getInt32();
  11425.  self.width = r.getInt16();
  11426.  self.height = r.getInt16();
  11427.  var numTextures = r.getInt32();
  11428.  self.textures = new Array(numTextures);
  11429.  for (var i = 0; i < numTextures; ++i) {
  11430.   self.textures[i] = new D.TexturePlate.Part(r)
  11431.  }
  11432. };
  11433. ZamModelViewer.Destiny.TexturePlate.prototype = {
  11434.  destroy: function() {
  11435.   var self = this;
  11436.   if (self.texture) self.texture.destroy()
  11437.  },
  11438.  load: function() {
  11439.   var self = this,
  11440.    D = ZamModelViewer.Destiny;
  11441.   if (self.name != "diffuse" && self.name != "gearstack" && self.name != "normal") return;
  11442.   if (!self.texture) {
  11443.    self.texture = new D.Texture(self.model, "textures/mobile/" + self.id + ".png");
  11444.    self.texture.load()
  11445.   }
  11446.  }
  11447. };
  11448. ZamModelViewer.Destiny.TexturePlate.Part = function(r) {
  11449.  var self = this;
  11450.  self.name = r.getString();
  11451.  self.index = r.getInt32();
  11452.  self.width = r.getInt16();
  11453.  self.height = r.getInt16();
  11454.  self.x = r.getInt16();
  11455.  self.y = r.getInt16()
  11456. };
  11457. ZamModelViewer.Destiny.VertexBuffer = function(model, r) {
  11458.  var self = this,
  11459.   Types = ZamModelViewer.Destiny.VertexBuffer.Types;
  11460.  self.model = model;
  11461.  self.renderer = model.renderer;
  11462.  self.count = r.getInt32();
  11463.  self.stride = r.getInt32();
  11464.  var numElements = r.getInt32();
  11465.  self.elements = new Array(numElements);
  11466.  var slot = 0,
  11467.   offset = 0,
  11468.   i, j;
  11469.  for (i = 0; i < numElements; ++i) {
  11470.   var type = r.getUint8();
  11471.   var obj = {
  11472.    type: type,
  11473.    slot: slot,
  11474.    offset: offset
  11475.   };
  11476.   if (type >= Types.Position && type <= Types.MaxPosition) {
  11477.    self.positions = new Array(numElements);
  11478.    self.hasPosition = true;
  11479.    obj.name = "position";
  11480.    obj.baseType = Types.Position;
  11481.    obj.size = 3;
  11482.    obj.read = self.readPosition;
  11483.    offset += 3
  11484.   } else if (type >= Types.TexCoord && type <= Types.MaxTexCoord) {
  11485.    obj.name = "texcoord";
  11486.    obj.baseType = Types.TexCoord;
  11487.    obj.size = 2;
  11488.    obj.read = self.readTexCoord;
  11489.    offset += 2
  11490.   } else if (type >= Types.Normal && type <= Types.MaxNormal) {
  11491.    self.normals = new Array(numElements);
  11492.    self.hasNormal = true;
  11493.    obj.name = "normal";
  11494.    obj.baseType = Types.Normal;
  11495.    obj.size = 4;
  11496.    obj.read = self.readNormal;
  11497.    offset += 4
  11498.   } else if (type >= Types.Tangent && type <= Types.MaxTangent) {
  11499.    self.tangents = new Array(numElements);
  11500.    self.hasTangent = true;
  11501.    obj.name = "tangent";
  11502.    obj.baseType = Types.Tangent;
  11503.    obj.size = 4;
  11504.    obj.read = self.readTangent;
  11505.    offset += 4
  11506.   } else if (type >= Types.Color && type <= Types.MaxColor) {
  11507.    obj.name = "color";
  11508.    obj.baseType = Types.Color;
  11509.    obj.size = 4;
  11510.    obj.read = self.readColor;
  11511.    offset += 4
  11512.   } else if (type >= Types.BlendWeight && type <= Types.MaxWeight) {
  11513.    self.weights = new Array(numElements);
  11514.    self.hasBlendWeights = true;
  11515.    obj.baseType = Types.BlendWeight;
  11516.    obj.read = self.readBlendWeight;
  11517.    obj.discard = true
  11518.   } else if (type >= Types.BlendIndex && type <= Types.MaxIndex) {
  11519.    self.indices = new Array(numElements);
  11520.    self.hasBlendIndices = true;
  11521.    obj.baseType = Types.BlendIndex;
  11522.    obj.read = self.readBlendIndex;
  11523.    obj.discard = true
  11524.   } else {
  11525.    throw "bad type"
  11526.   }
  11527.   self.elements[i] = obj;
  11528.   if (obj.discard) continue;
  11529.   slot++
  11530.  }
  11531.  self.vbStride = offset;
  11532.  self.vbSlots = slot;
  11533.  self.vbData = new Float32Array(self.count * self.vbStride);
  11534.  var idx = 0;
  11535.  for (i = 0; i < self.count; ++i) {
  11536.   for (j = 0; j < numElements; ++j) {
  11537.    idx = self.elements[j].read.call(this, r, self.vbData, idx, i)
  11538.   }
  11539.  }
  11540.  self.updateBuffers()
  11541. };
  11542. ZamModelViewer.Destiny.VertexBuffer.prototype = {
  11543.  destroy: function() {
  11544.   var self = this,
  11545.    gl = self.renderer.context;
  11546.   if (self.buffer) {
  11547.    gl.deleteBuffer(self.buffer);
  11548.    self.buffer = null
  11549.   }
  11550.  },
  11551.  enable: function() {
  11552.   var self = this,
  11553.    gl = self.renderer.context,
  11554.    i, e;
  11555.   gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
  11556.   for (i = 0; i < self.elements.length; ++i) {
  11557.    e = self.elements[i];
  11558.    if (e.name && e.type == e.baseType) {
  11559.     gl.enableVertexAttribArray(self.model.attribs[e.name]);
  11560.     gl.vertexAttribPointer(self.model.attribs[e.name], e.size, gl.FLOAT, false, self.vbStride * 4, e.offset * 4)
  11561.    }
  11562.   }
  11563.  },
  11564.  disable: function() {
  11565.   var self = this,
  11566.    gl = self.renderer.context,
  11567.    i, e;
  11568.   gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
  11569.   for (i = 0; i < self.elements.length; ++i) {
  11570.    e = self.elements[i];
  11571.    if (e.name && e.type == e.baseType) {
  11572.     gl.disableVertexAttribArray(self.model.attribs[e.name])
  11573.    }
  11574.   }
  11575.  },
  11576.  updateBuffers: function() {
  11577.   var self = this,
  11578.    gl = self.renderer.context;
  11579.   if (self.vbStride > 0) {
  11580.    if (!self.buffer) {
  11581.     self.buffer = gl.createBuffer();
  11582.     gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
  11583.     gl.bufferData(gl.ARRAY_BUFFER, self.vbData, gl.DYNAMIC_DRAW)
  11584.    } else {
  11585.     gl.bindBuffer(gl.ARRAY_BUFFER, self.buffer);
  11586.     gl.bufferSubData(gl.ARRAY_BUFFER, 0, self.vbData)
  11587.    }
  11588.   }
  11589.  },
  11590.  getTypeData: function(type) {
  11591.   var self = this,
  11592.    e, i;
  11593.   for (i = 0; i < self.elements.length; ++i) {
  11594.    e = self.elements[i];
  11595.    if (e.type == type) {
  11596.     return {
  11597.      buffer: self.vbData,
  11598.      offset: e.offset,
  11599.      stride: self.vbStride,
  11600.      count: self.count,
  11601.      vb: self
  11602.     }
  11603.    }
  11604.   }
  11605.   return null
  11606.  },
  11607.  getSlot: function(type) {
  11608.   var self = this,
  11609.    obj = {},
  11610.    e, i;
  11611.   for (i = 0; i < self.elements.length; ++i) {
  11612.    e = self.elements[i];
  11613.    if (e.discard) continue;
  11614.    if (type == e.baseType) {
  11615.     var index = e.type - e.baseType;
  11616.     obj[index] = e.slot
  11617.    }
  11618.   }
  11619.   var empty = true;
  11620.   for (var idx in obj) {
  11621.    empty = false;
  11622.    break
  11623.   }
  11624.   if (empty) return null;
  11625.   return obj
  11626.  },
  11627.  readPosition: function(r, vbData, idx, i) {
  11628.   var self = this;
  11629.   var pos = self.positions[i] = [r.getFloat(), r.getFloat(), r.getFloat(), r.getFloat()];
  11630.   vbData[idx++] = pos[0];
  11631.   vbData[idx++] = pos[1];
  11632.   vbData[idx++] = pos[2];
  11633.   return idx
  11634.  },
  11635.  readTexCoord: function(r, vbData, idx, i) {
  11636.   vbData[idx++] = r.getFloat();
  11637.   vbData[idx++] = r.getFloat();
  11638.   return idx
  11639.  },
  11640.  readNormal: function(r, vbData, idx, i) {
  11641.   var self = this;
  11642.   var normal = self.normals[i] = [r.getFloat(), r.getFloat(), r.getFloat(), r.getFloat()];
  11643.   vbData[idx++] = normal[0];
  11644.   vbData[idx++] = normal[1];
  11645.   vbData[idx++] = normal[2];
  11646.   vbData[idx++] = normal[3];
  11647.   return idx
  11648.  },
  11649.  readTangent: function(r, vbData, idx, i) {
  11650.   var self = this;
  11651.   var tangent = self.tangents[i] = [r.getFloat(), r.getFloat(), r.getFloat(), r.getFloat()];
  11652.   vbData[idx++] = tangent[0];
  11653.   vbData[idx++] = tangent[1];
  11654.   vbData[idx++] = tangent[2];
  11655.   vbData[idx++] = tangent[3];
  11656.   return idx
  11657.  },
  11658.  readColor: function(r, vbData, idx, i) {
  11659.   vbData[idx++] = r.getUint8() / 255;
  11660.   vbData[idx++] = r.getUint8() / 255;
  11661.   vbData[idx++] = r.getUint8() / 255;
  11662.   vbData[idx++] = r.getUint8() / 255;
  11663.   return idx
  11664.  },
  11665.  readBlendWeight: function(r, vbData, idx, i) {
  11666.   var self = this;
  11667.   self.weights[i] = [r.getUint8(), r.getUint8(), r.getUint8(), r.getUint8()];
  11668.   return idx
  11669.  },
  11670.  readBlendIndex: function(r, vbData, idx, i) {
  11671.   var self = this;
  11672.   self.indices[i] = [r.getUint8(), r.getUint8(), r.getUint8(), r.getUint8()];
  11673.   return idx
  11674.  }
  11675. };
  11676. ZamModelViewer.Destiny.VertexBuffer.Types = {
  11677.  Position: 1,
  11678.  MaxPosition: 3,
  11679.  TexCoord: 4,
  11680.  MaxTexCoord: 11,
  11681.  Normal: 12,
  11682.  MaxNormal: 18,
  11683.  Tangent: 19,
  11684.  MaxTangent: 25,
  11685.  Color: 26,
  11686.  MaxColor: 32,
  11687.  BlendWeight: 33,
  11688.  MaxWeight: 39,
  11689.  BlendIndex: 40,
  11690.  MaxIndex: 47
  11691. };
  11692. ZamModelViewer.Destiny.Skeleton = function(model, data) {
  11693.  var self = this,
  11694.   i, j;
  11695.  if (!data || !data.anim || !data.bones) {
  11696.   throw "Invalid skeleton data"
  11697.  }
  11698.  self.model = model;
  11699.  var anim = self.anim = data.anim;
  11700.  var bones = self.bones = data.bones;
  11701.  self.fps = 30;
  11702.  self.frameDuration = 1 / self.fps;
  11703.  self.frameTime = 0;
  11704.  self.frame = 0;
  11705.  self.animFrames = new Array(anim.frame_count);
  11706.  var tmpMat = mat4.create();
  11707.  var staticBoneData = anim.static_bone_data,
  11708.   staticScaleMap = staticBoneData.scale_control_map,
  11709.   staticRotationMap = staticBoneData.rotation_control_map,
  11710.   staticTranslationMap = staticBoneData.translation_control_map,
  11711.   staticFrame = staticBoneData.transform_stream_header.streams.frames[0],
  11712.   staticScales = staticFrame.scales,
  11713.   staticRotations = staticFrame.rotations,
  11714.   staticTranslations = staticFrame.translations,
  11715.   animBoneData = anim.animated_bone_data,
  11716.   animScaleMap = animBoneData.scale_control_map,
  11717.   animRotationMap = animBoneData.rotation_control_map,
  11718.   animTranslationMap = animBoneData.translation_control_map,
  11719.   animTransformFrames = animBoneData.transform_stream_header.streams.frames;
  11720.  for (i = 0; i < anim.frame_count; ++i) {
  11721.   var frameMats = new Array(anim.node_count);
  11722.   var frame = animTransformFrames[i];
  11723.   for (j = 0; j < anim.node_count; ++j) {
  11724.    var staticScaleIdx = staticScaleMap.indexOf(j),
  11725.     staticRotIdx = staticRotationMap.indexOf(j),
  11726.     staticTransIdx = staticTranslationMap.indexOf(j);
  11727.    var animScaleIdx = animScaleMap.indexOf(j),
  11728.     animRotIdx = animRotationMap.indexOf(j),
  11729.     animTransIdx = animTranslationMap.indexOf(j);
  11730.    var scale = staticScaleIdx >= 0 ? staticScales[staticScaleIdx] : frame.scales[animScaleIdx];
  11731.    var rot = staticRotIdx >= 0 ? staticRotations[staticRotIdx] : frame.rotations[animRotIdx];
  11732.    var trans = staticTransIdx >= 0 ? staticTranslations[staticTransIdx] : frame.translations[animTransIdx];
  11733.    mat4.fromQuat(tmpMat, rot);
  11734.    mat4.scale(tmpMat, tmpMat, [scale, scale, scale]);
  11735.    tmpMat[12] = trans[0];
  11736.    tmpMat[13] = trans[1];
  11737.    tmpMat[14] = trans[2];
  11738.    frameMats[j] = mat4.clone(tmpMat)
  11739.   }
  11740.   self.animFrames[i] = frameMats
  11741.  }
  11742.  self.frameMats = new Array(anim.node_count);
  11743.  self.finalMats = new Array(anim.node_count);
  11744.  for (i = 0; i < anim.node_count; ++i) {
  11745.   self.frameMats[i] = mat4.create();
  11746.   self.finalMats[i] = mat4.create()
  11747.  }
  11748.  self.parentNodes = new Array(bones.definition.nodes.length);
  11749.  self.invMatrices = new Array(bones.definition.default_inverse_object_space_transforms.length);
  11750.  for (i = 0; i < bones.definition.nodes.length; ++i) {
  11751.   self.parentNodes[i] = bones.definition.nodes[i].parent_node_index
  11752.  }
  11753.  for (i = 0; i < bones.definition.default_inverse_object_space_transforms.length; ++i) {
  11754.   var info = bones.definition.default_inverse_object_space_transforms[i];
  11755.   mat4.fromQuat(tmpMat, info.r);
  11756.   mat4.scale(tmpMat, tmpMat, [info.ts[3], info.ts[3], info.ts[3]]);
  11757.   tmpMat[12] = info.ts[0];
  11758.   tmpMat[13] = info.ts[1];
  11759.   tmpMat[14] = info.ts[2];
  11760.   self.invMatrices[i] = mat4.clone(tmpMat)
  11761.  }
  11762. };
  11763. ZamModelViewer.Destiny.Skeleton.prototype = {
  11764.  update: function(delta) {
  11765.   var self = this;
  11766.   self.frameTime += delta;
  11767.   while (self.frameTime >= self.frameDuration) {
  11768.    self.frameTime -= self.frameDuration;
  11769.    self.frame++
  11770.   }
  11771.   while (self.frame >= self.anim.frame_count) self.frame -= self.anim.frame_count;
  11772.   var mat, frameMat, parentId;
  11773.   var mats = self.animFrames[self.frame];
  11774.   for (var i = 0; i < self.anim.node_count; ++i) {
  11775.    mat = mats[i];
  11776.    frameMat = self.frameMats[i];
  11777.    parentId = self.parentNodes[i];
  11778.    if (parentId >= 0) {
  11779.     mat4.multiply(frameMat, self.frameMats[parentId], mat)
  11780.    } else {
  11781.     mat4.copy(frameMat, mat)
  11782.    }
  11783.    mat4.multiply(self.finalMats[i], frameMat, self.invMatrices[i])
  11784.   }
  11785.  }
  11786. };
  11787. ZamModelViewer.Lol = function() {};
  11788. ZamModelViewer.Lol.Model = function(renderer, viewer, model, index, parent) {
  11789.  var self = this;
  11790.  vec3.set(renderer.up, 0, 1, 0);
  11791.  self.renderer = renderer;
  11792.  self.viewer = viewer;
  11793.  self.model = model;
  11794.  self.modelIndex = index;
  11795.  self.loaded = false;
  11796.  self.animsLoaded = false;
  11797.  self.opts = self.viewer.options;
  11798.  self.meta = null;
  11799.  self.parent = parent || null;
  11800.  self.texture = null;
  11801.  self.meshTextures = {};
  11802.  self.animIndex = -1;
  11803.  self.animName = null;
  11804.  self.baseAnim = null;
  11805.  self.meshes = null;
  11806.  self.vertices = null;
  11807.  self.indices = null;
  11808.  self.transforms = null;
  11809.  self.bones = null;
  11810.  self.boneLookup = {};
  11811.  self.matrix = mat4.create();
  11812.  self.ib = null;
  11813.  self.shaderReady = false;
  11814.  self.vs = null;
  11815.  self.fs = null;
  11816.  self.program = null;
  11817.  self.uniforms = null;
  11818.  self.attribs = null;
  11819.  self.ambientColor = [.35, .35, .35, 1];
  11820.  self.primaryColor = [1, 1, 1, 1];
  11821.  self.secondaryColor = [.35, .35, .35, 1];
  11822.  self.lightDir1 = vec3.create();
  11823.  self.lightDir2 = vec3.create();
  11824.  self.lightDir3 = vec3.create();
  11825.  vec3.normalize(self.lightDir1, [5, 5, -5]);
  11826.  vec3.normalize(self.lightDir2, [5, 5, 5]);
  11827.  vec3.normalize(self.lightDir3, [-5, -5, -5]);
  11828.  self.animBounds = false;
  11829.  self.boundsCenter = [0, 0, 0];
  11830.  self.boundsSize = [0, 0, 0];
  11831.  self.boundsMin = [0, 0, 0];
  11832.  self.boundsMax = [0, 0, 0];
  11833.  self.modelOffset = 0;
  11834.  self.defaultDistance = 0;
  11835.  self.newAnimation = false;
  11836.  self.tmpMat = mat4.create();
  11837.  self.tmpVec = vec4.create();
  11838.  self.ANIMATED = true;
  11839.  self.hiddenBones = null;
  11840.  var hiddenBones = ZamModelViewer.Lol.Model.HiddenBones;
  11841.  if (hiddenBones[self.model.champion] !== undefined) {
  11842.   if (hiddenBones[self.model.champion][self.model.skin] !== undefined) {
  11843.    self.hiddenBones = hiddenBones[self.model.champion][self.model.skin]
  11844.   }
  11845.  }
  11846.  self.load()
  11847. };
  11848. ZamModelViewer.Models[ZamModelViewer.LOL] = ZamModelViewer.Lol.Model;
  11849. ZamModelViewer.Lol.Model.prototype = {
  11850.  external: {
  11851.   getNumAnimations: function() {
  11852.    return this.animations ? this.animations.length : 0
  11853.   },
  11854.   getAnimation: function(index) {
  11855.    if (this.animations && this.animations.length > index && index > -1) {
  11856.     return this.animations[index].name
  11857.    } else {
  11858.     return ""
  11859.    }
  11860.   },
  11861.   setAnimation: function(name) {
  11862.    for (i = 0; i < this.renderer.models.length; ++i) {
  11863.     this.renderer.models[i].setAnimation(name)
  11864.    }
  11865.   },
  11866.   isLoaded: function() {
  11867.    return this.loaded && this.animsLoaded
  11868.   }
  11869.  },
  11870.  destroy: function() {
  11871.   var self = this,
  11872.    gl = self.renderer.context,
  11873.    i, j;
  11874.   if (self.program) gl.deleteProgram(self.program);
  11875.   if (self.vs) gl.deleteShader(self.vs);
  11876.   if (self.fs) gl.deleteShader(self.fs);
  11877.   if (self.textures) {
  11878.    for (i = 0; i < self.textures.length; ++i) {
  11879.     self.textures[i].destroy()
  11880.    }
  11881.   }
  11882.   if (self.models) {
  11883.    for (i = 0; i < self.models.length; ++i) {
  11884.     self.models[i].destroy()
  11885.    }
  11886.   }
  11887.   if (self.geometry) {
  11888.    for (i = 0; i < self.geometry.length; ++i) {
  11889.     self.geometry[i].destroy()
  11890.    }
  11891.   }
  11892.  },
  11893.  getAnimation: function(name) {
  11894.   var self = this,
  11895.    i, animIndex = -1;
  11896.   if (!self.animations) return animIndex;
  11897.   name = name.toLowerCase();
  11898.   if (name == "idle" || name == "attack") {
  11899.    var anims = [],
  11900.     re = new RegExp(name + "[0-9]*");
  11901.    for (i = 0; i < self.animations.length; ++i) {
  11902.     if (self.animations[i].name.search(re) == 0) anims.push(i)
  11903.    }
  11904.    if (anims.length > 0) {
  11905.     animIndex = anims[Math.randomInt(0, anims.length)]
  11906.    }
  11907.   } else {
  11908.    for (i = 0; i < self.animations.length; ++i) {
  11909.     if (self.animations[i].name == name) {
  11910.      animIndex = i;
  11911.      break
  11912.     }
  11913.    }
  11914.   }
  11915.   return animIndex
  11916.  },
  11917.  setAnimation: function(name) {
  11918.   var self = this;
  11919.   self.animIndex = self.getAnimation(name);
  11920.   if (self.animIndex == -1) {
  11921.    if (name == "idle") {
  11922.     self.animIndex = 0;
  11923.     self.animName = self.animations[0].name
  11924.    } else {
  11925.     self.setAnimation("idle");
  11926.     return
  11927.    }
  11928.   } else {
  11929.    self.animName = name
  11930.   }
  11931.   var baseAnims = ZamModelViewer.Lol.Model.BaseAnimations;
  11932.   if (baseAnims[self.model.champion] !== undefined) {
  11933.    if (baseAnims[self.model.champion][self.model.skin] !== undefined) {
  11934.     var baseAnim = baseAnims[self.model.champion][self.model.skin],
  11935.      baseIndex = -1;
  11936.     if (baseAnim[self.animations[self.animIndex].name]) baseIndex = self.getAnimation(baseAnim[self.animations[self.animIndex].name]);
  11937.     else if (baseAnim["all"]) baseIndex = self.getAnimation(baseAnim["all"]);
  11938.     if (baseIndex > -1) self.baseAnim = self.animations[baseIndex];
  11939.     else self.baseAnim = null
  11940.    }
  11941.   }
  11942.   self.animTime = self.renderer.time;
  11943.   self.newAnimation = true
  11944.  },
  11945.  update: function() {
  11946.   var self = this,
  11947.    i, j, gl = self.renderer.context;
  11948.   if (!self.loaded || !self.vertices || !self.animations || self.animations.length == 0) return;
  11949.   if (self.animIndex == -1) self.setAnimation("idle");
  11950.   var time = self.renderer.time - self.animTime;
  11951.   var anim = self.animations[self.animIndex];
  11952.   if (time >= anim.duration) {
  11953.    self.setAnimation(self.animName);
  11954.    anim = self.animations[self.animIndex];
  11955.    time = 0
  11956.   }
  11957.   if (self.ANIMATED) {
  11958.    var timePerFrame = 1e3 / anim.fps;
  11959.    var frame = Math.floor(time / timePerFrame);
  11960.    var r = time % timePerFrame / timePerFrame;
  11961.    var hiddenBones = {};
  11962.    if (self.hiddenBones) {
  11963.     if (self.hiddenBones[anim.name]) hiddenBones = self.hiddenBones[anim.name];
  11964.     else if (self.hiddenBones["all"]) hiddenBones = self.hiddenBones["all"]
  11965.    }
  11966.    var b;
  11967.    if (self.version >= 1) {
  11968.     for (i = 0; i < self.bones.length; ++i) {
  11969.      b = self.bones[i];
  11970.      if (hiddenBones[b.name]) {
  11971.       mat4.identity(self.tmpMat);
  11972.       mat4.scale(self.tmpMat, self.tmpMat, vec3.set(self.tmpVec, 0, 0, 0));
  11973.       mat4.copy(self.transforms[i], self.tmpMat)
  11974.      } else if (anim.lookup[b.name] !== undefined) {
  11975.       anim.bones[anim.lookup[b.name]].update(i, frame, r)
  11976.      } else if (self.baseAnim && self.baseAnim.lookup[b.name] !== undefined) {
  11977.       self.baseAnim.bones[self.baseAnim.lookup[b.name]].update(i, frame, r)
  11978.      } else {
  11979.       if (b.parent != -1) {
  11980.        mat4.mulSlimDX(self.transforms[i], b.incrMatrix, self.transforms[b.parent])
  11981.       } else {
  11982.        mat4.copy(self.transforms[i], b.incrMatrix)
  11983.       }
  11984.      }
  11985.     }
  11986.    } else {
  11987.     for (i = 0; i < anim.bones.length; ++i) {
  11988.      b = anim.bones[i];
  11989.      if (self.boneLookup[b.bone] !== undefined) {
  11990.       b.update(self.boneLookup[b.bone], frame, r)
  11991.      } else {
  11992.       var parentBone = anim.bones[i - 1];
  11993.       if (!parentBone) continue;
  11994.       if (parentBone.index + 1 < self.transforms.length) {
  11995.        mat4.copy(self.transforms[parentBone.index + 1], self.transforms[parentBone.index])
  11996.       }
  11997.       b.index = parentBone.index + 1
  11998.      }
  11999.     }
  12000.    }
  12001.    var numBones = Math.min(self.transforms.length, self.bones.length);
  12002.    for (i = 0; i < numBones; ++i) {
  12003.     mat4.mulSlimDX(self.transforms[i], self.bones[i].baseMatrix, self.transforms[i])
  12004.    }
  12005.    mat4.identity(self.tmpMat);
  12006.    var numVerts = self.vertices.length,
  12007.     vbData = self.vbData,
  12008.     vec = self.tmpVec,
  12009.     v, w, m, idx;
  12010.    for (i = 0; i < numVerts; ++i) {
  12011.     v = self.vertices[i];
  12012.     idx = i * 8;
  12013.     vbData[idx] = vbData[idx + 1] = vbData[idx + 2] = vbData[idx + 3] = vbData[idx + 4] = vbData[idx + 5] = 0;
  12014.     for (j = 0; j < 4; ++j) {
  12015.      if (v.weights[j] > 0) {
  12016.       w = v.weights[j];
  12017.       m = anim.fps == 1 ? self.tmpMat : self.transforms[v.bones[j]];
  12018.       vec3.transformMat4(vec, v.position, m);
  12019.       vbData[idx] += vec[0] * w;
  12020.       vbData[idx + 1] += vec[1] * w;
  12021.       vbData[idx + 2] += vec[2] * w;
  12022.       vec4.transformMat4(vec, v.normal, m);
  12023.       vbData[idx + 3] += vec[0] * w;
  12024.       vbData[idx + 4] += vec[1] * w;
  12025.       vbData[idx + 5] += vec[2] * w
  12026.      }
  12027.     }
  12028.    }
  12029.    if (!self.animBounds) {
  12030.     self.updateBounds(true);
  12031.     self.animBounds = true
  12032.    }
  12033.    gl.bindBuffer(gl.ARRAY_BUFFER, self.vb);
  12034.    gl.bufferSubData(gl.ARRAY_BUFFER, 0, self.vbData)
  12035.   }
  12036.   if (self.newAnimation) {
  12037.    self.updateBounds(true);
  12038.    self.newAnimation = false
  12039.   }
  12040.  },
  12041.  updatePosition: function() {
  12042.   var self = this,
  12043.    index = self.modelIndex,
  12044.    offset = self.renderer.models[0].boundsSize[0] * 1.5;
  12045.   if (index > 2) {
  12046.    offset += Math.abs(self.renderer.models[index - 2].modelOffset)
  12047.   }
  12048.   if (self.modelIndex % 2 > 0) offset = -offset;
  12049.   self.modelOffset = offset;
  12050.   mat4.identity(self.matrix);
  12051.   mat4.translate(self.matrix, self.matrix, vec3.negate(self.tmpVec, self.boundsCenter));
  12052.   mat4.scale(self.matrix, self.matrix, vec3.set(self.tmpVec, -1, 1, 1));
  12053.   vec3.normalize(self.tmpVec, vec3.set(self.tmpVec, 4, 0, -1));
  12054.   vec3.scale(self.tmpVec, self.tmpVec, offset);
  12055.   if (offset < 0) self.tmpVec[2] = -self.tmpVec[2];
  12056.   self.matrix[12] += self.tmpVec[0];
  12057.   self.matrix[13] += self.tmpVec[1];
  12058.   self.matrix[14] += self.tmpVec[2]
  12059.  },
  12060.  updateBounds: function(useVb) {
  12061.   var self = this,
  12062.    i, j, m, idx, verts = self.vertices,
  12063.    vbData = self.vbData;
  12064.   var min = vec3.set(self.boundsMin, 9999, 9999, 9999),
  12065.    max = vec3.set(self.boundsMax, -9999, -9999, -9999),
  12066.    pos;
  12067.   if (!verts) return;
  12068.   if (self.meshes && self.indices) {
  12069.    var firstIndex, numIndices, visible;
  12070.    for (i = 0; i < self.meshes.length; ++i) {
  12071.     m = self.meshes[i];
  12072.     visible = !(self.meta && self.meta.meshVis[m.name] === false);
  12073.     if (!visible) continue;
  12074.     firstIndex = m.iStart;
  12075.     numIndices = m.iCount;
  12076.     for (j = 0; j < numIndices; ++j) {
  12077.      if (useVb) {
  12078.       idx = self.indices[firstIndex + j] * 8;
  12079.       pos = vec3.set(self.tmpVec, vbData[idx], vbData[idx + 1], vbData[idx + 2])
  12080.      } else {
  12081.       pos = vec3.copy(self.tmpVec, verts[self.indices[firstIndex + j]].position)
  12082.      }
  12083.      if (pos[1] < -250) pos[1] = min[1];
  12084.      min = vec3.min(min, min, pos);
  12085.      max = vec3.max(max, max, pos)
  12086.     }
  12087.    }
  12088.   } else {
  12089.    for (i = 0; i < verts.length; ++i) {
  12090.     if (useVb) {
  12091.      idx = i * 8;
  12092.      pos = vec3.set(self.tmpVec, vbData[idx], vbData[idx + 1], vbData[idx + 2])
  12093.     } else {
  12094.      pos = vec3.copy(self.tmpVec, verts[i].position)
  12095.     }
  12096.     if (pos[1] < -250) pos[1] = min[1];
  12097.     min = vec3.min(min, min, pos);
  12098.     max = vec3.max(max, max, pos)
  12099.    }
  12100.   }
  12101.   vec3.subtract(self.boundsSize, max, min);
  12102.   vec3.scaleAndAdd(self.boundsCenter, min, self.boundsSize, .5);
  12103.   vec3.copy(self.tmpVec, self.boundsCenter);
  12104.   self.tmpVec[1] = -self.tmpVec[1];
  12105.   mat4.identity(self.matrix);
  12106.   mat4.translate(self.matrix, self.matrix, self.tmpVec);
  12107.   mat4.scale(self.matrix, self.matrix, vec3.set(self.tmpVec, -1, 1, 1));
  12108.   var models = self.renderer.models;
  12109.   if (models.length > 1) {
  12110.    for (i = 1; i < models.length; ++i) {
  12111.     models[i].updatePosition()
  12112.    }
  12113.    if (self.modelIndex != 0) models[0].updateDistance()
  12114.   }
  12115.   if (self.modelIndex == 0) {
  12116.    self.updateDistance()
  12117.   }
  12118.  },
  12119.  updateDistance: function() {
  12120.   var self = this,
  12121.    models = self.renderer.models;
  12122.   var wSize = self.boundsSize[0],
  12123.    hSize = self.boundsSize[1],
  12124.    dSize = self.boundsSize[2];
  12125.   if (models.length > 1) {
  12126.    var width = Math.abs(models[models.length - 1].modelOffset) + models[models.length - 1].boundsSize[0];
  12127.    if (models.length > 2) {
  12128.     width += Math.abs(models[models.length - 2].modelOffset) + models[models.length - 2].boundsSize[0]
  12129.    } else {
  12130.     width *= 2
  12131.    }
  12132.    wSize = Math.max(wSize, width)
  12133.   }
  12134.   var dist;
  12135.   if (self.opts.dist) {
  12136.    dist = self.opts.dist
  12137.   } else {
  12138.    var ratio = self.renderer.width / self.renderer.height;
  12139.    var hTan = 2 * Math.tan(self.renderer.fov / 2 * .0174532925);
  12140.    var wTan = hTan * ratio;
  12141.    var hDist = hSize * 1.2 / hTan;
  12142.    var wDist = wSize * 1.2 / wTan;
  12143.    dist = Math.max(Math.max(hDist, wDist), dSize * 2)
  12144.   }
  12145.   if (self.defaultDistance == 0 || self.defaultDistance == self.renderer.distance) {
  12146.    self.defaultDistance = self.renderer.distance = dist
  12147.   }
  12148.  }
  12149. };
  12150. ZamModelViewer.Lol.Model.prototype.load = function() {
  12151.  var self = this;
  12152.  if (self.model && self.model.champion !== undefined && self.model.skin !== undefined) {
  12153.   self._load(self.model.champion, self.model.skin)
  12154.  }
  12155. };
  12156. ZamModelViewer.Lol.Model.prototype._load = function(champion, skin) {
  12157.  var self = this;
  12158.  self.champion = champion;
  12159.  self.skin = skin;
  12160.  $.getJSON(self.opts.contentPath + "meta/" + champion + "_" + skin + ".json", function(data) {
  12161.   self.loadMeta(data)
  12162.  });
  12163.  var url = self.opts.contentPath + "models/" + champion + "_" + skin + ".lmesh";
  12164.  $.ajax({
  12165.   url: url,
  12166.   type: "GET",
  12167.   dataType: "binary",
  12168.   responseType: "arraybuffer",
  12169.   processData: false,
  12170.   renderer: self.renderer,
  12171.   success: function(buffer) {
  12172.    self.loadMesh(buffer)
  12173.   },
  12174.   error: function(xhr, status, error) {
  12175.    console.log(error)
  12176.   }
  12177.  })
  12178. };
  12179. ZamModelViewer.Lol.Model.prototype.loadMeta = function(meta) {
  12180.  var self = this;
  12181.  self.meta = meta;
  12182.  if (self.animations) self.updateBounds(self.animBounds);
  12183.  for (var t in meta.meshTextures) {
  12184.   self.meshTextures[t] = new ZamModelViewer.Lol.Texture(self, self.champion + "/" + meta.meshTextures[t] + ".png")
  12185.  }
  12186. };
  12187. ZamModelViewer.Lol.Model.prototype.loadMesh = function(buffer) {
  12188.  if (!buffer) {
  12189.   console.error("Bad buffer for DataView");
  12190.   return
  12191.  }
  12192.  var self = this,
  12193.   r = new ZamModelViewer.DataView(buffer),
  12194.   i, v, idx, Lol = ZamModelViewer.Lol;
  12195.  var gl = self.renderer.context;
  12196.  var magic = r.getUint32();
  12197.  if (magic != 604210091) {
  12198.   console.log("Bad magic value");
  12199.   return
  12200.  }
  12201.  self.version = r.getUint32();
  12202.  var animFile = r.getString();
  12203.  var textureFile = r.getString();
  12204.  if (animFile && animFile.length > 0) {
  12205.   var url = self.opts.contentPath + "models/" + animFile + ".lanim";
  12206.   $.ajax({
  12207.    url: url,
  12208.    type: "GET",
  12209.    dataType: "binary",
  12210.    responseType: "arraybuffer",
  12211.    processData: false,
  12212.    renderer: self.renderer,
  12213.    success: function(buffer) {
  12214.     self.loadAnim(buffer)
  12215.    },
  12216.    error: function(xhr, status, error) {
  12217.     console.log(error)
  12218.    }
  12219.   })
  12220.  }
  12221.  if (textureFile && textureFile.length > 0) {
  12222.   self.texture = new Lol.Texture(self, self.champion + "/" + textureFile + ".png")
  12223.  }
  12224.  var numMeshes = r.getUint32();
  12225.  if (numMeshes > 0) {
  12226.   self.meshes = new Array(numMeshes);
  12227.   for (i = 0; i < numMeshes; ++i) {
  12228.    var name = r.getString().toLowerCase();
  12229.    var vStart = r.getUint32();
  12230.    var vCount = r.getUint32();
  12231.    var iStart = r.getUint32();
  12232.    var iCount = r.getUint32();
  12233.    self.meshes[i] = {
  12234.     name: name,
  12235.     vStart: vStart,
  12236.     vCount: vCount,
  12237.     iStart: iStart,
  12238.     iCount: iCount
  12239.    }
  12240.   }
  12241.  }
  12242.  var numVerts = r.getUint32();
  12243.  if (numVerts > 0) {
  12244.   self.vertices = new Array(numVerts);
  12245.   self.vbData = new Float32Array(numVerts * 8);
  12246.   for (i = 0; i < numVerts; ++i) {
  12247.    idx = i * 8;
  12248.    self.vertices[i] = v = new Lol.Vertex(r);
  12249.    self.vbData[idx] = v.position[0];
  12250.    self.vbData[idx + 1] = v.position[1];
  12251.    self.vbData[idx + 2] = v.position[2];
  12252.    self.vbData[idx + 3] = v.normal[0];
  12253.    self.vbData[idx + 4] = v.normal[1];
  12254.    self.vbData[idx + 5] = v.normal[2];
  12255.    self.vbData[idx + 6] = v.u;
  12256.    self.vbData[idx + 7] = v.v
  12257.   }
  12258.  }
  12259.  var numIndices = r.getUint32();
  12260.  if (numIndices > 0) {
  12261.   self.indices = new Array(numIndices);
  12262.   for (i = 0; i < numIndices; ++i) {
  12263.    self.indices[i] = r.getUint16()
  12264.   }
  12265.  }
  12266.  var numBones = r.getUint32();
  12267.  if (numBones > 0) {
  12268.   self.transforms = new Array(numBones);
  12269.   self.bones = new Array(numBones);
  12270.   for (i = 0; i < numBones; ++i) {
  12271.    self.bones[i] = new Lol.Bone(self, i, r);
  12272.    if (self.boneLookup[self.bones[i].name] !== undefined) {
  12273.     self.bones[i].name = self.bones[i].name + "2"
  12274.    }
  12275.    self.boneLookup[self.bones[i].name] = i;
  12276.    self.transforms[i] = new mat4.create
  12277.   }
  12278.  }
  12279.  if (self.vbData) {
  12280.   self.vb = gl.createBuffer();